Доступ к методам класса ActiveSupport::Concern из методов экземпляра

Я работаю над учебником Майкла Хартла, но обнаружил, что класс User становится немного загроможденным. Я хотел немного подчистить его, вытащив куски функциональности в отдельные миксины (используя новый шаблон ActiveSupport::Concern вместо старого шаблона self.included(klass)).

У меня небольшие проблемы с разделом Session.

Из '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

Что я включаю в 'models/user.rb':

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

class User < ActiveRecord::Base
  ...

  include Authentication
  include SessionManagement

  ...

end

Это отлично работает для модуля аутентификации (который на самом деле просто проверки и has_secure_password). Однако метод экземпляра create_remember_token выдает ошибку при попытке доступа к методам классов encrypt и new_remember_token.

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)>

Я чувствую, что упускаю что-то очевидное. Мы будем очень признательны за любое понимание. Заранее спасибо!


person TheWiseAxe    schedule 08.01.2014    source источник


Ответы (1)


Эти два метода являются методами класса, и вы вызываете их в экземпляре. Пытаться:

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

или (предпочтительно) переместить их из модуля ClassMethods.

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
person BroiSatse    schedule 08.01.2014
comment
А, это имеет смысл. В контексте учебника ожидается, что методы будут доступны как User.new_remember_token и User.encrypt, поэтому я думаю, что это первое решение (хотя я понимаю аргумент против). Спасибо! - person TheWiseAxe; 08.01.2014