简体   繁体   中英

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

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

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.

For code reusability, we use modules. The more common usage of modules in Rails is to share common code. so the answer is

  • write the same method in module
  • place it in lib like lib/some_token_generation.rb

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

  • after that include this module, in which model you want to use like models/some_model1.rb

class SomeModel1 include SomeTokenGeneration end

or models/some_model2.rb

class SomeModel2 include SomeTokenGeneration end

The include method adds any methods in the module as instance methods to the class

Let's look at a scenario where two classes could share an instance method.

So you can use that method in both models as models/some_model1.rb

class SomeModel1 include SomeTokenGeneration def some_method1 self.generate_token(column) end end

or models/some_model2.rb

class SomeModel2 include SomeTokenGeneration def some_method2 self.generate_token(column) end end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM