【问题标题】:Stubing a model constant for assosiation (undefined method `relation_delegate_class')为关联存根模型常量(未定义的方法“relation_delegate_class”)
【发布时间】:2015-09-14 11:12:34
【问题描述】:

我有一个与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

我使用 RSpec stub_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 不再是与课程模型相关的导轨。关于如何获得这一轮的任何想法。

Gem 版本:rspec-3.3.0rspec-rails-3.3.3rails-4.2.3

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 rspec rspec3


    【解决方案1】:

    仔细查看此错误消息:

    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
    

    编辑:作为旁注,我不认为将嵌套常量暴露给其他类是一个好主意,您几乎无法控制常量(只是更改名称或值)并且您不能像使用方法那样包装任何行为。我建议将 publicPermission 的 API 更改为 using a 方法,这样也更容易存根:

    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
    

    【讨论】:

    • 成功了!有类似的想法,但不知道这会导致 RSpec 改变行为。谢谢!将其包装在一个方法中。
    【解决方案2】:

    我遇到的唯一选择就是在示例中明确设置常量:

    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
    

    【讨论】:

      猜你喜欢
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多