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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +34 -0
- data/Gemfile +1 -3
- data/README.md +29 -13
- data/Rakefile +4 -7
- data/abstract_mapper.gemspec +3 -2
- data/config/metrics/STYLEGUIDE +14 -15
- data/lib/abstract_mapper.rb +4 -1
- data/lib/abstract_mapper/attributes.rb +65 -0
- data/lib/abstract_mapper/branch.rb +17 -7
- data/lib/abstract_mapper/builder.rb +7 -3
- data/lib/abstract_mapper/command.rb +68 -0
- data/lib/abstract_mapper/commands.rb +11 -31
- data/lib/abstract_mapper/errors/unknown_command.rb +1 -1
- data/lib/abstract_mapper/errors/wrong_node.rb +1 -1
- data/lib/abstract_mapper/errors/wrong_rule.rb +2 -2
- data/lib/abstract_mapper/functions.rb +32 -5
- data/lib/abstract_mapper/node.rb +21 -10
- data/lib/abstract_mapper/optimizer.rb +3 -3
- data/lib/abstract_mapper/pair_rule.rb +2 -4
- data/lib/abstract_mapper/rspec.rb +1 -2
- data/lib/abstract_mapper/rule.rb +23 -2
- data/lib/abstract_mapper/rules.rb +3 -10
- data/lib/abstract_mapper/settings.rb +3 -3
- data/lib/abstract_mapper/sole_rule.rb +2 -4
- data/lib/abstract_mapper/version.rb +1 -1
- data/lib/rspec/doubles.rb +16 -0
- data/lib/rspec/nodes.rb +29 -16
- data/lib/rspec/rules.rb +3 -3
- data/spec/integration/faceter.rb +16 -7
- data/spec/integration/mapper_definition_spec.rb +1 -1
- data/spec/integration/rspec_examples_spec.rb +4 -30
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/abstract_mapper/branch_spec.rb +91 -14
- data/spec/unit/abstract_mapper/builder_spec.rb +66 -48
- data/spec/unit/abstract_mapper/command_spec.rb +92 -0
- data/spec/unit/abstract_mapper/commands_spec.rb +38 -79
- data/spec/unit/abstract_mapper/dsl_spec.rb +60 -55
- data/spec/unit/abstract_mapper/errors/wrong_rule_spec.rb +1 -1
- data/spec/unit/abstract_mapper/functions/compact_spec.rb +3 -3
- data/spec/unit/abstract_mapper/functions/filter_spec.rb +1 -1
- data/spec/unit/abstract_mapper/functions/identity_spec.rb +21 -0
- data/spec/unit/abstract_mapper/functions/restrict_spec.rb +16 -0
- data/spec/unit/abstract_mapper/functions/subclass_spec.rb +1 -1
- data/spec/unit/abstract_mapper/node_spec.rb +119 -48
- data/spec/unit/abstract_mapper/optimizer_spec.rb +38 -32
- data/spec/unit/abstract_mapper/pair_rule_spec.rb +4 -11
- data/spec/unit/abstract_mapper/rule_spec.rb +31 -15
- data/spec/unit/abstract_mapper/rules_spec.rb +2 -2
- data/spec/unit/abstract_mapper/settings_spec.rb +80 -73
- data/spec/unit/abstract_mapper/sole_rule_spec.rb +3 -10
- data/spec/unit/abstract_mapper_spec.rb +13 -5
- metadata +33 -12
- data/lib/rspec/functions.rb +0 -25
- 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
|
-
|
3
|
+
class AbstractMapper
|
4
4
|
|
5
|
-
|
6
|
-
let(:test) { Class.new(described_class) }
|
7
|
-
let(:branch) { Class.new(AbstractMapper::Branch) }
|
5
|
+
describe AbstractMapper::Commands do
|
8
6
|
|
9
|
-
|
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
|
-
|
12
|
-
it { is_expected.to be_frozen }
|
13
|
+
describe ".new" do
|
13
14
|
|
14
|
-
|
15
|
+
let(:registry) { { foo: foo, bar: bar } }
|
16
|
+
subject { test.new(registry) }
|
15
17
|
|
16
|
-
|
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
|
20
|
+
it "doesn't freeze arguments" do
|
29
21
|
expect { subject }.not_to change { registry.frozen? }
|
30
22
|
end
|
31
23
|
|
32
|
-
end #
|
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
|
-
|
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
|
-
|
28
|
+
subject { commands << ["foo", foo] }
|
57
29
|
|
58
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
41
|
+
end # describe #[]
|
81
42
|
|
82
|
-
|
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
|
-
|
45
|
+
subject { commands << ["foo", foo] << ["bar", bar, converter] }
|
89
46
|
|
90
|
-
|
47
|
+
it { is_expected.to be_kind_of test }
|
91
48
|
|
92
|
-
|
49
|
+
it "preserves registered commands" do
|
50
|
+
expect(subject[:foo]).to be_kind_of Command
|
51
|
+
end
|
93
52
|
|
94
|
-
it "
|
95
|
-
expect
|
96
|
-
|
97
|
-
|
98
|
-
|
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 #
|
60
|
+
end # describe #<<
|
102
61
|
|
103
|
-
end # describe
|
62
|
+
end # describe AbstractMapper::Commands
|
104
63
|
|
105
|
-
end #
|
64
|
+
end # class AbstractMapper
|
@@ -1,82 +1,87 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
14
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
31
|
+
describe "#configure" do
|
29
32
|
|
30
|
-
|
33
|
+
subject { config }
|
31
34
|
|
32
|
-
|
35
|
+
it { is_expected.to eql dsl }
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
44
|
+
end # describe #configure
|
42
45
|
|
43
|
-
|
46
|
+
describe "#finalize" do
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
58
|
+
subject { dsl.finalize }
|
56
59
|
|
57
|
-
|
60
|
+
it { is_expected.to be_kind_of Branch }
|
58
61
|
|
59
|
-
|
60
|
-
|
61
|
-
.to eql
|
62
|
-
|
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
|
-
|
69
|
+
describe "#respond_to?" do
|
65
70
|
|
66
|
-
|
71
|
+
subject { dsl.respond_to? :anything }
|
72
|
+
it { is_expected.to eql true }
|
67
73
|
|
68
|
-
|
69
|
-
it { is_expected.to eql true }
|
74
|
+
end # describe #respond_to?
|
70
75
|
|
71
|
-
|
76
|
+
describe ".inherited" do
|
72
77
|
|
73
|
-
|
78
|
+
let(:subklass) { Class.new(dsl) }
|
79
|
+
subject { subklass.settings }
|
74
80
|
|
75
|
-
|
76
|
-
subject { subklass.settings }
|
81
|
+
it { is_expected.to eql dsl.settings }
|
77
82
|
|
78
|
-
|
83
|
+
end # describe .inherited
|
79
84
|
|
80
|
-
end # describe
|
85
|
+
end # describe AbstractMapper::DSL
|
81
86
|
|
82
|
-
end #
|
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::
|
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 "
|
3
|
+
require "transproc/rspec"
|
4
4
|
|
5
5
|
describe AbstractMapper::Functions, "#compact" do
|
6
6
|
|
7
|
-
let(:
|
8
|
-
let(:arguments) { [:compact,
|
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) { [] }
|
@@ -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
|