abstract_mapper 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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