Rails HABTM checkboxes don't save to database
I am beginning Rails programming and all I want to accomplish is to have a list of check boxes from which I can choose the corresponding categories for a product. I have followed the railscast on this matter, but it doesn't seem to work for me.
I work with Rails 3.0.9 and Ruby 1.8.7.
I have the models properly set up and the migration for the join table as well. When I try to edit a product, the category_ids get POSTed, but they are never saved to the database.
Log :
Started POST "/products/1" for 127.0.0.1 at Mon Sep 19 01:39:33 +0300 2011
Processing by ProductsController#update as HTML
Parameters: {"commit"=>"Update Product", "authenticity_token"=>"x2Z5GGiNh9yLz6xjuQaMqdGW3Gw7dYe8dSghyrFpiYk=", "utf8"=>"���", "id"=>"1", "product"=>{"name"=>"Magicianulx2", "price"=>"121", "category_ids"=>["1"]}}
Product Load (0.1ms) SELECT "products".* FROM "products" WHERE "products"."id" = 1 LIMIT 1
WARNING: Can't mass-assign protected attributes: category_ids
Redirected to http://localhost:3000/products/1
Completed 302 Found in 10ms
Started GET "/products/1" for 127.0.0.1 at Mon Sep 19 01:39:33 +0300 2011
Processing by ProductsController#show as HTML
Parameters: {"id"=>"1"}
Product Load (0.1ms) SELECT "products".* FROM "products" WHERE "products"."id" = 1 LIMIT 1
Rendered products/show.html.erb within layouts/application (4.2ms)
Completed 200 OK in 11ms (Views: 6.1ms | ActiveRecord: 0.2ms)
Models :
class Product < ActiveRecord::Base
attr_accessible :name, :price
has_and_belongs_to_many :categories
end
class Category < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :products
end
Migration :
class AddCategoriesProducts < ActiveRecord::Migration
def self.up
create_table :categories_products, :id => false do |t|
t.integer :category_id
t.integer :product_id
end
end
def self.down
drop_table :categories_products
end
end
Controller (update method in product controller)
def update
@product = Product.find(params[:id])
if @product.update_attributes(params[:product])
redirect_to @product, :notice => "Successfully updated product."
else
render :action => 'edit'
end
end
My _form.html.erb in views/products
<%= form_for @product do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :price %><br />
<%= f.text_field :price %>
</p>
<% for category in Category.find(:all) %>
<div>
<%= check_box_tag "product[category_ids][]", category.i开发者_运维技巧d, @product.categories.include?(category) %>
<%= category.name %>
</div>
<% end %>
<p><%= f.submit %></p>
<% end %>
The controllers and the views were all generated using nifty scaffolding. Everything else seems to work just fine, but the values from the check boxes don't get saved to the database. Adding them by hand via the rails console works just fine. Any ideas on what I am doing wrong?
Your Product model has attr_accessible :name, :price
and that's why the log shows WARNING: Can't mass-assign protected attributes: category_ids
when you try to do @product.update_attributes(params[:product])
in your controller.
Try adding category_ids
to attr_accessible
.
When I did more or less the same thing, my check_box_tag
looked different:
<%= check_box_tag :category_ids,
cat.id,
@product.categories.include?(cat),
:name => 'product[category_ids][]' %>
I ended up not needing the attr_accessible
, although as I mention in my blog post describing the exact same thing, I'm still not sure why not. I also used has_many:through
.
精彩评论