Ruby Banter #004

Thijs van der Vossen, 26 Jul 2007, 12:09 in ruby on rails and video (edit).

In this episode Norbert shows how memoization is implemented and how you can use it to speed up slow methods.

Manfred and Norbert

5 comments

Quick Fix for acts_as_paranoid

Norbert Crombach, 17 Jul 2007, 08:26 in ruby on rails, testing, and broken (edit).

For those of you on Edge Rails, since changeset [7189] appears to have broken the current acts_as_paranoid we’ve been getting some test errors. There’s a quick patch I wrote available in this Pastie, but because scope_out is now recommended by Rick Olson himself this should only be seen as a migration path. Hopefully this will save you some trouble.

No comments yet

Ruby Banter #003

Thijs van der Vossen, 05 Jul 2007, 14:48 in ruby on rails and video (edit).

Here is the third episode in which Manfred shows how & maps to the to_proc method and what you can do with it.

Manfred and Norbert

7 comments

Helpers are for small snippets of code

Manfred Stienstra, 04 Jul 2007, 15:49 in ruby on rails and practices (edit).

Recently we contracted a local company to help out with a Rails project. Their primary job was to implement payments. During an audit or their work I found the following helper:

module CoursesHelper
  include ActiveMerchant::Billing 
  def issuers
    @gateway = IdealGateway.new(
         :merchant            => IDEAL_MERCHANT_ACCOUNT,
         :sub_id              => IDEAL_SUB_ID,
         :password            => IDEAL_PRIVATE_KEY_PASS,
         :private_cert        => IDEAL_PRIVATE_CERT,
         :language            => IDEAL_LANGUAGE,
         :private_key         => IDEAL_PRIVATE_KEY,
         :authentication_type => IDEAL_AUTHENTICATION_TYPE
    )
    
    list = Array.new()
    begin
      response = @gateway.issuers
      if response.success?
        list=Array.new()
        list.push({"issuerName"=>"Kies uw bank...", "issuerID"=>0})
        list=list + (response.params["list"])
      end
    rescue
      list = [{:issuerName=>"Kies uw bank...", :issuerID=>""},
      {:issuerName=>"ofline Simulator", :issuerID=>"00"}]
    end
    return list.map {|i| [ i["issuerName"], i["issuerID"] ] }

  end
  
end

Helpers are for keeping simple code out of your view. They should never include complicated logic. A helper should be so simple that you’d almost dare to deploy without testing.

Also, because it’s a good idea to keep coupling between classes to a minimum, the payment gateway should only be called from classes directly related to payment processing.

Finally, you don’t want such a large number of constants in your code. There are better ways to store the gateway configuration.

The contracter was asked to solve these issues. The gateway initialization was refactored to only appear once and the gateway object was assigned to a constant named IDEAL_GATEWAY. The code to find all issuers was moved to the Payment model.

class Payment < ActiveRecord::Base
  def self.ideal_issuers
    response = IDEAL_GATEWAY.issuers
    response.params["list"]
  end
end
module CoursesHelper
  
  def issuers
    list=Array.new()
    # 'Kies uw bank' means 'Choose your bank'
    list.push({"issuerName"=>"Kies uw bank...", "issuerID"=>0}) 
    list=list + Payment.ideal_issuers
    return list.map {|i| [i["issuerName"], i["issuerID"]] }
  end
  
end

Unfortunately, the issuers helper still looks more like Python than Ruby. I would have written it like this:

module CoursesHelper
  def issuers
    [['Kies uw bank...', 0]] + Payment.ideal_issuers.map \
      { |i|[i['issuerName'], i['issuerID']] }
  end  
end

I don’t think you should include instructions on how to use a drop-down as one of the options inside it. Furthermore, a default value makes no sense in this case. People always have to choose a bank, otherwise they can’t continue with the payment process.

After some refactoring I was left with the code below. I’ve also moved it to the helpers module for the payments controller, because that’s where the form is rendered.

module PaymentsHelper
  def issuers
    Payment.ideal_issuers.map { |i| [i['issuerName'], i['issuerID']] }
  end
end

8 comments

Why fake a link?

Thijs van der Vossen, 03 Jul 2007, 10:05 in web and broken (edit).

In Google Analytics there are a lot of tables where you can click a link to see content details. These links only work if you left-click. If you right-click to open the link in a new tab or window, you’ll end up opening the current Google Analytics screen again.

Screenshot showing a link that's not really a link in Google Analytics

I find this extremely annoying because this is precisely the usage scenario where browser tabs are really handy. If you’re looking at an overview with links to additional details, you really need to be able to open them in multiple new tabs of windows so that you can quickly look through them instead of having to wait for each page to load when you go back and forth between the overview list and the details pages.

Here’s the html source for the example above.

<a href="" onclick="window.PageTable._drillDown(2); return false;">
/2007/06/flex-can-t-do-rest</a>

I’m wondering why people do this? What’s the reason for using JavaScript here? Why not just use a real link instead of a fake one?

7 comments