问题
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:
- Add the member_id as a hidden field in the view.
- 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