在Rails 3中,我该如何在控制器中使用混合或模块?

28

我在控制器中有一些行为,我将其提取到模块中以便更好地进行测试,并在几个地方重复使用。关于此事有两个问题:

  1. 哪里是放置我的模块的好地方?它们需要被运行才能在控制器中使用,所以我考虑将它们放在 config/initializers/ 目录下。但这似乎有点可疑。应该放在 lib/ 目录下吗?
  2. 如何确保代码被运行,以使模块可以作为 include 添加到我的控制器中?

谢谢您。

3个回答

38
  1. lib/ 是一个非常好的模块存放位置,比起 config/initializers/ 来说要好得多,至少在我看来是这样。如果有多个模块或者一个较大的模块,你也可以考虑将它作为插件放置在 vendor/plugins 中。

  2. 如果你将其放置在 lib/ 中,你需要手动 require 这个文件。Rails 默认不会自动加载 lib/ 目录下的文件。你可以将 require 放置在其中一个配置文件中。

我通常会将我的附加 autoloads(自动加载)放在 config/application.rb 中。下面的代码应该能解决问题(假设你的 .rb 文件位于一个名为 lib/my_module 的目录中):

config.autoload_paths += Dir["#{Rails.root}/lib/my_module"]

您必须确保您的模块是实际的module而不是class。然后,您可以简单地包含它:

# lib/my_module/foobar.rb
module Foobar
  def foobar
    "Hello world!"
  end
end

# app/models/my_model.rb
class MyModel < ActiveRecord::Base
  include Foobar
end

# rails console
>> obj = MyModel.first
=> #<MyModel id: 1, ...>
>> obj.id
=> 1
>> obj.foobar
=> "Hello world!"

2
1)我喜欢把: 我的类扩展放在 app/extentions 下 我的模块放在 /app/mixins 下 我的服务放在 /app/services 下
2)您可以在 config/application.rb 中配置应用程序以加载所有这些内容: 类扩展应该立即被要求, 混合和服务可以添加到您的自动加载路径中。
  class Application < Rails::Application
    # require class extentions right now
    Dir[Rails.root.join('app', 'extentions', "*.rb")].each {|l| require l }

    # Custom directories with classes and modules you want to be autoloadable.
    config.autoload_paths += Dir[Rails.root.join('app', 'mixins', '{**}')]
    config.autoload_paths += Dir[Rails.root.join('app', 'services', '{**}')]

(我正在使用Rails 3)


-1

尝试将控制器特定的模块放在app/controllers中。不需要require


11
除非它们是控制器,否则不应放在 app/controllers 中。这样做会使目录结构失去意义。 - Jamison Dance
同意,Arbind Thakur的解决方案是最好的。我不喜欢/lib,因为在大型项目中,它肯定会变得难以管理。我们很可能会使用带有层次结构的app/mixins。 - jwg2s

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接