How can I use mixins or modules in my controllers

2019-03-09 18:03发布

问题:

I have some behavior in my controller that I pulled out into a module in order to test better and re-use it in a few places. Two questions about this:

  1. Where is a good place to put my modules? They need to run in order to be available to the controllers, so I was thinking the config/initializers/ directory. That seems a little suspect to me though. lib/?
  2. How do I ensure the code gets run so the modules are available to include in my controllers?

Thank you kindly sirs.

回答1:

  1. lib/ is an excellent place for modules; much better than config/initializers/--at least in my opinion. If it's several modules, or one large one, you can also consider making it a plugin and placing it in vendor/plugins.

  2. If you put it in lib/, you'll need to manually require the file. Rails, by default, does not autoload files in the lib/ directory. You can place the require in one of your config files.

I usually put my additional autoloads in config/application.rb. Something like this should do the trick (assuming that your .rb file is in a directory called lib/my_module):

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

You have to make sure that your module is an actual module and not a class. Then, you can simply include it:

# 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) I like to put: my class extentions under app/extentions my modules under /app/mixins my services under /app/services

2) You can configure your application to load all of these in config/application.rb: class extentions should be required right way and the mixins and services can be added to your autoload path

  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', '{**}')]

(I'm using rails 3)



回答3:

Try putting controller specific modules in app/controllers. No require required.