通过连接模型中的复选框和额外字段,Rails has_many [英] Rails has_many through form with checkboxes and extra field in the join model
问题描述
有三种模式:
class产品< ActiveRecord :: Base
validates:name,presence:true
has_many:categorizations
has_many:categories,:through => :分类
accept_nested_attributes_for:分类
结束
分类分类< ActiveRecord :: Base
belongs_to:产品
belongs_to:类别
验证:description,presence:true#注意这里的额外字段
结束
class Category< ActiveRecord :: Base
validates:name,presence:true
end
我的产品新/编辑表单出现问题。
在创建产品时,我需要检查它所属的类别(通过复选框)。我知道这可以通过创建名称为'product [category_ids] []'的复选框来完成。但是我还需要输入一个关于将存储在连接模型(Categorization)中的每个检查关系的描述。
我在复杂表单上看到了美丽的Railscast,habtm复选框等我几乎一直在寻找StackOverflow。但我没有成功。
任何thougts赞赏。
我是Rails的新手(从CakePHP切换),请耐心等待,并尽可能详细地写。请以正确的方式指出我的意见!
谢谢。 :)
看起来像我明白了!以下是我得到的:
我的模特:
class产品< ; ActiveRecord :: Base
has_many:categorizations,dependent :: destroy
has_many:categories,through::categorizations
accept_nested_attributes_for:categorizations,allow_destroy:true
validates:name,presence:true
def initialized_categorizations#这是关键方法
[] .tap do | o |
Category.allEach do | category |
如果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分类< ActiveRecord :: Base
belongs_to:产品
belongs_to:类别
验证:描述,状态:true
attr_accessor:enable#nice little thingy here
end
表格:
<%= form_for(@product)do | f | %GT;
...
< div class =field>
<%= f.label:name%>< br />
<%= f.text_field:name%>
< / div>
<%= f.fields_for:categorizations,@ product.initialized_categorizations do | builder | %GT;
<%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如果cat_attr [:enable]!='1'
结束
结束
...
#其余的都是标准的脚手架代码
end
乍一看它工作得很好。我希望它不会打破..:)
谢谢大家。特别感谢Sandip Ransing参与讨论。我希望它对像我这样的人有用。
I'm trying to solve a pretty common (as I thought) task.
There're three models:
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
My problems begin when it comes to Product new/edit form.
When creating a product I need to check categories (via checkboxes) which it belongs to. I know it can be done by creating checkboxes with name like 'product[category_ids][]'. But I also need to enter a description for each of checked relations which will be stored in the join model (Categorization).
I saw those beautiful Railscasts on complex forms, habtm checkboxes, etc. I've been searching StackOverflow hardly. But I haven't succeeded.
I found one post which describes almost exactly the same problem as mine. And the last answer makes some sense to me (looks like it is the right way to go). But it's not actually working well (i.e. if validation fails). I want categories to be displayed always in the same order (in new/edit forms; before/after validation) and checkboxes to stay where they were if validation fails, etc.
Any thougts appreciated. I'm new to Rails (switching from CakePHP) so please be patient and write as detailed as possible. Please point me in the right way!
Thank you. : )
Looks like I figured it out! Here's what I got:
My models:
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
The form:
<%= 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 %>
And the controller:
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
From the first glance it works just fine. I hope it won't break somehow.. :)
Thanks all. Special thanks to Sandip Ransing for participating in the discussion. I hope it will be useful for somebody like me.
这篇关于通过连接模型中的复选框和额外字段,Rails has_many的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!