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 +4 -4
- data/lib/superstructure/argument_error_builder.rb +27 -0
- data/lib/superstructure/attribute_parser.rb +45 -0
- data/lib/superstructure/value_obj.rb +15 -30
- data/lib/superstructure/version.rb +1 -1
- data/lib/superstructure.rb +2 -0
- data/spec/argument_error_builder_spec.rb +30 -0
- data/spec/value_obj_spec.rb +16 -6
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee6898266d56d163225dc8e36a560df58c775ad5
|
4
|
+
data.tar.gz: 0a54cd4233764e3709894e827a199cb4c6b250a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
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]
|
data/lib/superstructure.rb
CHANGED
@@ -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
|
data/spec/value_obj_spec.rb
CHANGED
@@ -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 |
|
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(
|
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(
|
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(
|
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",
|
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.
|
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:
|
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.
|
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:
|