Last active
September 4, 2022 16:40
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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