Остановка константы модели для ассоциации (неопределенный метод `lation_delegate_class')
У меня есть Lesson
модель, которая связана с Permission
модель:
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
Я использовал RSpec stub_const
метод заглушки вложенной определенной константы:
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
больше не рельсы, связанные с моделью урока. Любые идеи о том, как пройти этот раунд.
Gem версии: rspec-3.3.0
, rspec-rails-3.3.3
, rails-4.2.3
,
2 ответа
Внимательно посмотрите на это сообщение об ошибке:
NoMethodError:
undefined method `relation_delegate_class' for Permission:Module
Permission
описывается как Module
здесь, а не как Class
, Я думаю, что это происходит потому, что в момент заглушения вложенного const, Permission
класс еще не загружен, и RSpec тоже должен заглушить его через Module
,
Попробуйте это в качестве обходного пути:
before(:each) do
Permission # load real ActiveRecord Permission class
stub_const('Permission::DEFAULTS', {lesson: {some_action: 5}})
end
РЕДАКТИРОВАТЬ: Как примечание, я не думаю, что представление вложенных констант другим классам является хорошей идеей, у вас мало контроля над константой (просто изменение имени или значения), и вы не можете обернуть любое поведение, как вы делаете это методом. Я рекомендую сменить публику Permission
API для использования метода, также будет проще заглушки:
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
Единственный вариант, на который я натолкнулся, это просто явно указать константу в примере:
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