Search code examples
ruby-on-railsseparation-of-concernsrails-models

Rails logic best practices


I had some calculations on my controller like this

@travel.food_expenses.map { |e| e.value * e.amount }.sum

I know I shouldn't have the application logic on the controller, so I created a method on the Travel model

  def self.sum_food_expenses
    self.food_expenses.map { |e| e.value * e.amount }.sum
  end

But this will return me the undefined method sum_food_expenses for TravelsController

As a workaround I put all those methods on the ApplicationController as:

  def sum_food_expenses(travel)
    travel.food_expenses.map { |e| e.value * e.amount }.sum
  end

It works but its very very messy, how should I proceed?


Solution

  • On the travel model, def self.sum_food_expenses defined a class method, not an instance method. You want def sum_food_expenses. Then in the controller you can call @travel.sum_food_expenses.

    EDIT: Also, not to be a stickler, but self.food_expenses.map { |e| e.value * e.amount }.sum is O(2n), but could be written as food_expenses.sum { |e| e.value * e.amount }, which would only be O(n).