ardm 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +35 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE +21 -0
  5. data/README.md +70 -0
  6. data/Rakefile +4 -0
  7. data/ardm.gemspec +29 -0
  8. data/db/.gitignore +1 -0
  9. data/lib/ardm/active_record/associations.rb +80 -0
  10. data/lib/ardm/active_record/base.rb +49 -0
  11. data/lib/ardm/active_record/dirty.rb +25 -0
  12. data/lib/ardm/active_record/hooks.rb +31 -0
  13. data/lib/ardm/active_record/inheritance.rb +37 -0
  14. data/lib/ardm/active_record/is/state_machine.rb +21 -0
  15. data/lib/ardm/active_record/is.rb +22 -0
  16. data/lib/ardm/active_record/not_found.rb +7 -0
  17. data/lib/ardm/active_record/predicate_builder/array_handler.rb +31 -0
  18. data/lib/ardm/active_record/predicate_builder/rails3.rb +147 -0
  19. data/lib/ardm/active_record/predicate_builder/rails4.rb +139 -0
  20. data/lib/ardm/active_record/predicate_builder/relation_handler.rb +15 -0
  21. data/lib/ardm/active_record/predicate_builder.rb +19 -0
  22. data/lib/ardm/active_record/property.rb +357 -0
  23. data/lib/ardm/active_record/query.rb +108 -0
  24. data/lib/ardm/active_record/record.rb +70 -0
  25. data/lib/ardm/active_record/relation.rb +83 -0
  26. data/lib/ardm/active_record/repository.rb +38 -0
  27. data/lib/ardm/active_record/serialization.rb +164 -0
  28. data/lib/ardm/active_record/storage_names.rb +28 -0
  29. data/lib/ardm/active_record/validations.rb +111 -0
  30. data/lib/ardm/active_record.rb +43 -0
  31. data/lib/ardm/data_mapper/not_found.rb +5 -0
  32. data/lib/ardm/data_mapper/record.rb +41 -0
  33. data/lib/ardm/data_mapper.rb +5 -0
  34. data/lib/ardm/env.rb +5 -0
  35. data/lib/ardm/property/api_key.rb +30 -0
  36. data/lib/ardm/property/bcrypt_hash.rb +31 -0
  37. data/lib/ardm/property/binary.rb +23 -0
  38. data/lib/ardm/property/boolean.rb +29 -0
  39. data/lib/ardm/property/class.rb +19 -0
  40. data/lib/ardm/property/comma_separated_list.rb +28 -0
  41. data/lib/ardm/property/csv.rb +35 -0
  42. data/lib/ardm/property/date.rb +12 -0
  43. data/lib/ardm/property/datetime.rb +12 -0
  44. data/lib/ardm/property/decimal.rb +38 -0
  45. data/lib/ardm/property/discriminator.rb +65 -0
  46. data/lib/ardm/property/enum.rb +51 -0
  47. data/lib/ardm/property/epoch_time.rb +38 -0
  48. data/lib/ardm/property/file_path.rb +25 -0
  49. data/lib/ardm/property/flag.rb +65 -0
  50. data/lib/ardm/property/float.rb +18 -0
  51. data/lib/ardm/property/integer.rb +24 -0
  52. data/lib/ardm/property/invalid_value_error.rb +22 -0
  53. data/lib/ardm/property/ip_address.rb +35 -0
  54. data/lib/ardm/property/json.rb +49 -0
  55. data/lib/ardm/property/lookup.rb +29 -0
  56. data/lib/ardm/property/numeric.rb +40 -0
  57. data/lib/ardm/property/object.rb +36 -0
  58. data/lib/ardm/property/paranoid_boolean.rb +18 -0
  59. data/lib/ardm/property/paranoid_datetime.rb +17 -0
  60. data/lib/ardm/property/regexp.rb +22 -0
  61. data/lib/ardm/property/serial.rb +16 -0
  62. data/lib/ardm/property/slug.rb +29 -0
  63. data/lib/ardm/property/string.rb +40 -0
  64. data/lib/ardm/property/support/dirty_minder.rb +169 -0
  65. data/lib/ardm/property/support/flags.rb +41 -0
  66. data/lib/ardm/property/support/paranoid_base.rb +78 -0
  67. data/lib/ardm/property/text.rb +11 -0
  68. data/lib/ardm/property/time.rb +12 -0
  69. data/lib/ardm/property/uri.rb +27 -0
  70. data/lib/ardm/property/uuid.rb +65 -0
  71. data/lib/ardm/property/validation.rb +208 -0
  72. data/lib/ardm/property/yaml.rb +38 -0
  73. data/lib/ardm/property.rb +891 -0
  74. data/lib/ardm/property_set.rb +152 -0
  75. data/lib/ardm/query/expression.rb +85 -0
  76. data/lib/ardm/query/ext/symbol.rb +37 -0
  77. data/lib/ardm/query/operator.rb +64 -0
  78. data/lib/ardm/record.rb +1 -0
  79. data/lib/ardm/support/assertions.rb +8 -0
  80. data/lib/ardm/support/deprecate.rb +12 -0
  81. data/lib/ardm/support/descendant_set.rb +89 -0
  82. data/lib/ardm/support/equalizer.rb +48 -0
  83. data/lib/ardm/support/ext/array.rb +22 -0
  84. data/lib/ardm/support/ext/blank.rb +25 -0
  85. data/lib/ardm/support/ext/hash.rb +67 -0
  86. data/lib/ardm/support/ext/module.rb +47 -0
  87. data/lib/ardm/support/ext/object.rb +57 -0
  88. data/lib/ardm/support/ext/string.rb +24 -0
  89. data/lib/ardm/support/ext/try_dup.rb +12 -0
  90. data/lib/ardm/support/hook.rb +405 -0
  91. data/lib/ardm/support/lazy_array.rb +451 -0
  92. data/lib/ardm/support/local_object_space.rb +13 -0
  93. data/lib/ardm/support/logger.rb +201 -0
  94. data/lib/ardm/support/mash.rb +176 -0
  95. data/lib/ardm/support/naming_conventions.rb +90 -0
  96. data/lib/ardm/support/ordered_set.rb +380 -0
  97. data/lib/ardm/support/subject.rb +33 -0
  98. data/lib/ardm/support/subject_set.rb +250 -0
  99. data/lib/ardm/version.rb +3 -0
  100. data/lib/ardm.rb +56 -0
  101. data/spec/fixtures/api_user.rb +11 -0
  102. data/spec/fixtures/article.rb +22 -0
  103. data/spec/fixtures/bookmark.rb +14 -0
  104. data/spec/fixtures/invention.rb +5 -0
  105. data/spec/fixtures/network_node.rb +23 -0
  106. data/spec/fixtures/person.rb +17 -0
  107. data/spec/fixtures/software_package.rb +22 -0
  108. data/spec/fixtures/ticket.rb +12 -0
  109. data/spec/fixtures/tshirt.rb +15 -0
  110. data/spec/integration/api_key_spec.rb +25 -0
  111. data/spec/integration/bcrypt_hash_spec.rb +45 -0
  112. data/spec/integration/comma_separated_list_spec.rb +85 -0
  113. data/spec/integration/dirty_minder_spec.rb +197 -0
  114. data/spec/integration/enum_spec.rb +79 -0
  115. data/spec/integration/epoch_time_spec.rb +59 -0
  116. data/spec/integration/file_path_spec.rb +158 -0
  117. data/spec/integration/flag_spec.rb +72 -0
  118. data/spec/integration/ip_address_spec.rb +151 -0
  119. data/spec/integration/json_spec.rb +70 -0
  120. data/spec/integration/slug_spec.rb +65 -0
  121. data/spec/integration/uri_spec.rb +136 -0
  122. data/spec/integration/uuid_spec.rb +102 -0
  123. data/spec/integration/yaml_spec.rb +85 -0
  124. data/spec/public/property/binary_spec.rb +41 -0
  125. data/spec/public/property/boolean_spec.rb +30 -0
  126. data/spec/public/property/class_spec.rb +28 -0
  127. data/spec/public/property/date_spec.rb +22 -0
  128. data/spec/public/property/date_time_spec.rb +22 -0
  129. data/spec/public/property/decimal_spec.rb +23 -0
  130. data/spec/public/property/discriminator_spec.rb +133 -0
  131. data/spec/public/property/float_spec.rb +22 -0
  132. data/spec/public/property/integer_spec.rb +22 -0
  133. data/spec/public/property/object_spec.rb +103 -0
  134. data/spec/public/property/serial_spec.rb +22 -0
  135. data/spec/public/property/string_spec.rb +22 -0
  136. data/spec/public/property/text_spec.rb +23 -0
  137. data/spec/public/property/time_spec.rb +22 -0
  138. data/spec/public/property_spec.rb +316 -0
  139. data/spec/rcov.opts +6 -0
  140. data/spec/schema.rb +86 -0
  141. data/spec/semipublic/property/binary_spec.rb +14 -0
  142. data/spec/semipublic/property/boolean_spec.rb +48 -0
  143. data/spec/semipublic/property/class_spec.rb +36 -0
  144. data/spec/semipublic/property/date_spec.rb +44 -0
  145. data/spec/semipublic/property/date_time_spec.rb +47 -0
  146. data/spec/semipublic/property/decimal_spec.rb +83 -0
  147. data/spec/semipublic/property/discriminator_spec.rb +22 -0
  148. data/spec/semipublic/property/float_spec.rb +83 -0
  149. data/spec/semipublic/property/integer_spec.rb +83 -0
  150. data/spec/semipublic/property/lookup_spec.rb +27 -0
  151. data/spec/semipublic/property/serial_spec.rb +14 -0
  152. data/spec/semipublic/property/string_spec.rb +14 -0
  153. data/spec/semipublic/property/text_spec.rb +30 -0
  154. data/spec/semipublic/property/time_spec.rb +49 -0
  155. data/spec/semipublic/property_spec.rb +51 -0
  156. data/spec/shared/flags_shared_spec.rb +36 -0
  157. data/spec/shared/identity_function_group.rb +5 -0
  158. data/spec/shared/public_property_spec.rb +229 -0
  159. data/spec/shared/semipublic_property_spec.rb +159 -0
  160. data/spec/spec.opts +4 -0
  161. data/spec/spec_helper.rb +58 -0
  162. data/spec/unit/bcrypt_hash_spec.rb +154 -0
  163. data/spec/unit/csv_spec.rb +139 -0
  164. data/spec/unit/dirty_minder_spec.rb +64 -0
  165. data/spec/unit/enum_spec.rb +125 -0
  166. data/spec/unit/epoch_time_spec.rb +72 -0
  167. data/spec/unit/file_path_spec.rb +75 -0
  168. data/spec/unit/flag_spec.rb +114 -0
  169. data/spec/unit/ip_address_spec.rb +109 -0
  170. data/spec/unit/json_spec.rb +127 -0
  171. data/spec/unit/paranoid_boolean_spec.rb +142 -0
  172. data/spec/unit/paranoid_datetime_spec.rb +149 -0
  173. data/spec/unit/regexp_spec.rb +62 -0
  174. data/spec/unit/uri_spec.rb +64 -0
  175. data/spec/unit/yaml_spec.rb +111 -0
  176. data/tasks/spec.rake +40 -0
  177. data/tasks/yard.rake +9 -0
  178. data/tasks/yardstick.rake +19 -0
  179. metadata +350 -0
