listings 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/app/assets/javascripts/listings.js +1 -1
  2. data/app/views/listings/_filters.html.haml +5 -5
  3. data/app/views/listings/_table_content.html.haml +1 -1
  4. data/lib/listings.rb +1 -0
  5. data/lib/listings/base.rb +34 -35
  6. data/lib/listings/base_field_descriptor.rb +21 -0
  7. data/lib/listings/base_field_view.rb +39 -0
  8. data/lib/listings/column_descriptor.rb +7 -47
  9. data/lib/listings/column_view.rb +18 -27
  10. data/lib/listings/configuration_methods.rb +27 -10
  11. data/lib/listings/filter_descriptor.rb +7 -0
  12. data/lib/listings/filter_view.rb +19 -0
  13. data/lib/listings/sources.rb +7 -0
  14. data/lib/listings/sources/active_record_data_source.rb +159 -0
  15. data/lib/listings/sources/data_source.rb +76 -0
  16. data/lib/listings/sources/object_data_source.rb +91 -0
  17. data/lib/listings/version.rb +1 -1
  18. data/lib/rspec/listings_helpers.rb +27 -5
  19. data/spec/dummy/app/controllers/welcome_controller.rb +3 -0
  20. data/spec/dummy/app/listings/array_listing.rb +1 -0
  21. data/spec/dummy/app/listings/tracks_fixed_order_listing.rb +13 -0
  22. data/spec/dummy/app/listings/tracks_listing.rb +18 -0
  23. data/spec/dummy/app/models/album.rb +4 -0
  24. data/spec/dummy/app/models/object_album.rb +8 -0
  25. data/spec/dummy/app/models/object_track.rb +8 -0
  26. data/spec/dummy/app/models/track.rb +7 -0
  27. data/spec/dummy/app/views/welcome/index.html.haml +7 -1
  28. data/spec/dummy/app/views/welcome/tracks.html.haml +3 -0
  29. data/spec/dummy/config/routes.rb +1 -0
  30. data/spec/dummy/db/migrate/20150611185824_create_albums.rb +9 -0
  31. data/spec/dummy/db/migrate/20150611185922_create_tracks.rb +12 -0
  32. data/spec/dummy/db/schema.rb +17 -1
  33. data/spec/dummy/db/seeds.rb +6 -0
  34. data/spec/factories/albums.rb +25 -0
  35. data/spec/factories/post.rb +1 -0
  36. data/spec/factories/tracks.rb +14 -0
  37. data/spec/factories/traits.rb +9 -0
  38. data/spec/lib/filter_parser_spec.rb +5 -0
  39. data/spec/lib/sources/active_record_data_source_spec.rb +359 -0
  40. data/spec/lib/sources/object_data_source_spec.rb +231 -0
  41. data/spec/listings/tracks_fixed_order_listing_spec.rb +19 -0
  42. data/spec/listings/tracks_listing_spec.rb +27 -0
  43. data/spec/models/album_spec.rb +9 -0
  44. data/spec/models/post_spec.rb +2 -2
  45. data/spec/models/track_spec.rb +8 -0
  46. data/spec/spec_helper.rb +3 -0
  47. data/spec/support/query_counter.rb +29 -0
  48. metadata +49 -3
@@ -0,0 +1,231 @@
1
+ include Listings::Sources
2
+
3
+ RSpec.describe ObjectDataSource do
4
+
5
+ shared_examples "object datasource" do
6
+ let(:tracks) {
7
+ build_list(:object_album, 10).map(&:tracks).flatten
8
+ }
9
+
10
+ def add_tracks(ts)
11
+ if ts.is_a?(Array)
12
+ ts.each { |t| add_tracks t }
13
+ elsif ts.is_a?(ObjectAlbum)
14
+ add_tracks ts.tracks
15
+ elsif ts.is_a?(ObjectTrack)
16
+ tracks << ts
17
+ else
18
+ raise "Invalid Object #{ts}"
19
+ end
20
+ end
21
+
22
+ let(:track_title) { ds.build_field :title }
23
+
24
+ describe "DataSource factory" do
25
+ it "should have tracks with album" do
26
+ expect(tracks).to_not be_empty
27
+ expect(tracks.first.album).to_not be_nil
28
+ end
29
+
30
+ it "should create" do
31
+ expect(ds).to be_a(ObjectDataSource)
32
+ end
33
+
34
+ describe "field" do
35
+ let(:tracks) { [] }
36
+ before(:each) {
37
+ add_tracks build(:object_track, album: nil)
38
+ }
39
+
40
+ it "should deal with intermediate nils" do
41
+ expect(album_name.value_for(ds.items.first)).to be_nil
42
+ end
43
+
44
+ it "should have key" do
45
+ expect(album_name.key).to eq('album_name')
46
+ end
47
+ end
48
+
49
+ describe "items" do
50
+ it "should list all" do
51
+ expect(ds.items.count).to be(tracks.count)
52
+ end
53
+
54
+ it "should enumerate all items" do
55
+ expect(begin
56
+ c = 0
57
+ ds.items.each do
58
+ c = c + 1
59
+ end
60
+ c
61
+ end).to be(tracks.count)
62
+ end
63
+ end
64
+
65
+ describe "paginate" do
66
+ let(:page_size) { 5 }
67
+
68
+ before(:each) { ds.paginate(2, page_size) }
69
+
70
+ it "should get only paged items" do
71
+ expect(ds.items.count).to be(page_size)
72
+ end
73
+
74
+ it "should keep total_count" do
75
+ expect(ds.items.total_count).to be(tracks.count)
76
+ end
77
+ end
78
+
79
+ describe "field" do
80
+ it "should project attribute value" do
81
+ expect(track_title.value_for(ds.items.first)).to eq(tracks.first.title)
82
+ end
83
+
84
+ it "should navigate and project attribute value" do
85
+ expect(album_name.value_for(ds.items.first)).to eq(tracks.first.album.name)
86
+ end
87
+ end
88
+
89
+ describe "scope" do
90
+ before(:each) do
91
+ ds.scope do |items|
92
+ [].tap do |res|
93
+ tracks.each_with_index do |item, index|
94
+ next if index % 2 == 1
95
+ res << item
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ it "should return scoped items" do
102
+ expect(ds.items.count).to be(tracks.count / 2)
103
+ end
104
+ end
105
+
106
+ describe "search" do
107
+ before(:each) do
108
+ add_tracks build(:object_album, tracks_count: 5, name: 'album-name-magic-string-1')
109
+ add_tracks build(:object_album, tracks_count: 5, name: 'album-name-magic-string-2')
110
+ build_list(:object_album, 2).each do |album_with_tracks_to_match|
111
+ add_tracks build_list(:object_track, 5, title: 'title-magic-string', album: album_with_tracks_to_match)
112
+ end
113
+
114
+ ds.search([track_title, album_name], 'magic')
115
+ end
116
+
117
+ it "should return matching items" do
118
+ expect(ds.items.count).to be(20)
119
+ end
120
+ end
121
+
122
+ describe "filter" do
123
+ before(:each) do
124
+ add_tracks build(:object_album, tracks_count: 5, name: 'album-name-magic-string-1')
125
+ add_tracks build(:object_album, tracks_count: 5, name: 'album-name-magic-string-2')
126
+
127
+ ds.filter(album_name, 'album-name-magic-string-1')
128
+ end
129
+
130
+ it "should return matching items" do
131
+ expect(ds.items.count).to be(5)
132
+ end
133
+ end
134
+
135
+ describe "sort" do
136
+ def all_track_albumns_name
137
+ tracks.map { |t| t.album.name }
138
+ end
139
+
140
+ before(:each) do
141
+ expect(all_track_albumns_name).to_not eq(all_track_albumns_name.sort)
142
+ ds.sort(album_name)
143
+ end
144
+
145
+ it "should return matching items" do
146
+ expect(ds.items.map { |e| album_name.value_for(e) }).to eq(all_track_albumns_name.sort)
147
+ end
148
+ end
149
+
150
+ describe "sort desc" do
151
+ def all_track_albumns_name
152
+ tracks.map { |t| t.album.name }
153
+ end
154
+
155
+ before(:each) do
156
+ expect(all_track_albumns_name).to_not eq(all_track_albumns_name.sort.reverse)
157
+ ds.sort(album_name, DataSource::DESC)
158
+ end
159
+
160
+ it "should return matching items" do
161
+ expect(ds.items.map { |e| album_name.value_for(e) }).to eq(all_track_albumns_name.sort.reverse)
162
+ end
163
+ end
164
+
165
+ describe "values_for_filter" do
166
+ let(:tracks) { [] } # skip default test albums
167
+
168
+ before(:each) do
169
+ add_tracks build(:object_album, tracks_count: 5, name: 'album-name-1')
170
+ add_tracks build(:object_album, tracks_count: 5, name: 'album-name-3')
171
+ add_tracks build(:object_album, tracks_count: 5, name: 'album-name-2')
172
+ add_tracks build(:object_album, tracks_count: 5, name: nil)
173
+ end
174
+
175
+ context "without search" do
176
+ it "should matching values" do
177
+ expect(ds.values_for_filter(album_name)).to eq(['album-name-1', 'album-name-2', 'album-name-3'])
178
+ end
179
+ end
180
+
181
+ context "with scope" do
182
+ before(:each) do
183
+ ds.scope do |items|
184
+ [].tap do |res|
185
+ tracks.each_with_index do |item, index|
186
+ next if index % 2 == 1
187
+ res << item
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ it "should matching values" do
194
+ expect(ds.values_for_filter(album_name)).to eq(['album-name-1', 'album-name-2', 'album-name-3'])
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ end
201
+
202
+ context "using array of objects" do
203
+ let(:ds) { DataSource.for(tracks) }
204
+ let(:album_name) { nil }
205
+
206
+ context "and hash like fields" do
207
+ let(:album_name) { ds.build_field album: :name }
208
+ it_behaves_like "object datasource"
209
+ end
210
+
211
+ context "and array like fields" do
212
+ let(:album_name) { ds.build_field [:album, :name] }
213
+ it_behaves_like "object datasource"
214
+ end
215
+ end
216
+
217
+ context "using array of hash" do
218
+ let(:ds) { DataSource.for(tracks.map(&:to_h)) }
219
+ let(:album_name) { nil }
220
+
221
+ context "and hash like fields" do
222
+ let(:album_name) { ds.build_field album: :name }
223
+ it_behaves_like "object datasource"
224
+ end
225
+
226
+ context "and array like fields" do
227
+ let(:album_name) { ds.build_field [:album, :name] }
228
+ it_behaves_like "object datasource"
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,19 @@
1
+ RSpec.describe TracksFixedOrderListing, type: :listing do
2
+ describe "List entities" do
3
+ let!(:track) { create(:album, tracks_count: 1) }
4
+
5
+ let(:listing) { query_listing :tracks_fixed_order }
6
+
7
+ it "should list all" do
8
+ expect(listing.items.count).to eq(1)
9
+ end
10
+
11
+ it "can be rendered" do
12
+ render_listing :tracks
13
+ end
14
+
15
+ it "can't be sorted" do
16
+ expect(listing).to_not be_sortable
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ RSpec.describe TracksListing, type: :listing do
2
+ describe "List entities" do
3
+ let!(:track) { create(:album, tracks_count: 1) }
4
+
5
+ let(:listing) { query_listing :tracks }
6
+
7
+ it "should list all" do
8
+ expect(listing.items.count).to eq(1)
9
+ end
10
+
11
+ it "can be rendered" do
12
+ render_listing :tracks
13
+ end
14
+
15
+ it "should get name from model" do
16
+ expect(listing.column_with_key('album_name').human_name).to eq('Album Name')
17
+ end
18
+
19
+ it "should get name from title option for column" do
20
+ expect(listing.column_with_key('album_id').human_name).to eq('The Album Id')
21
+ end
22
+
23
+ it "should get name from title option for filter" do
24
+ expect(listing.filter_with_key('album_id').human_name).to eq('The Album Id')
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ RSpec.describe Album, type: :model do
2
+ describe "Factory" do
3
+ it "can create" do
4
+ create(:album)
5
+ expect(Album.count).to eq(1)
6
+ expect(Album.first.tracks.count).to be > 1
7
+ end
8
+ end
9
+ end
@@ -1,6 +1,6 @@
1
1
  RSpec.describe Post, type: :model do
2
- describe "Create" do
3
- it "can be created" do
2
+ describe "Factory" do
3
+ it "can create" do
4
4
  create(:post)
5
5
  expect(Post.count).to eq(1)
6
6
  end
@@ -0,0 +1,8 @@
1
+ RSpec.describe Track, type: :model do
2
+ describe "Factory" do
3
+ it "can create" do
4
+ create(:track)
5
+ expect(Track.count).to eq(1)
6
+ end
7
+ end
8
+ end
@@ -22,6 +22,9 @@ RSpec.configure do |config|
22
22
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
23
23
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
24
24
 
25
+ config.filter_run :focus => true
26
+ config.run_all_when_everything_filtered = true
27
+
25
28
  # If you're not using ActiveRecord, or you'd prefer not to run each of your
26
29
  # examples within a transaction, remove the following line or assign false
27
30
  # instead of true.
@@ -0,0 +1,29 @@
1
+ module ActiveRecord
2
+ class QueryCounter
3
+ cattr_accessor :query_count do
4
+ 0
5
+ end
6
+
7
+ IGNORED_SQL = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/]
8
+
9
+ def call(name, start, finish, message_id, values)
10
+ # FIXME: this seems bad. we should probably have a better way to indicate
11
+ # the query was cached
12
+ unless 'CACHE' == values[:name]
13
+ self.class.query_count += 1 unless IGNORED_SQL.any? { |r| values[:sql] =~ r }
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ ActiveSupport::Notifications.subscribe('sql.active_record', ActiveRecord::QueryCounter.new)
20
+
21
+ module ActiveRecord
22
+ class Base
23
+ def self.count_queries(&block)
24
+ ActiveRecord::QueryCounter.query_count = 0
25
+ yield
26
+ ActiveRecord::QueryCounter.query_count
27
+ end
28
+ end
29
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: listings
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -198,14 +198,22 @@ files:
198
198
  - config/routes.rb
199
199
  - lib/listings/action_view_extensions.rb
200
200
  - lib/listings/base.rb
201
+ - lib/listings/base_field_descriptor.rb
202
+ - lib/listings/base_field_view.rb
201
203
  - lib/listings/column_descriptor.rb
202
204
  - lib/listings/column_view.rb
203
205
  - lib/listings/configuration.rb
204
206
  - lib/listings/configuration_methods.rb
205
207
  - lib/listings/dynamic_binding.rb
206
208
  - lib/listings/engine.rb
209
+ - lib/listings/filter_descriptor.rb
210
+ - lib/listings/filter_view.rb
207
211
  - lib/listings/kaminari_helpers_tag_patch.rb
208
212
  - lib/listings/scope_descriptor.rb
213
+ - lib/listings/sources/active_record_data_source.rb
214
+ - lib/listings/sources/data_source.rb
215
+ - lib/listings/sources/object_data_source.rb
216
+ - lib/listings/sources.rb
209
217
  - lib/listings/version.rb
210
218
  - lib/listings/view_helper_methods.rb
211
219
  - lib/listings.rb
@@ -226,7 +234,13 @@ files:
226
234
  - spec/dummy/app/listings/filtered_posts_listing.rb
227
235
  - spec/dummy/app/listings/hash_listing.rb
228
236
  - spec/dummy/app/listings/posts_listing.rb
237
+ - spec/dummy/app/listings/tracks_fixed_order_listing.rb
238
+ - spec/dummy/app/listings/tracks_listing.rb
239
+ - spec/dummy/app/models/album.rb
240
+ - spec/dummy/app/models/object_album.rb
241
+ - spec/dummy/app/models/object_track.rb
229
242
  - spec/dummy/app/models/post.rb
243
+ - spec/dummy/app/models/track.rb
230
244
  - spec/dummy/app/views/layouts/application.html.erb
231
245
  - spec/dummy/app/views/posts/filtered.html.haml
232
246
  - spec/dummy/app/views/posts/index.html.haml
@@ -234,6 +248,7 @@ files:
234
248
  - spec/dummy/app/views/welcome/array.html.haml
235
249
  - spec/dummy/app/views/welcome/hash.html.haml
236
250
  - spec/dummy/app/views/welcome/index.html.haml
251
+ - spec/dummy/app/views/welcome/tracks.html.haml
237
252
  - spec/dummy/config/application.rb
238
253
  - spec/dummy/config/boot.rb
239
254
  - spec/dummy/config/database.yml
@@ -254,6 +269,8 @@ files:
254
269
  - spec/dummy/db/migrate/20130618143317_create_posts.rb
255
270
  - spec/dummy/db/migrate/20130618195559_add_author_to_posts.rb
256
271
  - spec/dummy/db/migrate/20140728151246_add_category_to_post.rb
272
+ - spec/dummy/db/migrate/20150611185824_create_albums.rb
273
+ - spec/dummy/db/migrate/20150611185922_create_tracks.rb
257
274
  - spec/dummy/db/schema.rb
258
275
  - spec/dummy/db/seeds.rb
259
276
  - spec/dummy/db/test.sqlite3
@@ -295,11 +312,21 @@ files:
295
312
  - spec/dummy/tmp/cache/assets/E2E/B10/sprockets%2F4e77441cbd1f4fadabea28dd0be9a977
296
313
  - spec/dummy/tmp/cache/assets/E57/F10/sprockets%2Fb7a56dbe6cb518caaa4cb8eac55df770
297
314
  - spec/dummy/tmp/pids/server.pid
315
+ - spec/factories/albums.rb
298
316
  - spec/factories/post.rb
317
+ - spec/factories/tracks.rb
318
+ - spec/factories/traits.rb
299
319
  - spec/lib/filter_parser_spec.rb
320
+ - spec/lib/sources/active_record_data_source_spec.rb
321
+ - spec/lib/sources/object_data_source_spec.rb
300
322
  - spec/listings/posts_listing_spec.rb
323
+ - spec/listings/tracks_fixed_order_listing_spec.rb
324
+ - spec/listings/tracks_listing_spec.rb
325
+ - spec/models/album_spec.rb
301
326
  - spec/models/post_spec.rb
327
+ - spec/models/track_spec.rb
302
328
  - spec/spec_helper.rb
329
+ - spec/support/query_counter.rb
303
330
  homepage: http://github.com/manastech/listings
304
331
  licenses: []
305
332
  post_install_message:
@@ -314,7 +341,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
314
341
  version: '0'
315
342
  segments:
316
343
  - 0
317
- hash: -1318764667279982391
344
+ hash: -3833283271247279800
318
345
  required_rubygems_version: !ruby/object:Gem::Requirement
319
346
  none: false
320
347
  requirements:
@@ -323,7 +350,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
323
350
  version: '0'
324
351
  segments:
325
352
  - 0
326
- hash: -1318764667279982391
353
+ hash: -3833283271247279800
327
354
  requirements: []
328
355
  rubyforge_project:
329
356
  rubygems_version: 1.8.23.2
@@ -342,7 +369,13 @@ test_files:
342
369
  - spec/dummy/app/listings/filtered_posts_listing.rb
343
370
  - spec/dummy/app/listings/hash_listing.rb
344
371
  - spec/dummy/app/listings/posts_listing.rb
372
+ - spec/dummy/app/listings/tracks_fixed_order_listing.rb
373
+ - spec/dummy/app/listings/tracks_listing.rb
374
+ - spec/dummy/app/models/album.rb
375
+ - spec/dummy/app/models/object_album.rb
376
+ - spec/dummy/app/models/object_track.rb
345
377
  - spec/dummy/app/models/post.rb
378
+ - spec/dummy/app/models/track.rb
346
379
  - spec/dummy/app/views/layouts/application.html.erb
347
380
  - spec/dummy/app/views/posts/filtered.html.haml
348
381
  - spec/dummy/app/views/posts/index.html.haml
@@ -350,6 +383,7 @@ test_files:
350
383
  - spec/dummy/app/views/welcome/array.html.haml
351
384
  - spec/dummy/app/views/welcome/hash.html.haml
352
385
  - spec/dummy/app/views/welcome/index.html.haml
386
+ - spec/dummy/app/views/welcome/tracks.html.haml
353
387
  - spec/dummy/config/application.rb
354
388
  - spec/dummy/config/boot.rb
355
389
  - spec/dummy/config/database.yml
@@ -370,6 +404,8 @@ test_files:
370
404
  - spec/dummy/db/migrate/20130618143317_create_posts.rb
371
405
  - spec/dummy/db/migrate/20130618195559_add_author_to_posts.rb
372
406
  - spec/dummy/db/migrate/20140728151246_add_category_to_post.rb
407
+ - spec/dummy/db/migrate/20150611185824_create_albums.rb
408
+ - spec/dummy/db/migrate/20150611185922_create_tracks.rb
373
409
  - spec/dummy/db/schema.rb
374
410
  - spec/dummy/db/seeds.rb
375
411
  - spec/dummy/db/test.sqlite3
@@ -411,8 +447,18 @@ test_files:
411
447
  - spec/dummy/tmp/cache/assets/E2E/B10/sprockets%2F4e77441cbd1f4fadabea28dd0be9a977
412
448
  - spec/dummy/tmp/cache/assets/E57/F10/sprockets%2Fb7a56dbe6cb518caaa4cb8eac55df770
413
449
  - spec/dummy/tmp/pids/server.pid
450
+ - spec/factories/albums.rb
414
451
  - spec/factories/post.rb
452
+ - spec/factories/tracks.rb
453
+ - spec/factories/traits.rb
415
454
  - spec/lib/filter_parser_spec.rb
455
+ - spec/lib/sources/active_record_data_source_spec.rb
456
+ - spec/lib/sources/object_data_source_spec.rb
416
457
  - spec/listings/posts_listing_spec.rb
458
+ - spec/listings/tracks_fixed_order_listing_spec.rb
459
+ - spec/listings/tracks_listing_spec.rb
460
+ - spec/models/album_spec.rb
417
461
  - spec/models/post_spec.rb
462
+ - spec/models/track_spec.rb
418
463
  - spec/spec_helper.rb
464
+ - spec/support/query_counter.rb