Friday, November 2, 2007

Law of Demeter and Forwardable

Dan Manges has an excellent post explaining Law of Demeter and when it makes sense to use Forwardable to comply the principle, or I should say when it doesn't make sense to use the module.

The point is, use it when it makes sense. Take his example, customer_name is just not a sensible method for an order. Asking an order for its customer name is a wrong question because all the order should care is who is its customer. The name is irrelevant to the order.

In fact, I think by putting cusomer_name method in an order. the encapsulation is actually broken because now an order knows the inside details of a customer, thus tightly coupled these two classes.

Monday, September 10, 2007

Simple Captcha and Validatable

I need a captcha in a form, whose associated model is a Validatable. After googling, I decided to go with Simple Captcha. The Simple captcha is extremely easy to use, see its documentation, you'll know. But it works fine with a ActiveRecord::Base, not a Validatable. There has to be some hack to make it work. I could use "Controller mode" of it. But it will be nice to put it into model, make it part of validation process. and here's my code:

First, include SimpleCaptcha into your Validatable model:


YourValidatable.module_eval do
class << self; include SimpleCaptcha::ModelHelpers; end
end



And overwrite apply_simple_captcha


  def self.apply_simple_captcha(options = {})
module_eval do
require 'pstore'
include SimpleCaptcha::ConfigTasks
attr_accessor :captcha, :captcha_code,
:authenticate_with_captcha
alias_method :valid_without_captcha?, :valid?
end
@captcha_invalid_message =
(options[:message].nil? || options[:message].empty?) ?
" image did not match with text" : options[:message]
module_eval(turing_valid_method)
module_eval(turing_save_method)
end


Finally, call apply_simple_captcha


That's it.

In the controller, instead of calling valid? to decide if the object is valid, you call valid_with_captcha?

BTW: Follow this link to see how to install RMagick on Ubuntu

Friday, April 27, 2007

Checking if a method called in transaction

Sometimes it's comforting to know your method is called within a transaction.


if Thread.current['open_transactions'].nil? ||
Thread.current['open_transactions'] == 0


will do. Any better idea?

Monday, April 23, 2007

Using Singleton Method

Ruby has some good features such as you can define/override a method just for one specific object. Basically you can do this:

(in irb)


class A
end

a = A.new
b = A.new

def a.one
1
end

irb(main):007:0> a.one
=> 1

irb(main):007:0> b.one
NoMethodError: undefined method `one' for #
from (irb):11
from :0


This feature is coming in handy when you want to mock out an instance method for a specific object.

Mocha can do this as well, but for an ActiveRecord object, it looks like do something like (assuming a is an ActiveRecord object)


a.expects(:some_method).returns(something)


has unpredictable behavior. Sometimes Mocha complains actual calls is 0 even though we do call some_method in the code being tested. We suspect it's because somehow Mocha couldn't find this specific object. If you change the statement to:


A.any_instance.expects(:some_method).returns(:some_thing)


where A is the type of a.

Then it works just fine, but we are not quite comfortable with this.

And in case if we want to mock out the same method on two different objects and behaves differently, Mocha is no help. In this case, we can use Singleton method to do the mocking:


...
def a.some_method
something
end

def b.some_method
something_else
end
...


This will effectively mock out the method some_method and has no side effect. Pretty neat.

Saturday, February 3, 2007

GVIM for RoR

I used TextMate at work. It's as good as you can get, but it's only for Mac OS which I don't have at home. Today I tried rails.vim for gvim on my newly installed Ubuntu. Again, it proves that vim is a forever favorite. Mastering all key bindings with the rails script may take time, but I can smell it's worth it.

Another IDE I tried was RadRails, for some reason, on my Ubuntu box, it was super slow and it sounds funny to have a RoR IDE written in Java anyway.