我正在努力解决一个很常见的问题(正如我所想)的任务.
有三种型号:
class Product < ActiveRecord::Base validates :name,presence: true has_many :categorizations has_many :categories,:through => :categorizations accepts_nested_attributes_for :categorizations end class Categorization < ActiveRecord::Base belongs_to :product belongs_to :category validates :description,presence: true # note the additional field here end class Category < ActiveRecord::Base validates :name,presence: true end
我的问题开始于产品新/编辑表单.
创建产品时,我需要检查它所属的类别(通过复选框).我知道可以通过创建名称为“product [category_ids] []”的复选框来完成.但是,我还需要为每个被关联的关联输入一个描述,这些关系将存储在连接模型(Categorization)中.
我看到那些美丽的Railscasts在复杂的形式,habtm复选框等.我一直在搜索StackOverflow几乎没有.但我没有成功.
我发现一个post描述了与我的几乎完全相同的问题.最后一个答案对我来说很有意义(看起来是正确的方式).但是实际上并不能很好地工作(即如果验证失败).我希望类别总是以相同的顺序显示(在新的/编辑表单中,验证之前/之后)和复选框,以保持在验证失败的地方等等.
任何人都赞赏
我是Rails的新手(从CakePHP切换),所以请耐心等待,尽可能详细地写下.请指点正确的方法!
谢谢. :)
解决方法
看起来我想出来了!这是我得到的:
我的型号:
class Product < ActiveRecord::Base has_many :categorizations,dependent: :destroy has_many :categories,through: :categorizations accepts_nested_attributes_for :categorizations,allow_destroy: true validates :name,presence: true def initialized_categorizations # this is the key method [].tap do |o| Category.all.each do |category| if c = categorizations.find { |c| c.category_id == category.id } o << c.tap { |c| c.enable ||= true } else o << Categorization.new(category: category) end end end end end class Category < ActiveRecord::Base has_many :categorizations,dependent: :destroy has_many :products,through: :categorizations validates :name,presence: true end class Categorization < ActiveRecord::Base belongs_to :product belongs_to :category validates :description,presence: true attr_accessor :enable # nice little thingy here end
表格:
<%= form_for(@product) do |f| %> ... <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name %> </div> <%= f.fields_for :categorizations,@product.initialized_categorizations do |builder| %> <% category = builder.object.category %> <%= builder.hidden_field :category_id %> <div class="field"> <%= builder.label :enable,category.name %> <%= builder.check_Box :enable %> </div> <div class="field"> <%= builder.label :description %><br /> <%= builder.text_field :description %> </div> <% end %> <div class="actions"> <%= f.submit %> </div> <% end %>
控制器:
class ProductsController < ApplicationController before_filter :process_categorizations_attrs,only: [:create,:update] def process_categorizations_attrs params[:product][:categorizations_attributes].values.each do |cat_attr| cat_attr[:_destroy] = true if cat_attr[:enable] != '1' end end ... # all the rest is a standard scaffolded code end
从第一眼看,它的工作很好.我希望它不会打破某种方式..