获取工厂内的两个关联以共享另一个关联
我有这五个模型:卫报,学生,关系,关系类型和学校。 在他们之间,我有这些联想
class Guardian :destroy has_many :students, :through => :relationships end class Student :destroy has_many :guardians, :through => :relationships end class Relationship < ActiveRecord::Base belongs_to :student belongs_to :guardian belongs_to :relationship_type end class School :destroy has_many :students, :dependent => :destroy end class RelationshipType < ActiveRecord::Base has_many :relationships end
我想写一个定义关系的FactoryGirl。 每个关系都必须有一个监护人和一个学生。 这两个必须属于同一所学校。 监护人工厂与学校有联系,学生工厂也是如此。 我一直无法让他们在同一所学校建造。 我有以下代码:
FactoryGirl.define do factory :relationship do association :guardian association :student, :school => self.guardian.school relationship_type RelationshipType.first end end
当我尝试使用此工厂构建关系时,这会导致以下错误:
undefined method `school' for # (NoMethodError)
有没有办法做我想做的事,让监护人和学生属于同一所学校,而不必诉诸已经创建的监护人和学生到工厂(这不是它的目的)?
我认为这应该有效:
FactoryGirl.define do factory :relationship do association :guardian relationship_type RelationshipType.first after_build do |relationship| relationship.student = Factory(:student, :school => relationship.guardian.school) end end end
这个答案是谷歌“工厂女孩共享协会”的第一个结果,santuxus的回答真的帮助了我:)
以下是有关其他人偶然发现的最新版工厂女孩的语法更新:
FactoryGirl.define do factory :relationship do guardian relationship_type RelationshipType.first after(:build) do |relationship| relationship.student = FactoryGirl.create(:student, school: relationship.guardian.school) unless relationship.student.present? end end end
unless
student
已经通过FactoryGirl.create(:relationship, student: foo)
传递到工厂,则unless
子句会阻止student
被替换。
有更清晰的方式来编写这种关联。 答案来自这个github问题 。
FactoryGirl.define do factory :relationship do association :guardian student { build(:student, school: relationship.guardian.school) } relationship_type RelationshipType.first end end
这不是您正在寻求的答案,但似乎创建此关联的困难表明可能需要调整表格设计。
提出问题What if the user changes school?
, Student
和Guardian
的学校需要更新,否则,模型会不同步。
我提出一个学生,一个监护人和一个学校,都有一个关系。 如果学生改变学校,则为新学校创建新的Relationship
。 作为一个很好的副作用,这使得学生在学习的地方存在历史。
belongs_to
关联将从Student
和Guardian
删除,并转移到Relationship
。
然后可以将工厂更改为如下所示:
factory :relationship do school student guardian relationship_type end
然后可以通过以下方式使用它:
# use the default relationship which creates the default associations relationship = Factory.create :relationship school = relationship.school student = relationship.student guardian = relationship.guardian # create a relationship with a guardian that has two charges at the same school school = Factory.create :school, name: 'Custom school' guardian = Factory.create :guardian relation1 = Factory.create :relationship, school: school, guardian: guardian relation2 = Factory.create :relationship, school: school, guardian: guardian student1 = relation1.student student2 = relation2.student
在这种情况下,我会使用瞬态和依赖属性:
FactoryGirl.define do factory :relationship do transient do school { create(:school) } # now you can even override the school if you want! end guardian { create(:guardian, school: school) } student { create(:student, school: school) } relationship_type RelationshipType.first end end
用法:
relationship = FactoryGirl.create(:relationship) relationship.guardian.school == relationship.student.school # => true
如果你愿意,你甚至可以覆盖学校:
awesome_school = FactoryGirl.create(:school) awesome_relationship = FactoryGirl.create(:relationship, school: awesome_school) awesome_relationship.guardian.school == awesome_school # => true awesome_relationship.student.school == awesome_school # => true
根据nitsas的解决方案,您可以滥用@overrides
来检查监护人或学生协会是否已被覆盖,并使用监护人/学生的学校协会。 这使您不仅可以覆盖学校,还可以覆盖监护人或学生。
不幸的是,这依赖于实例变量,而不是公共API。 未来的更新很可能打破你的工厂。
factory :relationship do guardian { create(:guardian, school: school) } student { create(:student, school: school) } transient do school do if @overrides.key?(:guardian) guardian.school elsif @overrides.key?(:student) student.school else create(:school) end end end end
- 从User.rb模型访问ApplicationHelper
- 如何在Rails 5.0.0上修复bundle install“nio4r error”
- 如何以轨道forms处理多个模型
- Ruby on Rails 4:使用rspec测试嵌套资源不起作用
- 如何保护Rails应用程序免受Firesheep的攻击?
- wkhtmltopdf RuntimeError(wkhtmltopdf的位置未知)
- Ruby on Rails 3:Devise :: LdapAdapter.get_ldap_param undefined方法错误
- 查询以检查rails上的ruby中的整数值
- flag_shih_tzu可以处理的最大标志数量是多少?