Automatically Initializing Instance Variables

Problem

You're writing a class constructor that takes a lot of arguments, each of which is simply assigned to an instance variable.

	class RGBColor(red=0, green=0, blue=0)
	 @red = red
	 @green = green
	 @blue = blue
	end

You'd like to avoid all the typing necessary to do those variable assignments.

Solution

Here's a method that initializes the instance variables for you. It takes as an argument the list of variables passed into the initialize method, and the binding of the variables to values.

	class Object
	 private
	 def set_instance_variables(binding, *variables)
	 variables.each do |var|
	 instance_variable_set("@#{var}", eval(var, binding))
	 end
	 end
	end

Using this method, you can eliminate the tedious variable assignments:

	class RGBColor
	 def initialize(red=0, green=0, blue=0)
	 set_instance_variables(binding, *local_variables)
	 end
	end

	RGBColor.new(10, 200, 300)
	# => #

 

Discussion

Our set_ instance_variables takes a list of argument names to turn into instance variables, and a Binding containing the values of those arguments as of the method call. For each argument name, an eval statement binds the corresponding instance variable to the corresponding value in the Binding. Since you control the names of your own variables, this eval is about as safe as it gets.

The names of a method's arguments aren't accessible from Ruby code, so how do we get that list? Through trickery. When a method is called, any arguments passed in are immediately bound to local variables. At the very beginning of the method, these are the only local variables defined. This means that calling Kernel#local_variables at the beginning of a method will get a list of all the argument names.

If your method accepts arguments that you don't want to set as instance variables, simply remove their names from the result of Kernel#local_variables before passing the list into set_instance_variables:

	class RGBColor
	 def initialize(red=0, green=0, blue=0, debug=false)
	 set_instance_variables(binding, *local_variables-['debug'])
	 puts "Color: #{red}/#{green}/#{blue}" if debug
	 end
	end

	RGBColor.new(10, 200, 255, true)
	# Color: 10/200/255
	# => #


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net