简体   繁体   English

Rails&Rspec:使用通过扩展ActiveSupport :: Concern的模块定义的方法测试模型

[英]Rails & Rspec: testing model with methods defined via module extending ActiveSupport::Concern

I have a module that defines a class method to dynamically define a series of instance methods based on values in given columns, roughly as follows: 我有一个模块,该模块定义一个类方法,以基于给定列中的值动态定义一系列实例方法,大致如下:

lib/active_record_extension.rb LIB / active_record_extension.rb

module ActiveRecordExtension
  extend ActiveSupport::Concern

  module ClassMethods
    def define_some_methods(*attribute_names)
      # define some methods
    end
  end
end

ActiveRecord::Base.send(:include, ActiveRecordExtension)

config/initializers/extensions.rb 配置/初始化/ extensions.rb中

require 'active_record_extension.rb'

app/models/my_model.rb 应用程序/模型/ my_model.rb

class MyModel < ActiveRecord::Base
  define_some_methods :first_attribute, :second_attribute
end

This setup for adding a class method to ActiveRecord::Base is based on the first answer to this question . 用于将类方法添加到ActiveRecord :: Base的此设置基于此问题的第一个答案。

This works beautifully in my Rails app and console, allowing me to define a variety of similar methods without cluttering up my model. 这在我的Rails应用程序和控制台中可以很好地工作,使我可以定义各种相似的方法而不会弄乱我的模型。 However, it doesn't work at all in my rspec tests, which now all fail with NoMethodError s for calls to the dynamically defined methods. 但是,它在我的rspec测试中根本不起作用,现在所有这些都由于对动态定义方法的调用而导致NoMethodError失败。

How can I be sure this module (or just this method) is correctly included in my models while running rspec? 在运行rspec时,如何确定该模块(或仅此方法)正确包含在我的模型中?

EDIT: Here is my spec/spec_helper.rb : 编辑:这是我的spec / spec_helper.rb

ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'

#to test with sunspot
require 'sunspot/rails/spec_helper'
RSpec.configure do |config|
  ::Sunspot.session = ::Sunspot::Rails::StubSessionProxy.new(::Sunspot.session)
end

#adds devise and jasmine fixture test helpers
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_base_class_for_anonymous_controllers = false
  config.order = "random"
end

I would propose an alternative way to solve the first problem which should also solve the current issue you're asking about. 我将提出一种解决第一个问题的替代方法,该方法也应解决您正在询问的当前问题。 There's nothing ActiveSupport::Concern can do for you here that ruby can't so I would just stick with pure ruby and do: 这里没有ActiveSupport :: Concern可以为您做的事情,而ruby无法做到,所以我会坚持使用纯ruby来做:

module ActiveRecordExtension
  def self.included(klass)
    klass.class_eval do 
      extend ClassMethods
    end
  end 
 module ClassMethods
  def define_some_methods(*attribute_names)
   # define some methods
  end
 end
end

ActiveRecord::Base.send(:include, ActiveRecordExtension)

If you have any questions about the included hook I can explain in more detail. 如果您对随附的挂钩有任何疑问,我可以详细解释。 You also don't need to require this file in an initializer(although when you make changes you will need to restart your local server) 您也不需要在初始化程序中要求此文件(尽管进行更改时,您将需要重新启动本地服务器)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM