MattSom
MattSom

Reputation: 2377

Rails - where to put model helper methods

I want to hide certain implementations from the main Model methods, because of clean code reasons. I don't want my Model to contain a lot of huge methods, only the clearest and verbose functionalities.

For example:

class SomeModel
  #included stuff
  #fields & attrs

  def modelMethod
      variable = functionality1(functionality2)
      if some condition
        functionality3
      else
        functionality4
      end
  end

Should I put my functionality methods under a private or protected part at the end of the same model file, or should I put them into a helper file?

If I'm right, the codes in the helpers are only used for the View. What is the convention for this?

Upvotes: 4

Views: 3186

Answers (2)

Michael Gorman
Michael Gorman

Reputation: 1077

If you have a method or set of methods that are used in various models: Rails Concerns

This is different from private/protected and you can have private/protected methods in a concern. This is just how to extract out duplication.

If you have a method that is needed by the model, and only the model (not subclasses of the model, and never called outside the class: private

If you have a method that is needed by the model and its subclasses but not from outside the model: protected

If you need to be able to call the method from outside the class: neither

this answer goes into better detail on those

Upvotes: 1

fbelanger
fbelanger

Reputation: 3568

Having private or protected has nothing to do with the type of cleanup you're trying to do.

This is related to inheritance method visibility/access (though inheritance can obviously be used for reusability).

Methods will depends on reusability. Why not leverage concerns? Say we have SomeModel and want multiple models to implement suspensions.

# app/models/some_model.rb
class SomeModel
  include Suspendable
end

Then add your model concern.

# app/models/concerns/suspendable.rb
module Suspendable
  extend ActiveSupport::Concern

  included do
    has_one :suspension
    scope :active, -> { joins('LEFT OUTER JOIN suspensions').where(suspension: {id: nil} }
  end
end

Or if this only really applies to a single model, but want to keep the model strictly DB manipulations (not Business oriented), then you could have namespaced concerns.

# app/models/concerns/some_model/availability.rb
module SomeModel::Availability
  extend ActiveSupport::Concern

  module ClassMethods
    def availabilities_by_some_logic
    end
  end
end

http://api.rubyonrails.org/v5.0/classes/ActiveSupport/Concern.html

Upvotes: 6

Related Questions