abstract_mapper 0.0.1 → 0.0.2

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +34 -0
  4. data/Gemfile +1 -3
  5. data/README.md +29 -13
  6. data/Rakefile +4 -7
  7. data/abstract_mapper.gemspec +3 -2
  8. data/config/metrics/STYLEGUIDE +14 -15
  9. data/lib/abstract_mapper.rb +4 -1
  10. data/lib/abstract_mapper/attributes.rb +65 -0
  11. data/lib/abstract_mapper/branch.rb +17 -7
  12. data/lib/abstract_mapper/builder.rb +7 -3
  13. data/lib/abstract_mapper/command.rb +68 -0
  14. data/lib/abstract_mapper/commands.rb +11 -31
  15. data/lib/abstract_mapper/errors/unknown_command.rb +1 -1
  16. data/lib/abstract_mapper/errors/wrong_node.rb +1 -1
  17. data/lib/abstract_mapper/errors/wrong_rule.rb +2 -2
  18. data/lib/abstract_mapper/functions.rb +32 -5
  19. data/lib/abstract_mapper/node.rb +21 -10
  20. data/lib/abstract_mapper/optimizer.rb +3 -3
  21. data/lib/abstract_mapper/pair_rule.rb +2 -4
  22. data/lib/abstract_mapper/rspec.rb +1 -2
  23. data/lib/abstract_mapper/rule.rb +23 -2
  24. data/lib/abstract_mapper/rules.rb +3 -10
  25. data/lib/abstract_mapper/settings.rb +3 -3
  26. data/lib/abstract_mapper/sole_rule.rb +2 -4
  27. data/lib/abstract_mapper/version.rb +1 -1
  28. data/lib/rspec/doubles.rb +16 -0
  29. data/lib/rspec/nodes.rb +29 -16
  30. data/lib/rspec/rules.rb +3 -3
  31. data/spec/integration/faceter.rb +16 -7
  32. data/spec/integration/mapper_definition_spec.rb +1 -1
  33. data/spec/integration/rspec_examples_spec.rb +4 -30
  34. data/spec/spec_helper.rb +1 -1
  35. data/spec/unit/abstract_mapper/branch_spec.rb +91 -14
  36. data/spec/unit/abstract_mapper/builder_spec.rb +66 -48
  37. data/spec/unit/abstract_mapper/command_spec.rb +92 -0
  38. data/spec/unit/abstract_mapper/commands_spec.rb +38 -79
  39. data/spec/unit/abstract_mapper/dsl_spec.rb +60 -55
  40. data/spec/unit/abstract_mapper/errors/wrong_rule_spec.rb +1 -1
  41. data/spec/unit/abstract_mapper/functions/compact_spec.rb +3 -3
  42. data/spec/unit/abstract_mapper/functions/filter_spec.rb +1 -1
  43. data/spec/unit/abstract_mapper/functions/identity_spec.rb +21 -0
  44. data/spec/unit/abstract_mapper/functions/restrict_spec.rb +16 -0
  45. data/spec/unit/abstract_mapper/functions/subclass_spec.rb +1 -1
  46. data/spec/unit/abstract_mapper/node_spec.rb +119 -48
  47. data/spec/unit/abstract_mapper/optimizer_spec.rb +38 -32
  48. data/spec/unit/abstract_mapper/pair_rule_spec.rb +4 -11
  49. data/spec/unit/abstract_mapper/rule_spec.rb +31 -15
  50. data/spec/unit/abstract_mapper/rules_spec.rb +2 -2
  51. data/spec/unit/abstract_mapper/settings_spec.rb +80 -73
  52. data/spec/unit/abstract_mapper/sole_rule_spec.rb +3 -10
  53. data/spec/unit/abstract_mapper_spec.rb +13 -5
  54. metadata +33 -12
  55. data/lib/rspec/functions.rb +0 -25
  56. data/lib/rspec/mapper.rb +0 -40
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+
3
+ class AbstractMapper
4
+
5
+ describe AbstractMapper::Command do
6
+
7
+ let(:command) { described_class.new name, klass, converter }
8
+ let(:name) { "foo" }
9
+ let(:klass) { Class.new }
10
+ let(:converter) { -> *args { args.reverse } }
11
+ let(:arguments) { [baz: :QUX] }
12
+ let(:block) { proc { :foo } }
13
+
14
+ describe ".new" do
15
+
16
+ subject { command }
17
+ it { is_expected.to be_frozen }
18
+
19
+ end # describe .new
20
+
21
+ describe "#name" do
22
+
23
+ subject { command.name }
24
+ it { is_expected.to eql name.to_sym }
25
+
26
+ end # describe #name
27
+
28
+ describe "#klass" do
29
+
30
+ subject { command.klass }
31
+ it { is_expected.to eql klass }
32
+
33
+ end # describe #name
34
+
35
+ describe "#converter" do
36
+
37
+ subject { command.converter }
38
+
39
+ context "by default" do
40
+
41
+ let(:command) { described_class.new name, klass }
42
+
43
+ it "returns identity function" do
44
+ expect(subject.call(foo: :BAR)).to eql(foo: :BAR)
45
+ expect(subject.call).to eql({})
46
+ end
47
+
48
+ end # context
49
+
50
+ context "initialized" do
51
+
52
+ it { is_expected.to eql converter }
53
+
54
+ end # context
55
+
56
+ end # describe #name
57
+
58
+ describe "#call" do
59
+
60
+ subject { command.call(arguments, &block) }
61
+
62
+ context "when the klass is not a branch" do
63
+
64
+ it "builds a node" do
65
+ expect(klass).to receive(:new) do |args, &blk|
66
+ expect(args).to eql(converter.call(arguments))
67
+ expect(blk).to eql block
68
+ end
69
+ subject
70
+ end
71
+
72
+ end # context
73
+
74
+ context "when the klass is a branch" do
75
+
76
+ let(:klass) { Class.new(Branch) }
77
+
78
+ it "builds a branch" do
79
+ expect(klass).to receive(:new) do |args, &blk|
80
+ expect(args).to eql(converter.call(arguments))
81
+ expect(blk).to be_nil
82
+ end
83
+ subject
84
+ end
85
+
86
+ end # context
87
+
88
+ end # describe #call
89
+
90
+ end # describe AbstractMapper::Command
91
+
92
+ end # class AbstractMapper
@@ -1,105 +1,64 @@
1
1
  # encoding: utf-8
2
2
 
3
- describe AbstractMapper::Commands do
3
+ class AbstractMapper
4
4
 
5
- let(:commands) { test.new }
6
- let(:test) { Class.new(described_class) }
7
- let(:branch) { Class.new(AbstractMapper::Branch) }
5
+ describe AbstractMapper::Commands do
8
6
 
9
- describe ".new" do
7
+ let(:foo) { Test::Foo = Class.new(AbstractMapper::Branch) }
8
+ let(:bar) { Test::Bar = Class.new(AbstractMapper::Node) }
9
+ let(:test) { Class.new(described_class) }
10
+ let(:commands) { test.new }
11
+ let(:converter) { -> v { v.reverse } }
10
12
 
11
- subject { commands }
12
- it { is_expected.to be_frozen }
13
+ describe ".new" do
13
14
 
14
- end # describe .new
15
+ let(:registry) { { foo: foo, bar: bar } }
16
+ subject { test.new(registry) }
15
17
 
16
- describe "#registry" do
17
-
18
- subject { commands.registry }
19
-
20
- context "with a hash" do
21
-
22
- let(:commands) { test.new(registry) }
23
- let(:registry) { { foo: branch } }
24
-
25
- it { is_expected.to eql registry }
26
- it { is_expected.to be_frozen }
18
+ it { is_expected.to be_frozen }
27
19
 
28
- it "doesn't freeze the source" do
20
+ it "doesn't freeze arguments" do
29
21
  expect { subject }.not_to change { registry.frozen? }
30
22
  end
31
23
 
32
- end # context
33
-
34
- context "without a hash" do
35
-
36
- let(:commands) { test.new }
37
-
38
- it { is_expected.to eql({}) }
39
- it { is_expected.to be_frozen }
40
-
41
- end # context
42
-
43
- end # describe #builder
44
-
45
- describe "#<<" do
46
-
47
- let(:commands) { test.new(foo: branch) }
48
-
49
- subject { commands << ["bar", branch] }
24
+ end # describe .new
50
25
 
51
- it "registers a command" do
52
- expect(subject).to be_kind_of test
53
- expect(subject.registry).to eql(foo: branch, bar: branch)
54
- end
26
+ describe "#[]" do
55
27
 
56
- end # describe #<<
28
+ subject { commands << ["foo", foo] }
57
29
 
58
- describe "#[]" do
59
-
60
- let(:block) { proc { [:foo] } }
61
- let(:args) { [:baz, qux: :QUX] }
62
- let(:commands) do
63
- test.new(foo: AbstractMapper::Node, bar: AbstractMapper::Branch)
64
- end
65
-
66
- context "simple node" do
67
-
68
- subject { commands["foo", *args, &block] }
69
-
70
- it "builds a node with a block" do
71
- expect(subject).to be_kind_of AbstractMapper::Node
72
- expect(subject.attributes).to eql args
73
- expect(subject.block).to eql block
30
+ it "returns registered command" do
31
+ expect(subject["foo"]).to be_kind_of Command
74
32
  end
75
33
 
76
- end # context
77
-
78
- context "branch command" do
34
+ it "complains about unknown command" do
35
+ expect { subject[:baz] }.to raise_error do |error|
36
+ expect(error).to be_kind_of AbstractMapper::Errors::UnknownCommand
37
+ expect(error.message).to include "baz"
38
+ end
39
+ end
79
40
 
80
- subject { commands["bar", *args, &block] }
41
+ end # describe #[]
81
42
 
82
- it "builds a branch" do
83
- expect(subject).to be_kind_of AbstractMapper::Node
84
- expect(subject.attributes).to eql args
85
- expect(subject.entries).to eql []
86
- end
43
+ describe "#<<" do
87
44
 
88
- end # context
45
+ subject { commands << ["foo", foo] << ["bar", bar, converter] }
89
46
 
90
- context "unknown command" do
47
+ it { is_expected.to be_kind_of test }
91
48
 
92
- subject { commands["baz"] }
49
+ it "preserves registered commands" do
50
+ expect(subject[:foo]).to be_kind_of Command
51
+ end
93
52
 
94
- it "fails" do
95
- expect { subject }.to raise_error do |error|
96
- expect(error).to be_kind_of AbstractMapper::Errors::UnknownCommand
97
- expect(error.message).to include "baz"
98
- end
53
+ it "registers new command" do
54
+ expect(subject[:bar]).to be_kind_of Command
55
+ expect(subject[:bar].name).to eql :bar
56
+ expect(subject[:bar].klass).to eql bar
57
+ expect(subject[:bar].converter).to eql converter
99
58
  end
100
59
 
101
- end # context
60
+ end # describe #<<
102
61
 
103
- end # describe #build
62
+ end # describe AbstractMapper::Commands
104
63
 
105
- end # describe AbstractMapper::Commands
64
+ end # class AbstractMapper
@@ -1,82 +1,87 @@
1
1
  # encoding: utf-8
2
2
 
3
- describe AbstractMapper::DSL do
4
-
5
- let!(:bar) { AbstractMapper::Test::Bar = Class.new(AbstractMapper::Branch) }
6
- let!(:foo) { AbstractMapper::Test::Foo = Class.new(AbstractMapper::Node) }
7
- let!(:rule) do
8
- AbstractMapper::Test::Rule = Class.new(AbstractMapper::PairRule) do
9
- def optimize?
10
- left.instance_of?(AbstractMapper::Test::Foo)
11
- end
3
+ class AbstractMapper
4
+
5
+ describe AbstractMapper::DSL do
12
6
 
13
- def optimize
14
- AbstractMapper::Test::Foo.new(nodes.flat_map(&:attributes))
7
+ let!(:dsl) { Class.new { extend DSL } }
8
+ let!(:foo) { Test::Foo = Class.new(Node) { attribute :foo } }
9
+ let!(:bar) { Test::Bar = Class.new(Branch) { attribute :bar } }
10
+
11
+ let!(:rule) do
12
+ Test::Rule = Class.new(PairRule) do
13
+ def optimize?
14
+ left.instance_of?(Test::Foo)
15
+ end
16
+
17
+ def optimize
18
+ Test::Foo.new(left.attributes.merge(right.attributes))
19
+ end
15
20
  end
16
21
  end
17
- end
18
- let!(:dsl) { Class.new { extend AbstractMapper::DSL } }
19
-
20
- let!(:config) do
21
- dsl.configure do
22
- command :foo, AbstractMapper::Test::Foo
23
- command :bar, AbstractMapper::Test::Bar
24
- rule AbstractMapper::Test::Rule
22
+
23
+ let!(:config) do
24
+ dsl.configure do
25
+ command :foo, Test::Foo
26
+ command(:bar, Test::Bar) { |value| { bar: value } }
27
+ rule Test::Rule
28
+ end
25
29
  end
26
- end
27
30
 
28
- describe "#configure" do
31
+ describe "#configure" do
29
32
 
30
- subject { config }
33
+ subject { config }
31
34
 
32
- it { is_expected.to eql dsl }
35
+ it { is_expected.to eql dsl }
33
36
 
34
- it "configures settings" do
35
- subject
36
- expect(dsl.settings).to be_kind_of AbstractMapper::Settings
37
- expect(dsl.settings.rules.registry).to eql [rule]
38
- expect(dsl.settings.commands.registry).to eql(foo: foo, bar: bar)
39
- end
37
+ it "configures settings" do
38
+ subject
39
+ expect(dsl.settings).to be_kind_of Settings
40
+ expect(dsl.settings.rules.registry).to eql [rule]
41
+ expect { dsl.settings.commands[:foo] }.not_to raise_error
42
+ end
40
43
 
41
- end # describe #configure
44
+ end # describe #configure
42
45
 
43
- describe "#finalize" do
46
+ describe "#finalize" do
44
47
 
45
- before do
46
- dsl.instance_eval do
47
- bar :baz do
48
- foo :qux
49
- foo :quxx
48
+ before do
49
+ dsl.instance_eval do
50
+ bar :baz do
51
+ foo foo: :qux
52
+ foo foo: :quxx
53
+ end
54
+ foo foo: :foo
50
55
  end
51
- foo :foo
52
56
  end
53
- end
54
57
 
55
- subject { dsl.finalize }
58
+ subject { dsl.finalize }
56
59
 
57
- it { is_expected.to be_kind_of AbstractMapper::Branch }
60
+ it { is_expected.to be_kind_of Branch }
58
61
 
59
- it "is optimized" do
60
- expect(subject.inspect)
61
- .to eql "<Root [<Bar(:baz) [<Foo([:qux, :quxx])>]>, <Foo(:foo)>]>"
62
- end
62
+ it "is optimized" do
63
+ desc = "<Root [<Bar(bar: :baz) [<Foo(foo: :quxx)>]>, <Foo(foo: :foo)>]>"
64
+ expect(subject.inspect).to eql(desc)
65
+ end
66
+
67
+ end # describe #finalize
63
68
 
64
- end # describe #finalize
69
+ describe "#respond_to?" do
65
70
 
66
- describe "#respond_to?" do
71
+ subject { dsl.respond_to? :anything }
72
+ it { is_expected.to eql true }
67
73
 
68
- subject { dsl.respond_to? :anything }
69
- it { is_expected.to eql true }
74
+ end # describe #respond_to?
70
75
 
71
- end # describe #respond_to?
76
+ describe ".inherited" do
72
77
 
73
- describe ".inherited" do
78
+ let(:subklass) { Class.new(dsl) }
79
+ subject { subklass.settings }
74
80
 
75
- let(:subklass) { Class.new(dsl) }
76
- subject { subklass.settings }
81
+ it { is_expected.to eql dsl.settings }
77
82
 
78
- it { is_expected.to eql dsl.settings }
83
+ end # describe .inherited
79
84
 
80
- end # describe .inherited
85
+ end # describe AbstractMapper::DSL
81
86
 
82
- end # describe AbstractMapper::DSL
87
+ end # class AbstractMapper
@@ -15,7 +15,7 @@ describe AbstractMapper::Errors::WrongRule do
15
15
 
16
16
  subject { error.message }
17
17
  it do
18
- is_expected.to eql "Symbol is not a subclass of AbstractMapper::SoleRule"
18
+ is_expected.to eql "Symbol is not a subclass of AbstractMapper::Rule"
19
19
  end
20
20
 
21
21
  end # describe #message
@@ -1,11 +1,11 @@
1
1
  # encoding: utf-8
2
2
 
3
- require "abstract_mapper/rspec"
3
+ require "transproc/rspec"
4
4
 
5
5
  describe AbstractMapper::Functions, "#compact" do
6
6
 
7
- let(:function) { -> a, b { (a == b) ? [a + b] : [a, b] } }
8
- let(:arguments) { [:compact, function] }
7
+ let(:fn) { -> a, b { (a == b) ? [a + b] : [a, b] } }
8
+ let(:arguments) { [:compact, fn] }
9
9
 
10
10
  it_behaves_like :transforming_immutable_data do
11
11
  let(:input) { [] }
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require "abstract_mapper/rspec"
3
+ require "transproc/rspec"
4
4
 
5
5
  describe AbstractMapper::Functions, "#filter" do
6
6
 
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ require "transproc/rspec"
4
+
5
+ describe AbstractMapper::Functions, "#identity" do
6
+
7
+ it_behaves_like :transforming_immutable_data do
8
+ let(:arguments) { [:identity] }
9
+
10
+ let(:input) { :foo }
11
+ let(:output) { :foo }
12
+ end
13
+
14
+ it_behaves_like :transforming_immutable_data do
15
+ let(:arguments) { [:identity, :bar, :baz] }
16
+
17
+ let(:input) { :foo }
18
+ let(:output) { :foo }
19
+ end
20
+
21
+ end # describe AbstractMapper::Functions#identity
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ require "transproc/rspec"
4
+
5
+ describe AbstractMapper::Functions, "#restrict" do
6
+
7
+ let(:arguments) { [:restrict, default] }
8
+ let(:default) { { foo: :FOO, bar: :BAR } }
9
+
10
+ it_behaves_like :transforming_immutable_data do
11
+
12
+ let(:input) { { foo: :BAZ, qux: :QUX } }
13
+ let(:output) { { foo: :BAZ, bar: :BAR } }
14
+ end
15
+
16
+ end # describe AbstractMapper::Functions#restrict