Reputation: 10207
In my new Rails application (it's my first one!) Users can manage their Clients and also create Projects for each Client.
Users -----< Clients -----< Projects
In order to create a new Project for a Client, a user has to select the Client from a select box like this:
<%= f.label :client_id %>
<% options = current_user.clients.all.map { |client| [client.name, client.id] } %>
<%= f.select(:client_id, options) %>
My controller action looks like this:
client = current_user.clients.find(params[:project][:client_id])
@project = client.projects.build(params[:project])
This works quite well but I don't feel particularly good about putting the client_id into my form directly. In my Project model it even says:
attr_accessible :name, :client_id
So is this a security flaw? I don't want anyone to tamper with these foreign keys. Is there a more secure way to set foreign keys in Rails?
Upvotes: 1
Views: 65
Reputation: 7998
So Rails has a bunch of great form helpers for this sort of thing. Check this out:
This method will generate what you are looking for. To answer your question, no one can really tamper with these ids.
If you are comfortable allowing a user to select a Client for the Project, then the worst thing that can really happen is that you have an extra Project with a Client who isn't associated with that project.
Here's how I'd do what you were going for:
<%= f.select :client_id, options_from_collection_for_select(current_user.clients.all, 'id', 'name') %>
The methods takes the colleciton first (In your case its current_user.clients.all), then the attribute for the value of the option (in your case the id), then it takes the label attribute (in your case the name of the client)
You are correct that you need attr_accesible :client_id
but like I said, this really isn't a security concern.
Upvotes: 1