listings 0.0.3 → 0.1.0

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 (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