【问题标题】:Reuse methods in multiple Rails models在多个 Rails 模型中重用方法
【发布时间】:2015-04-07 14:38:56
【问题描述】:

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

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

我想在不同的模型中重用相同的方法,比如我的 Account 模型。

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

谢谢

【问题讨论】:

  • 如果您使用的是 rails 4,则需要注意的是 rails 约定在哪里放置这样的东西。self.class 应该可以正常工作

标签: ruby-on-rails ruby


【解决方案1】:

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

【讨论】:

  • 我假设如果我想在 before_ 中调用它,我会使用: before_create { self.class.generate_token(:activation_token) } ?
  • 您可以在included 块中找到它。
【解决方案2】:

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

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

class Account < NewAbstractClass
end
class user < NewAbstratClass
end

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

【讨论】:

  • 当2个子类的母类有理由存在时,即代表一个真实的概念,这是一个很好的解决方案。
【解决方案3】:

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

  • 在模块中写同样的方法
  • lib/some_token_generation.rb一样把它放在lib中

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

【讨论】:

  • 你的答案在 Rails concerns,只是为了避免将可共享的代码放入lib' s.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
  • 2012-11-10
相关资源
最近更新 更多