重用多个Rails模型中的方法

时间:2015-04-07 14:38:56

标签: ruby-on-rails ruby

初学者ruby / rails问题在这里。我有一个方法,我目前在我的“用户”模型中使用。

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

我想在不同的模型中重复使用相同的方法,比如我的帐户模型。

在哪里放置这样的代码才能在模型之间共享? 另外,为了获得调用类,我只使用“self.class”?

由于

3 个答案:

答案 0 :(得分:7)

Rails 4 concerns就是为了完成这项工作。 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

答案 1 :(得分:1)

如果您曾经两次编写相同的方法,那么你可能是写错代码的标志。如果是我,我会创建一个抽象类,它是Account和User的父类。使Account和User继承此父类,并将所有共享逻辑放在该父类中。然后,帐户和用户将自动访问该共享逻辑。

您将需要查找如何在rails中创建抽象类。一旦你创建了新的父抽象类,请确保Account和User继承父类而不是ActiveRecord :: Base,如下所示:

class Account < NewAbstractClass
end
class user < NewAbstratClass
end

通过使用问题或使用模块,我既不同意也不同意上面或下面的答案。但是,这是我以前解决这个问题的方法,这是尝试解决多个类之间共享逻辑问题的一种很好的面向对象方式。

答案 2 :(得分:0)

对于代码可重用性,我们使用模块。 Rails中模块的更常见用法是共享公共代码。 所以答案是

  • 在模块中编写相同的方法
  • 将其放在lib中,如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

models/some_model2.rb

class SomeModel2 include SomeTokenGeneration end

include方法将模块中的所有方法作为实例方法添加到类

让我们看一下两个类可以共享实例方法的场景。

因此,您可以在两个模型中将该方法用作models/some_model1.rb

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

models/some_model2.rb

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