2017-06-12 46 views
3

我正在使用应用程序记录来简化整个应用程序中的共享逻辑。在Rails 5应用程序记录类中包含模块

下面是一个为布尔及其反转写入作用域的示例。这种运作良好:

class ApplicationRecord < ActiveRecord::Base 
    self.abstract_class = true 

    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 
    boolean_scope :verified, :unverified 
end 

class Message < ApplicationRecord 
    boolean_scope :sent, :pending 
end 

我的应用程序记录类有足够长的时间这是有意义对我来说,它分解成单独的模块,并根据需要加载这些。

这是我尝试的解决方案:

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

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 
    boolean_scope :verified, :unverified 
end 

class Message < ApplicationRecord 
    boolean_scope :sent, :pending 
end 

在这种情况下,我没有得到一个加载错误,但boolean_scope然后在UserMessage不确定。

有没有一种方法可以确保包含的模块在适当的时候被加载,并且可用于应用程序记录及其继承模型?


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

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 

回答

4

作为替代@帕文的答案,你可以这样做:

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 
1

UserMessage类似乎并没有被继承ApplicationRecord。他们将如何访问::boolean_scope

试试这个:

class User < ApplicationRecord 
    boolean_scope :verified, :unverified 
end 

class Message < ApplicationRecord 
    boolean_scope :sent, :pending 
end 
+0

良好的渔获物。不幸的是,这些模型继承了应用程序记录。 AFAIK这个问题似乎与继承无关,因为我也尝试过直接包含模块。这并没有奏效。我已经更新了这个问题。 – seancdavis

3

在这种情况下,我没有得到一个加载错误,但boolean_scope然后 未定义的用户和消息

的问题是include加方法在类的实例上。您需要使用extend

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

现在你可以这样调用它User.boolean_scope。下面是例如,对于包括VS延长

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 #<Baz:0x1e708> 
相关问题