finding id of nested attribute - ruby-on-rails-3

I am very new to RoR so this may be very fundamental. My structure keeps getting a level deeper and I can't figure out how to find the id anymore.
First you have a Company which can have many Users. Users sign in and are authenticated and the current_user is saved in a cookie with the Session.
Since the User has one Company I can always find the Company.id through the current_user.
Next a Company has many Farms. In farms create I can get the company id from the user cookie and the farm id is new so that works, and in farm show Rails knows which farm it is supposed to show. So that level works.
Now I want to add that a Farm has many Blocks. I am adding Blocks through the associated Farm show page, but the Blocks_controller doesn't know what farm page it is on (as far as I can tell, if it can any info is appreciated).
Here is the FarmsController create that works:
def create
company_id = current_user.company_id
#company = Company.find(company_id)
#farm = #company.farms.build(params[:farm])
if #farm.save
flash[:success] = "farm created"
redirect_to root_path
else
render 'pages/home'
end
end
And this code just complains that it doesn't know what id I am talking about:
BlocksController
def create
#farm = Farm.find(params[:id])
#block = #farm.blocks.build(params[:block])
end
This is displaying on the associated Farm show page, so if there is a way to capture the id I would love to know what it is.
Thank you for your time.

The three easiest ways to get that id is to:
Pass in that farm_id using a hidden form field. When creating the link to your blocks/new form just pass in the farm_id ie use a path like new_blocks_path(:id => #farm.id) inside your blocks controller you will want to make sure that the farm_id is set on the Block model.
def new
#block = new Block
#block.farm_id = params[:farm_id]
end
Then if you are using form for the farm_id field (which should probably be of type hidden), it should contain the right id. Now change the first line in the "create" block method to
#farm = Farm.find(params[:block][:farm_id])
You can combine the process of adding the blocks and the farms using nested forms. Take a look at http://railscasts.com/episodes/196-nested-model-form-part-1 for how to do this.
You can use nested RESTful resources to make sure that within the blocks controller you always have access to the farm id. For more information about how to do this try take a look at http://railscasts.com/episodes/139-nested-resources

Related

How to find_or_initialize based on two fields when both fields correspond to possible uninitialized objects

Hi guys I have a situation where on a form I'm taking in orders for a car servicing application. I have the following models:
Car
belongs_to :car_company
Car_company
has_many :cars
Services
attributes_accessible :car_company_id, :car_id
#virtual attributes
attributes_accessible :car_company_name, :car_reg
The thing is that on a single form the user can enter in the name of the car company as well as the registration number of a car. If the company name doesnt exist it creates a new company and associates it with the service and the same goes for the car. I got this part working however the thing is that I want that on submitting this form the car created should be automatically associated with the car_company whether the carcompany exists or doesn't exist.
I'm pretty stuck here on how to get this thing done the right way? Its basically just to avoid having to enter the car details and the company details seperately just to use them on a form. Any ideas guys?
I see you are using an unconventional model name. By convention in rails, your model should be CarCompany. However, I think what you have will work.
Putting something like this in the appropriate controller may be something like what you want. If not, please clarify what you want.
car_company = Car_company.find_or_initialize_by_name(params[:car_company_name])
car = Car.find_or_initialize_by_registration(params[:car_registration])
car_company.cars << car
car_company.save
You actually may be able to combine the middle two lines with car_company.cars.find_or..., but I'm not sure if that works or not.
I hope that helps.

Finding Records using Rails without a Match (Fault without Fault Cleared)

I'm attempting to write a site in Rails where a user in a manufacturing plant can see what devices are failing. The program storing the alarm data stores one entry when a device faults, and then stores another entry when the device gets fixed. The entries are linked only by having the same value in the EventAssociationID column. How might I write a named scope in Rails to check which faults have been fixed and which ones haven't?
I wasn't able to do it in a named scope, however, I was able to define a method for the model that solved the problem:
def inAlarm
return ConditionEvent.count(:all, :conditions => ['EventAssociationID = ?', self.EventAssociationID]) == 1
end

In Rails 3, is there a difference between = and assign_attributes?

Let's say you're in your user controller and you want to change the name a #user based on some params you have available to you.
I want to know if there is any difference between the following:
#user.name = params[:user][:name]
or
#user.assign_attributes({:name=> params[:user][:name]})
Thanks in advance!
A great way to figure out questions like this is to dive into the source. I found the method in activerecord/lib/active_record/attribute_assignment.rbCheck it out here.
The assign_attributes method will actually just loop through the parameters given and sends the :name= message to your model. However, because you are possibly assigning many attributes, it takes into account mass-assignment precautions. (ie. make sure that the attribute is listed as attr_accessible).
The = (e.g. #user.name = params[:user][:name]) directly calls the attribute setter with no security check. The assign_attributes checks security for the values passed in.
From the Rails API for assign_attributes:
Allows you to set all the attributes for a particular mass-assignment
security role by passing in a hash of attributes with keys matching
the attribute names (which again matches the column names) and the
role name using the :as option.
Source for assign_attributes

How to get deeply nested errors to get to my REST API?

First, some background:
I have a Company model, a Project model and a Task model. A Project belongs to a company and a Task belongs_to a Project.
The Project model holds several attributes: company_id, date. These attributes uniquely identify a project
I am letting the users create a task by API by POSTing to a URL that contains the details necessary to identify the Project. For example:
POST /projects/<comnpany_name>/<date>/tasks/
In order to make life easier for the users, in case there is no project with the given details, I'd like to create the project on the fly by the given details, and then to create the task and assign it to the project.
...And my problem is:
When there is a problem to create the project, let's say that the company name is not valid, what is the right way to return the error message and communicate to the user?
I'll explain what I mean: I added a create_by_name_and_company_name method to the Project:
def self.create_by_name_and_company_name(name, company_name)
if company = Company.find_by_name(company_name)
project = Project.create(company_id: company.id,
name: name)
else # cannot create this project, trying to communicate the error
project = Project.new(name: name)
project.errors.add(:company, 'must have a valid name')
end
company
end
I was hoping that by returning an unsaved Company object, with errors set, will be a good way communicate the error (This is similar to how rails work when there's a validation error).
The problem is that when calling valid? on the company object, it removed the error I wrote there and adds the regular validation errors (in this case, company can't be blank).
And a bonus question...
And there is a conceptual problem as well: since I'm creating a model by providing parameters that are being used to create the actual attributes, they doesn't always map nicely to the errors[:attr] hash. In this case it is not so bad and I'm using the company field for the company name parameter, but I guess this can get messier when the parameters provided to the create method are less similar to the model attributes.
So what is the preferred approach to tackle that problem? Is there something basically wrong with that approach? if so, what is the preferred approach?
About overriding the default rails validation error message, you need to write your validation constraint like this:
validates_presence_of :name, :message => "must be a valid name"
I figure that it is best to avoid such nesting and stick to a shallower API.

Creating a good search solution

I have an app where users have a role,a username,faculty and so on.When I'm looking for a list of users by their role or faculty or anything they have in common I can call (among others possible)
#users = User.find_by_role(params[:role]) #or
#users = User.find_by_shift(params[:shift])
So it keeps the system
Class.find_by_property
So the question is: What if at different points users lists should be generated based on different properties.I mean: I'm passing from different links
params[:role] or
params[:faculty] or
params[:department]
to my list action in my users controller.As I see it all has to be in that action,but which parameter should the search be made by?
Try https://github.com/ernie/meta_search if you're on Rails 3