为关联添加模型常量(未定义的方法“relation_delegate_class”)
Stubing a model constant for assosiation (undefined method `relation_delegate_class')
我有一个与 Permission
模型关联的 Lesson
模型:
app/models/lesson.rb
:
class Lesson < ActiveRecord::Base
has_many :permissions, :class_name => 'Permission', as: :permissible, dependent: :destroy
...
def create_permissions
Permission::DEFAULTS[:lesson].each do |action, value|
..
end
end
app/models/permission.rb
:
class Permission < ActiveRecord::Base
DEFAULTS = {
lesson: {some_more_action: 15}
}
belongs_to :permissible, polymorphic: true
end
我用了RSpecstub_const
方法stub a nested defined constant:
spec/models/lesson_spec.rb
:
require 'rails_helper'
RSpec.describe Lesson, :type => :model do
describe "#create_permissions" do
let!(:lesson) { FactoryGirl.build_stubbed :lesson }
before(:each) do
stub_const('Permission::DEFAULTS', {lesson: {some_action: 5}})
end
it 'should create permissions' do
lesson.create_permissions
permission = lesson.permissions.first
...
end
end
end
但规范因错误而失败:
Failure/Error: permission = lesson.permissions.first
NoMethodError:
undefined method `relation_delegate_class' for Permission:Module
# /home/install/.rvm/gems/ruby-2.1.4/gems/activerecord-4.2.3/lib/active_record/relation/delegation.rb:112:in `relation_class_for'
# /home/install/.rvm/gems/ruby-2.1.4/gems/activerecord-4.2.3/lib/active_record/relation/delegation.rb:106:in `create'
# /home/install/.rvm/gems/ruby-2.1.4/gems/activerecord-4.2.3/lib/active_record/associations/collection_association.rb:41:in `reader'
# /home/install/.rvm/gems/ruby-2.1.4/gems/activerecord-4.2.3/lib/active_record/associations/builder/association.rb:115:in `permissions'
# ./spec/models/lesson_spec.rb:285:in `block (3 levels) in <top (required)>'
看起来 permissions
不再 rails 与课程模型相关联。关于如何获得这一轮的任何想法。
Gem 版本:rspec-3.3.0
、rspec-rails-3.3.3
、rails-4.2.3
.
我想到的唯一选择就是在示例中明确设置常量:
before(:each) do
Permission::DEFAULTS = {lesson: {some_action: 5}}
end
但我觉得这不是个好主意。它还会发出一些警告:
spec/models/lesson_spec.rb:279: warning: already initialized constant Permission::DEFAULTS
app/models/permission.rb:2: warning: previous definition of DEFAULTS was here
仔细查看此错误消息:
NoMethodError:
undefined method `relation_delegate_class' for Permission:Module
Permission
在这里被描述为 Module
,而不是 Class
。我认为发生这种情况是因为在存根嵌套常量的那一刻,Permission
class 尚未加载,并且 RSpec 也必须通过 Module
.[=20 存根它=]
试试这个作为解决方法:
before(:each) do
Permission # load real ActiveRecord Permission class
stub_const('Permission::DEFAULTS', {lesson: {some_action: 5}})
end
编辑:附带说明一下,我不认为将嵌套常量暴露给其他 classes 是个好主意,您几乎无法控制常量(只是更改名称或值)并且您不能像使用方法那样包装任何行为。我建议将 public Permission
的 API 更改为 using 方法,它也会更容易存根:
class Permission < ActiveRecord::Base
DEFAULTS = {
lesson: {some_more_action: 15}
}
def self.defaults
DEFAULTS
end
end
在您的规范中:
before(:each) do
allow(Permission).to receive(:defaults).and_return(lesson: {some_action: 5})
end
我有一个与 Permission
模型关联的 Lesson
模型:
app/models/lesson.rb
:
class Lesson < ActiveRecord::Base
has_many :permissions, :class_name => 'Permission', as: :permissible, dependent: :destroy
...
def create_permissions
Permission::DEFAULTS[:lesson].each do |action, value|
..
end
end
app/models/permission.rb
:
class Permission < ActiveRecord::Base
DEFAULTS = {
lesson: {some_more_action: 15}
}
belongs_to :permissible, polymorphic: true
end
我用了RSpecstub_const
方法stub a nested defined constant:
spec/models/lesson_spec.rb
:
require 'rails_helper'
RSpec.describe Lesson, :type => :model do
describe "#create_permissions" do
let!(:lesson) { FactoryGirl.build_stubbed :lesson }
before(:each) do
stub_const('Permission::DEFAULTS', {lesson: {some_action: 5}})
end
it 'should create permissions' do
lesson.create_permissions
permission = lesson.permissions.first
...
end
end
end
但规范因错误而失败:
Failure/Error: permission = lesson.permissions.first
NoMethodError:
undefined method `relation_delegate_class' for Permission:Module
# /home/install/.rvm/gems/ruby-2.1.4/gems/activerecord-4.2.3/lib/active_record/relation/delegation.rb:112:in `relation_class_for'
# /home/install/.rvm/gems/ruby-2.1.4/gems/activerecord-4.2.3/lib/active_record/relation/delegation.rb:106:in `create'
# /home/install/.rvm/gems/ruby-2.1.4/gems/activerecord-4.2.3/lib/active_record/associations/collection_association.rb:41:in `reader'
# /home/install/.rvm/gems/ruby-2.1.4/gems/activerecord-4.2.3/lib/active_record/associations/builder/association.rb:115:in `permissions'
# ./spec/models/lesson_spec.rb:285:in `block (3 levels) in <top (required)>'
看起来 permissions
不再 rails 与课程模型相关联。关于如何获得这一轮的任何想法。
Gem 版本:rspec-3.3.0
、rspec-rails-3.3.3
、rails-4.2.3
.
我想到的唯一选择就是在示例中明确设置常量:
before(:each) do
Permission::DEFAULTS = {lesson: {some_action: 5}}
end
但我觉得这不是个好主意。它还会发出一些警告:
spec/models/lesson_spec.rb:279: warning: already initialized constant Permission::DEFAULTS
app/models/permission.rb:2: warning: previous definition of DEFAULTS was here
仔细查看此错误消息:
NoMethodError:
undefined method `relation_delegate_class' for Permission:Module
Permission
在这里被描述为 Module
,而不是 Class
。我认为发生这种情况是因为在存根嵌套常量的那一刻,Permission
class 尚未加载,并且 RSpec 也必须通过 Module
.[=20 存根它=]
试试这个作为解决方法:
before(:each) do
Permission # load real ActiveRecord Permission class
stub_const('Permission::DEFAULTS', {lesson: {some_action: 5}})
end
编辑:附带说明一下,我不认为将嵌套常量暴露给其他 classes 是个好主意,您几乎无法控制常量(只是更改名称或值)并且您不能像使用方法那样包装任何行为。我建议将 public Permission
的 API 更改为 using 方法,它也会更容易存根:
class Permission < ActiveRecord::Base
DEFAULTS = {
lesson: {some_more_action: 15}
}
def self.defaults
DEFAULTS
end
end
在您的规范中:
before(:each) do
allow(Permission).to receive(:defaults).and_return(lesson: {some_action: 5})
end