工厂女孩与belongs_to:class_name

时间:2015-10-17 18:31:12

标签: ruby-on-rails rspec factory-bot

我有一个带有role_definitions表的架构:

  create_table "role_definitions", :force => true do |t|
    t.integer  "role_id"
    t.integer  "profile_id"
    t.datetime "created_at",                         :null => false
    t.datetime "updated_at",                         :null => false
    t.integer  "patient_resource_id", :default => 1, :null => false
  end

  add_index "role_definitions", ["patient_resource_id"], :name => "index_role_definitions_on_patient_profile_id"
  add_index "role_definitions", ["profile_id"], :name => "index_role_definitions_on_profile_id"
  add_index "role_definitions", ["role_id"], :name => "index_role_definitions_on_role_id"

和模型RoleDefinition:

class RoleDefinition < ActiveRecord::Base
  attr_accessible :patient_profile_id, :role_id, :profile_id

  belongs_to :role
  belongs_to :profile
  belongs_to :patient_resource, :class_name => :resource

  has_many :resource_authorizations
  has_many :resources, :through => :resource_authorizations

  validates :profile, :role, :patient_resource, :presence => true

  def role_information
    "Profile: " + self.profile.full_name + ", Role: " + self.role.role + "Patient: " + self.patient_resource.resource_label
  end
end

和FactoryGirl工厂:

require 'faker'

FactoryGirl.define do
  factory :role_definition do |f|
    rt = ResourceType.where(:resource_type => "Patient").first_or_create()
    p = Resource.where(:fhir_base_url_id => 1, :fhir_resource_id => 1, :resource_type_id => rt.id).first_or_create()
    f.patient_resource_id { p.id }
    association :role
    association :profile
  end
end

我也尝试过:

require 'faker'

FactoryGirl.define do
  factory :role_definition do |f|
    association :role
    association :profile
    association :patient_resource, :factory => :resource
  end
end

以及许多其他尝试。

有一个RSpec测试,role_definition_spec.rb:

require 'rails_helper'

RSpec.describe RoleDefinition, :type => :model do
  it "has a valid factory" do
    expect(FactoryGirl.build(:role_definition)).to be_valid
  end
#  
#  it "must have an role_definition" do
#    expect(FactoryGirl.build(:role_definition, :role => nil)).to be_invalid
#  end
#  
#  it "must have a resource" do
#    expect(FactoryGirl.build(:role_definition, :profile => nil)).to be_invalid
#  end
#
#  it "must have a patient resource" do
#    expect(FactoryGirl.build(:role_definition, :patient_resource => nil)).to be_invalid
#  end
end

使用第二个工厂示例(与我在网上找到的示例相匹配,此时我不在乎,我只是希望它构建任何旧资源并附加它),RSpec失败并出现错误:

Failures:

  1) RoleDefinition has a valid factory
     Failure/Error: expect(FactoryGirl.build(:role_definition)).to be_valid
     NameError:
       uninitialized constant RoleDefinition::resource
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.13/lib/active_record/inheritance.rb:111:in `compute_type'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.13/lib/active_record/reflection.rb:172:in `klass'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.13/lib/active_record/associations/association.rb:202:in `raise_on_type_mismatch'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.13/lib/active_record/associations/belongs_to_association.rb:6:in `replace'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.13/lib/active_record/associations/singular_association.rb:17:in `writer'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.13/lib/active_record/associations/builder/association.rb:51:in `block in define_writers'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:16:in `public_send'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:16:in `block (2 levels) in object'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:15:in `each'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:15:in `block in object'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:14:in `tap'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:14:in `object'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/evaluation.rb:12:in `object'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/strategy/build.rb:9:in `result'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/factory.rb:42:in `run'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/factory_runner.rb:23:in `block in run'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/activesupport-3.2.13/lib/active_support/notifications.rb:125:in `instrument'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/factory_runner.rb:22:in `run'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/factory_girl-4.5.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
     # ./spec/models/role_definition_spec.rb:5:in `block (2 levels) in <top (required)>'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/zeus-0.15.4/lib/zeus/rails.rb:216:in `test'
     # ./custom_plan.rb:7:in `test'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/zeus-0.15.4/lib/zeus.rb:148:in `block in command'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/zeus-0.15.4/lib/zeus.rb:135:in `fork'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/zeus-0.15.4/lib/zeus.rb:135:in `command'
     # /home/jfreivald/.rvm/gems/ruby-1.9.3-p551/gems/zeus-0.15.4/lib/zeus.rb:50:in `go'
     # -e:1:in `<main>'

Finished in 1.25 seconds (files took 3 minutes 39.9 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/models/role_definition_spec.rb:4 # RoleDefinition has a valid factory

其他正在使用的对象是资源:

class Resource < ActiveRecord::Base
  require 'rest-client'

  attr_accessible :fhir_base_url_id, :resource_type_id, :fhir_resource_id

  belongs_to :resource_type
  belongs_to :fhir_base_url

  has_many :resource_authorizations
  has_many :role_definitions, :through => :resource_authorizations
  has_many :profiles, :through => :role_definitions

  validates :resource_type_id, :fhir_base_url_id, :fhir_resource_id, :presence => true
  validates_associated :resource_type, :fhir_base_url
  validates_uniqueness_of :fhir_resource_id, :scope => [ :fhir_base_url_id, :resource_type_id ]

# support functions removed

end

和ResourceType:

class ResourceType < ActiveRecord::Base
  attr_accessible :resource_type

  validates :resource_type, :presence => true, :uniqueness => true
end

在我看来,reference patient_resource正在尝试将自己分配给RoleDefinition::resourceresource不存在patient_resource,而是:patient_resource

此应用程序的所有其他600多个测试都有效,除了那些依赖于此应用程序的测试。

问题是:FactoryGirl创建资源类型为“患者”的资源并将其分配给RoleDefinition中的{{1}}引用的正确语法是什么。

我使用的是Ruby 1.9.3p551,Rails 3.2.13(以保持与我的托管网站的兼容性)和factory_girl_rails 4.5.0。

谢谢。

1 个答案:

答案 0 :(得分:3)

RoleDefinition内,这一行:

belongs_to :patient_resource, :class_name => :resource

应为:

belongs_to :patient_resource, :class_name => 'Resource'