wyngle-ripple 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. data/.gitignore +35 -0
  2. data/Gemfile +17 -0
  3. data/Gemfile.lock +133 -0
  4. data/Gemfile.rails30 +3 -0
  5. data/Gemfile.rails31 +3 -0
  6. data/Gemfile.rails32 +3 -0
  7. data/Guardfile +17 -0
  8. data/LICENSE +16 -0
  9. data/README.markdown +166 -0
  10. data/RELEASE_NOTES.textile +286 -0
  11. data/Rakefile +63 -0
  12. data/lib/rails/generators/ripple/configuration/configuration_generator.rb +13 -0
  13. data/lib/rails/generators/ripple/configuration/templates/ripple.yml +25 -0
  14. data/lib/rails/generators/ripple/js/js_generator.rb +13 -0
  15. data/lib/rails/generators/ripple/js/templates/js/contrib.js +63 -0
  16. data/lib/rails/generators/ripple/js/templates/js/iso8601.js +76 -0
  17. data/lib/rails/generators/ripple/js/templates/js/ripple.js +132 -0
  18. data/lib/rails/generators/ripple/model/model_generator.rb +20 -0
  19. data/lib/rails/generators/ripple/model/templates/model.rb.erb +10 -0
  20. data/lib/rails/generators/ripple/observer/observer_generator.rb +16 -0
  21. data/lib/rails/generators/ripple/observer/templates/observer.rb.erb +2 -0
  22. data/lib/rails/generators/ripple/test/templates/cucumber.rb.erb +7 -0
  23. data/lib/rails/generators/ripple/test/test_generator.rb +45 -0
  24. data/lib/rails/generators/ripple_generator.rb +79 -0
  25. data/lib/ripple.rb +86 -0
  26. data/lib/ripple/associations.rb +380 -0
  27. data/lib/ripple/associations/embedded.rb +35 -0
  28. data/lib/ripple/associations/instantiators.rb +26 -0
  29. data/lib/ripple/associations/linked.rb +65 -0
  30. data/lib/ripple/associations/many.rb +38 -0
  31. data/lib/ripple/associations/many_embedded_proxy.rb +39 -0
  32. data/lib/ripple/associations/many_linked_proxy.rb +66 -0
  33. data/lib/ripple/associations/many_reference_proxy.rb +95 -0
  34. data/lib/ripple/associations/many_stored_key_proxy.rb +76 -0
  35. data/lib/ripple/associations/one.rb +20 -0
  36. data/lib/ripple/associations/one_embedded_proxy.rb +35 -0
  37. data/lib/ripple/associations/one_key_proxy.rb +58 -0
  38. data/lib/ripple/associations/one_linked_proxy.rb +26 -0
  39. data/lib/ripple/associations/one_stored_key_proxy.rb +43 -0
  40. data/lib/ripple/associations/proxy.rb +118 -0
  41. data/lib/ripple/attribute_methods.rb +132 -0
  42. data/lib/ripple/attribute_methods/dirty.rb +59 -0
  43. data/lib/ripple/attribute_methods/query.rb +34 -0
  44. data/lib/ripple/attribute_methods/read.rb +28 -0
  45. data/lib/ripple/attribute_methods/write.rb +25 -0
  46. data/lib/ripple/callbacks.rb +71 -0
  47. data/lib/ripple/conflict/basic_resolver.rb +86 -0
  48. data/lib/ripple/conflict/document_hooks.rb +46 -0
  49. data/lib/ripple/conflict/resolver.rb +96 -0
  50. data/lib/ripple/conflict/test_helper.rb +34 -0
  51. data/lib/ripple/conversion.rb +29 -0
  52. data/lib/ripple/core_ext.rb +3 -0
  53. data/lib/ripple/core_ext/casting.rb +151 -0
  54. data/lib/ripple/core_ext/indexes.rb +89 -0
  55. data/lib/ripple/core_ext/object.rb +8 -0
  56. data/lib/ripple/document.rb +105 -0
  57. data/lib/ripple/document/bucket_access.rb +25 -0
  58. data/lib/ripple/document/finders.rb +131 -0
  59. data/lib/ripple/document/key.rb +35 -0
  60. data/lib/ripple/document/link.rb +30 -0
  61. data/lib/ripple/document/persistence.rb +130 -0
  62. data/lib/ripple/embedded_document.rb +63 -0
  63. data/lib/ripple/embedded_document/around_callbacks.rb +18 -0
  64. data/lib/ripple/embedded_document/finders.rb +26 -0
  65. data/lib/ripple/embedded_document/persistence.rb +75 -0
  66. data/lib/ripple/i18n.rb +5 -0
  67. data/lib/ripple/indexes.rb +151 -0
  68. data/lib/ripple/inspection.rb +32 -0
  69. data/lib/ripple/locale/en.yml +26 -0
  70. data/lib/ripple/locale/fr.yml +24 -0
  71. data/lib/ripple/nested_attributes.rb +275 -0
  72. data/lib/ripple/observable.rb +28 -0
  73. data/lib/ripple/properties.rb +74 -0
  74. data/lib/ripple/property_type_mismatch.rb +12 -0
  75. data/lib/ripple/railtie.rb +26 -0
  76. data/lib/ripple/railties/ripple.rake +68 -0
  77. data/lib/ripple/serialization.rb +82 -0
  78. data/lib/ripple/test_server.rb +35 -0
  79. data/lib/ripple/timestamps.rb +25 -0
  80. data/lib/ripple/translation.rb +18 -0
  81. data/lib/ripple/validations.rb +65 -0
  82. data/lib/ripple/validations/associated_validator.rb +43 -0
  83. data/lib/ripple/version.rb +3 -0
  84. data/ripple.gemspec +29 -0
  85. data/spec/fixtures/config.yml +8 -0
  86. data/spec/generators/ripple/configuration_generator_spec.rb +9 -0
  87. data/spec/generators/ripple/js_generator_spec.rb +14 -0
  88. data/spec/generators/ripple/model_generator_spec.rb +64 -0
  89. data/spec/generators/ripple/observer_generator_spec.rb +20 -0
  90. data/spec/generators/ripple/test_generator_spec.rb +118 -0
  91. data/spec/generators/ripple_generator_spec.rb +11 -0
  92. data/spec/integration/ripple/associations_spec.rb +164 -0
  93. data/spec/integration/ripple/conflict_resolution_spec.rb +329 -0
  94. data/spec/integration/ripple/indexes_spec.rb +47 -0
  95. data/spec/integration/ripple/nested_attributes_spec.rb +261 -0
  96. data/spec/integration/ripple/persistence_spec.rb +36 -0
  97. data/spec/integration/ripple/search_associations_spec.rb +31 -0
  98. data/spec/ripple/associations/many_embedded_proxy_spec.rb +119 -0
  99. data/spec/ripple/associations/many_linked_proxy_spec.rb +191 -0
  100. data/spec/ripple/associations/many_reference_proxy_spec.rb +170 -0
  101. data/spec/ripple/associations/many_stored_key_proxy_spec.rb +158 -0
  102. data/spec/ripple/associations/one_embedded_proxy_spec.rb +125 -0
  103. data/spec/ripple/associations/one_key_proxy_spec.rb +82 -0
  104. data/spec/ripple/associations/one_linked_proxy_spec.rb +91 -0
  105. data/spec/ripple/associations/one_stored_key_proxy_spec.rb +72 -0
  106. data/spec/ripple/associations/proxy_spec.rb +84 -0
  107. data/spec/ripple/associations_spec.rb +153 -0
  108. data/spec/ripple/attribute_methods/dirty_spec.rb +80 -0
  109. data/spec/ripple/attribute_methods_spec.rb +286 -0
  110. data/spec/ripple/bucket_access_spec.rb +25 -0
  111. data/spec/ripple/callbacks_spec.rb +195 -0
  112. data/spec/ripple/conflict/resolver_spec.rb +42 -0
  113. data/spec/ripple/conversion_spec.rb +14 -0
  114. data/spec/ripple/core_ext_spec.rb +181 -0
  115. data/spec/ripple/document/link_spec.rb +67 -0
  116. data/spec/ripple/document_spec.rb +96 -0
  117. data/spec/ripple/embedded_document/finders_spec.rb +29 -0
  118. data/spec/ripple/embedded_document/persistence_spec.rb +80 -0
  119. data/spec/ripple/embedded_document_spec.rb +84 -0
  120. data/spec/ripple/finders_spec.rb +220 -0
  121. data/spec/ripple/indexes_spec.rb +111 -0
  122. data/spec/ripple/inspection_spec.rb +51 -0
  123. data/spec/ripple/key_spec.rb +31 -0
  124. data/spec/ripple/observable_spec.rb +120 -0
  125. data/spec/ripple/persistence_spec.rb +351 -0
  126. data/spec/ripple/properties_spec.rb +262 -0
  127. data/spec/ripple/ripple_spec.rb +71 -0
  128. data/spec/ripple/serialization_spec.rb +51 -0
  129. data/spec/ripple/timestamps_spec.rb +83 -0
  130. data/spec/ripple/validations/associated_validator_spec.rb +77 -0
  131. data/spec/ripple/validations_spec.rb +102 -0
  132. data/spec/spec_helper.rb +39 -0
  133. data/spec/support/associations.rb +1 -0
  134. data/spec/support/associations/proxies.rb +17 -0
  135. data/spec/support/generator_setup.rb +26 -0
  136. data/spec/support/integration_setup.rb +11 -0
  137. data/spec/support/models.rb +35 -0
  138. data/spec/support/models/address.rb +10 -0
  139. data/spec/support/models/box.rb +13 -0
  140. data/spec/support/models/car.rb +41 -0
  141. data/spec/support/models/cardboard_box.rb +2 -0
  142. data/spec/support/models/clock.rb +10 -0
  143. data/spec/support/models/clock_observer.rb +2 -0
  144. data/spec/support/models/company.rb +23 -0
  145. data/spec/support/models/credit_card.rb +5 -0
  146. data/spec/support/models/customer.rb +3 -0
  147. data/spec/support/models/email.rb +3 -0
  148. data/spec/support/models/family.rb +16 -0
  149. data/spec/support/models/favorite.rb +3 -0
  150. data/spec/support/models/indexer.rb +26 -0
  151. data/spec/support/models/invoice.rb +6 -0
  152. data/spec/support/models/late_invoice.rb +2 -0
  153. data/spec/support/models/nested.rb +12 -0
  154. data/spec/support/models/ninja.rb +7 -0
  155. data/spec/support/models/note.rb +4 -0
  156. data/spec/support/models/page.rb +3 -0
  157. data/spec/support/models/paid_invoice.rb +3 -0
  158. data/spec/support/models/post.rb +13 -0
  159. data/spec/support/models/profile.rb +7 -0
  160. data/spec/support/models/subscription.rb +26 -0
  161. data/spec/support/models/tasks.rb +9 -0
  162. data/spec/support/models/team.rb +11 -0
  163. data/spec/support/models/transactions.rb +17 -0
  164. data/spec/support/models/tree.rb +3 -0
  165. data/spec/support/models/user.rb +19 -0
  166. data/spec/support/models/widget.rb +23 -0
  167. data/spec/support/search.rb +14 -0
  168. data/spec/support/test_server.rb +39 -0
  169. data/spec/support/test_server.yml.example +14 -0
  170. metadata +434 -0
