【问题标题】:rails 3 has_many :through record save errorrails 3 has_many:通过记录保存错误
【发布时间】:2011-04-25 04:08:31
【问题描述】:

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

我有一个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

【问题讨论】:

  • 我很好奇那些1.times有什么用?
  • 我这样做是为了方便以后将其更改为 2.times 或更多。
  • 你是对的,这样做甚至可以让用户选择一次性添加10个婚礼。 :D
  • 您的错误说在 create_with_appointment 方法上有错误,但它在您的控制器输出中不存在。这是什么方法?
  • 您是否尝试过在您的create 方法中显式设置role 属性的值?您甚至可以通过暂时删除 role 属性上的验证条件来检查这是否有效。

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


【解决方案1】:

好吧,这有点猜想,如果我在这里浪费了你的时间,请见谅......

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

我很想稍微重构一下(未经测试的代码!):

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 等。不幸的是,它比您的示例要复杂一些,并且确实意味着您将难以支持多个婚礼。

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

【讨论】:

  • 迄今为止最好的答案。这样做意味着我将无法干净地生成表单字段(即:railscasts.com/episodes/196-nested-model-form-part-1)。 Rails 应该能够管理这些关联。在周末,我重新编写了代码以从连接模型WeddingAssignment 开始构建和运行,而不是Person,它运行良好。所以我认为你在关于 Rails '变得困惑'的正确轨道上
  • 我有一个类似的问题,我试图通过这个问题来解决,但我遇到了一个大规模分配安全错误。有什么想法吗?
【解决方案2】:

尝试将“Person.new”更改为“Person.create”,也许立即在数据库中创建记录将有助于关联。

【讨论】:

  • 我绝对不希望它们立即在数据库中。如果用户改变主意并离开页面会发生什么?如果我使用'create',我不会有一个空记录吗?
猜你喜欢
  • 1970-01-01
  • 2015-05-06
  • 2020-11-20
  • 2016-04-22
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
相关资源
最近更新 更多