18

In Rails, how do you use a specific method from a module. For eg,

# ./app/controllers/my_controller.rb
class MyController < ApplicationController
  include MyModule 

  def action
    MyModule.a_method
  end

  private
  def a_method
    ...
  end
end

# ------------------------------------------------ #

# ./app/helpers/my_module.rb
module MyModule 
  def a_method
    ...
  end
end

MyController includes MyModule. And in action ,I want to use MyModule.a_method (Please note I also have a private a_method in MyController and I don't want to use this.)

Things I've tried :

1) Defining the method in the module as self.

def self.a_method
end

2) Using the :: notation in controller (MyModule::a_method)

The error that I keep getting is Undefined method:a_method for MyModule:module For now, I've resorted to using a different name for the modules method. But I'd like to know how to namespace the function with either the Module:: or Module. notation

[UPDATE - 11/24/2014] adding file structure in code, since Rails heavily relies on convention.

gprasant
  • 15,589
  • 9
  • 43
  • 57

2 Answers2

26

So I am not really sure what you are trying to accomplish with your module but a quick solution to get it working is below.

  1. Move my_module.rb out of helpers and into lib/my_module.rb. The helpers directory is for methods that you use in your views. The convention is to utilize helpers that are namespaced after their respective controller or the application_helper.rb for global methods for your views. Not sure if that's what you are trying to accomplish with your module but wanted to throw that out there.
  2. Create an initializer (you can all it whatever) in config/initializers/custom_modules.rb and add require 'my_module'
  3. Update the a_method back to be self.a_method
  4. You can now call MyModule.a_method in your app

Don't forget to restart your server for changes to lib/my_module.rb to take effect.

Also, a lot of people reference this post by Yehuda Katz as guidance on where to store code for your app. Thought it might be a helpful reference.

Community
  • 1
  • 1
jgraft
  • 918
  • 8
  • 15
6

if you include MyModule into MyController, all the "instance methods" of the first will be mixed-in into the 2nd.

So if you only want to call MyModule.a_method, no need to include your module.

Then you'd want to require (or better autoload) your module before using it. To do so place it in controllers/concerns/my_module.rb, rails (4 at least) should autoload it, otherwise require its file in an intializer

# my_module.rb
module MyModule 
  def self.a_method
    ...
  end
end

should work, but doing

# my_module.rb
module MyModule 
  extend self
  def a_method
    ...
  end
end

is more clean to me. You'd like to have a look to rails active support concern to understand the "rails way" on this topic.

nicolas
  • 900
  • 6
  • 16