@@ -0,0 +1,316 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'addressable/uri'
4
+
5
+ # instance methods
6
+ describe Ardm::Property do
7
+
8
+ # define the model prior to supported_by
9
+ before do
10
+ class ::Track < Ardm::Record
11
+ property :id, Serial
12
+ property :artist, String, :lazy => false, :index => :artist_album
13
+ property :title, String, :field => 'name', :index => true
14
+ property :album, String, :index => :artist_album
15
+ property :musicbrainz_hash, String, :unique => true, :unique_index => true
16
+ end
17
+
18
+ class ::Image < Ardm::Record
19
+ property :md5hash, String, :key => true, :length => 32
20
+ property :title, String, :required => true, :unique => true
21
+ property :description, Text, :length => 1..1024, :lazy => [ :detail ]
22
+ property :width, Integer, :lazy => [:dimensions]
23
+ property :height, Integer, :lazy => [:dimensions]
24
+ property :format, String, :default => 'jpeg'
25
+ property :taken_at, Time, :default => proc { Time.now }
26
+
27
+ validates_presence_of :format
28
+ end
29
+ end
30
+
31
+ describe '#field' do
32
+ it 'returns @field value if it is present' do
33
+ Track.properties[:title].field.should eql('name')
34
+ end
35
+ end
36
+
37
+ describe '#default_for' do
38
+ it 'returns default value for non-callables' do
39
+ Image.properties[:format].default_for(Image.new).should == 'jpeg'
40
+ end
41
+
42
+ it 'returns result of a call for callable values' do
43
+ Image.properties[:taken_at].default_for(Image.new).year.should == Time.now.year
44
+ end
45
+
46
+ it "sets the default when the record is created" do
47
+ img = Image.create!(title: 'My Picture')
48
+ img.format.should == 'jpeg'
49
+ end
50
+ end
51
+
52
+ describe '#eql?' do
53
+ it 'is true for properties with the same model and name' do
54
+ Track.properties[:title].should eql(Track.properties[:title])
55
+ end
56
+
57
+
58
+ it 'is false for properties of different models' do
59
+ Track.properties[:title].should_not eql(Image.properties[:title])
60
+ end
61
+
62
+ it 'is false for properties with different names' do
63
+ Track.properties[:title].should_not eql(Track.properties[:id])
64
+ end
65
+ end
66
+
67
+ describe '#get!' do
68
+ before do
69
+ @image = Image.new
70
+
71
+ # now some dark Ruby magic
72
+ @image.instance_variable_set(:@description, 'Is set by magic')
73
+ end
74
+
75
+ it 'gets instance variable value from the resource directly' do
76
+ pending "support for this in ActiveRecord is questionable" do
77
+ # if you know a better way to test direct instance variable access,
78
+ # go ahead and make changes to this example
79
+ Image.properties[:description].get!(@image).should == 'Is set by magic'
80
+ end
81
+ end
82
+ end
83
+
84
+ describe '#index' do
85
+ it 'returns true when property has an index' do
86
+ Track.properties[:title].index.should be(true)
87
+ end
88
+
89
+ it 'returns index name when property has a named index' do
90
+ Track.properties[:album].index.should eql(:artist_album)
91
+ end
92
+
93
+ it 'returns false when property has no index' do
94
+ Track.properties[:musicbrainz_hash].index.should be(false)
95
+ end
96
+ end
97
+
98
+ describe '#initialize' do
99
+ describe 'when tracking strategy is explicitly given' do
100
+ it 'uses tracking strategy from options'
101
+ end
102
+ end
103
+
104
+ describe '#inspect' do
105
+ before do
106
+ @str = Track.properties[:title].inspect
107
+ end
108
+
109
+ it 'features model name' do
110
+ @str.should =~ /@model=Track/
111
+ end
112
+
113
+ it 'features property name' do
114
+ @str.should =~ /@name=:title/
115
+ end
116
+ end
117
+
118
+ describe '#key?' do
119
+ describe 'returns true when property is a ' do
120
+ it 'serial key' do
121
+ Track.properties[:id].key?.should be(true)
122
+ end
123
+ it 'natural key' do
124
+ Image.properties[:md5hash].key?.should be(true)
125
+ end
126
+ end
127
+
128
+ it 'returns true when property is a part of composite key'
129
+
130
+ it 'returns false when property does not relate to a key' do
131
+ Track.properties[:title].key?.should be(false)
132
+ end
133
+ end
134
+
135
+ describe '#lazy?' do
136
+ it 'returns true when property is lazy loaded' do
137
+ Image.properties[:description].lazy?.should be(true)
138
+ end
139
+
140
+ it 'returns false when property is not lazy loaded' do
141
+ Track.properties[:artist].lazy?.should be(false)
142
+ end
143
+ end
144
+
145
+ describe '#length' do
146
+ it 'returns upper bound for Range values' do
147
+ Image.properties[:description].length.should eql(1024)
148
+ end
149
+
150
+ it 'returns value as is for integer values' do
151
+ Image.properties[:md5hash].length.should eql(32)
152
+ end
153
+ end
154
+
155
+ describe '#min' do
156
+ describe 'when :min and :max options not provided to constructor' do
157
+ before do
158
+ @property = Image.property(:integer_with_nil_min, Integer)
159
+ end
160
+
161
+ it 'should be nil' do
162
+ @property.min.should be_nil
163
+ end
164
+ end
165
+
166
+ describe 'when :min option not provided to constructor, but :max is provided' do
167
+ before do
168
+ @property = Image.property(:integer_with_default_min, Integer, :max => 1)
169
+ end
170
+
171
+ it 'should be the default value' do
172
+ @property.min.should == 0
173
+ end
174
+ end
175
+
176
+ describe 'when :min and :max options provided to constructor' do
177
+ before do
178
+ @min = 1
179
+ @property = Image.property(:integer_with_explicit_min, Integer, :min => @min, :max => 2)
180
+ end
181
+
182
+ it 'should be the expected value' do
183
+ @property.min.should == @min
184
+ end
185
+ end
186
+ end
187
+
188
+ describe '#max' do
189
+ describe 'when :min and :max options not provided to constructor' do
190
+ before do
191
+ @property = Image.property(:integer_with_nil_max, Integer)
192
+ end
193
+
194
+ it 'should be nil' do
195
+ @property.max.should be_nil
196
+ end
197
+ end
198
+
199
+ describe 'when :max option not provided to constructor, but :min is provided' do
200
+ before do
201
+ @property = Image.property(:integer_with_default_max, Integer, :min => 1)
202
+ end
203
+
204
+ it 'should be the default value' do
205
+ @property.max.should == 2**31-1
206
+ end
207
+ end
208
+
209
+ describe 'when :min and :max options provided to constructor' do
210
+ before do
211
+ @max = 2
212
+ @property = Image.property(:integer_with_explicit_max, Integer, :min => 1, :max => @max)
213
+ end
214
+
215
+ it 'should be the expected value' do
216
+ @property.max.should == @max
217
+ end
218
+ end
219
+ end
220
+
221
+ describe '#allow_nil?' do
222
+ it 'returns true when property can accept nil as its value' do
223
+ Track.properties[:artist].allow_nil?.should be(true)
224
+ end
225
+
226
+ it 'returns false when property nil value is prohibited for this property' do
227
+ Image.properties[:title].allow_nil?.should be(false)
228
+ end
229
+ end
230
+
231
+ describe '#serial?' do
232
+ it 'returns true when property is serial (auto incrementing)' do
233
+ Track.properties[:id].serial?.should be(true)
234
+ end
235
+
236
+ it 'returns false when property is NOT serial (auto incrementing)' do
237
+ Image.properties[:md5hash].serial?.should be(false)
238
+ end
239
+ end
240
+
241
+ describe '#set' do
242
+ before do
243
+ # keep in mind we must run these examples with a
244
+ # saved model instance
245
+ @image = Image.create(
246
+ :md5hash => '5268f0f3f452844c79843e820f998869',
247
+ :title => 'Rome at the sunset',
248
+ :description => 'Just wow'
249
+ )
250
+
251
+ @property = Image.properties[:title]
252
+ end
253
+
254
+ it 'triggers lazy loading for given resource'
255
+
256
+ it 'type casts given value' do
257
+ @property.set(@image, Addressable::URI.parse('http://test.example/'))
258
+ # get a string that has been typecasted using #to_str
259
+ @image.title.should == 'http://test.example/'
260
+ end
261
+
262
+ it 'sets new property value' do
263
+ @property.set(@image, 'Updated value')
264
+ @image.title.should == 'Updated value'
265
+ end
266
+ end
267
+
268
+ describe '#set!' do
269
+ before do
270
+ @image = Image.new(:md5hash => '5268f0f3f452844c79843e820f998869',
271
+ :title => 'Rome at the sunset',
272
+ :description => 'Just wow')
273
+
274
+ @property = Image.properties[:title]
275
+ end
276
+
277
+ it 'directly sets instance variable on given resource' do
278
+ @property.set!(@image, 'Set with dark Ruby magic')
279
+ @image.title.should == 'Set with dark Ruby magic'
280
+ end
281
+ end
282
+
283
+ describe '#unique?' do
284
+ it 'is true for fields that explicitly given uniq index' do
285
+ Track.properties[:musicbrainz_hash].unique?.should be(true)
286
+ end
287
+
288
+ it 'is true for serial fields' do
289
+ pending do
290
+ Track.properties[:title].unique?.should be(true)
291
+ end
292
+ end
293
+
294
+ it 'is true for keys' do
295
+ Image.properties[:md5hash].unique?.should be(true)
296
+ end
297
+ end
298
+
299
+ describe '#unique_index' do
300
+ it 'returns true when property has unique index' do
301
+ Track.properties[:musicbrainz_hash].unique_index.should be(true)
302
+ end
303
+
304
+ it 'returns false when property has no unique index' do
305
+ Track.properties[:title].unique_index.should be(false)
306
+ end
307
+
308
+ it 'returns true when property is unique' do
309
+ Image.properties[:title].unique_index.should be(true)
310
+ end
311
+
312
+ it 'returns :key when property is a key' do
313
+ Track.properties[:id].unique_index.should == :key
314
+ end
315
+ end
316
+ end
data/spec/rcov.opts ADDED
@@ -0,0 +1,6 @@
1
+ --exclude "spec,^/"
2
+ --sort coverage
3
+ --callsites
4
+ --xrefs
5
+ --profile
6
+ --text-summary
data/spec/schema.rb ADDED
@@ -0,0 +1,86 @@
1
+ ::ActiveRecord::Schema.define do
2
+
3
+ create_table :api_users, :force => true do |t|
4
+ t.string :name
5
+ t.string :api_key
6
+ end
7
+
8
+ create_table :articles, :force => true do |t|
9
+ t.string :title
10
+ t.text :body
11
+ t.timestamps
12
+ t.datetime :published_at
13
+ t.boolean :deleted
14
+ t.datetime :deleted_at
15
+ t.string :slug
16
+ end
17
+
18
+ create_table :bookmarks, :force => true do |t|
19
+ t.string :title
20
+ t.boolean :shared
21
+ t.string :uri
22
+ t.text :tags
23
+ end
24
+
25
+ create_table :images, :force => true, :id => false do |t|
26
+ t.string :md5hash, :length => 32
27
+ t.index :md5hash, :unique => true
28
+ t.string :title
29
+ t.text :description, :length => 1024
30
+ t.integer :width
31
+ t.integer :height
32
+ t.string :format
33
+ t.time :taken_at
34
+ end
35
+
36
+ create_table :network_nodes, :force => true do |t|
37
+ t.string :ip_address
38
+ t.integer :cidr_subnet_bits
39
+ t.string :node_uuid
40
+ end
41
+
42
+ create_table :people, :force => true do |t|
43
+ t.string :name
44
+ t.text :positions
45
+ t.text :inventions
46
+ t.time :birthday
47
+ t.text :interests
48
+ t.string :password
49
+ end
50
+
51
+ create_table :software_packages, :force => true do |t|
52
+ t.integer :node_number
53
+ t.string :source_path
54
+ t.string :destination_path
55
+ t.string :product
56
+ t.string :version
57
+ t.datetime :released_at
58
+ t.boolean :security_update
59
+ t.datetime :installed_at
60
+ t.string :installed_by
61
+ end
62
+
63
+ create_table :tickets, :force => true do |t|
64
+ t.string :title
65
+ t.text :body
66
+ t.integer :status
67
+ end
68
+
69
+ create_table :tracks, :force => true do |t|
70
+ t.string :artist
71
+ t.string :name
72
+ t.string :album
73
+ t.string :musicbrainz_hash
74
+ t.index [:artist, :album]
75
+ t.index :name
76
+ t.index :musicbrainz_hash, :unique => true
77
+ end
78
+
79
+ create_table :tshirts, :force => true do |t|
80
+ t.string :writing
81
+ t.boolean :has_picture
82
+ t.text :picture
83
+ t.text :color
84
+ t.text :size
85
+ end
86
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ardm::Property::Binary do
4
+ let(:name) { :title }
5
+ let(:type) { described_class }
6
+ let(:options) { {} }
7
+ let(:value) { 'value' }
8
+ let(:other_value) { 'return value' }
9
+ let(:invalid_value) { 1 }
10
+ let(:model) { Blog::Article }
11
+ let(:property) { type.new(model, name, options) }
12
+
13
+ it_should_behave_like 'A semipublic Property'
14
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ardm::Property::Boolean do
4
+ let(:name) { :active }
5
+ let(:type) { described_class }
6
+ let(:options) { {:set => [true, false]} }
7
+ let(:value) { true }
8
+ let(:other_value) { false }
9
+ let(:invalid_value) { 1 }
10
+ let(:model) { Blog::Article }
11
+ let(:property) { type.new(model, name, options) }
12
+
13
+ it_should_behave_like 'A semipublic Property'
14
+
15
+ describe '#valid?' do
16
+ [ true, false ].each do |value|
17
+ it "returns true when value is #{value.inspect}" do
18
+ property.valid?(value).should be(true)
19
+ end
20
+ end
21
+
22
+ [ 'true', 'TRUE', '1', 1, 't', 'T', 'false', 'FALSE', '0', 0, 'f', 'F' ].each do |value|
23
+ it "returns false for #{value.inspect}" do
24
+ property.valid?(value).should be(false)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '#typecast' do
30
+ [ true, 'true', 'TRUE', '1', 1, 't', 'T' ].each do |value|
31
+ it "returns true when value is #{value.inspect}" do
32
+ property.typecast(value).should be(true)
33
+ end
34
+ end
35
+
36
+ [ false, 'false', 'FALSE', '0', 0, 'f', 'F' ].each do |value|
37
+ it "returns false when value is #{value.inspect}" do
38
+ property.typecast(value).should be(false)
39
+ end
40
+ end
41
+
42
+ [ 'string', 2, 1.0, BigDecimal('1.0'), DateTime.now, Time.now, Date.today, Class, Object.new, ].each do |value|
43
+ it "does not typecast value #{value.inspect}" do
44
+ property.typecast(value).should equal(value)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ardm::Property::Class do
4
+ before do
5
+ Object.send(:remove_const, :Foo) if defined?(Foo)
6
+ Object.send(:remove_const, :Bar) if defined?(Bar)
7
+
8
+ class ::Foo; end
9
+ class ::Bar; end
10
+ end
11
+
12
+ let(:name) { :type }
13
+ let(:type) { described_class }
14
+ let(:options) { {} }
15
+ let(:value) { Foo }
16
+ let(:other_value) { Bar }
17
+ let(:invalid_value) { 1 }
18
+ let(:model) { Blog::Article }
19
+ let(:property) { type.new(model, name, options) }
20
+
21
+ it_should_behave_like 'A semipublic Property'
22
+
23
+ describe '#typecast' do
24
+ it 'returns same value if a class' do
25
+ property.typecast(model).should equal(model)
26
+ end
27
+
28
+ it 'returns the class if found' do
29
+ property.typecast(model.name).should eql(model)
30
+ end
31
+
32
+ it 'does not typecast non-class values' do
33
+ property.typecast('NoClass').should eql('NoClass')
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ardm::Property::Date do
4
+ let(:name) { :created_on }
5
+ let(:type) { described_class }
6
+ let(:options) { {} }
7
+ let(:value) { Date.today }
8
+ let(:other_value) { Date.today + 1 }
9
+ let(:invalid_value) { 1 }
10
+ let(:model) { Blog::Article }
11
+ let(:property) { type.new(model, name, options) }
12
+
13
+ it_should_behave_like 'A semipublic Property'
14
+
15
+ describe '#typecast' do
16
+ describe 'and value given as a hash with keys like :year, :month, etc' do
17
+ it 'builds a Date instance from hash values' do
18
+ result = property.typecast(
19
+ :year => '2007',
20
+ :month => '3',
21
+ :day => '25'
22
+ )
23
+
24
+ result.should be_kind_of(Date)
25
+ result.year.should eql(2007)
26
+ result.month.should eql(3)
27
+ result.day.should eql(25)
28
+ end
29
+ end
30
+
31
+ describe 'and value is a string' do
32
+ it 'parses the string' do
33
+ result = property.typecast('Dec 20th, 2006')
34
+ result.month.should == 12
35
+ result.day.should == 20
36
+ result.year.should == 2006
37
+ end
38
+ end
39
+
40
+ it 'does not typecast non-date values' do
41
+ property.typecast('not-date').should eql('not-date')
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ardm::Property::DateTime do
4
+ let(:name) { :created_at }
5
+ let(:type) { described_class }
6
+ let(:options) { {} }
7
+ let(:value) { DateTime.now }
8
+ let(:other_value) { DateTime.now + 15 }
9
+ let(:invalid_value) { 1 }
10
+ let(:model) { Blog::Article }
11
+ let(:property) { type.new(model, name, options) }
12
+
13
+ it_should_behave_like 'A semipublic Property'
14
+
15
+ describe '#typecast' do
16
+ describe 'and value given as a hash with keys like :year, :month, etc' do
17
+ it 'builds a DateTime instance from hash values' do
18
+ result = property.typecast(
19
+ :year => '2006',
20
+ :month => '11',
21
+ :day => '23',
22
+ :hour => '12',
23
+ :min => '0',
24
+ :sec => '0'
25
+ )
26
+
27
+ result.should be_kind_of(DateTime)
28
+ result.year.should eql(2006)
29
+ result.month.should eql(11)
30
+ result.day.should eql(23)
31
+ result.hour.should eql(12)
32
+ result.min.should eql(0)
33
+ result.sec.should eql(0)
34
+ end
35
+ end
36
+
37
+ describe 'and value is a string' do
38
+ it 'parses the string' do
39
+ property.typecast('Dec, 2006').month.should == 12
40
+ end
41
+ end
42
+
43
+ it 'does not typecast non-datetime values' do
44
+ property.typecast('not-datetime').should eql('not-datetime')
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ardm::Property::Decimal do
4
+ let(:name) { :rate }
5
+ let(:type) { described_class }
6
+ let(:options) { { :precision => 5, :scale => 2 } }
7
+ let(:value) { BigDecimal('1.0') }
8
+ let(:other_value) { BigDecimal('2.0') }
9
+ let(:invalid_value) { true }
10
+ let(:model) { Blog::Article }
11
+ let(:property) { type.new(model, name, options) }
12
+
13
+ it_should_behave_like 'A semipublic Property'
14
+
15
+ describe '#typecast' do
16
+ it 'returns same value if a decimal' do
17
+ @value = BigDecimal('24.0')
18
+ property.typecast(@value).should equal(@value)
19
+ end
20
+
21
+ it 'returns decimal representation of a zero string integer' do
22
+ property.typecast('0').should eql(BigDecimal('0.0'))
23
+ end
24
+
25
+ it 'returns decimal representation of a positive string integer' do
26
+ property.typecast('24').should eql(BigDecimal('24.0'))
27
+ end
28
+
29
+ it 'returns decimal representation of a negative string integer' do
30
+ property.typecast('-24').should eql(BigDecimal('-24.0'))
31
+ end
32
+
33
+ it 'returns decimal representation of a zero string float' do
34
+ property.typecast('0.0').should eql(BigDecimal('0.0'))
35
+ end
36
+
37
+ it 'returns decimal representation of a positive string float' do
38
+ property.typecast('24.35').should eql(BigDecimal('24.35'))
39
+ end
40
+
41
+ it 'returns decimal representation of a negative string float' do
42
+ property.typecast('-24.35').should eql(BigDecimal('-24.35'))
43
+ end
44
+
45
+ it 'returns decimal representation of a zero string float, with no leading digits' do
46
+ property.typecast('.0').should eql(BigDecimal('0.0'))
47
+ end
48
+
49
+ it 'returns decimal representation of a positive string float, with no leading digits' do
50
+ property.typecast('.41').should eql(BigDecimal('0.41'))
51
+ end
52
+
53
+ it 'returns decimal representation of a zero integer' do
54
+ property.typecast(0).should eql(BigDecimal('0.0'))
55
+ end
56
+
57
+ it 'returns decimal representation of a positive integer' do
58
+ property.typecast(24).should eql(BigDecimal('24.0'))
59
+ end
60
+
61
+ it 'returns decimal representation of a negative integer' do
62
+ property.typecast(-24).should eql(BigDecimal('-24.0'))
63
+ end
64
+
65
+ it 'returns decimal representation of a zero float' do
66
+ property.typecast(0.0).should eql(BigDecimal('0.0'))
67
+ end
68
+
69
+ it 'returns decimal representation of a positive float' do
70
+ property.typecast(24.35).should eql(BigDecimal('24.35'))
71
+ end
72
+
73
+ it 'returns decimal representation of a negative float' do
74
+ property.typecast(-24.35).should eql(BigDecimal('-24.35'))
75
+ end
76
+
77
+ [ Object.new, true, '0.', '-.0', 'string' ].each do |value|
78
+ it "does not typecast non-numeric value #{value.inspect}" do
79
+ property.typecast(value).should equal(value)
80
+ end
81
+ end
82
+ end
83
+ end