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