Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 Strong Parameters - Handling Missing Model Params Hash

Models: Posts and Users

Post belongs_to :user
User has_many :posts

Simple.

Assuming a few users exist, we visit the edit page for a Post.

<%= form_for @post do |f| %>

...

<% User.all.each do |user| %>
  <div><%= f.radio_button "user_id", user.id %></div>
<% end %>

...

The Post's Controller leverages Rails 4 strong parameters.

params.require(:post).permit(:user_id)

Assume the edit post form only has the radio buttons as fields.

Problem: ActionController::ParameterMissing exception is thrown. param not found: post

The reason being the Post params hash is never created, causing the above exception to be thrown. Empty radio buttons, unlike empty text fields for example, do not trigger the model's param hash to be created.

What if the Post model requires a user_id to be valid? Certainly one would want to render the view again with the reason why the Post can't be saved.

Question: What is an elegant way to handle this situation while sticking to Rails convention?

UPDATE:

Brainstorming about this further, I'm sure there are probably plenty of other situations which generate this problem; it does not necessarily correspond to radio buttons.

like image 284
Benjamin Avatar asked Jun 27 '13 22:06

Benjamin


2 Answers

I have a similar problem, and didn't like either of these answers much. In the rails documentation (http://guides.rubyonrails.org/action_controller_overview.html#more-examples) I see the following solution:

params.fetch(:blog, {}).permit(:title, :author)

Effectively you are supplying a default of {}, which seems to work well enough (at least for my situation).

Applying to your code, you'd have:

params.fetch(:post, {}).permit(:user_id)

I think this is reasonably clean, and seems to work in my code.

like image 184
PaulL Avatar answered Dec 16 '22 06:12

PaulL


This was my immediate solution... though it seems a bit silly because why are you having to check for the post params if you are clearly in the post controller and you require them anyways. Seems very counterintuitive. Is this really the best way?

  params.require(:post).permit(:user_id) if params[:post]
like image 24
Benjamin Avatar answered Dec 16 '22 04:12

Benjamin