ruby-on-rails – 如何正确编写具有N-N关系的嵌套表单
在处理Rails 3应用程序时,我遇到了嵌套表单的问题.
一个集合是一组预定义对象(使用db:seed创建). 一个例子比长描述更好,所以在这里. 假设您有2个模型:用户和组. 假设有几个组:成员,管理员,客人,…… 您希望您的用户拥有多个组,因此您需要一个中间表:成员资格. 模型代码很明显: class User < ActiveRecord::Base has_many :memberships has_many :groups,:through => :memberships accepts_nested_attributes_for :memberships,:allow_destroy => true end class Membership < ActiveRecord::Base belongs_to :user belongs_to :group end class Group < ActiveRecord::Base has_many :memberships has_many :users,:through => :memberships end 控制器不需要更改. 我想显示一个复选框列表,以选择一些预定义的组. 我在这里使用特殊的_destroy字段,具有反转值,在实际未选中时销毁(因此在检查时将用户添加到组中) %p = f.label :name %br = f.text_field :name %ul = f.fields_for :memberships,@groups do |g| %li - group = g.object = g.hidden_field :group_id,:value => group.id = g.check_box :_destroy,{:checked => @user.groups.include?(group)},1 = g.label :_destroy,group.name 但是,这不能按预期工作,因为表单g将始终在每个组之后创建一个具有任意id的输入(甚至通过在< / li>之后包含它来打破布局): <input id="user_memberships_attributes_0_id" name="user[memberships_attributes][0][id]" type="hidden" value="1" /> <input id="user_memberships_attributes_1_id" name="user[memberships_attributes][1][id]" type="hidden" value="2" /> # ... 了解嵌套属性的语法如下: {:group_id => group.id,:_destroy => 0} # Create {:group_id => group.id,:_destroy => 0,:id => membership.id} # Update {:group_id => group.id,:_destroy => 1,:id => membership.id} # Destroy {:group_id => group.id,:_destroy => 1} # Do nothing 每次id都不起作用时发送,因为它会尝试更新不存在的记录而不是创建它,并在记录不存在时尝试销毁. 我找到的当前解决方案是删除所有错误,无论如何都是错误的(它们应该是成员资格的ID,而不是简单的索引),并在用户已经拥有该组时添加真实ID. def clean_memberships_attributes if membership_params = params[:user][:memberships_attributes] memberships = Membership.find_all_by_user_id params[:id] membership_params.each_value { |membership_param| membership_param.delete :id if m = memberships.find { |m| m[:group_id].to_s == membership_param[:group_id] } membership_param[:id] = m.id end } end end 这似乎是错误的,它在控制器中添加了很多逻辑,只是为了控制视图fields_for帮助程序的不良行为. 另一个解决方案是自己创建所有表单html,试图模仿Rails约定,并避免id问题,但这在代码中真的很吵,我相信有更好的方法. >是否可以让fields_for更好地工作? 谢谢 解决方法
我希望我理解正确吗?
这些组是预定义的,您希望能够将用户添加到组中. 以下是我在公司和项目中的表现: Class Company has_many :datasets has_many :projects,:through => :datasets Class Project has_many :datasets has_many :companies,:through => :datasets <% for company in Company.all %> <tr> <td> <%= check_box_tag 'project[company_ids][]',company.id,@project.companies.include?(company) %> </td> </tr> <% end %> 我列出所有公司并检查我想要包含在项目中的公司. 请告诉我这是否对你有帮助?我相信你在你的例子中使用haml.我并不习惯那种符号. 如果要使用子集,可以使用范围: scope :recent,Company.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight) 然后你可以像.all方法一样使用这个范围: Company.recent 这有帮助吗? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |