Including a Module in a Rails 5 Application Writer

I am using Application Record to simplify common logic throughout my application.

Here's an example that writes the scope for boolean and inverse. This works well:

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

      

The My Application Record class became quite long, and it made sense for me to split it into separate modules and load them as needed.

Here's my attempt at a solution:

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

      

In this case, I don't get a download error, but boolean_scope

then undefined on User

and Message

.

Is there a way to ensure that included modules are loaded at the appropriate time and are available to the Application Record and its inheriting models?


I have also tried to get models to include modules directly and that didn’t solve the problem.

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

      

+3


source to share


3 answers


As an alternative to @ Pavan's answer, you can do this:



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

      

+4


source


In this case I don't get the upload error, but the boolean_scope is then undefined for the user and the message

The problem lies in the include

methods of adding the class instance. You need to useextend

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

      



Now you can call it like User.boolean_scope

. Below is an example 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 #<Baz:0x1e708>

      

+3


source


Your classes User

and Message

don't seem to inherit ApplicationRecord

. How will they be able to access ::boolean_scope

?

Try the following:

class User < ApplicationRecord
  boolean_scope :verified, :unverified
end

class Message < ApplicationRecord
  boolean_scope :sent, :pending
end

      

+1


source







All Articles