在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
在这种情况下,我没有收到加载错误,但是在User
和Message
上未定义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 #
您的User
和Message
类似乎没有inheritanceApplicationRecord
。 他们将如何访问::boolean_scope
?
试试这个:
class User < ApplicationRecord boolean_scope :verified, :unverified end class Message < ApplicationRecord boolean_scope :sent, :pending end