91

I am using Ruby on Rails 3 and I would like to move some custom and shared code in a module.

  1. What syntax should I use to write the module code?
  2. In which folder of my application I have to place the module file?
  3. How I have to include that module in one or more controller classes?
  4. What other action, if any, do I have to use the custom module anywhere in my application?
  5. How can I call methods in the module from my application?
starball
  • 20,030
  • 7
  • 43
  • 238
user502052
  • 14,803
  • 30
  • 109
  • 188

2 Answers2

118

To 1. A module is created/opened by simply saying:

module MyModule
  def first_module_method
  end
end

To 2. The lib folder. If you want to organize your modules in the lib folder, you can put them into modules themselves. For example, if you wanted a subfolder super_modules your modules would be defined as follows:

module SuperModules
  module MyModule
    def first_module_method
    end
  end
end

To 3./5. When including the module in a class you can simply call the modules methods as if they were defined within the class:

class MyClass
  include MyModule
  def some_method
    first_module_method #calls module method
  end
end

To 4. Frst, make sure that your module is really needed in every class of your application. If it isn't it makes sense to only include it where it is need so as not to bloat the classes that don't need it anyways. If you really want the module everywhere, include look at the class hierarchy of your classes in the app. Do you want the module in all models? You could open ActiveRecord::Base and add add your module there.

Stephan
  • 2,853
  • 3
  • 20
  • 25
  • 2
    In order to organiza files, can I create a sub-folder in the 'lib' folder? If so, what changes? – user502052 Feb 05 '11 at 14:54
  • 2
    @user502052 I have updated the answer to point 2 to answer that question. – Stephan Feb 05 '11 at 18:08
  • In lib there is assets and tasks, are you to put it in one of these? Also what about naming of the module files... – Jonathan Apr 03 '12 at 12:29
  • 3
    Many things are unclear here. What file names to give? How to call the methods when not including all the module? I can't believe there are so many upvotes since I still don't know how to use a module at the end. – Augustin Riedinger Aug 08 '13 at 10:06
  • 5
    Once you create a module as above by including it in the `lib` folder, an important note is to enable Rails3 to uncomment the line in `config\application.rb` for `config.autoload_paths` - read e.g., http://stackoverflow.com/questions/1073076/rails-lib-modules-and ... Note also that you have to be careful to use a filename for your module that matches the module name itself. So if you save it in `lib/test/my_module.rb`, you have to `include Test::MyModule` - for more details see http://stackoverflow.com/questions/4073856/rails-3-autoload – sameers Oct 04 '13 at 06:28
  • 1
    I wrote a blog post that (hopefully) helps clarify this matter. http://www.benfranklinlabs.com/where-to-put-rails-modules/ – Jason Swett Feb 03 '14 at 22:59
  • 7
    I just found this old answer of mine. :( I want to downvote. Don't put anything in lib! Put your code (including additional modules) into `app/models` if the code needs access to other models. If your code is truly a 'library' and can exist on its own, I suggest vendoring a gem. For examples, see https://github.com/shageman/the_next_big_thing – Stephan Feb 04 '14 at 01:13
  • Modules are fine to put in `lib` folder. If it's not a model, then maybe it shouldn't go in `models` folder. Also, make sure you are either `require`ing the file that the module is defined within (otherwise you will get `undefined constant MyModule` error), or autoloading the path as mentioned in previous comments. – Danny May 30 '17 at 14:54
  • If module present `'/lib/super_modules/my_module'`, need to include in class as `include SuperModules::MyModule`. it worked for me. – S.Yadav Mar 31 '20 at 03:16
3

A>1. You can use the same syntax as any other ruby class. For instance, I'm defining a VehicleClassifer module which is going to use the classify_vehicle method to classify a vehicle based on the number of wheels it receives as an input.

module VehicleClassifer
  def classify_vehicle(number_of_wheels)
    VehicleType.where("number_of_wheels = ?", number_of_wheels)
  end
end

A>2. Modules are usually stored in the /lib folder.

questions 3,4,5 have more or less the same answer. you can use

class SomeController < ApplicationController
  include VehicleClassfier

  def index 
    classify_vehicle(4)  
  end
end

in the class you're using the module and you will have access to all the module's methods.

Also, In case you need to use a module through out your app, you can include it in your application controller.

dylanfm
  • 6,292
  • 5
  • 28
  • 29
Shreyas
  • 8,737
  • 7
  • 44
  • 56
  • 2
    I tryied this and got an undefined method error. Any idea of what Am I doing wrong? – Tony Jan 27 '12 at 18:02
  • Are you sure your module is accessible? http://stackoverflow.com/questions/6604272/call-module-function-from-controller-nomethoderror maybe helps you out? – Shreyas Jan 27 '12 at 20:31
  • 1
    @Tony - You may need to restart your server - even in dev-mode, to get the module's methods to be available. And every time you change the code in your module, you must restart the server again. For example, if an error, or it will error out on the old code, but highlight the new code on that line in the error msg - very confusing. – JosephK Jun 07 '16 at 14:55
  • Any idea how to include and use those custom modules inside `ApplicationHelper`? – W.M. Mar 09 '17 at 18:29