Nice trick you can do with anonymous functions

In MVC I stumble upon such problem from time to time, and today I’ve made up a fairly nice solution. So lets get into it.

You want to have generic lists (tables) in your views, since your admin wants user payments in his user view, and user should see them as well. But in my case those were little bit different. In admins eye – all the way to the bottom – summary of all payments should be visible (user should not see it since he could get a stroke from the amount or whatever ;))

I’ve got this partial (example in rails) “shared/user_payment_list”

  <%= render "shared/user_payments_list", 
             :user_payments => @user.user_payment 
  %>

(the view itself is simple – it just iterates through passed payments and generates table)

I didn’t want to create different view for admin (and I’m fresh from accomplishing Ruby Bits part 1 and 2) and did something like this:

In the partial at the end of the table is call for optionally passed method object (note: this is HAML)

    %td
      - additional_payment_info ||= nil
      = additional_payment_info.call(user_payments) unless additional_payment_info == nil

And in admins view I call the partial with the instantly created method:

  <%= render "shared/user_payments_list", 
             :user_payments => @user.user_payment,
             :additional_payment_info => 
                 Proc.new {|payments| 
                             payments.inject(0){|sum, p| sum += p.amount}
                 }
  %>

Further refactoring is possible, the simplest is to extract generic ‘injector’ as helper method:

  def collection_sum_by (access_method)
    Proc.new {|collection| collection.inject(0){|sum, p| sum += p.send(access_method)}}
  end

In such case the partial will be called like

  <%= render "shared/user_payments_list", 
             :user_payments => @user.user_payment,
             :additional_payment_info => collection_sum_by(:amount)
  %>
Share Button

Leave a Reply

Your email address will not be published. Required fields are marked *