嵌套表单和has_many:通过
我有一个小样本应用程序,其中有3个模型:成员,组和订阅。 这个想法是会员可以订阅群组。
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。
所以,目前,有两种方法可以使它工作:
- 将member_id添加为视图中的隐藏字段。
- 更改所有内容,因此订阅模型具有
accepts_nested_attributes_for
。 这样,要创建的新对象是Subscription,Group将是嵌套模型。
第一个选项有一个重要的安全漏洞,所以我不推荐它。
第二种选择虽然不太合乎逻辑,但更清晰,更可取的是解决这个问题的“Rails方法”。
我刚遇到同样的问题,解决方案是从相关模型中删除状态validation(基于此问题 ),在您的情况下,删除:
validation:group_id,presence:true
一旦validation结束,一切都像发条一样运行