嵌套表单和has_many:通过

我有一个小样本应用程序,其中有3个模型:成员,组和订阅。 这个想法是会员可以订阅群组。

ERD

class Member < ActiveRecord::Base has_many :subscriptions, dependent: :delete_all has_many :groups, through: :subscriptions attr_accessible :email validates :email, presence: true end class Group < ActiveRecord::Base has_many :subscriptions, dependent: :delete_all has_many :members, through: :subscriptions accepts_nested_attributes_for :subscriptions attr_accessible :name, :subscriptions_attributes validates :name, presence: true, uniqueness: true end class Subscription < ActiveRecord::Base belongs_to :group belongs_to :member attr_accessible :group_id, :introduction validates :group_id, presence: true validates :introduction, presence: true end 

我正在尝试为新组创建表单,并将introduction属性嵌套在其中。

我的控制器方法:

 def new @group = Group.new @group.subscriptions.build end def create @member = Member.first @group = @member.groups.build(params[:group]) if @group.save flash[:success] = "Saved" redirect_to group_path(@group) else render :new end end 

但它不起作用。 它抛出错误group_id can't be blank 。 所以我不知道如何将新组分配给订阅。

此外,member_id被创建为nil。 但正如你所看到的,我是从@member变量创建组的,所以我认为它应该初始化,但事实并非如此。

有谁能告诉我光明?

您可以在此处查看示例应用程序: https : //github.com/idavemm/nested_form

确保您尝试分配的所有属性都是attr_accessible。 您可以禁用它并查看它是否有效,或者查看Rails服务器日志中的警告。

更新 :您应该将accepts_nested_attributes_for添加到Member模型,并使用带有fields_for的多模型表单。

我认为你是以错误的方式思考你的模型。 每个成员是否会对每个小组都有不同的介绍。 那么,例如,member1有一个介绍,member2有不同的介绍吗?

订阅模型应存储有关成员和组之间关系的信息。 在这种情况下,在群组模型中引入会更好。 您收到错误的原因是您尝试为尚未制作的组创建订阅(当您设置简介属性时)。

因此,移动对组模型的介绍,然后,如果您希望组的创建者自动订阅它(您应该),请在保存记录后添加代码以在创建操作中创建对控制器的订阅。 然后,在订阅模型上,您可以做一些很酷的事情,比如拥有一个状态机来跟踪成员的状态(主持人,新手,资深成员等)。

经过数小时的调查和挫折,我向Rails devs报告了这个问题,我终于有了一个解决方案:

Rails 3无法按照问题中定义的方式自动初始化group_id和member_id。

所以,目前,有两种方法可以使它工作:

  1. 将member_id添加为视图中的隐藏字段。
  2. 更改所有内容,因此订阅模型具有accepts_nested_attributes_for 。 这样,要创建的新对象是Subscription,Group将是嵌套模型。

第一个选项有一个重要的安全漏洞,所以我不推荐它。

第二种选择虽然不太合乎逻辑,但更清晰,更可取的是解决这个问题的“Rails方法”。

我刚遇到同样的问题,解决方案是从相关模型中删除状态validation(基于此问题 ),在您的情况下,删除:

validation:group_id,presence:true

一旦validation结束,一切都像发条一样运行