@@ -0,0 +1,262 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ripple::Properties do
4
+ # require 'support/models/email'
5
+
6
+ it "should make the model class have a property definition method" do
7
+ Email.should respond_to(:property)
8
+ end
9
+
10
+ it "should add properties to the class via the property method" do
11
+ Email.property :from, String
12
+ Email.properties.should include(:from)
13
+ end
14
+
15
+ it "should make the model class have a collection of properties" do
16
+ Email.should respond_to(:properties)
17
+ Email.properties.should be_kind_of(Hash)
18
+ end
19
+
20
+ it "should make subclasses inherit properties from the parent class" do
21
+ Email.properties[:foo] = "bar"
22
+ class Forward < Email; end
23
+ Forward.properties[:foo].should == "bar"
24
+ end
25
+ end
26
+
27
+ describe Ripple::Property do
28
+ it "should have a key symbol" do
29
+ prop = Ripple::Property.new('foo', String)
30
+ prop.should respond_to(:key)
31
+ prop.key.should == :foo
32
+ end
33
+
34
+ it "should have a type" do
35
+ prop = Ripple::Property.new('foo', String)
36
+ prop.should respond_to(:type)
37
+ prop.type.should == String
38
+ end
39
+
40
+ it "should capture extra options" do
41
+ prop = Ripple::Property.new('foo', String, 'default' => "bar")
42
+ prop.should respond_to(:options)
43
+ prop.options.should == {:default => "bar"}
44
+ end
45
+
46
+ it "should expose validation options" do
47
+ prop = Ripple::Property.new('foo', String, 'default' => "bar", :presence => true)
48
+ prop.validation_options.should == {:presence => true}
49
+ end
50
+
51
+ describe "default value" do
52
+ it "should be nil when not specified" do
53
+ prop = Ripple::Property.new('foo', String)
54
+ prop.default.should be_nil
55
+ end
56
+
57
+ it "should allow literal values" do
58
+ prop = Ripple::Property.new('foo', String, :default => "bar")
59
+ prop.default.should == "bar"
60
+ end
61
+
62
+ it "should cast to the proper type" do
63
+ prop = Ripple::Property.new('foo', String, :default => :bar)
64
+ prop.default.should == "bar"
65
+ end
66
+
67
+ it "should allow false for a Boolean" do
68
+ prop = Ripple::Property.new('foo', Boolean, :default => false)
69
+ prop.default.should == false
70
+ end
71
+
72
+ it "should allow lambdas for deferred evaluation" do
73
+ prop = Ripple::Property.new('foo', String, :default => lambda { "bar" })
74
+ prop.default.should == "bar"
75
+ end
76
+ end
77
+
78
+ describe "casting a value" do
79
+ describe "when type is Boolean" do
80
+ before :each do
81
+ @prop = Ripple::Property.new('foo', Boolean)
82
+ end
83
+
84
+ [0, 0.0, "", "0", [], false, "f", "FALSE"].each do |v|
85
+ it "should cast #{v.inspect} to false" do
86
+ @prop.type_cast(v).should == false
87
+ end
88
+ end
89
+
90
+ [1, 1.0, "true", "1", [1], true, "t", "TRUE"].each do |v|
91
+ it "should cast #{v.inspect} to true" do
92
+ @prop.type_cast(v).should == true
93
+ end
94
+ end
95
+
96
+ it "should not cast nil" do
97
+ @prop.type_cast(nil).should be_nil
98
+ end
99
+ end
100
+
101
+ describe "when type is String" do
102
+ before :each do
103
+ @prop = Ripple::Property.new('foo', String)
104
+ end
105
+
106
+ it "should cast anything to a string using to_s" do
107
+ @prop.type_cast("s").should == "s"
108
+ @prop.type_cast(1).should == "1"
109
+ @prop.type_cast(true).should == "true"
110
+ @prop.type_cast(false).should == "false"
111
+ if RUBY_VERSION < "1.9"
112
+ @prop.type_cast([]).should == ""
113
+ else
114
+ @prop.type_cast([]).should == "[]"
115
+ end
116
+ end
117
+
118
+ it "should not cast nil" do
119
+ @prop.type_cast(nil).should be_nil
120
+ end
121
+
122
+ end
123
+
124
+ describe "when type is an Integer type" do
125
+ before :each do
126
+ @prop = Ripple::Property.new(:foo, Integer)
127
+ end
128
+
129
+ [5.0, "5", " 5", "05", Rational(10,2)].each do |v|
130
+ it "should cast #{v.inspect} to 5" do
131
+ @prop.type_cast(v).should == 5
132
+ end
133
+ end
134
+
135
+ [0.0, "0", " 000"].each do |v|
136
+ it "should cast #{v.inspect} to 0" do
137
+ @prop.type_cast(v).should == 0
138
+ end
139
+ end
140
+
141
+ it "should not cast the blank string" do
142
+ @prop.type_cast("").should be_nil
143
+ @prop.type_cast(" ").should be_nil
144
+ end
145
+
146
+ [true, false, [], {}, :symbol, ["something else"]].each do |v|
147
+ it "should raise an error casting #{v.inspect}" do
148
+ lambda { @prop.type_cast(v) }.should raise_error(Ripple::PropertyTypeMismatch)
149
+ end
150
+ end
151
+ end
152
+
153
+ describe "when type is a Float type" do
154
+ before :each do
155
+ @prop = Ripple::Property.new(:foo, Float)
156
+ end
157
+
158
+ [0, "0", "0.0", " 0.0"].each do |v|
159
+ it "should cast #{v.inspect} to 0.0" do
160
+ @prop.type_cast(v).should == 0.0
161
+ end
162
+ end
163
+
164
+ [5.0, "5", " 5.0", "05", Rational(10,2)].each do |v|
165
+ it "should cast #{v.inspect} to 5.0" do
166
+ @prop.type_cast(v).should == 5.0
167
+ end
168
+ end
169
+
170
+ it "should not cast the blank string" do
171
+ @prop.type_cast("").should be_nil
172
+ @prop.type_cast(" ").should be_nil
173
+ end
174
+
175
+ [true, false, :symbol, [], {}].each do |v|
176
+ it "should raise an error casting #{v.inspect}" do
177
+ lambda { @prop.type_cast(v) }.should raise_error(Ripple::PropertyTypeMismatch)
178
+ end
179
+ end
180
+ end
181
+
182
+ describe "when type is a Numeric type" do
183
+ before :each do
184
+ @prop = Ripple::Property.new(:foo, Numeric)
185
+ end
186
+
187
+ [5.0, "5", " 5.0", "05"].each do |v|
188
+ it "should cast #{v.inspect} to 5" do
189
+ @prop.type_cast(v).should == 5
190
+ end
191
+ end
192
+
193
+ [5.2, "5.2542", " 6.4", "0.5327284"].each do |v|
194
+ it "should cast #{v.inspect} to a float" do
195
+ @prop.type_cast(v).should be_kind_of(Float)
196
+ end
197
+ end
198
+
199
+ it "should not cast the blank string" do
200
+ @prop.type_cast("").should be_nil
201
+ @prop.type_cast(" ").should be_nil
202
+ end
203
+ end
204
+
205
+ describe "when type is a Time type" do
206
+ before :each do
207
+ @prop = Ripple::Property.new(:foo, Time)
208
+ end
209
+
210
+ ["Tue, 16 Mar 2010 12:00:00 -0000","2010/03/16 12:00:00 GMT", Time.utc(2010,03,16,12)].each do |v|
211
+ it "should cast #{v.inspect} to #{Time.utc(2010,03,16,12).inspect}" do
212
+ @prop.type_cast(v).should == Time.utc(2010,03,16,12)
213
+ end
214
+ end
215
+
216
+ it "should not cast blank types" do
217
+ @prop.type_cast([]).should be_nil
218
+ @prop.type_cast({}).should be_nil
219
+ @prop.type_cast("").should be_nil
220
+ @prop.type_cast(" ").should be_nil
221
+ end
222
+ end
223
+
224
+ describe "when type is a Date type" do
225
+ before :each do
226
+ @prop = Ripple::Property.new(:foo, Date)
227
+ end
228
+
229
+ ["Tue, 16 Mar 2010 00:00:00 -0000", "2010/03/16 12:00:00 GMT", Time.utc(2010,03,16,12), "2010/03/16"].each do |v|
230
+ it "should cast #{v.inspect} to 2010/03/16" do
231
+ @prop.type_cast(v).should == Date.civil(2010,3,16)
232
+ end
233
+ end
234
+
235
+ it "should not cast blank types" do
236
+ @prop.type_cast([]).should be_nil
237
+ @prop.type_cast({}).should be_nil
238
+ @prop.type_cast("").should be_nil
239
+ @prop.type_cast(" ").should be_nil
240
+ end
241
+ end
242
+
243
+ describe "when type is a Set type" do
244
+ let(:prop) { Ripple::Property.new(:foo, Set) }
245
+
246
+ it "casts an array to a a set" do
247
+ prop.type_cast([1]).should be_a(Set)
248
+ prop.type_cast([1]).to_a.should == [1]
249
+ end
250
+
251
+ it "does not cast nil" do
252
+ prop.type_cast(nil).should be_nil
253
+ end
254
+
255
+ it "raises an error when casting a non-enumerable" do
256
+ expect {
257
+ prop.type_cast(1)
258
+ }.to raise_error(Ripple::PropertyTypeMismatch)
259
+ end
260
+ end
261
+ end
262
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ripple do
4
+ it "should have a client" do
5
+ Ripple.client.should be_kind_of(Riak::Client)
6
+ end
7
+
8
+ it "should have a unique client per thread" do
9
+ client = Ripple.client
10
+ th = Thread.new { Ripple.client.should_not == client }
11
+ th.join
12
+ end
13
+
14
+ it "should be configurable" do
15
+ Ripple.should respond_to(:config)
16
+ end
17
+
18
+ it "should allow setting the client manually" do
19
+ Ripple.should respond_to(:client=)
20
+ client = Riak::Client.new(:http_port => 9000)
21
+ Ripple.client = client
22
+ Ripple.client.should == client
23
+ end
24
+
25
+ it "should reset the client when the configuration changes" do
26
+ c = Ripple.client
27
+ Ripple.config = {:http_port => 9000}
28
+ Ripple.client.should_not == c
29
+ Ripple.client.node.http_port.should == 9000
30
+ end
31
+
32
+ it "should raise No Such File or Directory when given a bad configuration file" do
33
+ lambda { Ripple.load_config('not-here') }.should raise_error(Ripple::MissingConfiguration)
34
+ end
35
+
36
+ it "should pass an empty hash into configure if the configuration file is missing the key" do
37
+ Ripple.should_receive(:config=).with({})
38
+ Ripple.load_config(File.join(File.dirname(__FILE__), '..', 'fixtures', 'config.yml'), [:ripple, 'not-here'])
39
+ end
40
+
41
+ it "should select the configuration hash from the config keys provided" do
42
+ Ripple.load_config(File.join(File.dirname(__FILE__), '..', 'fixtures', 'config.yml'), ['ripple_rails', 'development'])
43
+ Ripple.client.node.http_port.should == 9001
44
+ Ripple.client.node.host.should == '127.0.0.1'
45
+ end
46
+
47
+ it "should apply the configuration under the ripple key" do
48
+ Ripple.load_config(File.join(File.dirname(__FILE__), '..', 'fixtures', 'config.yml'))
49
+ Ripple.client.node.http_port.should == 9000
50
+ Ripple.client.node.host.should == 'localhost'
51
+ end
52
+
53
+ describe "date format" do
54
+ before { @date_format = Ripple.date_format }
55
+ after { Ripple.date_format = @date_format }
56
+
57
+ it "should default to :iso8601" do
58
+ Ripple.date_format.should == :iso8601
59
+ end
60
+
61
+ it "should allow setting via the config" do
62
+ Ripple.config = {"date_format" => "rfc822"}
63
+ Ripple.date_format.should == :rfc822
64
+ end
65
+
66
+ it "should allow setting manually" do
67
+ Ripple.date_format = "rfc822"
68
+ Ripple.date_format.should == :rfc822
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ripple::Serialization do
4
+ # require 'support/models/invoice'
5
+ # require 'support/models/note'
6
+ # require 'support/models/customer'
7
+
8
+ it "should provide JSON serialization" do
9
+ Invoice.new.should respond_to(:to_json)
10
+ end
11
+
12
+ context "when serializing" do
13
+ it "should include attributes" do
14
+ Note.new(:text => "Dear Jane,...").serializable_hash.should include('text')
15
+ end
16
+
17
+ it "should include the document key" do
18
+ doc = Invoice.new
19
+ doc.key = "1"
20
+ doc.serializable_hash['key'].should == "1"
21
+ end
22
+
23
+ it "should be able to exclude the document key" do
24
+ doc = Invoice.new
25
+ doc.key = "1"
26
+ doc.serializable_hash(:except => [:key]).should_not include("key")
27
+ end
28
+
29
+ it "should include embedded documents by default" do
30
+ doc = Invoice.new(:note => {:text => "Dear customer,..."}).serializable_hash
31
+ doc['note'].should eql({'text' => "Dear customer,..."})
32
+ end
33
+
34
+ it "should exclude the _type field from embedded documents" do
35
+ doc = Invoice.new
36
+ doc.note = Note.new :text => "Dear customer,..."
37
+ doc.serializable_hash['note'].should_not include("_type")
38
+ end
39
+
40
+ it "should exclude specified attributes" do
41
+ hash = Invoice.new.serializable_hash(:except => [:created_at])
42
+ hash.should_not include('created_at')
43
+ end
44
+
45
+ it "should limit to specified attributes" do
46
+ hash = Invoice.new.serializable_hash(:only => [:created_at])
47
+ hash.should include('created_at')
48
+ hash.should_not include('updated_at')
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "a timestamped model" do
4
+ it "adds a created_at property" do
5
+ subject.should respond_to(:created_at)
6
+ end
7
+
8
+ it "adds an updated_at property" do
9
+ subject.should respond_to(:updated_at)
10
+ end
11
+
12
+ it "sets the created_at timestamp when the object is initialized" do
13
+ subject.created_at.should_not be_nil
14
+ end
15
+
16
+ it "does not set the updated_at timestamp when the object is initialized" do
17
+ subject.updated_at.should be_nil
18
+ end
19
+
20
+ it "sets the updated_at timestamp when the object is saved" do
21
+ record_to_save.save
22
+ subject.updated_at.should_not be_nil
23
+ end
24
+
25
+ it "updates the updated_at timestamp when the object is updated" do
26
+ record_to_save.save
27
+ start = subject.updated_at
28
+ record_to_save.save
29
+ subject.updated_at.should > start
30
+ end
31
+
32
+ it "does not update the created_at timestamp when the object is updated" do
33
+ record_to_save.save
34
+ start = subject.created_at
35
+ record_to_save.save
36
+ subject.created_at.should == start
37
+ end
38
+ end
39
+
40
+ describe Ripple::Timestamps do
41
+ # require 'support/models/clock'
42
+
43
+ before(:each) { clock.robject.stub!(:store).and_return(true) }
44
+
45
+ context "for a Ripple::Document" do
46
+ it_behaves_like "a timestamped model" do
47
+ subject { Clock.new }
48
+ let(:clock) { subject }
49
+ let(:record_to_save) { subject }
50
+ end
51
+ end
52
+
53
+ context "for a Ripple::EmbeddedDocument when directly saved" do
54
+ it_behaves_like "a timestamped model" do
55
+ let(:clock) { Clock.new }
56
+ subject { Mode.new }
57
+ let(:record_to_save) { subject }
58
+
59
+ before(:each) do
60
+ clock.modes << subject
61
+ end
62
+ end
63
+ end
64
+
65
+ context "for a Ripple::EmbeddedDocument when the parent is saved" do
66
+ it_behaves_like "a timestamped model" do
67
+ let(:clock) { Clock.new }
68
+ subject { Mode.new }
69
+ let(:record_to_save) { clock }
70
+
71
+ before(:each) do
72
+ clock.modes << subject
73
+ end
74
+
75
+ it "should pass-through property options to the created properties" do
76
+ [:created_at, :updated_at].each do |p|
77
+ subject.class.properties[p].validation_options.should include(:presence)
78
+ subject.class.indexes[p].should be
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end