Skip to content

Instantly share code, notes, and snippets.

@0cjs
Last active September 4, 2022 16:40
Show Gist options
  • Save 0cjs/a54fc5cd65ae49ca0ecfe004f007988a to your computer and use it in GitHub Desktop.
Save 0cjs/a54fc5cd65ae49ca0ecfe004f007988a to your computer and use it in GitHub Desktop.
Replace boilerplate Ruby `def initialize` followed by instance variable settings with `initialize_vars` specifying variables once
# XXX This worked in 2009 with Ruby 1.8; I've not tested on anything
# more recent. But you get the general idea.
class Class
def initialize_vars(*vars, &initialize_block)
vars.each { |arg| attr_reader arg.to_sym }
varsyms = vars.collect { |arg| ('@' + arg.to_s).to_sym }
define_method(:initialize) { |*init_args|
raise(ArgumentError, "wrong number of arguments " +
"(#{init_args.length} for #{vars.length})") unless
vars.length == init_args.length
vars.zip(init_args).each { |var, arg|
instance_variable_set(('@' + var.to_s).to_sym, arg)
}
self.instance_eval(&initialize_block) if initialize_block
}
end
end
class TC_RubyExtensions < Test::Unit::TestCase
class TestInitializeVarsSimple
initialize_vars :a
end
def test_initialize_vars_simple
obj = TestInitializeVarsSimple.new('abc')
assert_equal('abc', obj.a)
assert_raise(NoMethodError) { obj.a = 'def' }
end
class TestInitializeVarsWithInitBlock
initialize_vars(:foo, :bar) do
@baz = bar * 3
end
attr_writer :bar
attr_reader :baz
end
def test_initialize_vars_with_init_block
obj = TestInitializeVarsWithInitBlock.new(1, 2)
assert_equal(1, obj.foo)
assert_equal(2, obj.bar)
assert_equal(6, obj.baz)
assert_raise(NoMethodError) { obj.foo = 1 }
obj.bar = 3; assert_equal(3, obj.bar)
end
def test_initialize_vars_wrong_number_of_args
klass = TestInitializeVarsWithInitBlock
e = assert_raise(ArgumentError) { klass.new }
assert_equal('wrong number of arguments (0 for 2)', e.message)
e = assert_raise(ArgumentError) { klass.new(1) }
assert_equal('wrong number of arguments (1 for 2)', e.message)
e = assert_raise(ArgumentError) { klass.new(1, 2, 3) }
assert_equal('wrong number of arguments (3 for 2)', e.message)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment