mr_muscle
mr_muscle

Reputation: 2910

Ruby pass params in method to call another class

I've got a ruby method:

  def build_total_sum(day)
    TotalSumBuilder.new(
      recurring_expenses: recurring_payments_data,
      expense_contracts: expense_contracts_data,
      day: day
    ).build
  end

Which I want to expand to call different method than builder from TotalSumBuilder. My goal is to be like:

  def initialize(day)
    @day = day
  end

  def call
    date.map do |day|
      {
        day: day,
        total_sum: build_total_sum(day, build),
        revenues_sum: build_total_sum(day, revenues_sum),
        expenses_sum: build_total_sum(day, revenues_sum)
      }
    end
  end

  def build_total_sum(day, method_name)
    TotalSumBuilder.new(
      recurring_expenses: recurring_payments_data,
      expense_contracts: expense_contracts_data,
      day: day
    ).method_name
  end

TotalSumBuilder.new.TotalSumBuilder.new.expenses_sum and TotalSumBuilder.new.expenses_sum will be triggered by the call method.

If I leave like it is at the top I'm getting an error:

SystemStackError (stack level too deep):

Upvotes: 0

Views: 364

Answers (1)

Vasfed
Vasfed

Reputation: 18504

In your code example first thig that comes to mind is just to reuse TotalSumBuilder instance:

def call
  date.map do |day|
    builder = total_sum_builder(day) # calls TotalSumBuilder.new and returns it
 
    {
      day: day,
      total_sum: builder.build,
      revenues_sum: builder.revenues_sum,
      expenses_sum: builder.expenses_sum
    }
  end
end

def total_sum_builder(day)
    TotalSumBuilder.new(
      recurring_expenses: recurring_payments_data,
      expense_contracts: expense_contracts_data,
      day: day
    )
end

but if for some reason you cannot do that - you can use blocks:

  def build_total_sum(day)
    yield TotalSumBuilder.new(
      recurring_expenses: recurring_payments_data,
      expense_contracts: expense_contracts_data,
      day: day
    )
  end

# and then
build_total_sum(day){|builder| builder.revenues_sum }

or finally, use send:

  def build_total_sum(day, method_name)
    builder = TotalSumBuilder.new(
      recurring_expenses: recurring_payments_data,
      expense_contracts: expense_contracts_data,
      day: day
    )
    raise "unknown method #{method name}" unless builder.respond_to?(method_name)
    builder.send(method_name)
  end

build_total_sum(day, :build)

Upvotes: 1

Related Questions