我有一些方法想要在模型之间共享,而不是复制和粘贴它们。在控制器中,我可以通过将这些方法放在application_controller.rb文件中来实现,这样每个控制器都会自动包含这些方法。 那么对于模型,是否有类似的方法呢?
谢谢!
我有一些方法想要在模型之间共享,而不是复制和粘贴它们。在控制器中,我可以通过将这些方法放在application_controller.rb文件中来实现,这样每个控制器都会自动包含这些方法。 那么对于模型,是否有类似的方法呢?
谢谢!
你可以在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!
上面的解决方案对我有用。在Rails 3中,我发现我还需要更新application.rb文件并添加:config.autoload_paths += Dir["#{config.root}/lib/**/"]
参考答案:Best way to load module/class from lib folder in Rails 3?
您可以选择a)类似于application_controller的方式,创建一个模型类,然后其他模块可以继承它,或者b)使用模块。
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
extend ActiveSupport :: Concern included
替换def self.included(base)base.instance_eval
。 - Joshua Coady