attr_extras 6.1.0 → 6.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d927809a2d8cd1a5da0e4e910942027d230dfb45
4
- data.tar.gz: 80988c71e715df538d82b902846ca660e5f5a4fb
2
+ SHA256:
3
+ metadata.gz: e4f8e12f94bbc166632e1a65a52f83ddc14e4982ad57f87043fa285e7e7a8cf2
4
+ data.tar.gz: 1d621e46616f5df763909d9481f983d60fe4e014a8a9a3b0dbfc2635d8867d71
5
5
  SHA512:
6
- metadata.gz: 8d9bd920c1a3227cd592dab70c0035124322bc0a358ed535b8aa5e42c6a8fb26bdcde0c85c8ef92a81131179e0b9fafbb928ccff2ab454164bc549cec36bd745
7
- data.tar.gz: 96ff27fb9e371d898f3056159a644cb3828ad2e10bc3c83273fb38ab8441661e78f46bf4f2960b59f0af09affaa39cb8033f5a75b64efbc74476705268a73735
6
+ metadata.gz: 44cade5ed299c18a1e8c01706e04767f1b49f3a934a53759542702fd6435c8ba225b360250dd276a78174fdea32e112ca1155cf20e172db765940ea05ecb3b03
7
+ data.tar.gz: 7fe165a6de71503666cb3344478c769385d50a31ca11de78cce7f934d87393867a5e2c3bc05703c7a3fdc86dd81da729703452c35d0999600f70b42a35851629
@@ -1,10 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.6.1
4
- - 2.5.3
5
- - 2.4.1
6
- - 2.3.3
3
+ - 2.7.1
4
+ - 2.6.6
5
+ - 2.5.8
7
6
  - jruby-head
8
- before_install: # For jruby-head to work.
9
- - gem install bundler
10
- - gem update bundler
@@ -1,13 +1,34 @@
1
1
  # Changelog
2
2
 
3
- # 6.1.0
3
+ ## [6.2.4](https://github.com/barsoom/attr_extras/releases/tag/v6.2.4)
4
+
5
+ - Fix keyword argument warnings with Ruby 2.7. Thanks to [Elliot Winkler](https://github.com/barsoom/attr_extras/pull/34)!
6
+
7
+ ## [6.2.3](https://github.com/barsoom/attr_extras/releases/tag/v6.2.3)
8
+
9
+ - `attr_implement` error says "an 'ear()' method" instead of "a 'ear()' method", when the method starts with a likely vowel.
10
+
11
+ ## [6.2.2](https://github.com/barsoom/attr_extras/releases/tag/v6.2.2)
12
+
13
+ - Fix warnings with Ruby 2.7. Thanks to [Juanito Fatas](https://github.com/barsoom/attr_extras/pull/31)!
14
+ - Fix deprecation warnings for Minitest 6. Thanks again to [Juanito Fatas](https://github.com/barsoom/attr_extras/pull/30)!
15
+
16
+ ## [6.2.1](https://github.com/barsoom/attr_extras/releases/tag/v6.2.1)
17
+
18
+ * Bugfix with keyword argument defaults. Thanks to [Roman Dubrovsky](https://github.com/barsoom/attr_extras/pull/29)!
19
+
20
+ ## [6.2.0](https://github.com/barsoom/attr_extras/releases/tag/v6.2.0)
21
+
22
+ * Another bugfix when passing hash values to positional arguments.
23
+
24
+ ## [6.1.0](https://github.com/barsoom/attr_extras/releases/tag/v6.1.0)
4
25
 
5
26
  * Bugfix when passing hash values to positional arguments.
6
27
 
7
- # 6.0.0 (yanked)
28
+ ## 6.0.0 (yanked)
8
29
 
9
30
  * Default arguments! Thanks to [Ola K](https://github.com/lesin). For example: `pattr_initialize [:foo, bar: "default value"]`
10
31
 
11
- # 5.2.0 and earlier
32
+ ## [5.2.0](https://github.com/barsoom/attr_extras/releases/tag/v5.2.0) and earlier
12
33
 
13
34
  Please [see Git history](https://github.com/barsoom/attr_extras/releases).
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+ [![Gem Version](https://badge.fury.io/rb/attr_extras.svg)](https://badge.fury.io/rb/attr_extras)
1
2
  [![Build status](https://secure.travis-ci.org/barsoom/attr_extras.svg)](https://travis-ci.org/#!/barsoom/attr_extras/builds)
2
3
  [![Code Climate](https://codeclimate.com/github/barsoom/attr_extras/badges/gpa.svg)](https://codeclimate.com/github/barsoom/attr_extras)
3
4
 
@@ -59,14 +60,35 @@ Also provides conveniences for creating value objects, method objects, query met
59
60
 
60
61
  `attr_initialize [:bar, :baz!]` defines an initializer that takes two keyword arguments, assigning `@bar` (optional) and `@baz` (required).
61
62
 
62
- Keyword arguments can have default values:
63
- `attr_initialize [:bar, baz: "default value"]` defines an initializer that takes two keyword arguments, assigning `@bar` (optional) and `@baz` (optional with default value `"default value"`).
64
-
65
63
  If you pass unknown keyword arguments, you will get an `ArgumentError`.
66
64
  If you don't pass required arguments and don't define default value for them, you will get a `KeyError`.
67
65
 
68
66
  `attr_initialize` can also accept a block which will be invoked after initialization. This is useful for e.g. initializing private data as necessary.
69
67
 
68
+ #### Default values
69
+
70
+ Keyword arguments can have default values:
71
+
72
+ `attr_initialize [:bar, baz: "default value"]` defines an initializer that takes two keyword arguments, assigning `@bar` (optional) and `@baz` (optional with default value `"default value"`).
73
+
74
+ Note that default values are evaluated *when the class is loaded* and not on every instantition. So `attr_initialize [time: Time.now]` might not do what you expect.
75
+
76
+ You can always use regular Ruby methods to achieve this:
77
+
78
+ ```
79
+ class Foo
80
+ attr_initialize [:time]
81
+
82
+ private
83
+
84
+ def time
85
+ @time || Time.now
86
+ end
87
+ end
88
+ ```
89
+
90
+ Or just use a regular initializer with default values.
91
+
70
92
 
71
93
  ### `attr_private`
72
94
 
@@ -1,8 +1,8 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/attr_extras/version', __FILE__)
2
+ require File.expand_path("../lib/attr_extras/version", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
- gem.authors = ["Henrik Nyh", "Joakim Kolsjö", "Victor Arias", "Ola K"]
5
+ gem.authors = ["Henrik Nyh", "Joakim Kolsjö", "Tomas Skogberg", "Victor Arias", "Ola K"]
6
6
  gem.email = ["henrik@nyh.se"]
7
7
  gem.summary = %q{Takes some boilerplate out of Ruby with methods like attr_initialize.}
8
8
  gem.homepage = "https://github.com/barsoom/attr_extras"
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.version = AttrExtras::VERSION
17
17
 
18
18
  gem.add_development_dependency "minitest", ">= 5"
19
- gem.add_development_dependency "m", "~> 1.5.0" # Running individual tests.
19
+ gem.add_development_dependency "m", "~> 1.5.1" # Running individual tests.
20
20
 
21
21
  # For Travis CI.
22
22
  gem.add_development_dependency "rake"
@@ -19,7 +19,7 @@ class AttrExtras::AttrImplement
19
19
  raise ArgumentError, "wrong number of arguments (#{provided_arity} for #{expected_arity})"
20
20
  end
21
21
 
22
- raise AttrExtras::MethodNotImplementedError, "Implement a '#{name}(#{arg_names.join(", ")})' method"
22
+ raise AttrExtras::MethodNotImplementedError, "Implement a#{"n" if name[0].match?(/\A[aeiou]/i)} '#{name}(#{arg_names.join(", ")})' method"
23
23
  else
24
24
  super(name, *args)
25
25
  end
@@ -19,7 +19,7 @@ class AttrExtras::AttrInitialize
19
19
  validate_args = method(:validate_args)
20
20
 
21
21
  klass.send(:define_method, :initialize) do |*values|
22
- hash_values = values.select { |name| name.is_a?(Hash) }.inject(:merge) || {}
22
+ hash_values = (values[(klass_params.positional_args.length)..-1] || []).inject(:merge) || {}
23
23
 
24
24
  validate_arity.call(values.length, self.class)
25
25
  validate_args.call(values, klass_params)
@@ -21,9 +21,8 @@ module AttrExtras
21
21
  end
22
22
 
23
23
  def attr_private(*names)
24
- # Need this to avoid "private attribute?" warnings when running
25
- # the full test suite; not sure why exactly.
26
- public
24
+ # Avoid warnings: https://github.com/barsoom/attr_extras/pull/31
25
+ return unless names && names.any?
27
26
 
28
27
  attr_reader(*names)
29
28
  private(*names)
@@ -62,9 +61,17 @@ module AttrExtras
62
61
  alias_method :attr_accessor_initialize, :aattr_initialize
63
62
 
64
63
  def static_facade(method_name_or_names, *names)
65
- Array(method_name_or_names).each do |method_name|
66
- define_singleton_method(method_name) do |*values, &block|
67
- new(*values).public_send(method_name, &block)
64
+ if names.any? { |name| name.is_a?(Array) }
65
+ Array(method_name_or_names).each do |method_name|
66
+ define_singleton_method(method_name) do |*args, **opts, &block|
67
+ new(*args, **opts).public_send(method_name, &block)
68
+ end
69
+ end
70
+ else
71
+ Array(method_name_or_names).each do |method_name|
72
+ define_singleton_method(method_name) do |*args, &block|
73
+ new(*args).public_send(method_name, &block)
74
+ end
68
75
  end
69
76
  end
70
77
 
@@ -1,5 +1,7 @@
1
1
  module AttrExtras::Utils
2
2
  def self.flat_names(names)
3
- names.flatten.map { |x| x.to_s.sub(/!\z/, "") }
3
+ names.flatten.
4
+ flat_map { |x| x.is_a?(Hash) ? x.keys : x }.
5
+ map { |x| x.to_s.sub(/!\z/, "") }
4
6
  end
5
7
  end
@@ -1,3 +1,3 @@
1
1
  module AttrExtras
2
- VERSION = "6.1.0"
2
+ VERSION = "6.2.4"
3
3
  end
@@ -8,7 +8,7 @@ describe Object, ".aattr_initialize" do
8
8
 
9
9
  example = klass.new("Foo", "Bar")
10
10
 
11
- example.foo.must_equal "Foo"
11
+ _(example.foo).must_equal "Foo"
12
12
  end
13
13
 
14
14
  it "creates public writers" do
@@ -19,17 +19,27 @@ describe Object, ".aattr_initialize" do
19
19
  example = klass.new("Foo", "Bar")
20
20
  example.foo = "Baz"
21
21
 
22
- example.foo.must_equal "Baz"
22
+ _(example.foo).must_equal "Baz"
23
23
  end
24
24
 
25
25
  it "works with hash ivars" do
26
26
  klass = Class.new do
27
- aattr_initialize :foo, [:bar, :baz!]
27
+ aattr_initialize :foo, [ :bar, :baz! ]
28
28
  end
29
29
 
30
30
  example = klass.new("Foo", bar: "Bar", baz: "Baz")
31
31
 
32
- example.baz.must_equal "Baz"
32
+ _(example.baz).must_equal "Baz"
33
+ end
34
+
35
+ it "works with hash ivars and default values" do
36
+ klass = Class.new do
37
+ aattr_initialize :foo, [ bar: "Bar", baz!: "Baz" ]
38
+ end
39
+
40
+ example = klass.new("Foo")
41
+
42
+ _(example.baz).must_equal "Baz"
33
43
  end
34
44
 
35
45
  it "accepts a block for initialization" do
@@ -43,7 +53,7 @@ describe Object, ".aattr_initialize" do
43
53
 
44
54
  example = klass.new("expected")
45
55
 
46
- example.copy.must_equal "expected"
56
+ _(example.copy).must_equal "expected"
47
57
  end
48
58
 
49
59
  it "accepts the alias attr_accessor_initialize" do
@@ -53,6 +63,6 @@ describe Object, ".aattr_initialize" do
53
63
 
54
64
  example = klass.new("Foo", "Bar")
55
65
 
56
- example.foo.must_equal "Foo"
66
+ _(example.foo).must_equal "Foo"
57
67
  end
58
68
  end
@@ -15,6 +15,6 @@ describe Object, ".attr_id_query" do
15
15
  end
16
16
 
17
17
  it "requires a trailing questionmark" do
18
- lambda { Object.attr_id_query(:foo) }.must_raise ArgumentError
18
+ _(lambda { Object.attr_id_query(:foo) }).must_raise ArgumentError
19
19
  end
20
20
  end
@@ -7,8 +7,8 @@ describe Object, ".attr_implement" do
7
7
  end
8
8
 
9
9
  example = klass.new
10
- exception = lambda { example.foo }.must_raise AttrExtras::MethodNotImplementedError
11
- exception.message.must_equal "Implement a 'foo()' method"
10
+ exception = _(lambda { example.foo }).must_raise AttrExtras::MethodNotImplementedError
11
+ _(exception.message).must_equal "Implement a 'foo()' method"
12
12
  end
13
13
 
14
14
  it "allows specifying arity and argument names" do
@@ -18,10 +18,10 @@ describe Object, ".attr_implement" do
18
18
 
19
19
  example = klass.new
20
20
 
21
- exception = lambda { example.foo(1, 2) }.must_raise AttrExtras::MethodNotImplementedError
22
- exception.message.must_equal "Implement a 'foo(name, age)' method"
21
+ exception = _(lambda { example.foo(1, 2) }).must_raise AttrExtras::MethodNotImplementedError
22
+ _(exception.message).must_equal "Implement a 'foo(name, age)' method"
23
23
 
24
- lambda { example.foo }.must_raise ArgumentError
24
+ _(lambda { example.foo }).must_raise ArgumentError
25
25
  end
26
26
 
27
27
  it "does not raise if method is implemented in a subclass" do
@@ -35,7 +35,7 @@ describe Object, ".attr_implement" do
35
35
  end
36
36
  end
37
37
 
38
- subklass.new.foo.must_equal "bar"
38
+ _(subklass.new.foo).must_equal "bar"
39
39
  end
40
40
 
41
41
  # E.g. when Active Record defines column query methods like "admin?"
@@ -55,7 +55,7 @@ describe Object, ".attr_implement" do
55
55
  include foo_interface
56
56
  end
57
57
 
58
- klass.new.foo.must_equal "bar"
58
+ _(klass.new.foo).must_equal "bar"
59
59
  end
60
60
 
61
61
  it "does not mess up missing-method handling" do
@@ -63,7 +63,17 @@ describe Object, ".attr_implement" do
63
63
  attr_implement :foo
64
64
  end
65
65
 
66
- lambda { klass.new.some_other_method }.must_raise NoMethodError
66
+ _(lambda { klass.new.some_other_method }).must_raise NoMethodError
67
+ end
68
+
69
+ it "says 'an' if followed by a vowel" do
70
+ klass = Class.new do
71
+ attr_implement :ear
72
+ end
73
+
74
+ example = klass.new
75
+ exception = _(lambda { example.ear }).must_raise AttrExtras::MethodNotImplementedError
76
+ _(exception.message).must_equal "Implement an 'ear()' method"
67
77
  end
68
78
  end
69
79
 
@@ -73,9 +83,9 @@ describe Object, ".cattr_implement" do
73
83
  cattr_implement :foo, [:name, :age]
74
84
  end
75
85
 
76
- exception = lambda { klass.foo(1, 2) }.must_raise AttrExtras::MethodNotImplementedError
77
- exception.message.must_equal "Implement a 'foo(name, age)' method"
86
+ exception = _(lambda { klass.foo(1, 2) }).must_raise AttrExtras::MethodNotImplementedError
87
+ _(exception.message).must_equal "Implement a 'foo(name, age)' method"
78
88
 
79
- lambda { klass.foo }.must_raise ArgumentError
89
+ _(lambda { klass.foo }).must_raise ArgumentError
80
90
  end
81
91
  end
@@ -13,13 +13,13 @@ describe Object, ".attr_initialize" do
13
13
 
14
14
  it "creates an initializer setting those instance variables" do
15
15
  example = klass.new("Foo", "Bar")
16
- example.instance_variable_get("@foo").must_equal "Foo"
17
- example.instance_variable_get("@bar").must_equal "Bar"
16
+ _(example.instance_variable_get("@foo")).must_equal "Foo"
17
+ _(example.instance_variable_get("@bar")).must_equal "Bar"
18
18
  end
19
19
 
20
20
  it "requires all arguments" do
21
- exception = lambda { klass.new("Foo") }.must_raise ArgumentError
22
- exception.message.must_equal "wrong number of arguments (1 for 2) for ExampleClass initializer"
21
+ exception = _(lambda { klass.new("Foo") }).must_raise ArgumentError
22
+ _(exception.message).must_equal "wrong number of arguments (1 for 2) for ExampleClass initializer"
23
23
  end
24
24
 
25
25
  it "can set ivars from a hash" do
@@ -28,9 +28,9 @@ describe Object, ".attr_initialize" do
28
28
  end
29
29
 
30
30
  example = klass.new("Foo", bar: "Bar", baz: "Baz")
31
- example.instance_variable_get("@foo").must_equal "Foo"
32
- example.instance_variable_get("@bar").must_equal "Bar"
33
- example.instance_variable_get("@baz").must_equal "Baz"
31
+ _(example.instance_variable_get("@foo")).must_equal "Foo"
32
+ _(example.instance_variable_get("@bar")).must_equal "Bar"
33
+ _(example.instance_variable_get("@baz")).must_equal "Baz"
34
34
  end
35
35
 
36
36
  it "can set default values for keyword arguments" do
@@ -39,12 +39,12 @@ describe Object, ".attr_initialize" do
39
39
  end
40
40
 
41
41
  example = klass.new("Foo", bar: "Bar")
42
- example.instance_variable_get("@foo").must_equal "Foo"
43
- example.instance_variable_get("@bar").must_equal "Bar"
44
- example.instance_variable_get("@baz").must_equal "default baz"
42
+ _(example.instance_variable_get("@foo")).must_equal "Foo"
43
+ _(example.instance_variable_get("@bar")).must_equal "Bar"
44
+ _(example.instance_variable_get("@baz")).must_equal "default baz"
45
45
 
46
46
  example = klass.new("Foo", bar: "Bar", baz: "Baz")
47
- example.instance_variable_get("@baz").must_equal "Baz"
47
+ _(example.instance_variable_get("@baz")).must_equal "Baz"
48
48
  end
49
49
 
50
50
  it "treats hash values as optional" do
@@ -53,10 +53,10 @@ describe Object, ".attr_initialize" do
53
53
  end
54
54
 
55
55
  example = klass.new("Foo", bar: "Bar")
56
- example.instance_variable_defined?("@baz").must_equal false
56
+ _(example.instance_variable_defined?("@baz")).must_equal false
57
57
 
58
58
  example = klass.new("Foo")
59
- example.instance_variable_defined?("@bar").must_equal false
59
+ _(example.instance_variable_defined?("@bar")).must_equal false
60
60
  end
61
61
 
62
62
  it "can require hash values" do
@@ -65,9 +65,9 @@ describe Object, ".attr_initialize" do
65
65
  end
66
66
 
67
67
  example = klass.new(required: "X")
68
- example.instance_variable_get("@required").must_equal "X"
68
+ _(example.instance_variable_get("@required")).must_equal "X"
69
69
 
70
- lambda { klass.new(optional: "X") }.must_raise KeyError
70
+ _(lambda { klass.new(optional: "X") }).must_raise KeyError
71
71
  end
72
72
 
73
73
  it "complains about unknown hash values" do
@@ -78,8 +78,8 @@ describe Object, ".attr_initialize" do
78
78
  # Should not raise.
79
79
  klass.new("Foo", bar: "Bar", baz: "Baz")
80
80
 
81
- exception = lambda { klass.new("Foo", bar: "Bar", baz: "Baz", hello: "Hello") }.must_raise ArgumentError
82
- exception.message.must_include "[:hello]"
81
+ exception = _(lambda { klass.new("Foo", bar: "Bar", baz: "Baz", hello: "Hello") }).must_raise ArgumentError
82
+ _(exception.message).must_include "[:hello]"
83
83
  end
84
84
 
85
85
  # Regression.
@@ -99,8 +99,21 @@ describe Object, ".attr_initialize" do
99
99
  end
100
100
 
101
101
  # Provides a hash to "foo" but does not provide "bar".
102
- exception = lambda { klass.new({ bar: 123 }) }.must_raise KeyError
103
- exception.message.must_include "[:bar]"
102
+ exception = _(lambda { klass.new({ bar: 123 }) }).must_raise KeyError
103
+ _(exception.message).must_include "[:bar]"
104
+ end
105
+
106
+ # Regression.
107
+ it "doesn't store hash values to positional arguments as ivars" do
108
+ klass = Class.new do
109
+ attr_initialize :foo
110
+ attr_reader :foo
111
+ end
112
+
113
+ # Should not raise.
114
+ example = klass.new({ "invalid.ivar.name" => 123 })
115
+
116
+ _(example.foo).must_equal({ "invalid.ivar.name" => 123 })
104
117
  end
105
118
 
106
119
  it "accepts a block for initialization" do
@@ -114,6 +127,6 @@ describe Object, ".attr_initialize" do
114
127
 
115
128
  example = klass.new("expected")
116
129
 
117
- example.copy.must_equal "expected"
130
+ _(example.copy).must_equal "expected"
118
131
  end
119
132
  end
@@ -11,8 +11,8 @@ describe Object, ".attr_private" do
11
11
  example = klass.new
12
12
  example.instance_variable_set("@foo", "Foo")
13
13
  example.instance_variable_set("@bar", "Bar")
14
- example.send(:foo).must_equal "Foo"
15
- example.send(:bar).must_equal "Bar"
16
- lambda { example.foo }.must_raise NoMethodError
14
+ _(example.send(:foo)).must_equal "Foo"
15
+ _(example.send(:bar)).must_equal "Bar"
16
+ _(lambda { example.foo }).must_raise NoMethodError
17
17
  end
18
18
  end
@@ -14,6 +14,6 @@ describe Object, ".attr_query" do
14
14
  end
15
15
 
16
16
  it "requires a trailing questionmark" do
17
- lambda { Object.attr_query(:foo) }.must_raise ArgumentError
17
+ _(lambda { Object.attr_query(:foo) }).must_raise ArgumentError
18
18
  end
19
19
  end
@@ -9,7 +9,7 @@ describe Object, ".attr_value" do
9
9
 
10
10
  example = klass.new
11
11
  example.instance_variable_set("@foo", "Foo")
12
- example.foo.must_equal "Foo"
12
+ _(example.foo).must_equal "Foo"
13
13
  end
14
14
 
15
15
  it "does not create writers" do
@@ -17,7 +17,7 @@ describe Object, ".attr_value" do
17
17
  attr_value :foo
18
18
  end
19
19
 
20
- lambda { klass.new.foo = "new value" }.must_raise NoMethodError
20
+ _(lambda { klass.new.foo = "new value" }).must_raise NoMethodError
21
21
  end
22
22
 
23
23
  describe "object equality" do
@@ -92,21 +92,21 @@ describe Object, ".attr_value" do
92
92
  klass1_bar = klass1.new("Bar")
93
93
  klass2_foo = klass2.new("Foo")
94
94
 
95
- klass1_foo.hash.must_equal klass1_foo2.hash
96
- klass1_foo.hash.wont_equal klass1_bar.hash
97
- klass1_foo.hash.wont_equal klass2_foo.hash
95
+ _(klass1_foo.hash).must_equal klass1_foo2.hash
96
+ _(klass1_foo.hash).wont_equal klass1_bar.hash
97
+ _(klass1_foo.hash).wont_equal klass2_foo.hash
98
98
 
99
99
  assert klass1_foo.eql?(klass1_foo2), "Examples should be 'eql?'"
100
100
  refute klass1_foo.eql?(klass1_bar), "Examples should not be 'eql?'"
101
101
  refute klass1_foo.eql?(klass2_foo), "Examples should not be 'eql?'"
102
102
 
103
- Set[klass1_foo, klass1_foo2, klass1_bar, klass2_foo].length.must_equal 3
103
+ _(Set[klass1_foo, klass1_foo2, klass1_bar, klass2_foo].length).must_equal 3
104
104
 
105
105
  hash = {}
106
106
  hash[klass1_foo] = :awyeah
107
107
  hash[klass1_bar] = :wat
108
108
  hash[klass2_foo] = :nooooo
109
- hash[klass1_foo2].must_equal :awyeah
109
+ _(hash[klass1_foo2]).must_equal :awyeah
110
110
  end
111
111
  end
112
112
  end
@@ -7,11 +7,11 @@ describe AttrExtras::AttrInitialize::ParamsBuilder do
7
7
  let(:names) { [ :foo, :bar, [ :baz, :qux!, quux: "Quux" ]] }
8
8
 
9
9
  it "properly devides params by the type" do
10
- subject.positional_args.must_equal [ :foo, :bar ]
11
- subject.hash_args.must_equal [ :baz, :qux!, :quux ]
12
- subject.hash_args_names.must_equal [ :baz, :qux, :quux ]
13
- subject.hash_args_required.must_equal [ :qux ]
14
- subject.default_values.must_equal({ quux: "Quux" })
10
+ _(subject.positional_args).must_equal [ :foo, :bar ]
11
+ _(subject.hash_args).must_equal [ :baz, :qux!, :quux ]
12
+ _(subject.hash_args_names).must_equal [ :baz, :qux, :quux ]
13
+ _(subject.hash_args_required).must_equal [ :qux ]
14
+ _(subject.default_values).must_equal({ quux: "Quux" })
15
15
  end
16
16
  end
17
17
 
@@ -19,11 +19,11 @@ describe AttrExtras::AttrInitialize::ParamsBuilder do
19
19
  let(:names) { [ :foo, :bar] }
20
20
 
21
21
  it "properly devides params by the type" do
22
- subject.positional_args.must_equal [ :foo, :bar ]
23
- subject.hash_args.must_be_empty
24
- subject.hash_args_names.must_be_empty
25
- subject.hash_args_required.must_be_empty
26
- subject.default_values.must_be_empty
22
+ _(subject.positional_args).must_equal [ :foo, :bar ]
23
+ _(subject.hash_args).must_be_empty
24
+ _(subject.hash_args_names).must_be_empty
25
+ _(subject.hash_args_required).must_be_empty
26
+ _(subject.default_values).must_be_empty
27
27
  end
28
28
  end
29
29
 
@@ -31,11 +31,11 @@ describe AttrExtras::AttrInitialize::ParamsBuilder do
31
31
  let(:names) { [[ { baz: "Baz" }, :qux!, { quux: "Quux" } ]] }
32
32
 
33
33
  it "properly devides params by the type" do
34
- subject.positional_args.must_be_empty
35
- subject.hash_args.must_equal [ :baz, :qux!, :quux ]
36
- subject.hash_args_names.must_equal [ :baz, :qux, :quux ]
37
- subject.hash_args_required.must_equal [ :qux ]
38
- subject.default_values.must_equal({ quux: "Quux", baz: "Baz" })
34
+ _(subject.positional_args).must_be_empty
35
+ _(subject.hash_args).must_equal [ :baz, :qux!, :quux ]
36
+ _(subject.hash_args_names).must_equal [ :baz, :qux, :quux ]
37
+ _(subject.hash_args_required).must_equal [ :qux ]
38
+ _(subject.default_values).must_equal({ quux: "Quux", baz: "Baz" })
39
39
  end
40
40
  end
41
41
 
@@ -43,11 +43,11 @@ describe AttrExtras::AttrInitialize::ParamsBuilder do
43
43
  let(:names) { [] }
44
44
 
45
45
  it "properly devides params by the type" do
46
- subject.positional_args.must_be_empty
47
- subject.hash_args.must_be_empty
48
- subject.hash_args_names.must_be_empty
49
- subject.hash_args_required.must_be_empty
50
- subject.default_values.must_be_empty
46
+ _(subject.positional_args).must_be_empty
47
+ _(subject.hash_args).must_be_empty
48
+ _(subject.hash_args_names).must_be_empty
49
+ _(subject.hash_args_required).must_be_empty
50
+ _(subject.default_values).must_be_empty
51
51
  end
52
52
  end
53
53
  end
@@ -7,7 +7,7 @@ describe Object, ".pattr_initialize" do
7
7
  end
8
8
 
9
9
  example = klass.new("Foo", "Bar")
10
- example.send(:foo).must_equal "Foo"
10
+ _(example.send(:foo)).must_equal "Foo"
11
11
  end
12
12
 
13
13
  it "works with hash ivars" do
@@ -16,7 +16,16 @@ describe Object, ".pattr_initialize" do
16
16
  end
17
17
 
18
18
  example = klass.new("Foo", bar: "Bar", baz: "Baz")
19
- example.send(:baz).must_equal "Baz"
19
+ _(example.send(:baz)).must_equal "Baz"
20
+ end
21
+
22
+ it "works with hash ivars and default values" do
23
+ klass = Class.new do
24
+ pattr_initialize :foo, [ bar: "Bar", baz!: "Baz" ]
25
+ end
26
+
27
+ example = klass.new("Foo")
28
+ _(example.send(:baz)).must_equal "Baz"
20
29
  end
21
30
 
22
31
  it "can reference private initializer methods in an initializer block" do
@@ -30,7 +39,7 @@ describe Object, ".pattr_initialize" do
30
39
 
31
40
  example = klass.new("expected")
32
41
 
33
- example.copy.must_equal "expected"
42
+ _(example.copy).must_equal "expected"
34
43
  end
35
44
 
36
45
  it "accepts the alias attr_private_initialize" do
@@ -39,6 +48,6 @@ describe Object, ".pattr_initialize" do
39
48
  end
40
49
 
41
50
  example = klass.new("Foo", "Bar")
42
- example.send(:foo).must_equal "Foo"
51
+ _(example.send(:foo)).must_equal "Foo"
43
52
  end
44
53
  end
@@ -7,16 +7,25 @@ describe Object, ".rattr_initialize" do
7
7
  end
8
8
 
9
9
  example = klass.new("Foo", "Bar")
10
- example.public_send(:foo).must_equal "Foo"
10
+ _(example.public_send(:foo)).must_equal "Foo"
11
11
  end
12
12
 
13
13
  it "works with hash ivars" do
14
14
  klass = Class.new do
15
- rattr_initialize :foo, [:bar, :baz!]
15
+ rattr_initialize :foo, [ :bar, :baz! ]
16
16
  end
17
17
 
18
18
  example = klass.new("Foo", bar: "Bar", baz: "Baz")
19
- example.public_send(:baz).must_equal "Baz"
19
+ _(example.public_send(:baz)).must_equal "Baz"
20
+ end
21
+
22
+ it "works with hash ivars and default values" do
23
+ klass = Class.new do
24
+ rattr_initialize :foo, [ bar: "Bar", baz!: "Baz" ]
25
+ end
26
+
27
+ example = klass.new("Foo")
28
+ _(example.send(:baz)).must_equal "Baz"
20
29
  end
21
30
 
22
31
  it "accepts the alias attr_reader_initialize" do
@@ -25,6 +34,6 @@ describe Object, ".rattr_initialize" do
25
34
  end
26
35
 
27
36
  example = klass.new("Foo", "Bar")
28
- example.public_send(:foo).must_equal "Foo"
37
+ _(example.public_send(:foo)).must_equal "Foo"
29
38
  end
30
39
  end
@@ -56,4 +56,34 @@ describe Object, ".static_facade" do
56
56
 
57
57
  assert klass.foo { :bar } == :bar
58
58
  end
59
+
60
+ it "does not blow up when the class method is called with an empty hash" do
61
+ klass = Class.new do
62
+ static_facade :foo,
63
+ :value
64
+
65
+ def foo
66
+ end
67
+ end
68
+
69
+ refute_raises_anything { klass.foo({}) }
70
+ end
71
+
72
+ it "does not emit warnings when the initializer is overridden with more keyword arguments" do
73
+ superklass = Class.new do
74
+ static_facade :something, [ :foo!, :bar! ]
75
+
76
+ def something
77
+ end
78
+ end
79
+
80
+ klass = Class.new(superklass) do
81
+ def initialize(extra:, **rest)
82
+ super(**rest)
83
+ @extra = extra
84
+ end
85
+ end
86
+
87
+ refute_warnings_emitted { klass.something(foo: 1, bar: 2, extra: "yay") }
88
+ end
59
89
  end
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+
3
+ describe AttrExtras::Utils do
4
+ describe ".flat_names" do
5
+ subject { AttrExtras::Utils.flat_names(names) }
6
+
7
+ it "strips any bangs from a flat list of arguments" do
8
+ _(AttrExtras::Utils.flat_names([ :foo, :bar! ])).must_equal [ "foo", "bar" ]
9
+ end
10
+
11
+ it "flattens hash arguments and strips any bangs" do
12
+ _(AttrExtras::Utils.flat_names([ :foo, [ :bar, :baz! ] ])).must_equal [ "foo", "bar", "baz" ]
13
+ end
14
+
15
+ it "flattens hash arguments with defaults and strips any bangs" do
16
+ _(AttrExtras::Utils.flat_names([ :foo, [ bar: "Bar", baz!: "Baz"] ])).must_equal [ "foo", "bar", "baz" ]
17
+ end
18
+ end
19
+ end
@@ -9,8 +9,8 @@ describe Object, ".vattr_initialize" do
9
9
  example1 = klass.new("Foo", "Bar")
10
10
  example2 = klass.new("Foo", "Bar")
11
11
 
12
- example1.foo.must_equal "Foo"
13
- example1.must_equal example2
12
+ _(example1.foo).must_equal "Foo"
13
+ _(example1).must_equal example2
14
14
  end
15
15
 
16
16
  it "works with hash ivars" do
@@ -20,8 +20,19 @@ describe Object, ".vattr_initialize" do
20
20
 
21
21
  example1 = klass.new("Foo", bar: "Bar", baz: "Baz")
22
22
  example2 = klass.new("Foo", bar: "Bar", baz: "Baz")
23
- example1.baz.must_equal "Baz"
24
- example1.must_equal example2
23
+ _(example1.baz).must_equal "Baz"
24
+ _(example1).must_equal example2
25
+ end
26
+
27
+ it "works with hash ivars and default values" do
28
+ klass = Class.new do
29
+ vattr_initialize :foo, [ bar: "Bar", baz!: "Baz" ]
30
+ end
31
+
32
+ example1 = klass.new("Foo")
33
+ example2 = klass.new("Foo")
34
+ _(example1.baz).must_equal "Baz"
35
+ _(example1).must_equal example2
25
36
  end
26
37
 
27
38
  it "can accept an initializer block" do
@@ -34,7 +45,7 @@ describe Object, ".vattr_initialize" do
34
45
 
35
46
  klass.new("expected")
36
47
 
37
- called.must_equal true
48
+ _(called).must_equal true
38
49
  end
39
50
 
40
51
  it "accepts the alias attr_value_initialize" do
@@ -45,7 +56,7 @@ describe Object, ".vattr_initialize" do
45
56
  example1 = klass.new("Foo", "Bar")
46
57
  example2 = klass.new("Foo", "Bar")
47
58
 
48
- example1.foo.must_equal "Foo"
49
- example1.must_equal example2
59
+ _(example1.foo).must_equal "Foo"
60
+ _(example1).must_equal example2
50
61
  end
51
62
  end
@@ -10,6 +10,6 @@ describe AttrExtras do
10
10
  include mod
11
11
  end
12
12
 
13
- klass.new("Hello").send(:name).must_equal "Hello"
13
+ _(klass.new("Hello").send(:name)).must_equal "Hello"
14
14
  end
15
15
  end
@@ -2,3 +2,20 @@ require "minitest/autorun"
2
2
  require "minitest/pride"
3
3
 
4
4
  $: << File.dirname(__FILE__) + "/../lib"
5
+
6
+ Minitest::Test.class_eval do
7
+ def refute_warnings_emitted(&block)
8
+ _, stderr = capture_io(&block)
9
+
10
+ assert stderr.empty?, -> do
11
+ warnings = stderr.strip.split("\n").map { |line| " #{line}" }.join("\n")
12
+ "Expected no warnings to be emitted, but these ones were:\n\n#{warnings}"
13
+ end
14
+ end
15
+
16
+ def refute_raises_anything
17
+ yield
18
+ rescue => error
19
+ flunk "Expected no error to be raised, but got #{error.class} (#{error.message})."
20
+ end
21
+ end
metadata CHANGED
@@ -1,17 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attr_extras
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.0
4
+ version: 6.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henrik Nyh
8
8
  - Joakim Kolsjö
9
+ - Tomas Skogberg
9
10
  - Victor Arias
10
11
  - Ola K
11
12
  autorequire:
12
13
  bindir: bin
13
14
  cert_chain: []
14
- date: 2019-01-31 00:00:00.000000000 Z
15
+ date: 2020-06-08 00:00:00.000000000 Z
15
16
  dependencies:
16
17
  - !ruby/object:Gem::Dependency
17
18
  name: minitest
@@ -33,14 +34,14 @@ dependencies:
33
34
  requirements:
34
35
  - - "~>"
35
36
  - !ruby/object:Gem::Version
36
- version: 1.5.0
37
+ version: 1.5.1
37
38
  type: :development
38
39
  prerelease: false
39
40
  version_requirements: !ruby/object:Gem::Requirement
40
41
  requirements:
41
42
  - - "~>"
42
43
  - !ruby/object:Gem::Version
43
- version: 1.5.0
44
+ version: 1.5.1
44
45
  - !ruby/object:Gem::Dependency
45
46
  name: rake
46
47
  requirement: !ruby/object:Gem::Requirement
@@ -93,6 +94,7 @@ files:
93
94
  - spec/attr_extras/pattr_initialize_spec.rb
94
95
  - spec/attr_extras/rattr_initialize_spec.rb
95
96
  - spec/attr_extras/static_facade_spec.rb
97
+ - spec/attr_extras/utils_spec.rb
96
98
  - spec/attr_extras/vattr_initialize_spec.rb
97
99
  - spec/attr_extras_spec.rb
98
100
  - spec/spec_helper.rb
@@ -116,8 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
118
  - !ruby/object:Gem::Version
117
119
  version: '0'
118
120
  requirements: []
119
- rubyforge_project:
120
- rubygems_version: 2.6.11
121
+ rubygems_version: 3.1.2
121
122
  signing_key:
122
123
  specification_version: 4
123
124
  summary: Takes some boilerplate out of Ruby with methods like attr_initialize.
@@ -135,6 +136,7 @@ test_files:
135
136
  - spec/attr_extras/pattr_initialize_spec.rb
136
137
  - spec/attr_extras/rattr_initialize_spec.rb
137
138
  - spec/attr_extras/static_facade_spec.rb
139
+ - spec/attr_extras/utils_spec.rb
138
140
  - spec/attr_extras/vattr_initialize_spec.rb
139
141
  - spec/attr_extras_spec.rb
140
142
  - spec/spec_helper.rb