friendly 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/.document +5 -0
  2. data/.gitignore +23 -0
  3. data/APACHE-LICENSE +202 -0
  4. data/LICENSE +20 -0
  5. data/README.md +173 -0
  6. data/Rakefile +67 -0
  7. data/VERSION +1 -0
  8. data/examples/friendly.yml +7 -0
  9. data/friendly.gemspec +201 -0
  10. data/lib/friendly/attribute.rb +65 -0
  11. data/lib/friendly/boolean.rb +6 -0
  12. data/lib/friendly/cache/by_id.rb +33 -0
  13. data/lib/friendly/cache.rb +24 -0
  14. data/lib/friendly/config.rb +5 -0
  15. data/lib/friendly/data_store.rb +72 -0
  16. data/lib/friendly/document.rb +165 -0
  17. data/lib/friendly/document_table.rb +56 -0
  18. data/lib/friendly/index.rb +73 -0
  19. data/lib/friendly/memcached.rb +48 -0
  20. data/lib/friendly/newrelic.rb +6 -0
  21. data/lib/friendly/query.rb +42 -0
  22. data/lib/friendly/sequel_monkey_patches.rb +35 -0
  23. data/lib/friendly/storage.rb +31 -0
  24. data/lib/friendly/storage_factory.rb +24 -0
  25. data/lib/friendly/storage_proxy.rb +103 -0
  26. data/lib/friendly/table.rb +15 -0
  27. data/lib/friendly/table_creator.rb +43 -0
  28. data/lib/friendly/time.rb +14 -0
  29. data/lib/friendly/translator.rb +32 -0
  30. data/lib/friendly/uuid.rb +143 -0
  31. data/lib/friendly.rb +49 -0
  32. data/rails/init.rb +3 -0
  33. data/spec/fakes/data_store_fake.rb +29 -0
  34. data/spec/fakes/database_fake.rb +12 -0
  35. data/spec/fakes/dataset_fake.rb +28 -0
  36. data/spec/fakes/document.rb +18 -0
  37. data/spec/fakes/serializer_fake.rb +12 -0
  38. data/spec/fakes/time_fake.rb +12 -0
  39. data/spec/integration/basic_object_lifecycle_spec.rb +114 -0
  40. data/spec/integration/batch_insertion_spec.rb +29 -0
  41. data/spec/integration/convenience_api_spec.rb +25 -0
  42. data/spec/integration/count_spec.rb +12 -0
  43. data/spec/integration/default_value_spec.rb +15 -0
  44. data/spec/integration/find_via_cache_spec.rb +101 -0
  45. data/spec/integration/finder_spec.rb +64 -0
  46. data/spec/integration/index_spec.rb +57 -0
  47. data/spec/integration/pagination_spec.rb +63 -0
  48. data/spec/integration/table_creator_spec.rb +52 -0
  49. data/spec/integration/write_through_cache_spec.rb +53 -0
  50. data/spec/spec.opts +1 -0
  51. data/spec/spec_helper.rb +90 -0
  52. data/spec/unit/attribute_spec.rb +64 -0
  53. data/spec/unit/cache_by_id_spec.rb +102 -0
  54. data/spec/unit/cache_spec.rb +21 -0
  55. data/spec/unit/config_spec.rb +4 -0
  56. data/spec/unit/data_store_spec.rb +188 -0
  57. data/spec/unit/document_spec.rb +311 -0
  58. data/spec/unit/document_table_spec.rb +126 -0
  59. data/spec/unit/friendly_spec.rb +25 -0
  60. data/spec/unit/index_spec.rb +196 -0
  61. data/spec/unit/memcached_spec.rb +114 -0
  62. data/spec/unit/query_spec.rb +104 -0
  63. data/spec/unit/storage_factory_spec.rb +59 -0
  64. data/spec/unit/storage_proxy_spec.rb +218 -0
  65. data/spec/unit/translator_spec.rb +96 -0
  66. data/website/index.html +210 -0
  67. data/website/scripts/clipboard.swf +0 -0
  68. data/website/scripts/shBrushAS3.js +61 -0
  69. data/website/scripts/shBrushBash.js +66 -0
  70. data/website/scripts/shBrushCSharp.js +67 -0
  71. data/website/scripts/shBrushColdFusion.js +102 -0
  72. data/website/scripts/shBrushCpp.js +99 -0
  73. data/website/scripts/shBrushCss.js +93 -0
  74. data/website/scripts/shBrushDelphi.js +57 -0
  75. data/website/scripts/shBrushDiff.js +43 -0
  76. data/website/scripts/shBrushErlang.js +54 -0
  77. data/website/scripts/shBrushGroovy.js +69 -0
  78. data/website/scripts/shBrushJScript.js +52 -0
  79. data/website/scripts/shBrushJava.js +59 -0
  80. data/website/scripts/shBrushJavaFX.js +60 -0
  81. data/website/scripts/shBrushPerl.js +74 -0
  82. data/website/scripts/shBrushPhp.js +91 -0
  83. data/website/scripts/shBrushPlain.js +35 -0
  84. data/website/scripts/shBrushPowerShell.js +76 -0
  85. data/website/scripts/shBrushPython.js +66 -0
  86. data/website/scripts/shBrushRuby.js +57 -0
  87. data/website/scripts/shBrushScala.js +53 -0
  88. data/website/scripts/shBrushSql.js +68 -0
  89. data/website/scripts/shBrushVb.js +58 -0
  90. data/website/scripts/shBrushXml.js +71 -0
  91. data/website/scripts/shCore.js +30 -0
  92. data/website/scripts/shLegacy.js +30 -0
  93. data/website/styles/friendly.css +103 -0
  94. data/website/styles/help.png +0 -0
  95. data/website/styles/ie.css +35 -0
  96. data/website/styles/magnifier.png +0 -0
  97. data/website/styles/page_white_code.png +0 -0
  98. data/website/styles/page_white_copy.png +0 -0
  99. data/website/styles/print.css +29 -0
  100. data/website/styles/printer.png +0 -0
  101. data/website/styles/screen.css +257 -0
  102. data/website/styles/shCore.css +330 -0
  103. data/website/styles/shThemeDefault.css +173 -0
  104. data/website/styles/shThemeDjango.css +176 -0
  105. data/website/styles/shThemeEclipse.css +190 -0
  106. data/website/styles/shThemeEmacs.css +175 -0
  107. data/website/styles/shThemeFadeToGrey.css +177 -0
  108. data/website/styles/shThemeMidnight.css +175 -0
  109. data/website/styles/shThemeRDark.css +175 -0
  110. metadata +264 -0
