Nested form and has_many :through

丶灬走出姿态 提交于 2020-01-17 05:50:11

问题


I have a little sample app where there are 3 models: Members, Groups and Subscriptions. The idea is that member can subscribe to groups.

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

I'm trying to create a form for new groups, and nest the introduction attribute inside.

My controller methods:

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

But it does not work. It throws the error group_id can't be blank. So I don't know how to assign the new group to the subscription.

Also, the member_id is being created as nil. But as you can see, I'm creating the group from the @member variable, so I think it should be initialized, but it does not.

Anyone can show me the light?

You can see the sample app here: https://github.com/idavemm/nested_form


回答1:


Make sure all the attributes you're trying to assign are attr_accessible. You may just disable it and see if it works, or see at the warnings in the Rails server log.

Update: you should add accepts_nested_attributes_for to the Member model and use a multimodel form with fields_for.




回答2:


I think you're thinking about your models in the wrong way. Will each member have a different introduction for each group. So, for example, will member1 have one introduction and member2 have a different introduction?

The Subscriptions model should store information about the relationship between and member and group. In that case, introduction would be better to have in the group model. The reason you are getting an error is because you are trying to create a subscription(when you set the introduction attribute) for a group that hasn't been made yet.

So, move introduction to the group model and then, if you want the creator of a group to be automatically subscribed to it (which you should), add the code to create a subscription to the controller in the create action after the record is saved. Then, on the subscription model, you can do cool things like having a state machine that tracks a member's status with the group (moderator, newbie, veteran member, etc).




回答3:


After many hours of investigation and frustration, I reported it to Rails devs and I finally have a solution:

Rails 3 is unable to initialize group_id and member_id automatically in the way it is defined in the question.

So, for now, there are two ways to make it work:

  1. Add the member_id as a hidden field in the view.
  2. Change everything so is the Subscription model who has accepts_nested_attributes_for. That way, the new object to be created is the Subscription, and Group will be the nested model.

The first option has an important security hole, so I don't recommend it.

The second option, although not much logical, is the cleaner and supposedly the "Rails way" to fix this problem.




回答4:


I just ran into the same issue, the solution was to remove the presence validation from the related model (based on this question), in your case, remove:

validates :group_id, presence: true

Once that validation it's gone, everything runs like clockwork



来源:https://stackoverflow.com/questions/11087201/nested-form-and-has-many-through

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!