friendly 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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