【发布时间】:2023-04-09 21:15:02
【问题描述】:
我想在模型之间共享几种方法,而不是复制和粘贴它们。在控制器中,我可以通过将方法放在 application_controller.rb 中来做到这一点,它会自动包含在每个控制器中。 模型有类似的东西吗?
谢谢!
【问题讨论】:
标签: ruby-on-rails
我想在模型之间共享几种方法,而不是复制和粘贴它们。在控制器中,我可以通过将方法放在 application_controller.rb 中来做到这一点,它会自动包含在每个控制器中。 模型有类似的东西吗?
谢谢!
【问题讨论】:
标签: ruby-on-rails
为了补充 Josh 的答案,有时您可能想要共享一些定义多态关联的代码。你不能只把has_many方法调用放在你的模块中,因为你会得到一个错误,例如在一个名为Votable的模块中:
undefined method `has_many' for Voteable:Module (NoMethodError)
因此,您需要使用self.included(base) 方法和base.instance_eval。这是我的 Voteable 模块的示例:
module Voteable
def self.included(base)
base.instance_eval do
has_many :votes, as: :voteable
has_many :voters, through: :votes
end
end
def voted_up_by?(user)
user and votes.exists?(value: 1, voter_id: user)
end
def voted_down_by?(user)
user and votes.exists?(value: -1, voter_id: user)
end
end
现在您可以在具有该行为的模型中include Voteable。这将执行self.included(base) 方法并定义包含类的关联。
【讨论】:
def self.included(base) base.instance_eval 替换为 extend ActiveSupport::Concern included。
上面的最佳解决方案对我有用。在 Rails 3 中,我发现我还必须将 application.rb 文件更新为:config.autoload_paths += Dir["#{config.root}/lib/**/"],此处回答:Best way to load module/class from lib folder in Rails 3?
【讨论】:
您可以通过多种方式在 2 个模型类之间共享方法。
【讨论】:
Turn those methods into helper methods that both models have access to - 我认为模型无法访问辅助方法。这怎么可能(似乎是我正在尝试做的最干净的方法)
您可以在 Rails 应用程序的 lib 目录中创建一个名为 functionality.rb 或类似名称的文件。制作以模块命名的文件,以便在 Rails 启动时自动加载它。例如,如果我想为多个模型添加标记,我会创建一个名为 lib/flagging.rb 的文件,它看起来像这样:
module Flagging
# Flags an object for further review
def flag!
self.update_attribute(:flagged, true)
end
# Clears all flags on an object
def deflag!
self.update_attribute(:flagged, false)
end
end
在我想要添加此功能的每个模型中,我都会执行以下操作:
class Foo < ActiveRecord::Base
include Flagging
end
然后我就可以做类似的事情了:
foo = Foo.create
foo.flag!
【讨论】:
你可以 a) 做一些类似于 application_controller 的事情并创建一个模型类,其他人可以从中继承或 b) 使用一个模块。
【讨论】: