superstructure 1.0.0 → 1.0.1

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
2
  SHA1:
3
- metadata.gz: 1dba89c3e4aeda5883b1f0512c3f4e785ad206b0
4
- data.tar.gz: 27d2fbb43f389b2512ca582e9977c11c9daffe1a
3
+ metadata.gz: ee6898266d56d163225dc8e36a560df58c775ad5
4
+ data.tar.gz: 0a54cd4233764e3709894e827a199cb4c6b250a2
5
5
  SHA512:
6
- metadata.gz: 53a23c060e658cf07599f47ce5009d5b73ce88cfaa285d942fc18591e61371c6cd4982bc29f7e3ac387882d0579201b2aad24cb7d119948f412f527edbecad46
7
- data.tar.gz: a99d7e6f99bfce4d57241ed9e7e3a3cf74951f066a50b0234889a477719cde9954889d8aa3a78e12176247553edb207a9001e6658a3087715cbbbbfe0ceadfee
6
+ metadata.gz: 235118a7fc7df08713a74f8e08ff6fd603f574e73ad1e28af21c25cdd449fa85e5d2a38274efc8c12dd8ae7e87ba1e72eace08ef9a604a9503c6c0192be53edf
7
+ data.tar.gz: 820253eeb35ff0c77c0572a9b4132c0c3eb7df7e6e70a6631abb2ebf99823a2834489df12ff3bc06acf5e1f079856228e90ff65516c2601dca782520b9fffbb3
@@ -0,0 +1,27 @@
1
+ module Superstructure
2
+ class ArgumentErrorBuilder
3
+ def initialize
4
+ @errors = {
5
+ extra_params: [],
6
+ missing_params: [],
7
+ shadowed_params: []
8
+ }
9
+ end
10
+
11
+ def add_error(type, key)
12
+ add_errors(type, [key])
13
+ end
14
+
15
+ def add_errors(type, key)
16
+ @errors.fetch(type).concat(key)
17
+ end
18
+
19
+ def build
20
+ ArgumentError.new(@errors)
21
+ end
22
+
23
+ def error?
24
+ @errors.any? { |k, v| v.any? }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ module Superstructure
2
+ class AttributeParser
3
+ attr_reader :attributes
4
+
5
+ def initialize(arguments, opts)
6
+ @attributes = {}
7
+ @possible_error = ArgumentErrorBuilder.new
8
+ @arguments = arguments
9
+ @opts = opts
10
+
11
+ parse!
12
+ end
13
+
14
+ def error?
15
+ @possible_error.error?
16
+ end
17
+
18
+ def error
19
+ @possible_error.build
20
+ end
21
+
22
+ private
23
+
24
+ def parse!
25
+ used_params = []
26
+
27
+ @arguments.each do |argument|
28
+ if @opts.has_key?(argument) && @opts.has_key?(argument.to_s)
29
+ @possible_error.add_error(:shadowed_params, argument)
30
+ used_params << argument << argument.to_s
31
+ elsif @opts.has_key?(argument)
32
+ @attributes[argument] = @opts[argument]
33
+ used_params << argument
34
+ elsif @opts.has_key?(argument.to_s)
35
+ @attributes[argument] = @opts[argument.to_s]
36
+ used_params << argument.to_s
37
+ else
38
+ @possible_error.add_error(:missing_params, argument)
39
+ end
40
+ end
41
+
42
+ @possible_error.add_errors(:extra_params, @opts.keys - used_params)
43
+ end
44
+ end
45
+ end
@@ -4,35 +4,11 @@ module Superstructure
4
4
  def new *arguments, superclass: Object, &blk
5
5
  Class.new(superclass) do
6
6
  define_method(:initialize) do |opts={}|
7
- @attributes = {}
8
- missing_params = []
9
- shadowed_params = []
10
- used_params = []
11
-
12
- arguments.each do |argument|
13
- if opts.has_key?(argument) && opts.has_key?(argument.to_s)
14
- shadowed_params << argument
15
- used_params << argument << argument.to_s
16
-
17
- elsif opts.has_key?(argument)
18
- @attributes[argument] = opts[argument]
19
- used_params << argument
20
- elsif opts.has_key?(argument.to_s)
21
- @attributes[argument] = opts[argument.to_s]
22
- used_params << argument.to_s
23
- else
24
- missing_params << argument
25
- end
26
- end
27
-
28
- extra_params = opts.keys - used_params
29
-
30
- if missing_params.any? || shadowed_params.any? || extra_params.any?
31
- raise ArgumentError.new(
32
- missing_params: missing_params,
33
- shadowed_params: shadowed_params,
34
- extra_params: extra_params
35
- )
7
+ attribute_parser = AttributeParser.new(arguments, opts)
8
+ if attribute_parser.error?
9
+ raise attribute_parser.error
10
+ else
11
+ @attributes = attribute_parser.attributes
36
12
  end
37
13
  end
38
14
 
@@ -44,7 +20,12 @@ module Superstructure
44
20
  opts = @attributes.map do |k, v|
45
21
  "#{k}=#{v.inspect}"
46
22
  end.join(", ")
47
- "#<value_obj #{self.class} #{opts}>"
23
+
24
+ unless opts.empty?
25
+ opts.prepend(" ")
26
+ end
27
+
28
+ "#<value_obj #{self.class}#{opts}>"
48
29
  end
49
30
 
50
31
  def ==(o)
@@ -53,6 +34,10 @@ module Superstructure
53
34
 
54
35
  alias :eql? :==
55
36
 
37
+ def hash
38
+ self.class.hash ^ @attributes.hash
39
+ end
40
+
56
41
  arguments.each do |argument|
57
42
  define_method(argument) do
58
43
  to_hash[argument]
@@ -1,3 +1,3 @@
1
1
  module Superstructure
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -4,3 +4,5 @@ end
4
4
  require "superstructure/version"
5
5
  require "superstructure/value_obj"
6
6
  require "superstructure/argument_error"
7
+ require "superstructure/argument_error_builder"
8
+ require "superstructure/attribute_parser"
@@ -0,0 +1,30 @@
1
+ RSpec.describe Superstructure::ArgumentErrorBuilder do
2
+ let(:builder) { described_class.new }
3
+
4
+ describe "#error?" do
5
+ subject { builder.error? }
6
+
7
+ context "when at least one error has been added" do
8
+ before do
9
+ builder.add_error(:missing_params, :hello)
10
+ end
11
+
12
+ it { should be_truthy }
13
+ end
14
+
15
+ context "when no errors have been added" do
16
+ it { should be_falsy }
17
+ end
18
+ end
19
+
20
+ it "builds an ArgumentError with all of the added errors" do
21
+ builder.add_error(:extra_params, :alpha)
22
+ builder.add_errors(:missing_params, [:beta, :charlie])
23
+
24
+ expect(builder.build).to have_attributes(
25
+ extra_params: [:alpha],
26
+ missing_params: [:beta, :charlie],
27
+ shadowed_params: []
28
+ )
29
+ end
30
+ end
@@ -64,6 +64,12 @@ RSpec.describe Superstructure::ValueObj do
64
64
  foobar = FooBar.new(foo: [:a, :b], bar: 2)
65
65
  expect(foobar.inspect).to eq '#<value_obj FooBar foo=[:a, :b], bar=2>'
66
66
  end
67
+
68
+ context "when there are no attributes" do
69
+ it "omits the attibutes" do
70
+ expect(Empty.new.inspect).to eq "#<value_obj Empty>"
71
+ end
72
+ end
67
73
  end
68
74
 
69
75
  it "can inherit from other classes" do
@@ -94,17 +100,17 @@ RSpec.describe Superstructure::ValueObj do
94
100
  end
95
101
 
96
102
  describe "equality" do
97
- shared_examples_for "equality" do |operator|
103
+ shared_examples_for "equality" do |sameness_proc|
98
104
  it "is equal if all arguments are equal" do
99
105
  alpha = FooBar.new(foo: 1, bar: 2)
100
106
  beta = FooBar.new("foo" => 1, "bar" => 2)
101
- expect(alpha.public_send(operator, beta)).to be_truthy
107
+ expect(sameness_proc.(alpha, beta)).to be_truthy
102
108
  end
103
109
 
104
110
  it "is not equal if any argument doesn't equal" do
105
111
  alpha = FooBar.new(foo: 1, bar: 2000)
106
112
  beta = FooBar.new("foo" => 1, "bar" => 2)
107
- expect(alpha.public_send(operator, beta)).to be_falsey
113
+ expect(sameness_proc.(alpha, beta)).to be_falsey
108
114
  end
109
115
 
110
116
  it "is equal only to other instances of the same class" do
@@ -114,16 +120,20 @@ RSpec.describe Superstructure::ValueObj do
114
120
  foobar = FooBar.new(opts)
115
121
  barfoo = klass.new(opts)
116
122
 
117
- expect(foobar.public_send(operator, barfoo)).to be_falsey
123
+ expect(sameness_proc.(foobar, barfoo)).to be_falsey
118
124
  end
119
125
  end
120
126
 
121
127
  describe "==" do
122
- it_behaves_like "equality", :==
128
+ it_behaves_like "equality", proc { |a, b| a == b }
123
129
  end
124
130
 
125
131
  describe "eql?" do
126
- it_behaves_like "equality", :eql?
132
+ it_behaves_like "equality", proc { |a, b| a.eql? b }
133
+ end
134
+
135
+ describe "hash" do
136
+ it_behaves_like "equality", proc { |a, b| a.hash == b.hash }
127
137
  end
128
138
  end
129
139
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: superstructure
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Finnie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-15 00:00:00.000000000 Z
11
+ date: 2018-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,8 +67,11 @@ files:
67
67
  - Rakefile
68
68
  - lib/superstructure.rb
69
69
  - lib/superstructure/argument_error.rb
70
+ - lib/superstructure/argument_error_builder.rb
71
+ - lib/superstructure/attribute_parser.rb
70
72
  - lib/superstructure/value_obj.rb
71
73
  - lib/superstructure/version.rb
74
+ - spec/argument_error_builder_spec.rb
72
75
  - spec/argument_error_spec.rb
73
76
  - spec/spec_helper.rb
74
77
  - spec/value_obj_spec.rb
@@ -93,12 +96,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
96
  version: '0'
94
97
  requirements: []
95
98
  rubyforge_project:
96
- rubygems_version: 2.0.14
99
+ rubygems_version: 2.5.2
97
100
  signing_key:
98
101
  specification_version: 4
99
102
  summary: Immutable, keyword-argument based value objects for Ruby
100
103
  test_files:
104
+ - spec/argument_error_builder_spec.rb
101
105
  - spec/argument_error_spec.rb
102
106
  - spec/spec_helper.rb
103
107
  - spec/value_obj_spec.rb
104
- has_rdoc: