Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails undefined method for Module

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.

like image 895
gprasant Avatar asked Nov 25 '14 02:11

gprasant


2 Answers

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.

like image 63
jgraft Avatar answered Oct 18 '22 09:10

jgraft


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.

like image 6
nicolas Avatar answered Oct 18 '22 10:10

nicolas