Skip to content

Ruby Blender

  • Blog
  • About
  • Archives
  • Log in
 
Less
More
Trim
Untrim
« Older
Home
Loading
Newer »
Tag Archive for 'metaprogramming'
01Sep09 Default values for Attributes
metaprogramming programming ruby
0 Comments

This is the first in a series of entries which I’m pulling over articles from an old blog, revising, etc…

The Problem

One of the neat things about Ruby is it’s ability to create accessor methods for you, by simply declaring attr_reader, attr_writer, or attr_accessor.  However, there’s not an easy way to define a default value for an attribute.  The original version of this code was based off of Create getter and setter on a valorized variable and ideas from Ruby Quiz #67: Metakoans.  The main difference between it and Sandro Paganotti’s version is that you can pass in a block which will be evaluated each time it is invoked (in case the value might depend on something else).  Additionally, it will work with boolean types.

The Solution

class Object
def self.attribute(*arg,&block)
(name, default) = arg
short_name = name.to_s.sub(/\?/,"")
self.send(:define_method, name) {
if instance_variables.include? "@#{short_name}"
self.instance_eval "@#{short_name}"
else
if block_given?
instance_eval &block
else
default
end
end
}
self.send(:define_method, "#{short_name}="){ |value|
self.instance_eval "@#{short_name} = value"
}
end
end

 

In order to use it, you could do something like this:

class Foo
attribute :bar
attribute(:fud) {instance_variables.include?("@bar") ? @bar : ' '}
attribute :fi, 10
attribute :flag?, true
end

And, in action, it would look like this:

>> f=Foo.new
=> #
>> f.bar # defined, but not set to anything (nil)
=> nil
>> f.fud # since bar is not defined, return an empty space
=> " "
>> f.fi # just return the default
=> 10
>> f.flag? # and here's a boolean
=> true
>> f.bar = 5 # now we set bar
=> 5
>> f.fud # Since bar is set, then fud will return its value
=> 5
>> f.fud = 20 # now we explicitly set fud, and the block is no longer used
=> 20
>> f.fud # fud returns 20 as expected
=> 20
>> f.bar # and, as expected, changing fud has no effect on bar
=> 5

 

There might be a better way to do this; but one of the things I love about Ruby is that you can add new features to the language very easily.

Enhanced by Zemanta
 
Browse Archives »
  • administrivia (2)
  • configuration (1)
  • metaprogramming (1)
  • mini-saga (5)
  • programming (10)
  • rails (1)
  • ruby (15)
  • rubygems (2)
  • Uncategorized (1)
 

Recent Posts

  • Default values for Attributes
  • Arguments with Trollop
  • Database Paranoia — ActiveRecord Callbacks
  • Ruby Bindings and Scope
  • What’s #method_missing missing?

Search

Browse by Category

  • administrivia (2)
  • configuration (1)
  • metaprogramming (1)
  • mini-saga (5)
  • programming (10)
  • rails (1)
  • ruby (15)
  • rubygems (2)
  • Uncategorized (1)

Browse by Tag

  • ActiveRecord
  • binding
  • Command-line interface
  • gotcha
  • irb
  • irbc
  • Languages
  • Library
  • Local variable
  • metaprogramming
  • mini-saga
  • paradigm
  • philosophy
  • programming
  • rails
  • Recursion
  • ruby
  • rubygems
  • Ruby on Rails
  • scope
  • utilities

Browse by Month

  • September 2009 (1)
  • August 2009 (4)
  • April 2009 (1)
  • February 2009 (11)
 
 
  • Blog
  • About
  • Archives
  • Log in
 


Theme Design by Jay Kwong | Powered by WordPress and K2

 

Home Top Archives Entries FeedComments Feed