在Rails 5 Application Record类中包含一个模块

我正在使用Application Record来简化整个应用程序中的共享逻辑。

这是一个为布尔值及其逆写入范围的示例。 这很好用:

class ApplicationRecord  { where("#{attr}": true) }) scope(opposite, -> { where("#{attr}": false) }) if opposite.present? end end class User < ApplicationRecord boolean_scope :verified, :unverified end class Message < ApplicationRecord boolean_scope :sent, :pending end 

我的应用程序记录类得到了足够长的时间,我将它分解为单个模块并根据需要加载它们是有意义的。

这是我尝试的解决方案:

 class ApplicationRecord  { where("#{attr}": true) }) scope(opposite, -> { where("#{attr}": false) }) if opposite.present? end end class User < ApplicationRecord boolean_scope :verified, :unverified end class Message < ApplicationRecord boolean_scope :sent, :pending end 

在这种情况下,我没有收到加载错误,但是在UserMessage上未定义boolean_scope

有没有办法确保包含的模块在适当的时间加载并可用于Application Record及其inheritance模型?


我还尝试让模型直接包含模块,但没有解决问题。

 module ScopeHelpers def self.boolean_scope(attr, opposite = nil) scope(attr, -> { where("#{attr}": true) }) scope(opposite, -> { where("#{attr}": false) }) if opposite.present? end end class User < ApplicationRecord include ScopeHelpers boolean_scope :verified, :unverified end class Message < ApplicationRecord include ScopeHelpers boolean_scope :sent, :pending end 

作为@ Pavan答案的替代方案,您可以这样做:

 module ScopeHelpers extend ActiveSupport::Concern # to handle ClassMethods submodule module ClassMethods def boolean_scope(attr, opposite = nil) scope(attr, -> { where(attr => true) }) scope(opposite, -> { where(attr => false) }) if opposite.present? end end end # then use it as usual class ApplicationRecord < ActiveRecord::Base include ScopeHelpers ... end 

在这种情况下,我没有收到加载错误,但是在用户和消息上未定义boolean_scope

问题是include实例上添加方法。 你需要使用extend

 class ApplicationRecord < ActiveRecord::Base self.abstract_class = true extend ScopeHelpers end 

现在你可以像User.boolean_scope一样调用它。 以下是include vs extend的示例

 module Foo def foo puts 'heyyyyoooo!' end end class Bar include Foo end Bar.new.foo # heyyyyoooo! Bar.foo # NoMethodError: undefined method 'foo' for Bar:Class class Baz extend Foo end Baz.foo # heyyyyoooo! Baz.new.foo # NoMethodError: undefined method 'foo' for # 

您的UserMessage类似乎没有inheritanceApplicationRecord 。 他们将如何访问::boolean_scope

试试这个:

 class User < ApplicationRecord boolean_scope :verified, :unverified end class Message < ApplicationRecord boolean_scope :sent, :pending end