rails 3 has_many:通过记录保存错误

时间:2010-10-14 01:34:25

标签: ruby-on-rails ruby-on-rails-3 has-many-through

我不确定我的问题是什么,所以这个问题可能需要更多澄清,但这里似乎是最相关的:

我有一个has_many :through,并且连接模型有一些不是外键的字段。当我构建模型并尝试保存时,我从连接模型的非外键字段获得验证错误。

我的文件如下:

Person.rb

  has_many :wedding_assignments, :dependent => :destroy
  has_many :weddings, :through=>:wedding_assignments
  accepts_nested_attributes_for :weddings
  accepts_nested_attributes_for :wedding_assignments

Wedding.rb

  has_many :wedding_assignments, :dependent => :destroy
  has_many :people, :through=>:wedding_assignments
  accepts_nested_attributes_for :people
  accepts_nested_attributes_for :wedding_assignments

WeddingAssignment.rb

  belongs_to :person
  belongs_to :wedding
  validates_presence_of :role, :person, :wedding

(角色是一个字符串)

people_controller.rb

  def new
    @person = Person.new

    1.times do
      wedding = @person.weddings.build
      1.times do
        assignment = wedding.wedding_assignments.build
        assignment.person = @person
        assignment.wedding = wedding
      end
    end
  end

  def create
    @person = Person.new(params[:person])
    @person.weddings.each do |wedding|
      wedding.wedding_assignments.each do |assignment|
        assignment.person = @person  #i don't think I should need to set person and wedding manually, but I get a validation error if I don't
        assignment.wedding = wedding
      end
    end
 end
回来的参数如下:

{"first_name"=>"", "last_name"=>"", "weddings_attributes"=>{"0"=>{"wedding_assignments_attributes"=>{"0"=>{"role"=>"Bride's Maid", "budget"=>""}}, "date"=>"", "ceremony_notes"=>""}}}

确切的错误是:

ActiveRecord::RecordInvalid in PeopleController#create
Validation failed: Role can't be blank

这显然不正确,因为您可以在params[]

中看到它

我做错了什么?

这是rails 3.0.0

2 个答案:

答案 0 :(得分:1)

是的,这是一个猜测,如果我最终浪费你的时间在这里道歉......

在我看来,在您的创建方法中,您正在创建“婚礼”关系(这实际上只是一种“假装”关系,它正在使用:through =>:wedding_assignments),然后返回此关系。然后,您要求rails在您对Person.new的调用中重新创建这些对象。我的猜测是,通过尝试在has_many的远端创建一个对象来解决rails:通过没有中间对象存在。

我很想重新调整一下(未经测试的代码!):

def new
  @person = Person.new
  @wedding = Wedding.new
  @wedding_assignment = WeddingAssignment.new
end

def create
  @person = Person.new(params[:person])
  @wedding = Wedding.new(params[:person])
  @assignment = WeddingAssignment.new(params[:wedding_assignment].merge({:person => @person}))
end

我有一种感觉,直到最后一行才行。我怀疑要工作你可能需要使用交易:

def create
  @person = Person.new(params[:person])
  @wedding = Wedding.new(params[:person])
  ActiveRecord::Base.transaction do
    if @person.valid? && @wedding.valid?
      [@person,@wedding].each.save!
      @assignment = WeddingAssignment.new(params[:wedding_assignment].merge({:person => @person}))
      @assignment.save!
    end
  end
end

这应该确保所有内容都以正确的顺序创建,ID可以在合适的时间使用等等。不幸的是,它比你的例子更复杂,并且意味着你将难以支持多个婚礼。

希望这会有所帮助,并且不会成为一条死胡同。

答案 1 :(得分:0)

尝试将“Person.new”更改为“Person.create”,也许马上在db中创建记录将有助于协会。