Landon Lapensee
Landon Lapensee

Reputation: 81

Refactoring rails nested methods

Im trying to refactor my code in the Team model. Teams has:many Projections, and Projections has stats for a player (goals, assists, hits etc). I want to implement one method that can tally a specific total if you pass it the parameter you are looking for.

Something like this, where I could call: example_team.total(goals) or example_team.total(assists)

class Team < ApplicationRecord

# def total(value)
  #   total = 0    
  #   self.projections.each do |projection|
  #     total += projection.value
  #   end 
  #   return total
  # end

The issue im having is that im essentially trying to pass a method name within a different method as a parameter. Im getting errors when im trying to do this. How can I get this refactoring to work???

This is my current unfactored code:

class Team < ApplicationRecord

def goals
    total = 0    
    self.projections.each do |projection|
      total += projection.goals
    end 
    return total
  end 

  def assists
    total = 0    
    self.projections.each do |projection|
      total += projection.assists
    end 
    return total
  end 

  def pp_points
    total = 0    
    self.projections.each do |projection|
      total += projection.pp_points
    end 
    return total
  end 
  
  def hits
    total = 0    
    self.projections.each do |projection|
      total += projection.hits
    end 
    return total
  end 

  def blocks
    total = 0    
    self.projections.each do |projection|
      total += projection.blocks
    end 
    return total
  end 

Upvotes: 0

Views: 41

Answers (1)

yzalavin
yzalavin

Reputation: 1836

To send a method dynamically you can use public_send.

class Team < ApplicationRecord
  def total(field)
    total = 0    
    self.projections.each do |projection|
      total += projection.public_send(field)
    end
    return total
  end
end

To simplify the example we can use sum that takes a symbol as an argument.

class Team < ApplicationRecord
  def total(field)
    projections.sum(field)
  end
end

To make it work you should use something like this example_team.total(:goals).

Upvotes: 3

Related Questions