Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to refactor "shared" methods?

I am using Ruby on Rails 3.2.2 and I would like to "extract" some methods from my models / classes. That is, in more than one class / model I have some methods (note: methods are related to user authorizations and are named the "CRUD way") that are and work practically the same; so I thought that a DRY approach is to put those methods in a "shared" module or something like that.

What is a common and right way to accomplish that? For example, where (in which directories and files) should I put the "shared" code? how can I include mentioned methods in my classes / models? what do you advice about?

Note: I am looking for a "Ruby on Rails Way to make things".

like image 753
user12882 Avatar asked Sep 18 '12 15:09

user12882


2 Answers

One popular approach is to use ActiveSupport concerns. You would then place the common logic typically under app/concerns/ or app/models/concerns/ directory (based on your preference). An illustrative example:

# app/concerns/mooable.rb
module Mooable
  extend ActiveSupport::Concern

  included do
    before_create :say_moo

    self.mooables
      where(can_moo: true)
    end
  end

  private

  def say_moo
    puts "Moo!"
  end
end

And in the model:

# app/models/cow.rb
class Cow < ActiveRecord::Base
  include Mooable
end

In order to make it work this way you have to add the following line to config/application.rb

config.autoload_paths += %W(#{config.root}/app/concerns)

More information:

  • http://chris-schmitz.com/extending-activemodel-via-activesupportconcern/
  • http://blog.waxman.me/extending-your-models-in-rails-3
  • http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
like image 102
Timo Saloranta Avatar answered Oct 21 '22 12:10

Timo Saloranta


My answer has nothing to do with RoR directly but more with Ruby.

Shraing common code may be done in various ways in Ruby. In my opinion the most obvious way is to create Ruby Modules that contain the code and then include them inside your class/model. Those shared modules are frequently under the lib directory of your app root. For example:

# lib/authorizable.rb

module Authorizable
  def method1
     #some logic here
  end

  def method2
     #some more logic here
  end
end

# app/models/user.rb

 class User < ActiveRecord::Base
    include Authorizable
 end

The User class may now invoke method1 and method2 which belong to the Authorizable module. You can include this module in any other Ruby class you'd like, this way you DRY your code.

like image 45
Erez Rabih Avatar answered Oct 21 '22 10:10

Erez Rabih