首先让我先说这也可能是一个建模问题,我对模型建议持开放态度.
使用案例:
我有一个表单,我需要允许用户选择他们的帖子类别的复选框.如果没有适合其帖子检查的类别,则其他类别将显示用户添加自定义类别的文本字段.这应该用于创建和更新嵌套模块
数据库建模
class CreateCategories < ActiveRecord::Migration def change create_table :categories do |t| t.string :name,null: false t.timestamps null: false end reversible do |dir| dir.up { Category.create(name: 'Hats') Category.create(name: 'Shirts') Category.create(name: 'Pants') Category.create(name: 'Shoes') Category.create(name: 'Other') } end create_table :categorizations,id: false do |t| t.belongs_to :post,index: true,null: false t.belongs_to :category,null: false t.string :value end end end
应用模型
class Post < ActiveRecord::Base has_many :categorizations accepts_nested_attributes_for :categorizations,allow_destroy: true has_many :categories,through: :categorizations accepts_nested_attributes_for :categories end class Category < ActiveRecord::Base has_many :posts end
控制器:
def update if @post.update(post_params) flash.now[:success] = 'success' else flash.now[:alert] = @post.errors.full_messages.to_sentence end render :edit end private def set_post @post = Post.find(params[:id]) (Category.all - @post.categories).each do |category| @post.categorizations.build(category: category) end @post.categorizations.to_a.sort_by! {|x| x.category.id } end def post_params params.require(:post).permit(:name,:description,categorizations_attributes: [ :category_id,:value,:_destroy],) end
视图:
= f.fields_for :categorizations do |ff| = ff.check_Box :_destroy,{ checked: ff.object.persisted? },'0','1' = ff.label :_destroy,ff.object.category.name = ff.hidden_field :category_id = ff.text_field :value if ff.object.category.other?
解决方法
我更喜欢这样的东西:
楷模
post.rb
class Post < ActiveRecord::Base has_many :categorizations has_many :categories,through: :categorizations accepts_nested_attributes_for :categorizations,allow_destroy: true accepts_nested_attributes_for :categories end
category.rb
class Category < ActiveRecord::Base has_many :categorizations has_many :posts,through: :categorizations end
调节器
... def update if @post.update(post_params) flash.now[:success] = 'success' else flash.now[:alert] = @post.errors.full_messages.to_sentence end render :edit end private def set_post @post = Post.find(params[:id]) end def post_params params.require(:post).permit(:name,category_ids: []) end ...
查看
我总是喜欢普通的.erb所以,
在simple_form的帮助下.
<%= simple_form_for(@post) do |f| %> <%= f.error_notification %> <div class="form-inputs"> <%= f.input :content -%> ... </div> <div class="form-inputs"> <%= f.association :categories,as: :check_Boxes -%> </div> <div class="form-actions"> <%= f.button :submit %> </div> <% end %>
您可以通过这种方式检查/取消选中状态并轻松干净地销毁.
另外,你可以添加
<%= f.simple_fields_for :category do |category_fields| %> <%= category_fields.input :name -%> <% end %>
获取关联的嵌套字段,但不要忘记在执行此操作时将相关的参数添加到strong_params.
... def post_params params.require(:post).permit(:name,category_attributes: [:name]) end ....