Cássio Godinho
Cássio Godinho

Reputation: 596

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?

Upvotes: 1

Views: 83

Answers (2)

kddeisz
kddeisz

Reputation: 5192

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).

Upvotes: 2

AnkitG
AnkitG

Reputation: 6568

What you are trying to do is create a method on instance/object of Travel.

so in @travel.sum_food_expenses the sum_food_expenses is a instance method and can be written like

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

Whereas if you wanted to do something similar using class method then use self.your_method

Which makes the call look like Travel.your_method

Upvotes: 1

Related Questions