flat_map 0.0.3
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 +15 -0
- data/.gitignore +31 -0
- data/.metrics +17 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +20 -0
- data/LICENSE +20 -0
- data/README.markdown +211 -0
- data/Rakefile +15 -0
- data/flat_map.gemspec +30 -0
- data/lib/flat_map.rb +9 -0
- data/lib/flat_map/base_mapper.rb +95 -0
- data/lib/flat_map/base_mapper/attribute_methods.rb +54 -0
- data/lib/flat_map/base_mapper/factory.rb +238 -0
- data/lib/flat_map/base_mapper/mapping.rb +123 -0
- data/lib/flat_map/base_mapper/mounting.rb +168 -0
- data/lib/flat_map/base_mapper/persistence.rb +145 -0
- data/lib/flat_map/base_mapper/skipping.rb +62 -0
- data/lib/flat_map/base_mapper/traits.rb +94 -0
- data/lib/flat_map/empty_mapper.rb +29 -0
- data/lib/flat_map/errors.rb +57 -0
- data/lib/flat_map/mapper.rb +213 -0
- data/lib/flat_map/mapper/skipping.rb +45 -0
- data/lib/flat_map/mapper/targeting.rb +130 -0
- data/lib/flat_map/mapping.rb +124 -0
- data/lib/flat_map/mapping/factory.rb +21 -0
- data/lib/flat_map/mapping/reader.rb +12 -0
- data/lib/flat_map/mapping/reader/basic.rb +28 -0
- data/lib/flat_map/mapping/reader/formatted.rb +45 -0
- data/lib/flat_map/mapping/reader/formatted/formats.rb +28 -0
- data/lib/flat_map/mapping/reader/method.rb +25 -0
- data/lib/flat_map/mapping/reader/proc.rb +15 -0
- data/lib/flat_map/mapping/writer.rb +11 -0
- data/lib/flat_map/mapping/writer/basic.rb +25 -0
- data/lib/flat_map/mapping/writer/method.rb +28 -0
- data/lib/flat_map/mapping/writer/proc.rb +18 -0
- data/lib/flat_map/version.rb +3 -0
- data/spec/flat_map/empty_mapper_spec.rb +36 -0
- data/spec/flat_map/errors_spec.rb +23 -0
- data/spec/flat_map/mapper/attribute_methods_spec.rb +36 -0
- data/spec/flat_map/mapper/callbacks_spec.rb +76 -0
- data/spec/flat_map/mapper/factory_spec.rb +258 -0
- data/spec/flat_map/mapper/mapping_spec.rb +98 -0
- data/spec/flat_map/mapper/mounting_spec.rb +142 -0
- data/spec/flat_map/mapper/skipping_spec.rb +91 -0
- data/spec/flat_map/mapper/targeting_spec.rb +156 -0
- data/spec/flat_map/mapper/traits_spec.rb +172 -0
- data/spec/flat_map/mapper/validations_spec.rb +72 -0
- data/spec/flat_map/mapper_spec.rb +9 -0
- data/spec/flat_map/mapping/factory_spec.rb +12 -0
- data/spec/flat_map/mapping/reader/basic_spec.rb +15 -0
- data/spec/flat_map/mapping/reader/formatted_spec.rb +62 -0
- data/spec/flat_map/mapping/reader/method_spec.rb +13 -0
- data/spec/flat_map/mapping/reader/proc_spec.rb +13 -0
- data/spec/flat_map/mapping/writer/basic_spec.rb +15 -0
- data/spec/flat_map/mapping/writer/method_spec.rb +13 -0
- data/spec/flat_map/mapping/writer/proc_spec.rb +13 -0
- data/spec/flat_map/mapping_spec.rb +123 -0
- data/spec/spec_helper.rb +7 -0
- data/tmp/metric_fu/_data/20131218.yml +6902 -0
- data/tmp/metric_fu/_data/20131219.yml +6726 -0
- metadata +184 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
module FlatMap
|
2
|
+
module Mapping::Reader
|
3
|
+
# Proc reader accepts a lambda and calls it with the target
|
4
|
+
# as an argument for reading.
|
5
|
+
class Proc < Method
|
6
|
+
# Call a <tt>@method</tt>, which is a {Proc} object,
|
7
|
+
# passing the +target+ object to it.
|
8
|
+
#
|
9
|
+
# @return [Object] value returned by reader's lambda
|
10
|
+
def read
|
11
|
+
@method.call(target)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module FlatMap
|
2
|
+
# Writer module hosts various writer classes that are used
|
3
|
+
# by mappings to assign values to the target of an associated mapper.
|
4
|
+
module Mapping::Writer
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
autoload :Basic
|
8
|
+
autoload :Method
|
9
|
+
autoload :Proc
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module FlatMap
|
2
|
+
module Mapping::Writer
|
3
|
+
# Basic writer simply calls the target's attribute assignment method
|
4
|
+
# passing to it the value being written.
|
5
|
+
class Basic
|
6
|
+
attr_reader :mapping
|
7
|
+
|
8
|
+
delegate :target, :target_attribute, :to => :mapping
|
9
|
+
|
10
|
+
# Initialize writer by passing +mapping+ to it.
|
11
|
+
def initialize(mapping)
|
12
|
+
@mapping = mapping
|
13
|
+
end
|
14
|
+
|
15
|
+
# Call the assignment method of the target, passing
|
16
|
+
# the +value+ to it.
|
17
|
+
#
|
18
|
+
# @param [Object] value
|
19
|
+
# @return [Object] result of assignment
|
20
|
+
def write(value)
|
21
|
+
target.send("#{target_attribute}=", value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module FlatMap
|
2
|
+
module Mapping::Writer
|
3
|
+
# Method writer calls a method defined by mapper and sends mapping
|
4
|
+
# and value to it as arguments.
|
5
|
+
#
|
6
|
+
# Note that this doesn't set anything on the target itself.
|
7
|
+
class Method < Basic
|
8
|
+
delegate :mapper, :to => :mapping
|
9
|
+
|
10
|
+
# Initialize the writer with a +mapping+ and +method+ name
|
11
|
+
# that should be called on the mapping's mapper.
|
12
|
+
#
|
13
|
+
# @param [FlatMap::Mapping] mapping
|
14
|
+
# @param [Symbol] method
|
15
|
+
def initialize(mapping, method)
|
16
|
+
@mapping, @method = mapping, method
|
17
|
+
end
|
18
|
+
|
19
|
+
# Write a +value+ by sending it, along with the mapping itself.
|
20
|
+
#
|
21
|
+
# @param [Object] value
|
22
|
+
# @return [Object] result of writing
|
23
|
+
def write(value)
|
24
|
+
mapper.send(@method, mapping, value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module FlatMap
|
2
|
+
module Mapping::Writer
|
3
|
+
# Proc writer calls a lambda passed on the mapping definition and
|
4
|
+
# sends the mapper's target and value to it.
|
5
|
+
#
|
6
|
+
# Note that this doesn't set anything on the target itself.
|
7
|
+
class Proc < Method
|
8
|
+
# Call a <tt>@method</tt>, which is a +Proc+ object,
|
9
|
+
# passing it the mapping's +target+ and +value+.
|
10
|
+
#
|
11
|
+
# @param [Object] value
|
12
|
+
# @return [Object] result of writing
|
13
|
+
def write(value)
|
14
|
+
@method.call(target, value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module EmptyMapperSpec
|
4
|
+
class MountedMapper < ::FlatMap::Mapper
|
5
|
+
end
|
6
|
+
|
7
|
+
class Mapper < ::FlatMap::EmptyMapper
|
8
|
+
mount :mounted,
|
9
|
+
:mapper_class_name => 'EmptyMapperSpec::MountedMapper',
|
10
|
+
:target => Object.new
|
11
|
+
|
12
|
+
trait :some_trait do
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module FlatMap
|
18
|
+
describe EmptyMapper do
|
19
|
+
let(:mapper){ EmptyMapperSpec::Mapper.new(:some_trait){} }
|
20
|
+
|
21
|
+
it 'should be normally initialized' do
|
22
|
+
mapper.mounting(:mounted).should be_present
|
23
|
+
mapper.trait(:some_trait).should be_present
|
24
|
+
mapper.extension.should be_present
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should raise error for malounted mapper when target is not specified' do
|
28
|
+
mapper_class = Class.new(::FlatMap::EmptyMapper) do
|
29
|
+
mount :mounted, :mapper_class_name => 'EmptyMapperSpec::MountedMapper'
|
30
|
+
end
|
31
|
+
|
32
|
+
expect{ mapper_class.new.mounting(:mounted) }.
|
33
|
+
to raise_error(::FlatMap::Mapper::Targeting::NoTargetError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FlatMap::Errors do
|
4
|
+
let(:errors) {
|
5
|
+
described_class.new(
|
6
|
+
double( 'mapper', :suffixed? => true,
|
7
|
+
:suffix => 'foo',
|
8
|
+
'attr_foo' => 2)
|
9
|
+
)
|
10
|
+
}
|
11
|
+
|
12
|
+
it "preserved errors should appear on #empty? call exactly once" do
|
13
|
+
errors.preserve :base, 'an error'
|
14
|
+
errors.should_not be_empty
|
15
|
+
errors[:base].should == ['an error']
|
16
|
+
expect{ errors.empty? }.not_to change{ errors[:base].length }
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should add error to mapper with suffix" do
|
20
|
+
errors.add(:attr, 'an error')
|
21
|
+
errors[:attr_foo].should == ['an error']
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FlatMap
|
4
|
+
module AttributeMethodsSpec
|
5
|
+
class SpecMapper < Mapper
|
6
|
+
map :attr_a, :attr_b
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'Attribute Methods' do
|
11
|
+
let(:target){ OpenStruct.new }
|
12
|
+
let(:mapper){ AttributeMethodsSpec::SpecMapper.new(target) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
target.attr_a = 'a'
|
16
|
+
target.attr_b = 'b'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should be able to read values via method calls' do
|
20
|
+
mapper.attr_a.should == 'a'
|
21
|
+
mapper.attr_b.should == 'b'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should be able to write values via method calls' do
|
25
|
+
mapper.attr_a = 'A'
|
26
|
+
mapper.attr_b = 'B'
|
27
|
+
target.attr_a.should == 'A'
|
28
|
+
target.attr_b.should == 'B'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should still raise for unknown or private method calls' do
|
32
|
+
expect{ mapper.undefined_method }.to raise_error(NoMethodError)
|
33
|
+
expect{ mapper.attribute_methods }.to raise_error(NoMethodError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FlatMap
|
4
|
+
module CallbacksSpec
|
5
|
+
class MountMapper < Mapper
|
6
|
+
map :attr_c
|
7
|
+
|
8
|
+
set_callback :validate, :before, :set_c
|
9
|
+
|
10
|
+
def set_c
|
11
|
+
self.attr_c = 'mounted before validate'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class SpecMapper < Mapper
|
16
|
+
map :attr_a
|
17
|
+
|
18
|
+
set_callback :save, :before, :set_a
|
19
|
+
|
20
|
+
trait :with_b do
|
21
|
+
map :attr_b
|
22
|
+
|
23
|
+
set_callback :validate, :before, :set_b
|
24
|
+
|
25
|
+
def set_b
|
26
|
+
self.attr_b = 'before validate'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_a
|
31
|
+
self.attr_a = 'before save'
|
32
|
+
end
|
33
|
+
|
34
|
+
mount :mount,
|
35
|
+
:mapper_class_name => 'FlatMap::CallbacksSpec::MountMapper',
|
36
|
+
:target => lambda{ |_| OpenStruct.new }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'Callbacks' do
|
41
|
+
let(:mapper) do
|
42
|
+
CallbacksSpec::SpecMapper.new(OpenStruct.new, :with_b) do
|
43
|
+
set_callback :validate, :before, :extension_set_b
|
44
|
+
|
45
|
+
def extension_set_b
|
46
|
+
self.attr_b = 'extension value'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should call callbacks once' do
|
52
|
+
mapper.should_receive(:set_a).once
|
53
|
+
mapper.save
|
54
|
+
end
|
55
|
+
|
56
|
+
specify 'validation callbacks' do
|
57
|
+
mapper.valid?
|
58
|
+
mapper.attr_a.should be_nil
|
59
|
+
mapper.attr_b.should == 'before validate'
|
60
|
+
mapper.attr_c.should == 'mounted before validate'
|
61
|
+
end
|
62
|
+
|
63
|
+
specify 'save callbacks' do
|
64
|
+
mapper.save
|
65
|
+
mapper.attr_a.should == 'before save'
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'extension trait and named traits' do
|
69
|
+
it 'should process extension first' do
|
70
|
+
mapper.extension.should_receive(:extension_set_b).once.and_call_original
|
71
|
+
mapper.valid?
|
72
|
+
mapper.attr_b.should == 'before validate'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FlatMap
|
4
|
+
describe BaseMapper::Factory do
|
5
|
+
let(:trait_class){ Class.new(Mapper) }
|
6
|
+
let(:target){ Object.new }
|
7
|
+
let(:other_target){ Object.new }
|
8
|
+
let(:mapper){ Class.new(Mapper).new(target) }
|
9
|
+
let(:mount_factory){ BaseMapper::Factory.new(:spec_mount, :traits => :used_traits) }
|
10
|
+
let(:trait_factory){ BaseMapper::Factory.new(trait_class, :trait_name => :a_trait) }
|
11
|
+
|
12
|
+
context 'when used for a trait' do
|
13
|
+
subject{ trait_factory }
|
14
|
+
|
15
|
+
it{ should be_traited }
|
16
|
+
its(:name){ should be_nil }
|
17
|
+
its(:trait_name){ should == :a_trait }
|
18
|
+
its(:mapper_class){ should == trait_class }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when used for a mounted mapper' do
|
22
|
+
subject{ mount_factory }
|
23
|
+
|
24
|
+
it{ should_not be_traited }
|
25
|
+
its(:name){ should == :spec_mount }
|
26
|
+
its(:trait_name){ should be_nil }
|
27
|
+
its(:traits){ should == [:used_traits] }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'behavior' do
|
31
|
+
describe '#mapper_class for mounted mappers' do
|
32
|
+
class ::SpecMountMapper < Mapper; end
|
33
|
+
class BaseMapper::Factory::SpecMountMapper; end
|
34
|
+
|
35
|
+
it "should be able to fetch class name from name" do
|
36
|
+
mount_factory.mapper_class.should == ::SpecMountMapper
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should use options if specified" do
|
40
|
+
factory = BaseMapper::Factory.new(
|
41
|
+
:spec_mount,
|
42
|
+
:mapper_class_name => 'FlatMap::BaseMapper::Factory::SpecMountMapper'
|
43
|
+
)
|
44
|
+
factory.mapper_class.should == ::FlatMap::BaseMapper::Factory::SpecMountMapper
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#fetch_target_from' do
|
49
|
+
it "should return owner's target for traited factory" do
|
50
|
+
trait_factory.fetch_target_from(mapper).should == target
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'explicit target' do
|
54
|
+
it "should use explicitly specified if applicable" do
|
55
|
+
factory = BaseMapper::Factory.new(:mount, :target => other_target)
|
56
|
+
factory.fetch_target_from(mapper).should == other_target
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should call Proc and pass owner target to it if Proc is specified as :target" do
|
60
|
+
factory = BaseMapper::Factory.new(:mount, :target => lambda{ |obj| obj.foo })
|
61
|
+
target.should_receive(:foo).and_return(other_target)
|
62
|
+
factory.fetch_target_from(mapper).should == other_target
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'target from association' do
|
67
|
+
before{ target.stub(:kind_of?).with(ActiveRecord::Base).and_return(true) }
|
68
|
+
|
69
|
+
let(:has_one_current_reflection) {
|
70
|
+
double('reflection', :macro => :has_one, :options => {:is_current => true})
|
71
|
+
}
|
72
|
+
let(:has_one_reflection) {
|
73
|
+
double('reflection', :macro => :has_one, :options => {})
|
74
|
+
}
|
75
|
+
let(:belongs_to_reflection) {
|
76
|
+
double('reflection', :macro => :belongs_to)
|
77
|
+
}
|
78
|
+
let(:has_many_reflection) {
|
79
|
+
double('reflection', :macro => :has_many, :name => :spec_mounts)
|
80
|
+
}
|
81
|
+
|
82
|
+
it "should refer to effective name for has_one_current association" do
|
83
|
+
# Note: has_one_current is not part of Rails
|
84
|
+
mount_factory.should_receive(:reflection_from_target).
|
85
|
+
with(target).
|
86
|
+
and_return(has_one_current_reflection)
|
87
|
+
target.should_receive(:effective_spec_mount).and_return(other_target)
|
88
|
+
mount_factory.fetch_target_from(mapper).should == other_target
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should refer to existing association object if possible, " \
|
92
|
+
"and build it if it is absent for :has_one" do
|
93
|
+
mount_factory.should_receive(:reflection_from_target).
|
94
|
+
with(target).
|
95
|
+
and_return(has_one_reflection)
|
96
|
+
target.should_receive(:spec_mount).and_return(nil)
|
97
|
+
target.should_receive(:build_spec_mount).and_return(other_target)
|
98
|
+
mount_factory.fetch_target_from(mapper).should == other_target
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should refer to existing association object if possible, " \
|
102
|
+
"and build it if it is absent for :belongs_to" do
|
103
|
+
mount_factory.should_receive(:reflection_from_target).
|
104
|
+
with(target).
|
105
|
+
and_return(belongs_to_reflection)
|
106
|
+
target.should_receive(:spec_mount).and_return(nil)
|
107
|
+
target.should_receive(:build_spec_mount).and_return(other_target)
|
108
|
+
mount_factory.fetch_target_from(mapper).should == other_target
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should always build a new record for :has_many association" do
|
112
|
+
mount_factory.should_receive(:reflection_from_target).
|
113
|
+
with(target).
|
114
|
+
and_return(has_many_reflection)
|
115
|
+
target.should_receive(:association).with(:spec_mounts)
|
116
|
+
target.stub_chain(:association, :build).and_return(other_target)
|
117
|
+
mount_factory.fetch_target_from(mapper).should == other_target
|
118
|
+
end
|
119
|
+
|
120
|
+
describe 'reflection_from_target' do
|
121
|
+
before{ target.stub(:is_a?).with(ActiveRecord::Base).and_return(true) }
|
122
|
+
|
123
|
+
it 'should first refer to singular association' do
|
124
|
+
target.stub_chain(:class, :reflect_on_association).
|
125
|
+
with(:spec_mount).
|
126
|
+
and_return(has_one_reflection)
|
127
|
+
mount_factory.reflection_from_target(target).should == has_one_reflection
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should use collection association if singular does not exist' do
|
131
|
+
target.stub_chain(:class, :reflect_on_association).
|
132
|
+
with(:spec_mount).
|
133
|
+
and_return(nil)
|
134
|
+
target.stub_chain(:class, :reflect_on_association).
|
135
|
+
with(:spec_mounts).
|
136
|
+
and_return(has_many_reflection)
|
137
|
+
mount_factory.reflection_from_target(target).should == has_many_reflection
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'target from name' do
|
143
|
+
it 'should simply send method to owner target' do
|
144
|
+
target.should_receive(:spec_mount).and_return(other_target)
|
145
|
+
mount_factory.fetch_target_from(mapper).should == other_target
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe '#create' do
|
151
|
+
specify 'traited factory should create an owned mapper' do
|
152
|
+
new_one = trait_factory.create(mapper)
|
153
|
+
new_one.owner.should == mapper
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'mounted empty mapper' do
|
157
|
+
class ::SpecEmptyMountMapper < EmptyMapper; end
|
158
|
+
let(:factory){ BaseMapper::Factory.new(:spec_empty_mount) }
|
159
|
+
|
160
|
+
it 'should not call fetch_target_from' do
|
161
|
+
factory.should_not_receive(:fetch_target_from)
|
162
|
+
factory.create(mapper)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'mounted mapper' do
|
167
|
+
let(:mount_class){ Class.new(Mapper) }
|
168
|
+
let(:factory){ mount_factory }
|
169
|
+
|
170
|
+
before do
|
171
|
+
factory.stub(:mapper_class).and_return(mount_class)
|
172
|
+
factory.stub(:fetch_target_from).and_return(other_target)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'should combine traits' do
|
176
|
+
mount_class.should_receive(:new).
|
177
|
+
with(other_target, :used_traits, :another_trait).
|
178
|
+
and_call_original
|
179
|
+
factory.create(mapper, :another_trait)
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should properly set properties' do
|
183
|
+
new_one = factory.create(mapper)
|
184
|
+
new_one.host .should == mapper
|
185
|
+
new_one.name .should == :spec_mount
|
186
|
+
new_one.save_order.should == :after
|
187
|
+
new_one.suffix.should be_nil
|
188
|
+
end
|
189
|
+
|
190
|
+
context 'when suffix is defined' do
|
191
|
+
let(:factory){ BaseMapper::Factory.new(:spec_mount, :suffix => :foo) }
|
192
|
+
|
193
|
+
it "should adjust properties with suffix" do
|
194
|
+
new_one = factory.create(mapper)
|
195
|
+
new_one.name .should == :spec_mount_foo
|
196
|
+
new_one.suffix.should == :foo
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context 'when extension is present' do
|
201
|
+
let(:extension){ Proc.new{} }
|
202
|
+
let(:factory){ BaseMapper::Factory.new(:spec_mount, &extension) }
|
203
|
+
|
204
|
+
it "should pass it to mapper initialization" do
|
205
|
+
mount_class.should_receive(:new).
|
206
|
+
with(other_target, &extension).
|
207
|
+
and_call_original
|
208
|
+
new_one = factory.create(mapper)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe 'save order' do
|
213
|
+
context 'when explicitly set' do
|
214
|
+
let(:factory){ BaseMapper::Factory.new(:spec_mount, :save => :before) }
|
215
|
+
|
216
|
+
it 'should fetch from options, if possible' do
|
217
|
+
new_one = factory.create(mapper)
|
218
|
+
new_one.save_order.should == :before
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'should be :before for belongs_to association' do
|
223
|
+
mount_factory.stub(:reflection_from_target).
|
224
|
+
and_return(double('reflection', :macro => :belongs_to))
|
225
|
+
factory.fetch_save_order(mapper).should == :before
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'should be :after for other cases' do
|
229
|
+
mount_factory.stub(:reflection_from_target).
|
230
|
+
and_return(double('reflection', :macro => :has_one))
|
231
|
+
factory.fetch_save_order(mapper).should == :after
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
describe '#required_for_any_trait?' do
|
238
|
+
let(:mapper_class) do
|
239
|
+
Class.new(FlatMap::Mapper) do
|
240
|
+
trait(:trait_a) {
|
241
|
+
trait(:trait_b) {
|
242
|
+
trait(:trait_c) {
|
243
|
+
} } }
|
244
|
+
end
|
245
|
+
end
|
246
|
+
let(:factory_for_b){ mapper_class.mountings.first.mapper_class.mountings.first }
|
247
|
+
|
248
|
+
it "should be required for nested trait" do
|
249
|
+
factory_for_b.required_for_any_trait?([:trait_c]).should be_true
|
250
|
+
end
|
251
|
+
|
252
|
+
it "should not be required for top trait" do
|
253
|
+
factory_for_b.required_for_any_trait?([:trait_a]).should be_false
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|