Accessing ActiveSupport::Concern class methods from within instance methods

8.7k views Asked by At

I'm working my way through Michael Hartl's tutorial, but was finding the User class getting a bit cluttered. I wanted to clean it up a bit by pulling chunks of functionality into separate mixins (using the new-ish ActiveSupport::Concern, vs the older self.included(klass) pattern).

I'm having a bit of trouble with the Session section of things.

From 'models/user/session_management.rb':

require 'active_support/concern'

module SessionManagement
  extend ActiveSupport::Concern

  included do
    before_create :create_remember_token
  end

  private
      def create_remember_token
        self.remember_token = self.encrypt(self.new_remember_token)
      end

  module ClassMethods
   def new_remember_token
      SecureRandom.urlsafe_base64
    end

    def encrypt(token)
      Digest::SHA1.hexdigest(token.to_s)
    end
  end
end

Which I include in 'models/user.rb':

require 'user/authentication'
require 'user/session_management'

class User < ActiveRecord::Base
  ...

  include Authentication
  include SessionManagement

  ...

end

This works fine for the authentication module (which is really just validations and has_secure_password). However, the create_remember_token instance method is throwing up trying to access the encrypt and new_remember_token class methods.

NoMethodError:
  undefined method `new_remember_token' for #<User:0x007f8e17e338f0>
  # ./app/models/user/session_management.rb:13:in 'create_remember_token'
  # ./spec/models/user_spec.rb:152:in `block (4 levels) in <top (required)>

I feel like I'm missing something obvious. Any insight would be greatly appreciated. Thanks in advance!

1

There are 1 answers

1
BroiSatse On BEST ANSWER

Those two methods are class methods, and you are calling them on the instance. Try:

def create_remember_token
  self.remember_token = self.class.encrypt(self.class.new_remember_token)
end

or (prefered) move them out of ClassMethods module.

require 'active_support/concern'

module SessionManagement
  extend ActiveSupport::Concern

  included do
    before_create :create_remember_token
  end

  private
    def create_remember_token
      self.remember_token = encrypt(new_remember_token)
    end

    def new_remember_token
      SecureRandom.urlsafe_base64
    end

   def encrypt(token)
     Digest::SHA1.hexdigest(token.to_s)
   end

end