ActiveRecord模拟相互依赖性和相关性

时间:2016-01-02 13:36:33

标签: ruby-on-rails ruby-on-rails-4 activerecord database-design model

我有一堆相互依赖的AR模型,我无法弄清楚如何让所有东西一起工作......

首先是Pet and a Dog模型:

class Pet < ActiveRecord::Base
  belongs_to :animal, polymorphic: true, dependent: :destroy
  belongs_to :facility
  has_many :pet_pictures, dependent: :destroy
  validates :name, :birth, :facility, :pet_pictures, presence: true
end

class Dog < ActiveRecord::Base
  has_one :pet, as: :animal
  has_many :mixtures, as: :blended, dependent: :destroy
  validates :mixtures, presence: true
end

然后是PetPictures和Mixtures:

class PetPicture < ActiveRecord::Base
  belongs_to :pet
  validates :photo_file, presence: true
end

class Mixture < ActiveRecord::Base
  belongs_to :blended, polymorphic: true
  validates :breed, presence: true
  validates :breed, uniqueness: { scope: [:blended_id, :blended_type] }
end

问题是这太复杂了,我在协调所有依赖关系时遇到了很大的问题,我也不得不删除一些验证(pic必须有一个与之相关的宠物,但是我最终删除它很困难它)。在我看来,没有正确的创作顺序,最终得到一个有效的对象。

例如,请遵循以下规范:

RSpec.describe PetPicture, type: :model do
  let(:dog) do
    FactoryGirl.build(:marley,
                       mixtures: [mixture_yorkshire, mixture_dachsund],
                       pet: FactoryGirl.build(
                         :dog,
                         pet_pictures: [FactoryGirl.build(:marleys_pic),
                                    FactoryGirl.build(:second_marleys_pic)],
                         facility: lida))
  end

  context 'when creating' do
    it 'should be valid' do
      # dog.save && dog.pet.save
      dog.pet.pictures.each do |picture|
        expect(picture).to be_valid
      end
    end
  end
end

此规范仅在手动保存后通过(如果我FactoryGirl.create由于与创建顺序相关的验证错误而未创建任何内容) BUT ,我认真地看不出这种行为的原因, picture.pet_id为NULL。

你可以帮我调试吗?关于如何改进/重构/清理这个烂摊子的任何建议或链接都​​是非常受欢迎的 - 请记住我采用这个是有原因的,所以宠物有很多照片,可以是狗,猫或其他什么,都有一组非常特定于其类的属性。此外,狗可以是50%dachsund和50%约克郡,以解释混合物的关系。

提前致谢。

1 个答案:

答案 0 :(得分:0)

我认为如果你要检查每个验证,你应该一次一个,不要尝试创建一堆。例如:

RSpec.describe PetPicture, type: :model do
  let(:pet) { FactoryGirl.create(:pet) }
  let(:picture) do
    FactoryGirl.build(:marleys_pic, pet: pet)
  end

  context 'when creating' do
    it 'should be valid' do
      expect(picture).to be_valid
    end
  end
end

如果你想要一些非常干净和清晰的东西,试试shoulda-matchers。每个关联和验证只能通过一行代码进行测试。