![Params[] call coming back nil in controller](https://www.xszz.org/skin/wt/rpic/t10.jpg)
Question:
I have a scaffolded view <em>comments/new</em> that lets the user input :body and :lunch_id. When the form opens the URL string is:
<a href="http://localhost:3000/comments/new?lunch_id=1" rel="nofollow">http://localhost:3000/comments/new?lunch_id=1</a>
I am trying to update_attribute lunch_id by reading the url string with the comments_controller create method below:
def create
lunch_id = params[:lunch_id]
@commenttest = Comment.new(comment_params)
@commenttest.update_attribute(:lunch_id, lunch_id)
@commenttest.save
end
The problem is the params[:lunch_id] always returns a nill. Why won't it read into the URL string?
I've been at it for hours, so any ideas will help
Edit:
Below is the rake routes from a recreated environment in a hello world app. This only has a few pages but the params[:lunch_id] is still nil:
Prefix Verb URI Pattern Controller#Act
> comments GET /comments(.:format) comments#index
> POST /comments(.:format) comments#creat
> new_comment GET /comments/new(.:format) comments#new
> edit_comment GET /comments/:id/edit(.:format) comments#edit
> comment GET /comments/:id(.:format) comments#show
> PATCH /comments/:id(.:format) comments#updat
> PUT /comments/:id(.:format) comments#updat
> DELETE /comments/:id(.:format) comments#destr
> say_hello GET /say/hello(.:format) say#hello
> say_goodbye GET /say/goodbye(.:format) say#goodbye
Answer1:I'm guessing you have a form in new.html.erb
and, when you click submit, it posts the info and calls your create
action, and that's when your params[:lunch_id]
is nil
.
The reason this is happening is because the params
hash does not have permanency when you move through actions. Web servers execute one single action basically from scratch every time you make a request from your browser. When you visit /comments/new?lunch_id=1
, you are making a GET
request, which is mapped to your CommentsController
's new
action. However, when you submit the form, you are making a POST
request to the /comments
path, therefore calling CommentsController
's create
action. But <strong>this is a new request</strong>, with a whole new params
hash, generated from the new request's path <strong>and the data submitted by the form</strong>.
So, the simple way to fix your problem is to add a new field to keep track of your param:
<%= form_for(@comment) do |f| %>
<%= hidden_field_tag :lunch_id, params[:lunch_id] %>
. . . .
<% end %>
<strong>However</strong>, it seems like you are trying to create comments for lunches, and the right way to do it is to use nested attributes:
#/config/routes.rb
resources :lunches do
resources :comments
end
This way, you can get the form for a new comment in GET /lunches/1/comments/new
and point it to POST /lunches/1/comments
, and rails will automatically set the params[:lunch_id]
value without you having to juggle it around anymore.
As pointed out by AbM the params[:lunch_id] create method cannot see the <a href="http://localhost:3000/comments/new?lunch_id=1" rel="nofollow">http://localhost:3000/comments/new?lunch_id=1</a> URL string. The new method, however, can see the URL string.
So, an instance variable should be set in the new method:
def new
@comment = Comment.new
@lunch_id = params[:lunch_id]
end
Then, the form itself, should have a hidden field that points to this variable:
<div class="field">
<%= f.label :lunch_id %><br>
<%= f.hidden_field :lunch_id, :value => @lunch_id %>
</div>
When the form is submitted with the create method, the hidden field already has the proper lunch_id from the URL string.