Reputation: 123
I'm trying to build a simple product backlog application to teach myself Rails. For each product, there can be multiple product backlog entries, so I want to create a product view that shows the product information, all the backlog entries for the product, and includes a nested form for adding more backlog entries.
Everything works until I try to add the form to the view, which then results in the following error:
NoMethodError in Products#show
Showing app/views/products/show.html.erb where line #29 raised:
undefined method `pblog_ref' for #<Product:0x10423ba68>
Extracted source (around line #29):
26: <%= f.error_messages %>
27: <p>
28: <%= f.label :pblog_ref %><br />
29: <%= f.text_field :pblog_ref %>
30: </p>
31: <p>
32: <%= f.label :product %><br />
The product view where the problem is reported is as follows (the partial works fine, so I won't include that code):
<h1>Showing product</h1>
<p>
<b>Product ref:</b>
<%=h @product.product_ref %>
</p>
<p>
<b>Description:</b>
<%=h @product.description %>
</p>
<p>
<b>Owner:</b>
<%=h @product.owner %>
</p>
<p>
<b>Status:</b>
<%=h @product.status %>
</p>
<h2>Product backlog</h2>
<div id="product-backlog">
<%= render :partial => @product.product_backlogs %>
</div>
<% form_for(@product, ProductBacklog.new) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :pblog_ref %><br />
<%= f.text_field :pblog_ref %>
</p>
<p>
<%= f.label :product %><br />
<%= f.text_field :product %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_field :description %>
</p>
<p>
<%= f.label :owner %><br />
<%= f.text_field :owner %>
</p>
<p>
<%= f.label :status %><br />
<%= f.text_field :status %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Edit', edit_product_path(@product) %> |
<%= link_to 'Back', products_path %>
This is the Product model:
class Product < ActiveRecord::Base
validates_presence_of :product_ref, :description, :owner
has_many :product_backlogs
end
This is the ProductBacklog model:
class ProductBacklog < ActiveRecord::Base
belongs_to :product
end
These are the routes:
map.resources :product_backlogs
map.resources :products, :has_many => :product_backlogs
All the columns exist in the schema for this model:
create_table "product_backlogs", :force => true do |t|
t.string "pblog_ref"
t.integer "product_id"
t.string "description"
t.string "owner"
t.string "status"
t.datetime "created_at"
t.datetime "updated_at"
end
I've checked what I'm doing against the Creating a weblog in 15 minutes with Rails 2 screencast, and in principle I seem to be doing the same thing as him - only his nested comments form works, and mine doesn't!
I hope someone can help with this, before I turn mad! I'm sure it's something trivial.
Upvotes: 0
Views: 1099
Reputation: 123
The solution was to replace the line:
<% form_for(@product, ProductBacklog.new) do |f| %>
with:
<% form_for [@product, ProductBacklog.new] do |f| %>
Note the space after form_for, and the square brackets.
Upvotes: 0
Reputation: 14967
It seems that you don't have pblog_ref
field in your model. Take a look into migration that created products table, is there pblog_ref
field?
EDIT: Ok, it seems that this line is wrong:
<% form_for(@product, ProductBacklog.new) do |f| %>
It creates form for your @product
not for ProductBacklog.new
. Try:
<% form_for(ProductBacklog.new) do |f| %>
I always have problems with form_for
arguments with some nested models, so I prefer using accepts_nested_attributes_for
and then creating subobjects with fields_for
.
In your case form_for
should look like this:
<% form_for ProductBacklog.new, :url => new_product_product_backlog_path(@product) do |f| %>
However I didn't check it and it probably is wrong (as I said I always have problems with those paths).
Upvotes: 1
Reputation: 33217
check your database, maybe some migration failed and you have only part of fields there
you can also check with running script/console first, and then issuing "p Product.new". It will show you an empty Product object with all known fields, like:
#./script/console
Loading development environment (Rails 2.3.5)
>> p User.new
#<User id: nil, type: nil, login: nil, name: "", email: nil, crypted_password: nil, salt: nil, created_by_id: nil, created_at: nil, updated_at: nil, remember_token: nil, remember_token_expires_at: nil, male: true, dept_id: nil, deleted: nil>
=> nil
Upvotes: 1