Marty
Marty

Reputation: 2224

How to refactor method that occurs in multiple models?

I have a method that is repeated in multiple models. Should I just repeat this code in multiple models or is there a way to include the method in 1 place and make it available to multiple models?

  # Returns true if the given token matches the digest.
  def authenticated?(attribute, token)
    digest = send("#{attribute}_digest")
    return false if digest.nil?
    BCrypt::Password.new(digest).is_password?(token)
  end

Upvotes: 3

Views: 189

Answers (1)

Richard Peck
Richard Peck

Reputation: 76774

You'll be best using a concern, although in theory you could also use a superclass:


Concerns

This is standard Rails functionality:

#app/models/concerns/auth.rb
module Auth
  extend ActiveSupport::Concern

  def authenticated?(attribute, token)
     digest = send("#{attribute}_digest")
     return false if digest.nil?
     BCrypt::Password.new(digest).is_password?(token)
  end
end

Then you just have to include auth in your model:

#app/models/your_model.rb
class YourModel < ActiveRecord::Base
   include Auth
end

Excellent writeup here


Superclass

Another way would be to create a "superclass".

This will be hacky (because it's populating the ActiveRecord method chain with another model), but could be interesting to try.

#app/models/auth.rb
class Auth < ActiveRecord::Base
   def authenticate?
     ....
   end
end

#app/models/user.rb
class User < Auth
   self.table_name = self.model_name.plural
end

Being honest, this method seems hacky, although it will allow you to extend model functionality much more than a concern would.

Refs:

Upvotes: 4

Related Questions