require "spec_helper" describe Object, ".attr_initialize" do let(:klass) do Class.new do attr_initialize :foo, :bar def self.name "ExampleClass" end end end it "creates an initializer setting those instance variables" do example = klass.new("Foo", "Bar") _(example.instance_variable_get("@foo")).must_equal "Foo" _(example.instance_variable_get("@bar")).must_equal "Bar" end it "requires all arguments" do exception = _(lambda { klass.new("Foo") }).must_raise ArgumentError _(exception.message).must_equal "wrong number of arguments (1 for 2) for ExampleClass initializer" end it "can set ivars from a hash" do klass = Class.new do attr_initialize :foo, [ :bar, :baz ] end example = klass.new("Foo", bar: "Bar", baz: "Baz") _(example.instance_variable_get("@foo")).must_equal "Foo" _(example.instance_variable_get("@bar")).must_equal "Bar" _(example.instance_variable_get("@baz")).must_equal "Baz" end it "can set default values for keyword arguments" do klass = Class.new do attr_initialize :foo, [ :bar, baz: "default baz" ] end example = klass.new("Foo", bar: "Bar") _(example.instance_variable_get("@foo")).must_equal "Foo" _(example.instance_variable_get("@bar")).must_equal "Bar" _(example.instance_variable_get("@baz")).must_equal "default baz" example = klass.new("Foo", bar: "Bar", baz: "Baz") _(example.instance_variable_get("@baz")).must_equal "Baz" end it "treats hash values as optional" do klass = Class.new do attr_initialize :foo, [ :bar, :baz ] end example = klass.new("Foo", bar: "Bar") _(example.instance_variable_defined?("@baz")).must_equal false example = klass.new("Foo") _(example.instance_variable_defined?("@bar")).must_equal false end it "can require hash values" do klass = Class.new do attr_initialize [ :optional, :required! ] end example = klass.new(required: "X") _(example.instance_variable_get("@required")).must_equal "X" _(lambda { klass.new(optional: "X") }).must_raise KeyError end it "complains about unknown hash values" do klass = Class.new do attr_initialize :foo, [ :bar, :baz! ] end # Should not raise. klass.new("Foo", bar: "Bar", baz: "Baz") exception = _(lambda { klass.new("Foo", bar: "Bar", baz: "Baz", hello: "Hello") }).must_raise ArgumentError _(exception.message).must_include "[:hello]" end # Regression. it "assigns hash values to positional arguments even when there's also hash arguments" do klass = Class.new do attr_initialize :foo, [ :bar ] end # Should not raise. klass.new({ inside_foo: 123 }, bar: 456) end # Regression. it "only looks at hash arguments when determining missing required keys" do klass = Class.new do attr_initialize :foo, [ :bar! ] end # Provides a hash to "foo" but does not provide "bar". exception = _(lambda { klass.new({ bar: 123 }) }).must_raise KeyError _(exception.message).must_include "[:bar]" end # Regression. it "doesn't store hash values to positional arguments as ivars" do klass = Class.new do attr_initialize :foo attr_reader :foo end # Should not raise. example = klass.new({ "invalid.ivar.name" => 123 }) _(example.foo).must_equal({ "invalid.ivar.name" => 123 }) end it "accepts a block for initialization" do klass = Class.new do attr_initialize :value do @copy = @value end attr_reader :copy end example = klass.new("expected") _(example.copy).must_equal "expected" end end