Jumbalaya Wanton
Jumbalaya Wanton

Reputation: 1621

How do I include a gem's class method in a Rails model?

I'm learning how to write a gem. I want to add some methods that I will use in a User model in Rails.

# app/models/user.rb
class User
  include Mongoid::Document
  include Authme::Model  # here's my gem.

  field :password_digest, type: String
end
# Gemfile
gem 'authme'

Now, inside my gem I have the following:

- authme
  - lib
    + authme
      - model.rb
    - authme.rb

Here are the contents of the gem.

# lib/authme.rb
require 'authme/version'
require 'authme/model'
module Authme
end

# lib/authme/model.rb
module Authme
  module Model
    extend ActiveSupport::Concern

    included do
      include ActiveModel::SecurePassword
      has_secure_password validations: false
      before_create :create_session_token
    end

    module ClassMethods
      def new_session_token
        SecureRandom.urlsafe_base64
      end

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

    private

    def create_session_token
      self.session_token = self.class.encrypt(self.class.new_session_token)
    end
  end
end

I add this to my gemspec:

spec.add_dependency "activesupport", "~> 4.0.1"

To test this, inside the terminal, I tried User.new_session_token and got this error:

NoMethodError: undefined method `new_session_token' for User:Class

What am I doing wrong? I really want to test this, but I'm out of my depth. I'm not sure how to test that the class User has the included the gem module.

Upvotes: 2

Views: 2841

Answers (1)

Kyle Decot
Kyle Decot

Reputation: 20815

The problem is that you're creating Authme::Model and Authme::Model::ClassMethods but you're never actually adding new_session_token as class methods of Authme::Model.

If you want to add these methods onto Authme::Model you need to do something like

module Authme
  module Model
    module ClassMethods
      # define all of your class methods here...
    end

    extend ClassMethods
  end
end

The key part here is the Object#extend.

Upvotes: 3

Related Questions