Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 循环一对一模型保存调用,两边都有状态验证_Ruby On Rails_Validation_Factory Bot - Fatal编程技术网

Ruby on rails 循环一对一模型保存调用,两边都有状态验证

Ruby on rails 循环一对一模型保存调用,两边都有状态验证,ruby-on-rails,validation,factory-bot,Ruby On Rails,Validation,Factory Bot,假设存在一个Foo和Bar模型,具有一对一关系和相互存在验证: class Foo < ActiveRecord::Base has_one :foo_bar has_one :bar, through: :foo_bar, inverse_of: :foo validates :bar, presence: true end class FooBar < ActiveRecord::Base belongs_to :foo belongs_to :bar e

假设存在一个
Foo
Bar
模型,具有
一对一
关系和相互存在验证:

class Foo < ActiveRecord::Base
  has_one :foo_bar
  has_one :bar, through: :foo_bar, inverse_of: :foo

  validates :bar, presence: true
end

class FooBar < ActiveRecord::Base
  belongs_to :foo
  belongs_to :bar
end

class Bar < ActiveRecord::Base
  has_one :foo_bar
  has_one :foo, through: :foo_bar, inverse_of: :bar

  validates :foo, presence: true
end
当我试图用
FactoryGirl.create(:Foo)
创建
Foo
Bar
的实例时,我得到了
SystemStackError:堆栈级别太深

原因是:

  • 当保存
    foo
    对象时,它会查看相关的
  • 哈哈<代码>栏未保存,我们需要先保存它
  • 保存
    bar
    时,它会查看
    foo
    (尚未保存)和 决定拯救它
  • 以此类推,它试图互相拯救,从而导致无限循环
  • 一种解决方案是在关联的一端添加
    autosave:false
    ,如:

    class Bar 
      has_one :foo, through: :foo_bar, inverse_of: :bar, autosave: false
    end
    
    这允许创建
    Foo
    ,但阻止
    create(:bar)
    ,因为
    Foo
    关联将不会被保存,从而导致无效的
    bar
    记录(由于验证)


    如何修复它,使
    foo
    bar
    工厂都有效?

    我认为
    验证:foo,presence:true
    最终使用
    验证相关的

    文档状态:不要在关联的两端使用关联的validates\u。他们会在无限循环中互相呼叫。


    基本上,一个人必须是一个追随者。。。也许您可以解释一下您的用例,并获得一些数据模型反馈?

    我同意模型结构似乎有问题。最好的解决方案可能是通过不同的关联实现您想要的。然而,如果这不是一个选择,我会抛出一个想法,可能会让你的地方

    您可以覆盖autosave并自己检查是否存在。您仍然需要一个依赖于另一个,但您可以在您的Foo模型中执行以下操作:

    def autosave_associated_records_for_bar
      #validate data
      #save bar
      #probably need to save ids on foobar
    end
    
    注意:执行此操作时应小心,并真正确保了解效果(验证程序可能无法运行等)

    您可以在以下源代码中查看有关AutosaveAssociation的更多信息:


    也许里面有些东西会有帮助。

    这是一个概念问题。想想看,你在国外,你的文件丢了。你去你的大使馆,他们想看你的机票来签发新护照。你去航空公司,他们要你的护照签发一份机票复印件。这是一个僵局,一个鸡和蛋的问题

    解决这个问题的唯一办法是重新定义它。您可以决定是否要验证关系,但对于至少一个方向,您将仅在创建关系后进行验证

    class Foo < ActiveRecord::Base
      has_one :foo_bar
      has_one :bar, through: :foo_bar, inverse_of: :foo
    
      validates :bar, presence: true, on: :update
    end
    
    class Foo

    因此,在我们的例子中,航空公司仍然不会给你没有护照的机票,但是大使馆会给你没有机票的护照。此外,如果您已经持有护照并且出于任何原因前往大使馆,他们会要求查看机票以进行确认。

    您能解释一下为什么您会使用这种关系而不是
    是否有一个
    &
    属于
    ?使用一个额外的模型而不是一个额外的字段似乎很复杂。@TheChamp这听起来很合理,但我仍然对解决原始问题感兴趣。
    
    class Foo < ActiveRecord::Base
      has_one :foo_bar
      has_one :bar, through: :foo_bar, inverse_of: :foo
    
      validates :bar, presence: true, on: :update
    end