Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reuse methods in multiple Rails models

Beginner ruby/rails question here. I have a method That I am currently using in my "User" model.

def generate_token(column) begin self[column] = SecureRandom.urlsafe_base64 end while User.exists?(column => self[column]) end

I want to reuse the same method in a different model say my Account model.

Where is a good place to put code like this to be shared between models? Also, in order to get the calling class would I just use "self.class"?

Thanks

like image 250
rmstar25 Avatar asked Apr 07 '15 14:04

rmstar25


2 Answers

Rails 4 concerns are here to do this job. http://api.rubyonrails.org/classes/ActiveSupport/Concern.html

app/models/user.rb:

class User < ActiveRecord::Base
  include TokenGenerator

  def foo
    $stderr.puts self.class.generate_token("bar")
  end
end

app/models/account.rb:

class Account < ActiveRecord::Base
  include TokenGenerator

  class << self
    def bar
      return generate_token("foo")
    end
  end
end

app/models/concerns/token_generator.rb

module TokenGenerator
  extend ActiveSupport::Concern

  module ClassMethods
    def generate_token(c)
      return "some_thing"
    end
  end
end
like image 158
pierallard Avatar answered Sep 22 '22 17:09

pierallard


If you are ever writing the same method twice, you are right that it's probably a sign of writing bad code. If it were me, I would create an abstract class that is a parent class to both Account and User. Make Account and User inherit from this parent class, and put all of the shared logic in that parent class. Then Account and User will automatically have access to that shared logic.

You will want to look up how to make abstract classes in rails. Once you've made the new parent abstract class, make sure Account and User inherit from the parent class instead of ActiveRecord::Base like so:

class Account < NewAbstractClass
end
class user < NewAbstratClass
end

I am neither agreeing nor disagreeing with the above or below answers, through using concerns or through using modules. However, this is the way that I have solved this problem before in the past, and this is a good object orient way to try and solve the problem of shared logic between multiple classes.

like image 32
James Avatar answered Sep 23 '22 17:09

James