我正在构建一个应该显示作品列表的应用程序。每件作品都由Work
模型表示,可以有多张图片,由WorkPicture
模型表示。
工作.rb
class Work < ActiveRecord::Base
belongs_to :category
has_many :pictures, class_name: "WorkPicture", dependent: :destroy
accepts_nested_attributes_for :pictures, allow_destroy: true
# Ensures that we have at least 1 picture
validates :pictures, length: { minimum: 1, message: "are not enough." }
validates :name, presence: true
validates :description, presence: true
validates :category_id, presence: true
end
我使用这条线validates :pictures, length: { minimum: 1, message: "are not enough." }
来确保这个模型的任何实例都至少附有一张图片。
这是图片的模型(它使用paperclip
宝石作为附件图片):
work_picture.rb
class WorkPicture < ActiveRecord::Base
belongs_to :work
CONVERT_OPTIONS = "-gravity north"
has_attached_file :picture, styles: { big: ["945x584#", :png], thumb: ["360x222#", :png] },
convert_options: { big: CONVERT_OPTIONS, thumb: CONVERT_OPTIONS }
validates_attachment :picture, presence: true,
content_type: { content_type: /image/ }
end
我无法测试这两个模型之间的关系。这是我尝试使用factory_girl
gem 设置它们的方法:
工厂.rb
include ActionDispatch::TestProcess
FactoryGirl.define do
factory :work do
sequence(:name) { |n| "Project #{n}" }
description "A description"
category
after :build do |work, evaluator|
create(:work_picture, work: work) # Creating a picture for this work
end
end
factory :category do
sequence(:name) { |n| "Category #{n}" }
end
factory :work_picture do
picture { fixture_file_upload Rails.root.join("spec/fixtures/files/work.png"), "image/png" }
work
after :create do |work_picture, evaluator|
evaluator.picture.close
end
end
end
在:work_picture
工厂里,我只是简单地给它添加了一个预定义的图片。
在:work
工厂中,我尝试在刚刚创建的作品中添加图片,但这无法完成,因为work_picture
需要有效的 id 才能将其与作品正确关联,而这是不可能的,因为我的作品m created 尚未保存,因此没有 id。
我需要一种在构建图片时(在保存之前)将图片与其关联的方法,因为当保存作品时,它会验证它拥有的图片数量,并且由于它尚未与任何图片相关联,所以验证不会通过,它仍然没有图片的 id。
仔细一想,结果有点悖论,因为图片需要一个有id的作品才能关联到它,但是一个作品需要一张图片才能被分配一个id,所以两者都不是条件要靠对方的存在才能成真。
这是我的模型规格Work
:
工作规范.rb
require 'spec_helper'
describe Work do
let!(:work) { build(:work) }
subject { work }
it { should respond_to :name }
it { should respond_to :description }
it { should respond_to :category }
it { should respond_to :category_id }
it { should respond_to :pictures }
it { should be_valid } # Fails, because we have no picture
# ... Unrelated tests omitted
# This test is here to check if the factory_girl setup is working
describe "picture count" do
it "should be 1" do
expect(work.pictures.count).to eq 1 # Fails, because we are unable to add the picture
end
end
end
我的问题
我该如何解决这个问题,以便模型上至少存在一张图片的要求保持不变,但同时我将能够在它与图片关联之前创建(并保存)它的一个实例?