dm-core 1.1.0.rc2 → 1.1.0.rc3
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.
- data/Gemfile +1 -8
- data/VERSION +1 -1
- data/dm-core.gemspec +24 -15
- data/lib/dm-core.rb +9 -48
- data/lib/dm-core/adapters.rb +1 -1
- data/lib/dm-core/adapters/abstract_adapter.rb +2 -1
- data/lib/dm-core/associations/many_to_many.rb +3 -3
- data/lib/dm-core/associations/many_to_one.rb +15 -4
- data/lib/dm-core/associations/one_to_many.rb +1 -1
- data/lib/dm-core/associations/relationship.rb +7 -6
- data/lib/dm-core/collection.rb +7 -2
- data/lib/dm-core/core_ext/pathname.rb +0 -14
- data/lib/dm-core/ext/array.rb +41 -0
- data/lib/dm-core/ext/blank.rb +24 -0
- data/lib/dm-core/ext/hash.rb +67 -0
- data/lib/dm-core/ext/module.rb +49 -0
- data/lib/dm-core/ext/object.rb +57 -0
- data/lib/dm-core/ext/singleton_class.rb +8 -0
- data/lib/dm-core/ext/string.rb +24 -0
- data/lib/dm-core/ext/try_dup.rb +12 -0
- data/lib/dm-core/model.rb +2 -1
- data/lib/dm-core/model/property.rb +3 -2
- data/lib/dm-core/property.rb +1 -1
- data/lib/dm-core/property/class.rb +1 -1
- data/lib/dm-core/property/date.rb +3 -3
- data/lib/dm-core/property/date_time.rb +3 -3
- data/lib/dm-core/property/time.rb +3 -3
- data/lib/dm-core/property/typecast/time.rb +2 -2
- data/lib/dm-core/property_set.rb +1 -1
- data/lib/dm-core/query.rb +9 -12
- data/lib/dm-core/resource.rb +2 -2
- data/lib/dm-core/spec/lib/counter_adapter.rb +1 -1
- data/lib/dm-core/spec/lib/spec_helper.rb +1 -1
- data/lib/dm-core/spec/shared/resource_spec.rb +2 -1
- data/lib/dm-core/support/equalizer.rb +1 -1
- data/lib/dm-core/support/hook.rb +0 -15
- data/lib/dm-core/support/inflections.rb +60 -0
- data/lib/dm-core/support/inflector.rb +3 -0
- data/lib/dm-core/support/inflector/inflections.rb +211 -0
- data/lib/dm-core/support/inflector/methods.rb +151 -0
- data/lib/dm-core/support/lazy_array.rb +4 -4
- data/lib/dm-core/support/mash.rb +176 -0
- data/lib/dm-core/support/subject.rb +1 -1
- data/lib/dm-core/version.rb +1 -1
- data/spec/public/model/relationship_spec.rb +2 -1
- data/spec/public/shared/collection_shared_spec.rb +5 -2
- data/spec/public/shared/finder_shared_spec.rb +10 -6
- data/spec/semipublic/adapters/in_memory_adapter_spec.rb +1 -1
- data/spec/semipublic/query_spec.rb +2 -2
- data/spec/semipublic/resource/state/immutable_spec.rb +2 -1
- data/spec/semipublic/resource/state_spec.rb +1 -3
- data/spec/semipublic/shared/resource_state_shared_spec.rb +2 -1
- data/spec/semipublic/shared/subject_shared_spec.rb +1 -1
- data/spec/support/core_ext/hash.rb +10 -0
- data/spec/support/core_ext/inheritable_attributes.rb +46 -0
- data/spec/unit/array_spec.rb +8 -20
- data/spec/unit/blank_spec.rb +62 -0
- data/spec/unit/data_mapper/ordered_set/hash_spec.rb +1 -1
- data/spec/unit/hash_spec.rb +8 -16
- data/spec/unit/lazy_array_spec.rb +3 -14
- data/spec/unit/mash_spec.rb +312 -0
- data/spec/unit/module_spec.rb +15 -15
- data/spec/unit/object_spec.rb +9 -9
- data/spec/unit/try_dup_spec.rb +8 -8
- metadata +32 -39
- data/lib/dm-core/core_ext/array.rb +0 -36
- data/lib/dm-core/core_ext/hash.rb +0 -30
- data/lib/dm-core/core_ext/module.rb +0 -46
- data/lib/dm-core/core_ext/object.rb +0 -31
- data/lib/dm-core/core_ext/string.rb +0 -22
- data/lib/dm-core/core_ext/try_dup.rb +0 -44
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'dm-core/
|
1
|
+
require 'dm-core/ext/try_dup'
|
2
2
|
|
3
3
|
class LazyArray # borrowed partially from StrokeDB
|
4
4
|
include Enumerable
|
@@ -358,9 +358,9 @@ class LazyArray # borrowed partially from StrokeDB
|
|
358
358
|
end
|
359
359
|
|
360
360
|
def initialize_copy(original)
|
361
|
-
@head = @head
|
362
|
-
@tail = @tail
|
363
|
-
@array = @array
|
361
|
+
@head = DataMapper::Ext.try_dup(@head)
|
362
|
+
@tail = DataMapper::Ext.try_dup(@tail)
|
363
|
+
@array = DataMapper::Ext.try_dup(@array)
|
364
364
|
end
|
365
365
|
|
366
366
|
def lazy_load
|
@@ -0,0 +1,176 @@
|
|
1
|
+
module DataMapper
|
2
|
+
# This class has dubious semantics and we only have it so that people can write
|
3
|
+
# params[:key] instead of params['key'].
|
4
|
+
class Mash < Hash
|
5
|
+
|
6
|
+
# Initializes a new mash.
|
7
|
+
#
|
8
|
+
# @param [Hash, Object] constructor
|
9
|
+
# The default value for the mash. If +constructor+ is a Hash, a new mash
|
10
|
+
# will be created based on the keys of the hash and no default value will
|
11
|
+
# be set.
|
12
|
+
def initialize(constructor = {})
|
13
|
+
if constructor.is_a?(Hash)
|
14
|
+
super()
|
15
|
+
update(constructor)
|
16
|
+
else
|
17
|
+
super(constructor)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Gets the default value for the mash.
|
22
|
+
#
|
23
|
+
# @param [Object] key
|
24
|
+
# The default value for the mash. If +key+ is a Symbol and it is a key in
|
25
|
+
# the mash, then the default value will be set to the value matching the
|
26
|
+
# key.
|
27
|
+
def default(key = nil)
|
28
|
+
if key.is_a?(Symbol) && include?(key = key.to_s)
|
29
|
+
self[key]
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
36
|
+
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
37
|
+
|
38
|
+
# Sets the +value+ associated with the specified +key+.
|
39
|
+
#
|
40
|
+
# @param [Object] key The key to set.
|
41
|
+
# @param [Object] value The value to set the key to.
|
42
|
+
def []=(key, value)
|
43
|
+
regular_writer(convert_key(key), convert_value(value))
|
44
|
+
end
|
45
|
+
|
46
|
+
# Updates the mash with the key/value pairs from the specified hash.
|
47
|
+
#
|
48
|
+
# @param [Hash] other_hash
|
49
|
+
# A hash to update values in the mash with. The keys and the values will be
|
50
|
+
# converted to Mash format.
|
51
|
+
#
|
52
|
+
# @return [Mash] The updated mash.
|
53
|
+
def update(other_hash)
|
54
|
+
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
alias_method :merge!, :update
|
59
|
+
|
60
|
+
# Determines whether the mash contains the specified +key+.
|
61
|
+
#
|
62
|
+
# @param [Object] key The key to check for.
|
63
|
+
# @return [Boolean] True if the key exists in the mash.
|
64
|
+
def key?(key)
|
65
|
+
super(convert_key(key))
|
66
|
+
end
|
67
|
+
|
68
|
+
alias_method :include?, :key?
|
69
|
+
alias_method :has_key?, :key?
|
70
|
+
alias_method :member?, :key?
|
71
|
+
|
72
|
+
# @param [Object] key The key to fetch.
|
73
|
+
# @param [Array] *extras Default value.
|
74
|
+
#
|
75
|
+
# @return [Object] The value at key or the default value.
|
76
|
+
def fetch(key, *extras)
|
77
|
+
super(convert_key(key), *extras)
|
78
|
+
end
|
79
|
+
|
80
|
+
# @param [Array] *indices
|
81
|
+
# The keys to retrieve values for.
|
82
|
+
#
|
83
|
+
# @return [Array] The values at each of the provided keys.
|
84
|
+
def values_at(*indices)
|
85
|
+
indices.collect {|key| self[convert_key(key)]}
|
86
|
+
end
|
87
|
+
|
88
|
+
# @param [Hash] hash The hash to merge with the mash.
|
89
|
+
#
|
90
|
+
# @return [Mash] A new mash with the hash values merged in.
|
91
|
+
def merge(hash)
|
92
|
+
self.dup.update(hash)
|
93
|
+
end
|
94
|
+
|
95
|
+
# @param [Object] key The key to delete from the mash.
|
96
|
+
def delete(key)
|
97
|
+
super(convert_key(key))
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns a mash that includes everything but the given +keys+.
|
101
|
+
#
|
102
|
+
# @param [Array<String, Symbol>] *keys The mash keys to exclude.
|
103
|
+
#
|
104
|
+
# @return [Mash] A new mash without the selected keys.
|
105
|
+
#
|
106
|
+
# @example
|
107
|
+
# { :one => 1, :two => 2, :three => 3 }.except(:one)
|
108
|
+
# #=> { "two" => 2, "three" => 3 }
|
109
|
+
def except(*keys)
|
110
|
+
self.dup.except!(*keys.map {|k| convert_key(k)})
|
111
|
+
end
|
112
|
+
|
113
|
+
# Removes the specified +keys+ from the mash.
|
114
|
+
#
|
115
|
+
# @param [Array] *keys The mash keys to exclude.
|
116
|
+
#
|
117
|
+
# @return [Hash] +hash+
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
# mash = { :one => 1, :two => 2, :three => 3 }
|
121
|
+
# mash.except!(:one, :two)
|
122
|
+
# mash # => { :three => 3 }
|
123
|
+
def except!(*keys)
|
124
|
+
keys.each { |key| delete(key) }
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
# Used to provide the same interface as Hash.
|
129
|
+
#
|
130
|
+
# @return [Mash] This mash unchanged.
|
131
|
+
def stringify_keys!; self end
|
132
|
+
|
133
|
+
# @return [Hash] The mash as a Hash with symbolized keys.
|
134
|
+
def symbolize_keys
|
135
|
+
h = Hash.new(default)
|
136
|
+
each { |key, val| h[key.to_sym] = val }
|
137
|
+
h
|
138
|
+
end
|
139
|
+
|
140
|
+
# @return [Hash] The mash as a Hash with string keys.
|
141
|
+
def to_hash
|
142
|
+
Hash.new(default).merge(self)
|
143
|
+
end
|
144
|
+
|
145
|
+
protected
|
146
|
+
# @param [Object] key The key to convert.
|
147
|
+
#
|
148
|
+
# @param [Object]
|
149
|
+
# The converted key. If the key was a symbol, it will be converted to a
|
150
|
+
# string.
|
151
|
+
#
|
152
|
+
# @api private
|
153
|
+
def convert_key(key)
|
154
|
+
key.kind_of?(Symbol) ? key.to_s : key
|
155
|
+
end
|
156
|
+
|
157
|
+
# @param [Object] value The value to convert.
|
158
|
+
#
|
159
|
+
# @return [Object]
|
160
|
+
# The converted value. A Hash or an Array of hashes, will be converted to
|
161
|
+
# their Mash equivalents.
|
162
|
+
#
|
163
|
+
# @api private
|
164
|
+
def convert_value(value)
|
165
|
+
if value.class == Hash
|
166
|
+
mash = Mash.new(value)
|
167
|
+
mash.default = value.default
|
168
|
+
mash
|
169
|
+
elsif value.is_a?(Array)
|
170
|
+
value.collect { |e| convert_value(e) }
|
171
|
+
else
|
172
|
+
value
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
data/lib/dm-core/version.rb
CHANGED
@@ -281,7 +281,8 @@ share_examples_for 'it creates a many accessor' do
|
|
281
281
|
@expected.should_not be_nil
|
282
282
|
|
283
283
|
# set the model scope to only return the first record
|
284
|
-
@model.default_scope.update(
|
284
|
+
@model.default_scope.update(
|
285
|
+
DataMapper::Ext::Array.to_hash(@model.key(@repository.name).zip(@expected.key)))
|
285
286
|
|
286
287
|
@return = @car.model.get(*@car.key).__send__(@name)
|
287
288
|
end
|
@@ -123,7 +123,10 @@ share_examples_for 'A public Collection' do
|
|
123
123
|
end
|
124
124
|
|
125
125
|
it 'should update the Collection inline' do
|
126
|
-
@articles.each { |resource|
|
126
|
+
@articles.each { |resource|
|
127
|
+
DataMapper::Ext::Hash.only(resource.attributes, :title, :content).should ==
|
128
|
+
{ :title => 'Sample Article', :content => 'New Content' }
|
129
|
+
}
|
127
130
|
end
|
128
131
|
end
|
129
132
|
end
|
@@ -919,7 +922,7 @@ share_examples_for 'A public Collection' do
|
|
919
922
|
end
|
920
923
|
|
921
924
|
it 'should be a Resource with attributes matching the Hash' do
|
922
|
-
@return.first.attributes
|
925
|
+
DataMapper::Ext::Hash.only(@return.first.attributes, *@array.first.keys).should == @array.first
|
923
926
|
end
|
924
927
|
end
|
925
928
|
end
|
@@ -342,7 +342,8 @@ share_examples_for 'Finder Interface' do
|
|
342
342
|
|
343
343
|
describe 'with a collection' do
|
344
344
|
before :all do
|
345
|
-
@collection = @article_model.all(
|
345
|
+
@collection = @article_model.all(
|
346
|
+
DataMapper::Ext::Array.to_hash(@article_model.key.zip(@original.key)))
|
346
347
|
|
347
348
|
@return = @articles.all(:original => @collection)
|
348
349
|
end
|
@@ -479,7 +480,8 @@ share_examples_for 'Finder Interface' do
|
|
479
480
|
|
480
481
|
describe 'with a collection' do
|
481
482
|
before :all do
|
482
|
-
@collection = @article_model.all(
|
483
|
+
@collection = @article_model.all(
|
484
|
+
DataMapper::Ext::Array.to_hash(@article_model.key.zip(@new.key)))
|
483
485
|
|
484
486
|
@return = @articles.all(:previous => @collection)
|
485
487
|
end
|
@@ -615,7 +617,8 @@ share_examples_for 'Finder Interface' do
|
|
615
617
|
|
616
618
|
describe 'with a collection' do
|
617
619
|
before :all do
|
618
|
-
@collection = @article_model.all(
|
620
|
+
@collection = @article_model.all(
|
621
|
+
DataMapper::Ext::Array.to_hash(@article_model.key.zip(@new.key)))
|
619
622
|
|
620
623
|
@return = @articles.all(:revisions => @collection)
|
621
624
|
end
|
@@ -755,7 +758,8 @@ share_examples_for 'Finder Interface' do
|
|
755
758
|
|
756
759
|
describe 'with a collection' do
|
757
760
|
before :all do
|
758
|
-
@collection = @publication_model.all(
|
761
|
+
@collection = @publication_model.all(
|
762
|
+
DataMapper::Ext::Array.to_hash(@publication_model.key.zip(@publication.key)))
|
759
763
|
|
760
764
|
@return = @articles.all(:publications => @collection)
|
761
765
|
end
|
@@ -1093,7 +1097,7 @@ share_examples_for 'Finder Interface' do
|
|
1093
1097
|
end
|
1094
1098
|
|
1095
1099
|
it 'should be expected Resource' do
|
1096
|
-
@resource.attributes
|
1100
|
+
DataMapper::Ext::Hash.only(@resource.attributes, *@conditions.keys).should == @conditions
|
1097
1101
|
end
|
1098
1102
|
|
1099
1103
|
it 'should be a saved Resource' do
|
@@ -1136,7 +1140,7 @@ share_examples_for 'Finder Interface' do
|
|
1136
1140
|
end
|
1137
1141
|
|
1138
1142
|
it 'should be expected Resource' do
|
1139
|
-
@resource.attributes
|
1143
|
+
DataMapper::Ext::Hash.only(@resource.attributes, *@conditions.keys).should == @conditions
|
1140
1144
|
end
|
1141
1145
|
|
1142
1146
|
it 'should not be a saved Resource' do
|
@@ -791,7 +791,7 @@ describe DataMapper::Query do
|
|
791
791
|
it 'should raise an exception' do
|
792
792
|
lambda {
|
793
793
|
DataMapper::Query.new(@repository, @model, @options.update(:conditions => { 'unknown.id' => 1 }))
|
794
|
-
}.should raise_error(ArgumentError, "condition \"unknown.id\" does not map to a relationship in #{@model}")
|
794
|
+
}.should raise_error(ArgumentError, "condition \"unknown.id\" does not map to a property or relationship in #{@model}")
|
795
795
|
end
|
796
796
|
end
|
797
797
|
|
@@ -1952,7 +1952,7 @@ describe DataMapper::Query do
|
|
1952
1952
|
end
|
1953
1953
|
|
1954
1954
|
it 'should return expected value' do
|
1955
|
-
@return.should == <<-INSPECT
|
1955
|
+
@return.should == DataMapper::Ext::String.compress_lines(<<-INSPECT)
|
1956
1956
|
#<DataMapper::Query
|
1957
1957
|
@repository=:default
|
1958
1958
|
@model=User
|
@@ -21,7 +21,8 @@ describe DataMapper::Resource::State::Immutable do
|
|
21
21
|
@parent = @model.create(:name => 'John Doe')
|
22
22
|
|
23
23
|
@resource = @model.create(:name => 'Dan Kubb', :parent => @parent)
|
24
|
-
|
24
|
+
attributes = DataMapper::Ext::Array.to_hash(@model.key.zip(@resource.key))
|
25
|
+
@resource = @model.first(attributes.merge(:fields => [ :name, :parent_id ]))
|
25
26
|
|
26
27
|
@state = @resource.persisted_state
|
27
28
|
@state.should be_kind_of(DataMapper::Resource::State::Immutable)
|
@@ -181,9 +181,7 @@ describe DataMapper::Resource::State do
|
|
181
181
|
describe '#hash' do
|
182
182
|
subject { @state.hash }
|
183
183
|
|
184
|
-
it
|
185
|
-
should == @resource.hash
|
186
|
-
end
|
184
|
+
it { should == @state.class.hash ^ @resource.hash }
|
187
185
|
end
|
188
186
|
|
189
187
|
describe '#resource' do
|
@@ -49,7 +49,8 @@ share_examples_for 'Resource::State::Persisted#get' do
|
|
49
49
|
@resource.should be_dirty
|
50
50
|
@resource.save.should be(true)
|
51
51
|
|
52
|
-
|
52
|
+
attributes = DataMapper::Ext::Array.to_hash(@model.key.zip(@resource.key))
|
53
|
+
@resource = @model.first(attributes.merge(:fields => @model.key))
|
53
54
|
@state = @state.class.new(@resource)
|
54
55
|
|
55
56
|
# make sure the subject is not loaded
|
@@ -18,7 +18,7 @@ share_examples_for 'A semipublic Subject' do
|
|
18
18
|
subject { @subject_without_default.default_for(@resource) }
|
19
19
|
|
20
20
|
it 'should match the default value' do
|
21
|
-
should
|
21
|
+
DataMapper::Ext.blank?(subject).should == true
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'should be used as a default for the subject accessor' do
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Class
|
2
|
+
def class_inheritable_reader(*ivars)
|
3
|
+
instance_reader = ivars.pop[:reader] if ivars.last.is_a?(Hash)
|
4
|
+
|
5
|
+
ivars.each do |ivar|
|
6
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
7
|
+
def self.#{ivar}
|
8
|
+
return @#{ivar} if defined?(@#{ivar})
|
9
|
+
return nil if self.object_id == #{self.object_id}
|
10
|
+
ivar = superclass.#{ivar}
|
11
|
+
return nil if ivar.nil?
|
12
|
+
@#{ivar} = DataMapper::Ext.try_dup(ivar)
|
13
|
+
end
|
14
|
+
RUBY
|
15
|
+
|
16
|
+
unless instance_reader == false
|
17
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
18
|
+
def #{ivar}
|
19
|
+
self.class.#{ivar}
|
20
|
+
end
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def class_inheritable_writer(*ivars)
|
27
|
+
instance_writer = ivars.pop[:instance_writer] if ivars.last.is_a?(Hash)
|
28
|
+
ivars.each do |ivar|
|
29
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
30
|
+
def self.#{ivar}=(obj)
|
31
|
+
@#{ivar} = obj
|
32
|
+
end
|
33
|
+
RUBY
|
34
|
+
unless instance_writer == false
|
35
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
36
|
+
def #{ivar}=(obj) self.class.#{ivar} = obj end
|
37
|
+
RUBY
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def class_inheritable_accessor(*syms)
|
43
|
+
class_inheritable_reader(*syms)
|
44
|
+
class_inheritable_writer(*syms)
|
45
|
+
end
|
46
|
+
end
|
data/spec/unit/array_spec.rb
CHANGED
@@ -1,25 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'dm-core/
|
2
|
+
require 'dm-core/ext/array'
|
3
|
+
require 'dm-core/support/mash'
|
3
4
|
|
4
|
-
|
5
|
-
require 'active_support/hash_with_indifferent_access'
|
6
|
-
unless defined?(Mash)
|
7
|
-
Mash = ActiveSupport::HashWithIndifferentAccess
|
8
|
-
end
|
9
|
-
rescue LoadError
|
10
|
-
require 'extlib/mash'
|
11
|
-
end
|
12
|
-
|
13
|
-
describe Array do
|
5
|
+
describe DataMapper::Ext::Array do
|
14
6
|
before :all do
|
15
7
|
@array = [ [ :a, [ 1 ] ], [ :b, [ 2 ] ], [ :c, [ 3 ] ] ].freeze
|
16
8
|
end
|
17
9
|
|
18
|
-
|
19
|
-
|
20
|
-
describe '#to_hash' do
|
10
|
+
describe '.to_hash' do
|
21
11
|
before :all do
|
22
|
-
@return = @array
|
12
|
+
@return = DataMapper::Ext::Array.to_hash(@array)
|
23
13
|
end
|
24
14
|
|
25
15
|
it 'should return a Hash' do
|
@@ -31,15 +21,13 @@ describe Array do
|
|
31
21
|
end
|
32
22
|
end
|
33
23
|
|
34
|
-
|
35
|
-
|
36
|
-
describe '#to_mash' do
|
24
|
+
describe '.to_mash' do
|
37
25
|
before :all do
|
38
|
-
@return = @array
|
26
|
+
@return = DataMapper::Ext::Array.to_mash(@array)
|
39
27
|
end
|
40
28
|
|
41
29
|
it 'should return a Mash' do
|
42
|
-
@return.should be_kind_of(Mash)
|
30
|
+
@return.should be_kind_of(DataMapper::Mash)
|
43
31
|
end
|
44
32
|
|
45
33
|
it 'should return expected value' do
|