Skip to content

Instantly share code, notes, and snippets.

@mrrooijen
Created June 18, 2010 15:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrrooijen/443747 to your computer and use it in GitHub Desktop.
Save mrrooijen/443747 to your computer and use it in GitHub Desktop.
A simple Ruby module that, when extended inside a class, will provide a method that will enable the creation of methods that could be used to create nice block-notation setters.
##
# AttrAccessorBlock
#
# This module is to be "extended" (not included) into a class
# Then just invoke the "attr_accessor_block" method, like you would with "attr_accessor"
# This will enable you to make use of "block notations" and "instance_eval" to create "prettier"
# and more "readable" attribute setters.
#
# class Example
# extend AttrAccessorBlock
# attr_accessor_block :example1, :example2, :example3, :etc
# end
#
module AttrAccessorBlock
def attr_accessor_block(*attributes)
attributes.each do |method|
define_method method do |*value|
if value = value.first
instance_variable_set("@#{method}", value)
else
instance_variable_get("@#{method}")
end
end
define_method "#{method}=" do |value|
instance_variable_set("@#{method}", value)
end
end
end
end
##
# Example Person Class
# Extend the class with AttrAccessorBlock (ClassMethods)
# Use the attr_accessor_block instead of the built-in attr_accessor
#
# attr_accessor_block creates 2 methods, like attr_accessor
# except that the "attribute()" method that's produced will act a bit different
# from the one you get with attr_accessor, the main difference being:
# - If no value is set, e.g. "person.name()", then the @name is returned
# - If a value is set, e.g. "person.name('Michael')", then the @name is set to 'Michael'
# This is to allow for prettier block configurations. Other than that, it practically works the same
# as attr_accessor, you can still also use person.name = 'Michael'
class Person
##
# Extend the "AttrAccessorBlock" module
extend AttrAccessorBlock
##
# Define some methods to dynamically generate like you would with "attr_accessor"
attr_accessor_block :name, :age, :gender
##
# For Example 1
def update_example_1
yield self
end
##
# For Example 2 and 3
def update_example_2_and_3(&block)
instance_eval &block
end
end
##
# Example 1 with "object.attribute = value"
person = Person.new
person.update_example_1 do |object|
object.name = 'Michael'
object.age = 21
object.gender = 'Male'
end
puts person.name, person.age, person.gender
##
# Example 2 with "object.attribute value"
person = Person.new
person.update_example_2_and_3 do |object|
object.name 'Michael'
object.age 21
object.gender 'Male'
end
puts person.name, person.age, person.gender
##
# Example 3 with "attribute value"
person = Person.new
person.update_example_2_and_3 do
name 'Michael'
age 21
gender 'Male'
end
puts person.name, person.age, person.gender
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment