montage_rails 0.3.2 → 0.4.1

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +28 -0
  4. data/lib/montage_rails/base/column.rb +57 -0
  5. data/lib/montage_rails/base.rb +406 -0
  6. data/lib/montage_rails/errors.rb +7 -0
  7. data/lib/montage_rails/log_subscriber.rb +48 -0
  8. data/lib/montage_rails/query_cache.rb +44 -0
  9. data/lib/montage_rails/railtie.rb +0 -0
  10. data/lib/montage_rails/relation.rb +88 -0
  11. data/lib/montage_rails/version.rb +3 -0
  12. data/lib/montage_rails.rb +57 -0
  13. data/lib/tasks/montage_rails_tasks.rake +4 -0
  14. data/test/dummy/README.rdoc +28 -0
  15. data/test/dummy/Rakefile +6 -0
  16. data/test/dummy/app/assets/javascripts/application.js +13 -0
  17. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  18. data/test/dummy/app/controllers/application_controller.rb +5 -0
  19. data/test/dummy/app/helpers/application_helper.rb +2 -0
  20. data/test/dummy/app/models/actor.rb +3 -0
  21. data/test/dummy/app/models/movie.rb +30 -0
  22. data/test/dummy/app/models/studio.rb +3 -0
  23. data/test/dummy/app/models/test.rb +2 -0
  24. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  25. data/test/dummy/bin/bundle +3 -0
  26. data/test/dummy/bin/rails +4 -0
  27. data/test/dummy/bin/rake +4 -0
  28. data/test/dummy/bin/setup +29 -0
  29. data/test/dummy/config/application.rb +25 -0
  30. data/test/dummy/config/boot.rb +5 -0
  31. data/test/dummy/config/database.yml +25 -0
  32. data/test/dummy/config/environment.rb +5 -0
  33. data/test/dummy/config/environments/development.rb +41 -0
  34. data/test/dummy/config/environments/production.rb +79 -0
  35. data/test/dummy/config/environments/test.rb +42 -0
  36. data/test/dummy/config/initializers/assets.rb +11 -0
  37. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  38. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  39. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  40. data/test/dummy/config/initializers/inflections.rb +16 -0
  41. data/test/dummy/config/initializers/mime_types.rb +4 -0
  42. data/test/dummy/config/initializers/montage.rb +4 -0
  43. data/test/dummy/config/initializers/session_store.rb +3 -0
  44. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  45. data/test/dummy/config/locales/en.yml +23 -0
  46. data/test/dummy/config/routes.rb +56 -0
  47. data/test/dummy/config/secrets.yml +22 -0
  48. data/test/dummy/config.ru +4 -0
  49. data/test/dummy/db/development.sqlite3 +0 -0
  50. data/test/dummy/db/schema.rb +16 -0
  51. data/test/dummy/db/test.sqlite3 +0 -0
  52. data/test/dummy/log/RAILS_ENV=development.log +0 -0
  53. data/test/dummy/log/development.log +1038 -0
  54. data/test/dummy/log/test.log +12368 -0
  55. data/test/dummy/public/404.html +67 -0
  56. data/test/dummy/public/422.html +67 -0
  57. data/test/dummy/public/500.html +66 -0
  58. data/test/dummy/public/favicon.ico +0 -0
  59. data/test/montage_rails/base/column_test.rb +59 -0
  60. data/test/montage_rails/base_test.rb +375 -0
  61. data/test/montage_rails/query_cache_test.rb +68 -0
  62. data/test/montage_rails/relation_test.rb +114 -0
  63. data/test/montage_rails_test.rb +97 -0
  64. data/test/resources/actor_resource.rb +141 -0
  65. data/test/resources/movie_resource.rb +160 -0
  66. data/test/resources/studio_resource.rb +56 -0
  67. data/test/test_helper.rb +196 -0
  68. metadata +123 -3
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/404.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The page you were looking for doesn't exist.</h1>
62
+ <p>You may have mistyped the address or the page may have moved.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+ require 'montage_rails/base/column'
3
+
4
+ class MontageRails::Base::ColumnTest < Minitest::Test
5
+ context "#value_valid?" do
6
+ should "return false if the value is required and nil is passed in" do
7
+ @column = MontageRails::Base::Column.new("foo", "integer", true)
8
+ assert !@column.value_valid?(nil)
9
+ end
10
+
11
+ should "return true if the value is required and a proper value is passed in" do
12
+ @column = MontageRails::Base::Column.new("foo", "integer", true)
13
+ assert @column.value_valid?(1)
14
+ end
15
+
16
+ should "return true if the value is not required and nil is passed in" do
17
+ @column = MontageRails::Base::Column.new("foo", "integer", false)
18
+ assert @column.value_valid?(nil)
19
+ end
20
+ end
21
+
22
+ context "#coerce" do
23
+ should "not perform a coercion if the value is already in the right format" do
24
+ column = MontageRails::Base::Column.new("foo", "numeric")
25
+ Virtus::Attribute.expects(:build).never
26
+ assert_equal 4.0, column.coerce(4.0)
27
+ end
28
+
29
+ should "coerce a float to a float" do
30
+ column = MontageRails::Base::Column.new("foo", "float")
31
+ assert_equal 4.0, column.coerce("4.0")
32
+ end
33
+
34
+ should "coerce an integer to an integer" do
35
+ column = MontageRails::Base::Column.new("foo", "float")
36
+ assert_equal 4, column.coerce("4")
37
+ end
38
+
39
+ should "coerce a date time to a date time" do
40
+ column = MontageRails::Base::Column.new("foo", "datetime")
41
+ assert_equal DateTime.new(2015, 4, 20), column.coerce("2015-04-20")
42
+ end
43
+
44
+ should "coerce an integer to an integer when the type is numeric" do
45
+ column = MontageRails::Base::Column.new("foo", "numeric")
46
+ assert_equal 4, column.coerce("4")
47
+ end
48
+
49
+ should "coerce a float to a float when the type is numeric" do
50
+ column = MontageRails::Base::Column.new("foo", "numeric")
51
+ assert_equal 4.0, column.coerce("4.0")
52
+ end
53
+
54
+ should "coerce a string to a string" do
55
+ column = MontageRails::Base::Column.new("foo", "float")
56
+ assert_equal "foo", column.coerce("foo")
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,375 @@
1
+ require 'test_helper'
2
+ require 'montage_rails/relation'
3
+ require 'montage_rails/base'
4
+
5
+ class MontageRails::BaseTest < MiniTest::Test
6
+ context "initialization" do
7
+ should "initialize all the variables with nil when nothing is passed in" do
8
+ @movie = Movie.new
9
+
10
+ assert_nil @movie.rank
11
+ assert_nil @movie.rating
12
+ assert_nil @movie.title
13
+ assert_nil @movie.votes
14
+ assert_nil @movie.year
15
+ end
16
+
17
+ should "initialize with the passed in parameters" do
18
+ @movie = Movie.new(MontageRails::MovieResource.to_hash)
19
+
20
+ assert_equal 4, @movie.rank
21
+ assert_equal 2.0, @movie.rating
22
+ assert_equal "The Jerk", @movie.title
23
+ assert_equal 500, @movie.votes
24
+ assert_equal 1983, @movie.year
25
+ end
26
+
27
+ should "set persisted to the value passed in if it is passed in" do
28
+ @movie = Movie.new(persisted: true)
29
+
30
+ assert @movie.persisted?
31
+ end
32
+
33
+ should "default persisted to false" do
34
+ @movie = Movie.new
35
+
36
+ assert !@movie.persisted?
37
+ end
38
+ end
39
+
40
+ context "class setup" do
41
+ setup do
42
+ class FooBar < MontageRails::Base
43
+ self.table_name = "movies"
44
+ end
45
+ end
46
+
47
+ should "allow the table_name to be overriden" do
48
+ assert_equal "movies", FooBar.table_name
49
+ end
50
+ end
51
+
52
+ context "callbacks" do
53
+ should "respond to the before_save callback and before_create callback when it's not persisted" do
54
+ @movie = Movie.new(MontageRails::MovieResource.to_hash)
55
+
56
+ @movie.save
57
+
58
+ assert_equal "FOO", @movie.before_save_var
59
+ assert_equal "BAR", @movie.before_create_var
60
+ end
61
+
62
+ should "only call the before_create callback if the record is not persisted" do
63
+ @movie = Movie.create(MontageRails::MovieResource.to_hash)
64
+
65
+ @movie.before_create_var = nil
66
+ @movie.before_save_var = nil
67
+
68
+ @movie.votes = 600
69
+ @movie.save
70
+
71
+ assert_nil @movie.before_create_var
72
+ assert_equal "FOO", @movie.before_save_var
73
+ end
74
+
75
+ should "call the before_create callback on creation" do
76
+ @movie = Movie.create(MontageRails::MovieResource.to_hash)
77
+
78
+ assert_equal "BAR", @movie.before_create_var
79
+ end
80
+
81
+ should "respond to the after_save callback and after_create callback when it's not persisted" do
82
+ @movie = Movie.new(MontageRails::MovieResource.to_hash)
83
+
84
+ @movie.save
85
+
86
+ assert_equal "AFTER SAVE", @movie.after_save_var
87
+ assert_equal "AFTER CREATE", @movie.after_create_var
88
+ end
89
+
90
+ should "only call the after_create callback if the record is not persisted" do
91
+ @movie = Movie.create(MontageRails::MovieResource.to_hash)
92
+
93
+ @movie.after_create_var = nil
94
+ @movie.after_save_var = nil
95
+
96
+ @movie.votes = 600
97
+ @movie.save
98
+
99
+ assert_nil @movie.after_create_var
100
+ assert_equal "AFTER SAVE", @movie.after_save_var
101
+ end
102
+
103
+ should "call the after_create callback on creation" do
104
+ @movie = Movie.create(MontageRails::MovieResource.to_hash)
105
+
106
+ assert_equal "AFTER CREATE", @movie.after_create_var
107
+ end
108
+ end
109
+
110
+ context "delegation" do
111
+ should "delegate the first query method called to a Relation object and return a relation" do
112
+ assert_equal MontageRails::Relation, Movie.where(foo: "bar").class
113
+ assert_equal MontageRails::Relation, Movie.limit(10).class
114
+ assert_equal MontageRails::Relation, Movie.offset(10).class
115
+ assert_equal MontageRails::Relation, Movie.order(foo: :asc).class
116
+ end
117
+
118
+ should "create finder methods for all the column names" do
119
+ assert Movie.respond_to?(:find_by_rank)
120
+ assert Movie.respond_to?(:find_by_title)
121
+ assert Movie.respond_to?(:find_by_votes)
122
+ assert Movie.respond_to?(:find_by_id)
123
+ assert Movie.respond_to?(:find_by_year)
124
+ assert Movie.respond_to?(:find_by_rating)
125
+ end
126
+ end
127
+
128
+ context "column methods" do
129
+ setup do
130
+ @movie = Movie.new
131
+ end
132
+
133
+ should "respond to method names that correspond to column names" do
134
+ assert @movie.respond_to?(:rank)
135
+ assert @movie.respond_to?(:rating)
136
+ assert @movie.respond_to?(:title)
137
+ assert @movie.respond_to?(:votes)
138
+ assert @movie.respond_to?(:year)
139
+ end
140
+ end
141
+
142
+ context ".has_many" do
143
+ setup do
144
+ @movie = Movie.create(MontageRails::MovieResource.to_hash)
145
+ @actor = Actor.create(MontageRails::ActorResource.steve_martin)
146
+ @actor2 = Actor.create(MontageRails::ActorResource.mark_hamill)
147
+ end
148
+
149
+ should "define an instance method for the given table name" do
150
+ assert @movie.respond_to?(:actors)
151
+
152
+ assert_equal 1, @movie.actors.count
153
+ assert_equal @actor.attributes, @movie.actors.first.attributes
154
+ end
155
+
156
+ should "allow the resulting relation to be chainable" do
157
+ assert_equal @actor.attributes, @movie.actors.where(name: "Steve Martin").first.attributes
158
+ end
159
+
160
+ context "when the table name has been overridden" do
161
+ setup do
162
+ class TestClass < MontageRails::Base
163
+ self.table_name = "movies"
164
+
165
+ has_many :actors
166
+ end
167
+
168
+ @test = TestClass.where(title: "The Jerk").first
169
+ end
170
+
171
+ should "use the new table name to define the methods" do
172
+ assert_equal "Steve Martin", @test.actors.first.name
173
+ end
174
+ end
175
+ end
176
+
177
+ context ".belongs_to" do
178
+ should "define an instance method for the given table name" do
179
+ @movie = Movie.find_by_title("The Jerk")
180
+ @studio = Studio.create(name: "Universal")
181
+
182
+ assert @movie.respond_to?(:studio)
183
+ assert @movie.respond_to?(:studio=)
184
+ assert_equal @studio.attributes, @movie.studio.attributes
185
+
186
+ @movie.studio = @studio
187
+ @movie.save
188
+
189
+ assert_equal @studio.attributes, @movie.studio.attributes
190
+ end
191
+ end
192
+
193
+ context ".columns" do
194
+ should "retrieve the column names from the database if they have not been already" do
195
+ Movie.columns.each_with_index do |column, index|
196
+ assert_equal column.name, Movie.columns[index].name
197
+ assert_equal column.type, Movie.columns[index].type
198
+ assert_equal column.required, Movie.columns[index].required
199
+ end
200
+ end
201
+
202
+ should "not call out to the database if the columns have already been retrieved" do
203
+ Movie.columns
204
+
205
+ MontageRails.connection.expects(:schemas).never
206
+
207
+ Movie.columns
208
+ end
209
+ end
210
+
211
+ context ".create" do
212
+ should "save a new object and return an instance of the class" do
213
+ @movie = Movie.create(MontageRails::MovieResource.to_hash)
214
+
215
+ assert @movie.persisted?
216
+ assert_equal 4, @movie.rank
217
+ assert_equal 2.0, @movie.rating
218
+ assert_equal "The Jerk", @movie.title
219
+ assert_equal 600, @movie.votes
220
+ assert_equal 1983, @movie.year
221
+ end
222
+ end
223
+
224
+ context ".find_or_initialize_by" do
225
+ context "when the document is found" do
226
+ should "return an instance of the document" do
227
+ @movie = Movie.find_or_initialize_by(title: "The Jerk")
228
+
229
+ assert @movie.persisted?
230
+ assert_equal 4, @movie.rank
231
+ assert_equal 2.0, @movie.rating
232
+ assert_equal "The Jerk", @movie.title
233
+ assert_equal 600, @movie.votes
234
+ assert_equal 1983, @movie.year
235
+ end
236
+ end
237
+
238
+ context "when the document is not found" do
239
+ should "return a new instance of the document" do
240
+ @movie = Movie.find_or_initialize_by(title: "Foo")
241
+
242
+ assert !@movie.persisted?
243
+ assert_equal "Foo", @movie.title
244
+ end
245
+ end
246
+ end
247
+
248
+ context ".all" do
249
+ setup do
250
+ @movies = Movie.all
251
+ end
252
+
253
+ should "fetch all the movies" do
254
+ refute @movies.empty?
255
+ end
256
+ end
257
+
258
+ context ".column_names" do
259
+ setup do
260
+ @column_names = Movie.column_names
261
+
262
+ @expected = %w(id created_at updated_at studio_id rank rating title votes year)
263
+ end
264
+
265
+ should "return an array of strings that contains the column names" do
266
+ assert_equal @expected, @column_names
267
+ end
268
+ end
269
+
270
+ context "#inspect" do
271
+ setup do
272
+ @inspect = Movie.inspect
273
+ end
274
+
275
+ should "return a Rails style formatted inspect string" do
276
+ assert_equal "Movie(id: text, created_at: datetime, updated_at: datetime, studio_id: text, rank: numeric, rating: numeric, title: text, votes: numeric, year: numeric)", @inspect
277
+ end
278
+ end
279
+
280
+ context "#attributes_valid?" do
281
+ should "return false if there is an invalid attribute" do
282
+ @movie = Movie.new(rank: nil, rating: 2.0, title: "Foo", votes: 1, year: 1983, studio_id: "19442e09-5c2d-4e5d-8f34-675570e81414")
283
+
284
+ assert !@movie.attributes_valid?
285
+ end
286
+ end
287
+
288
+ context "#save" do
289
+ context "when valid attributes are provided" do
290
+ setup do
291
+ @movie = Movie.new(MontageRails::MovieResource.to_hash)
292
+ end
293
+
294
+ should "successfully save the document, return a copy of itself, and set persisted to true" do
295
+ @movie.save
296
+
297
+ assert @movie.persisted?
298
+ end
299
+ end
300
+
301
+ context "when valid attributes are not provided" do
302
+ setup do
303
+ @movie = Movie.new
304
+ end
305
+
306
+ should "not save the document and return nil" do
307
+ @movie.save
308
+
309
+ assert !@movie.persisted?
310
+ end
311
+ end
312
+ end
313
+
314
+ context "#update_attributes" do
315
+ setup do
316
+ @movie = Movie.create(MontageRails::MovieResource.to_hash)
317
+ end
318
+
319
+ context "when valid attributes are given" do
320
+ should "update the attributes and return a copy of self" do
321
+ @movie.update_attributes(votes: 600)
322
+
323
+ assert_equal 600, @movie.votes
324
+ end
325
+ end
326
+
327
+ context "when the document is not yet persisted and the attributes are valid" do
328
+ setup do
329
+ @movie = Movie.new
330
+ end
331
+
332
+ should "create a new document" do
333
+ @movie.update_attributes(MontageRails::MovieResource.to_hash)
334
+
335
+ assert @movie.persisted?
336
+ end
337
+ end
338
+
339
+ context "when invalid attributes are given" do
340
+ should "not update any attributes and return false" do
341
+ assert !@movie.update_attributes(votes: nil)
342
+
343
+ assert_equal 600, @movie.votes
344
+ end
345
+ end
346
+
347
+ context "when none of the attributes have changed" do
348
+ should "not update the document" do
349
+ MontageRails.connection.expects(:update_document).never
350
+ @movie.update_attributes(MontageRails::MovieResource.update_body.shift)
351
+ end
352
+ end
353
+
354
+ context "when only one, unchanged attribute is passed in" do
355
+ should "not update the document" do
356
+ MontageRails.connection.expects(:update_document).never
357
+ @movie.update_attributes(rank: 4)
358
+ end
359
+ end
360
+
361
+ context "when two, unchanged attributes are passed in" do
362
+ should "not update the document" do
363
+ MontageRails.connection.expects(:update_document).never
364
+ @movie.update_attributes(rank: 4, rating: 2.0)
365
+ end
366
+ end
367
+
368
+ context "when data types passed in don't match and attributes haven't changed" do
369
+ should "not update the document" do
370
+ MontageRails.connection.expects(:update_document).never
371
+ @movie.update_attributes(rank: "4", rating: "2.0")
372
+ end
373
+ end
374
+ end
375
+ end
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+ require 'montage_rails/query_cache'
3
+
4
+ class QueryCacheTest < Minitest::Test
5
+ context "#get_or_set_query" do
6
+ setup do
7
+ @meth = Struct.new(:foo)
8
+ @cache = MontageRails::QueryCache.new
9
+ end
10
+
11
+ context "when the query is already cached" do
12
+ setup do
13
+ @cache.cache["foo/bar"] = "foobar"
14
+ end
15
+
16
+ should "not run the query, and return the cached value" do
17
+ @meth.expects(:foo).never
18
+ @cache.get_or_set_query("foo", "bar") do
19
+ @meth.foo
20
+ end
21
+ end
22
+ end
23
+
24
+ context "when the query is not already cached, and set the cached value" do
25
+ should "run the query" do
26
+ @meth.expects(:foo).once.returns("bar")
27
+ @cache.get_or_set_query("foo", "bar") do
28
+ @meth.foo
29
+ end
30
+
31
+ assert_equal @cache.cache["foo/bar"], "bar"
32
+ end
33
+ end
34
+ end
35
+
36
+ context "#clear" do
37
+ setup do
38
+ @meth = Struct.new(:foo)
39
+ @cache = MontageRails::QueryCache.new
40
+ end
41
+
42
+ should "clear the cache" do
43
+ @meth.stubs(:foo).once.returns("bar")
44
+ @cache.get_or_set_query("foo", "bar") { @meth.foo }
45
+ @cache.clear
46
+
47
+ assert @cache.cache.empty?
48
+ end
49
+ end
50
+
51
+ context "#remove" do
52
+ setup do
53
+ @meth = Struct.new(:foo)
54
+ @meth.stubs(:foo).returns("bar")
55
+ @cache = MontageRails::QueryCache.new
56
+ @cache.get_or_set_query("foo", "bar") { @meth.foo }
57
+ end
58
+
59
+ should "remove the cache key and return the cached value if the key exists" do
60
+ assert_equal "bar", @cache.remove("foo/bar")
61
+ assert_nil @cache.cache["foo/bar"]
62
+ end
63
+
64
+ should "return nil if the key does not exist" do
65
+ assert_nil @cache.remove("foobar")
66
+ end
67
+ end
68
+ end