Ruby Tricks

Posted on August 30, 2006

How often did you write this kind of code?

    def initialize(arg1, arg2, arg3)
      @arg1 = arg1
      @arg2 = arg2
      @arg3 = arg3
    end

All this constructor does it propagates parameters to initialize method to instance variables. In Ruby, there is a better way:

    class Binding
      def local_to_instance
        eval("local_variables").each do |name|
          eval("self").instance_variable_set("@#{name}", eval(name))
        end
      end

      alias :kernel_eval :eval
      def eval(code)
        kernel_eval(code, self)
      end
    end

    class Test
      attr_accessor :arg1, :arg2, :arg3

      def initialize(arg1, arg2, arg3)
        binding.local_to_instance
      end
    end

    t = Test.new(1,2,3)
    puts t.arg1
    # => 1
    puts t.arg3
    # => 3
    p t
    # => #<Test:0x1c6600 @arg1=1, @arg3=3, @arg2=2>

Note that Ruby 1.9 already provides Binding#eval method, so you don't need this kernel_eval hack.

I know this kind of silly and, I guess, inefficient. But still.

Comments
  1. Pat EylerAugust 30, 2006 @ 10:31 AM

    Very cool little trick. This is something I do far too often. Or maybe I should say, used to do far too often.

  2. joshAugust 30, 2006 @ 10:35 AM

    @arg1, @arg2, @arg3 = arg1, arg2, arg3

    It’s still just one line, but it has the advantage of being readable and meaningful.

  3. KentAugust 30, 2006 @ 04:47 PM

    Josh,

    I agree. I was just playing with the idea. It’s not like I’m going to use it in all my applications, mostly because of the overhead it introduces. Pat Eyler blogs about it.

    As for the readability, consider when a method takes more than tree arguments and they all have more meaningful and longer names. Besides, you have to repeat the name of each argument tree times: once in the method signature, and two times in the assignment itself.

    http://on-ruby.blogspot.com/2006/08/binding-and-benchmarking-or-what-i-did.html
  4. Ruby on rails hostingJuly 21, 2008 @ 02:24 AM

    I like this trick.. but i really wondering where to place the Binding class in rails?