我有两种方法可以在模型之间共享,而不是复制和粘贴它们。在控制器中,我可以通过将方法放在application_controller.rb中来实现,该方法自动包含在每个控制器中。 模型有类似的东西吗?
谢谢!
答案 0 :(得分:16)
您可以在Rails应用的functionality.rb
目录中创建名为lib
或类似内容的文件。使模块命名的文件在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!
答案 1 :(得分:4)
上面的顶级解决方案对我有用。在Rails 3中,我发现我还必须使用:config.autoload_paths += Dir["#{config.root}/lib/**/"]
更新application.rb文件,如下所示:Best way to load module/class from lib folder in Rails 3?
答案 2 :(得分:3)
你可以a)做一些类似于application_controller的事情,并创建一个模型类,其他人可以从中继承或b)使用模块。
答案 3 :(得分:2)
您可以通过多种方式在两个模型类之间共享方法。
答案 4 :(得分:0)
要添加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)
方法,它将定义包含类的关联。