问题
I'm having problems implementing a kind of comments form, where comments (called "microposts") belong_to both users and posts, users have_many comments, and posts (called "propositions") have_many comments.
My code for the comments form is:
<%= form_for @micropost do |f| %>
<div class="field">
<%= f.text_area :content %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
The MicropostsController has this in the create action:
def create
@proposition = Proposition.find(params[:proposition_id])
@micropost = current_user.microposts.build(params[:micropost])
@micropost.proposition = @proposition
if @micropost.save
flash[:success] = "Contribution submitted"
redirect_to root_path
else
@feed_items = []
render 'pages/home'
end
end
The form for creating a new micropost is on the same page as a proposition, yet the proposition id doesn't seem to get passed at any point.
This is the error I get on submitting the micropost form:
ActiveRecord::RecordNotFound in MicropostsController#create
Couldn't find Proposition without an ID
Parameters are:
{"commit"=>"Submit", "micropost"=>{"proposition_id"=>"", "content"=>"First comment"}, "authenticity_token"=>"TD6kZaHv3CPWM7xLzibEbaLJHI0Uw43H+pq88HLZFjc=", "utf8"=>"✓"}
I'm completely new to rails and very new to coding anything at all, so I'd be grateful for any help you can give me!
Thanks in advance.
回答1:
Your params are:
"micropost"=>{"proposition_id"=>"", "content"=>"First comment"}
So to get proposition_id
, you have to do :
params[:micropost][:proposition_id]
But this is empty. And there is nowhere else to get this id
, that's why this line retrieves nil
:
@proposition = Proposition.find(params[:proposition_id])
Making this fail:
@micropost.proposition = @proposition
You must either:
add the
proposition_id
as anhidden_field
store it in session
But I don't know your context enough to give you the proper solution here.
EDIT:
In your link, replace:
<%= f.hidden_field :proposition_id %>
with:
<%= f.hidden_field :proposition_id, :value => @proposition.id %>
If it doesn't work, show your params.
Note: it's bad practice to rely on instance variables, you should send local variable to each partial
回答2:
As you can see, the proposition_id
parameter is empty, so your controller can't find the proposition unless you give it a valid id.
You need to make sure your new
form sends the proposition_id
attribute. One way to do this is:
Set the proposition in the
new
action in the controller:@micropost.proposition = ...
In the form, add a hidden field for the id:
f.hidden_field :proposition_id
In the
create
action, find the appropriate Proposition withparams[:micropost][:proposition_id]
(You'll also want to make sure to use attr_accessible
in your Micropost model, and make sure proposition_id
is NOT in that list. Otherwise, you'll be open to nasty security holes. See http://www.kalzumeus.com/2010/09/22/security-lessons-learned-from-the-diaspora-launch/ and Which fields should be protected from mass assignment?)
EDIT (due to comment):
Your new action should be like this:
def new
@micropost = Micropost.new
@micropost.proposition_id = params[:proposition_id]
This is slightly different from what is said above, and is due to the fact you're sending the proposition id in the request to new
. There's no need to look up the actual proposition record, since we're only interested in the id
field (which we already have).
来源:https://stackoverflow.com/questions/6215533/couldnt-find-object-without-an-id