@@ -0,0 +1,114 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe "Friendly::Memcached" do
4
+ before do
5
+ @cache = stub(:set => nil)
6
+ @memcached = Friendly::Memcached.new(@cache)
7
+ end
8
+
9
+ describe "setting a key" do
10
+ before do
11
+ @memcached.set("key", "value")
12
+ end
13
+
14
+ it "sets the key in memcached" do
15
+ @cache.should have_received(:set).with("key", "value")
16
+ end
17
+ end
18
+
19
+ describe "getting an existing key" do
20
+ before do
21
+ @cache.stubs(:get).with("Some Key").returns("Some Value")
22
+ end
23
+
24
+ it "returns the value from cache" do
25
+ @memcached.get("Some Key").should == "Some Value"
26
+ end
27
+ end
28
+
29
+ describe "getting a missing key" do
30
+ before do
31
+ @cache.stubs(:get).raises(Memcached::NotFound)
32
+ end
33
+
34
+ describe "with no block supplied" do
35
+ it "returns nil if no block is supplied" do
36
+ @memcached.get("Some Key").should be_nil
37
+ end
38
+ end
39
+
40
+ describe "with a block" do
41
+ before do
42
+ @returned = @memcached.get("Some Key") { "THE VALUE!" }
43
+ end
44
+
45
+ it "returns the value of the supplied block" do
46
+ @returned.should == "THE VALUE!"
47
+ end
48
+
49
+ it "sets the key to that value" do
50
+ @cache.should have_received(:set).with("Some Key", "THE VALUE!")
51
+ end
52
+ end
53
+ end
54
+
55
+ describe "getting multiple keys" do
56
+ describe "when all keys are found" do
57
+ before do
58
+ @hits = {"a" => "foo", "b" => "bar", "c" => "baz"}
59
+ @keys = ["a", "b", "c"]
60
+ @cache.stubs(:get).with(@keys).returns(@hits)
61
+ end
62
+
63
+ it "delegates to the cache object" do
64
+ @memcached.multiget(@keys).should == @hits
65
+ end
66
+ end
67
+
68
+ describe "when only some of the keys are found" do
69
+ before do
70
+ @hits = {"a" => "foo", "b" => "bar"}
71
+ @keys = ["a", "b", "c"]
72
+ @cache.stubs(:get).with(@keys).returns(@hits)
73
+ @returned = @memcached.multiget(@keys) { |k| "#{k}/fromblock" }
74
+ end
75
+
76
+ it "fetches the rest of the keys by yielding to the block" do
77
+ @returned.should == @hits.merge("c" => "c/fromblock")
78
+ end
79
+
80
+ it "sets the missing keys in the cache" do
81
+ @cache.should have_received(:set).with("c", "c/fromblock")
82
+ end
83
+ end
84
+
85
+ describe "when the list of keys is empty" do
86
+ it "returns {}" do
87
+ @memcached.multiget([]).should == {}
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "deleting" do
93
+ describe "an existing key" do
94
+ before do
95
+ @cache.stubs(:delete).returns(nil)
96
+ @memcached.delete("some key")
97
+ end
98
+
99
+ it "asks the cache to delete" do
100
+ @cache.should have_received(:delete).with("some key")
101
+ end
102
+ end
103
+
104
+ describe "a missing key" do
105
+ before do
106
+ @cache.stubs(:delete).raises(Memcached::NotFound)
107
+ end
108
+
109
+ it "just returns nil" do
110
+ lambda { @memcached.delete("some key") }.should_not raise_error
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,104 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe "Friendly::Query" do
4
+ before do
5
+ @order = :created_at.desc
6
+ @query = Friendly::Query.new(:name => "x",
7
+ :limit! => 10,
8
+ :order! => @order,
9
+ :preserve_order! => true,
10
+ :offset! => 2)
11
+ end
12
+
13
+ it "extracts the conditions" do
14
+ @query.conditions.should == {:name => "x"}
15
+ end
16
+
17
+ it "extracts the limit parameter" do
18
+ @query.limit.should == 10
19
+ end
20
+
21
+ it "extracts the order parameter" do
22
+ @query.order.should == @order
23
+ end
24
+
25
+ it "extracts the preserve order parameter" do
26
+ @query.should be_preserve_order
27
+ end
28
+
29
+ it "extracts the offset parameter" do
30
+ @query.should be_offset
31
+ @query.offset.should == 2
32
+ end
33
+
34
+ it "should not be preserver order by default" do
35
+ Friendly::Query.new({}).should_not be_preserve_order
36
+ end
37
+
38
+ it "converts string representations of UUID to UUID" do
39
+ uuid = stub
40
+ uuid_klass = stub
41
+ uuid_klass.stubs(:new).with("asdf").returns(uuid)
42
+ query = Friendly::Query.new({:id => "asdf"}, uuid_klass)
43
+ query.conditions[:id].should == uuid
44
+ end
45
+
46
+ it "converts arrays of ids to UUID" do
47
+ uuid = stub
48
+ uuid_klass = stub
49
+ uuid_klass.stubs(:new).with("asdf").returns(uuid)
50
+ query = Friendly::Query.new({:id => ["asdf"]}, uuid_klass)
51
+ query.conditions[:id].should == [uuid]
52
+ end
53
+
54
+ describe "a pagination query" do
55
+ describe "page nil" do
56
+ before do
57
+ @query = Friendly::Query.new(:page! => nil,
58
+ :per_page! => 5)
59
+ end
60
+
61
+ it "is page 1" do
62
+ @query.page.should == 1
63
+ end
64
+
65
+ it "has an offset of 0" do
66
+ @query.offset.should == 0
67
+ end
68
+
69
+ it "has a limit of :per_page" do
70
+ @query.limit.should == 5
71
+ end
72
+ end
73
+
74
+ describe "page 2" do
75
+ before do
76
+ @query = Friendly::Query.new(:page! => 2,
77
+ :per_page! => 5)
78
+ end
79
+
80
+ it "has an offset of :per_page * page-1" do
81
+ @query.offset.should == 5
82
+ end
83
+
84
+ it "has a limit of :per_page" do
85
+ @query.limit.should == 5
86
+ end
87
+ end
88
+
89
+ describe "when page is a string" do
90
+ before do
91
+ @query = Friendly::Query.new(:page! => "2",
92
+ :per_page! => 5)
93
+ end
94
+
95
+ it "has an offset of :per_page * page-1" do
96
+ @query.offset.should == 5
97
+ end
98
+
99
+ it "has a limit of :per_page" do
100
+ @query.limit.should == 5
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe "Friendly::StorageFactory" do
4
+ before do
5
+ @doc_table = stub
6
+ @doc_table_klass = stub(:new => @doc_table)
7
+ @index = stub
8
+ @index_klass = stub(:new => @index)
9
+ @cache_by_id = stub
10
+ @cache_klass = stub(:cache_for => @cache_by_id)
11
+ @factory = Friendly::StorageFactory.new(@doc_table_klass, @index_klass,
12
+ @cache_klass)
13
+ end
14
+
15
+ describe "creating a document table" do
16
+ before do
17
+ @klass = stub
18
+ @returned = @factory.document_table(@klass)
19
+ end
20
+
21
+ it "returns the result of the constructor" do
22
+ @returned.should == @doc_table
23
+ end
24
+
25
+ it "passes along the arguments to the constructor" do
26
+ @doc_table_klass.should have_received(:new).with(@klass)
27
+ end
28
+ end
29
+
30
+ describe "creating an index table" do
31
+ before do
32
+ @klass = stub
33
+ @returned = @factory.index(@klass)
34
+ end
35
+
36
+ it "returns the result of the constructor" do
37
+ @returned.should == @index
38
+ end
39
+
40
+ it "passes along the arguments to the constructor" do
41
+ @index_klass.should have_received(:new).with(@klass)
42
+ end
43
+ end
44
+
45
+ describe "creating an id cache table" do
46
+ before do
47
+ @klass = stub
48
+ @returned = @factory.cache(@klass, [:id])
49
+ end
50
+
51
+ it "delegates to Cache.for" do
52
+ @returned.should == @cache_by_id
53
+ end
54
+
55
+ it "supplies arguments to Cache" do
56
+ @cache_klass.should have_received(:cache_for).with(@klass, [:id])
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,218 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe "Friendly::StorageProxy" do
4
+ before do
5
+ @klass = stub
6
+ @index = stub(:create => nil,
7
+ :update => nil,
8
+ :destroy => nil,
9
+ :satsifies? => nil)
10
+ @table = stub(:satisfies? => false, :create => nil,
11
+ :update => nil, :destroy => nil)
12
+ @storage_factory = stub(:index => @index)
13
+ @storage_factory.stubs(:document_table).with(@klass).returns(@table)
14
+ @storage = Friendly::StorageProxy.new(@klass, @storage_factory)
15
+ end
16
+
17
+ it "instantiates and adds a document table by default" do
18
+ @storage.tables.should include(@table)
19
+ end
20
+
21
+ describe "doing a `first`" do
22
+ before do
23
+ @id = stub
24
+ @index = stub(:satisfies? => true, :first => @id)
25
+ @storage.tables << @index
26
+ end
27
+
28
+ describe "when there's an index that matches the conditions" do
29
+ before do
30
+ @result = @storage.first(:name => "x")
31
+ end
32
+
33
+ it "delegates to the index that satisfies the conditions" do
34
+ @index.should have_received(:first).once
35
+ @index.should have_received(:first).with(:name => "x")
36
+ end
37
+
38
+ it "returns id" do
39
+ @result.should == @id
40
+ end
41
+ end
42
+
43
+ describe "when there's no index that matches" do
44
+ before do
45
+ @index.stubs(:satisfies?).returns(false)
46
+ end
47
+
48
+ it "raises MissingIndex" do
49
+ lambda {
50
+ @storage.first(:name => "x")
51
+ }.should raise_error(Friendly::MissingIndex)
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "doing an `all`" do
57
+ before do
58
+ @ids = [stub]
59
+ @index = stub(:satisfies? => true, :all => @ids)
60
+ @storage.tables << @index
61
+ end
62
+
63
+ describe "when there's an index that matches the conditions" do
64
+ before do
65
+ @query = query(:name => "x")
66
+ @result = @storage.all(@query)
67
+ end
68
+
69
+ it "delegates to the index that satisfies the conditions" do
70
+ @index.should have_received(:all).once
71
+ @index.should have_received(:all).with(@query)
72
+ end
73
+
74
+ it "returns the results" do
75
+ @result.should == @ids
76
+ end
77
+ end
78
+
79
+ describe "when there's no index that matches" do
80
+ before do
81
+ @index.stubs(:satisfies?).returns(false)
82
+ end
83
+
84
+ it "raises MissingIndex" do
85
+ lambda {
86
+ @storage.all(:name => "x")
87
+ }.should raise_error(Friendly::MissingIndex)
88
+ end
89
+ end
90
+
91
+ describe "when :preserve_order is true" do
92
+ before do
93
+ @docs = [stub(:id => 4), stub(:id => 3), stub(:id => 2)]
94
+ @index.stubs(:all).returns(@docs)
95
+ @result = @storage.all(query(:id => [2,3,4], :preserve_order! => true))
96
+ end
97
+
98
+ it "sorts the results based on the order they're supplied in the query" do
99
+ @result.should == @docs.reverse
100
+ end
101
+ end
102
+ end
103
+
104
+ describe "adding an index to the set" do
105
+ before do
106
+ @storage.add(:name, :age)
107
+ end
108
+
109
+ it "creates an index" do
110
+ @storage_factory.should have_received(:index).once
111
+ @storage_factory.should have_received(:index).with(@klass, :name, :age)
112
+ end
113
+
114
+ it "adds the index to the set" do
115
+ @storage.tables.should include(@index)
116
+ end
117
+ end
118
+
119
+ describe "saving data" do
120
+ before do
121
+ @index_two = stub(:create => nil, :update => nil, :destroy => nil)
122
+ @storage_factory.stubs(:index).returns(@index).then.returns(@index_two)
123
+ @cache = stub(:create => nil, :update => nil, :destroy => nil)
124
+ @storage_factory.stubs(:cache).returns(@cache)
125
+ @storage.add(:name)
126
+ @storage.add(:age)
127
+ @storage.cache([:id])
128
+ @doc = stub
129
+ end
130
+
131
+ describe "on create" do
132
+ before do
133
+ @storage.create(@doc)
134
+ end
135
+
136
+ it "delegates to all of the storage including caches" do
137
+ @index.should have_received(:create).with(@doc)
138
+ @index_two.should have_received(:create).with(@doc)
139
+ @table.should have_received(:create).with(@doc)
140
+ @cache.should have_received(:create).with(@doc)
141
+ end
142
+ end
143
+
144
+ describe "on update" do
145
+ before do
146
+ @storage.update(@doc)
147
+ end
148
+
149
+ it "delegates to all of the storage including caches" do
150
+ @index.should have_received(:update).with(@doc)
151
+ @index_two.should have_received(:update).with(@doc)
152
+ @table.should have_received(:update).with(@doc)
153
+ @cache.should have_received(:update).with(@doc)
154
+ end
155
+ end
156
+
157
+ describe "on destroy" do
158
+ before do
159
+ @storage.destroy(@doc)
160
+ end
161
+
162
+ it "delegates to all of the storage including caches" do
163
+ @index.should have_received(:destroy).with(@doc)
164
+ @index_two.should have_received(:destroy).with(@doc)
165
+ @table.should have_received(:destroy).with(@doc)
166
+ @cache.should have_received(:destroy).with(@doc)
167
+ end
168
+ end
169
+ end
170
+
171
+ describe "adding a cache object" do
172
+ before do
173
+ @cache = stub
174
+ @storage_factory.stubs(:cache).returns(@cache)
175
+ @storage.cache([:id])
176
+ end
177
+
178
+ it "gets one from the storage_proxy" do
179
+ @storage_factory.should have_received(:cache).with(@klass, [:id], {})
180
+ end
181
+
182
+ it "adds it to its set of caches" do
183
+ @storage.caches.should include(@cache)
184
+ end
185
+ end
186
+
187
+ describe "finding with a matching cache" do
188
+ before do
189
+ @cache = stub(:satisfies? => true, :first => nil)
190
+ @storage_factory.stubs(:cache).returns(@cache)
191
+ @storage.cache([:id])
192
+ end
193
+
194
+ describe "when there's a hit" do
195
+ before do
196
+ @doc = stub
197
+ @cache.stubs(:first).returns(@doc)
198
+ end
199
+
200
+ it "returns the result from the cache" do
201
+ @storage.first(:id => "x").should == @doc
202
+ end
203
+ end
204
+ end
205
+
206
+ describe "counting objects" do
207
+ before do
208
+ @index = stub(:count => 10)
209
+ @index.stubs(:satisfies?).with(:x => 1).returns(true)
210
+ @storage_factory.stubs(:index).returns(@index)
211
+ @storage.add(:a)
212
+ end
213
+
214
+ it "delegates to a satisfying index" do
215
+ @storage.count(:x => 1).should == 10
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,96 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+ require 'ostruct'
3
+
4
+ describe "Friendly::Translator" do
5
+ before do
6
+ @serializer = stub
7
+ @time = stub
8
+ @translator = Friendly::Translator.new(@serializer, @time)
9
+ end
10
+
11
+ describe "translating a row to an object" do
12
+ before do
13
+ @serializer.stubs(:parse).with("THE JSON").returns(:name => "Stewie")
14
+ @time = Time.new
15
+ @row = {:added_id => 12345,
16
+ :created_at => @time,
17
+ :updated_at => @time,
18
+ :attributes => "THE JSON"}
19
+ @klass = FakeDocument
20
+ @doc = @translator.to_object(@klass, @row)
21
+ end
22
+
23
+ it "creates a klass with the attributes from the json" do
24
+ @doc.name.should == "Stewie"
25
+ end
26
+
27
+ it "sets updated_at" do
28
+ @doc.updated_at.should == @time
29
+ end
30
+
31
+ it "sets new_record to false" do
32
+ @doc.new_record.should be_false
33
+ end
34
+ end
35
+
36
+ describe "translating from a document in to a record" do
37
+ describe "when the document has yet to be saved" do
38
+ before do
39
+ @hash = {:name => "Stewie"}
40
+ @time.stubs(:new).returns(Time.new)
41
+ @serializer.stubs(:generate).with(@hash).returns("SOME JSON")
42
+ @document = stub(:to_hash => @hash,
43
+ :new_record? => true,
44
+ :created_at => nil,
45
+ :id => 12345)
46
+ @record = @translator.to_record(@document)
47
+ end
48
+
49
+ it "serializes the attributes" do
50
+ @record[:attributes].should == "SOME JSON"
51
+ end
52
+
53
+ it "sets updated_at" do
54
+ @record[:updated_at].should == @time.new
55
+ end
56
+
57
+ it "sets the id from the document" do
58
+ @record[:id].should == 12345
59
+ end
60
+ end
61
+
62
+ describe "when the document has already been saved" do
63
+ before do
64
+ @created_at = Time.new
65
+ @hash = {:name => "Stewie",
66
+ :id => 1,
67
+ :created_at => @created_at,
68
+ :updated_at => Time.new}
69
+ @time.stubs(:new).returns(Time.new + 5000)
70
+ @serializer.stubs(:generate).returns("SOME JSON")
71
+ @document = stub(:to_hash => @hash,
72
+ :created_at => @created_at,
73
+ :new_record? => false,
74
+ :id => 12345)
75
+ @record = @translator.to_record(@document)
76
+ end
77
+
78
+ it "serializes the attributes" do
79
+ @serializer.should have_received(:generate).with(:name => "Stewie")
80
+ @record[:attributes].should == "SOME JSON"
81
+ end
82
+
83
+ it "doesn't bump the created_at" do
84
+ @record[:created_at].should == @created_at
85
+ end
86
+
87
+ it "should bump the updated_at" do
88
+ @record[:updated_at].should == @time.new
89
+ end
90
+
91
+ it "takes the id from the documetn" do
92
+ @record[:id].should == 12345
93
+ end
94
+ end
95
+ end
96
+ end