trailblazer-finder 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 (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rubocop.yml +45 -0
  4. data/.rubocop_todo.yml +52 -0
  5. data/.travis.yml +15 -0
  6. data/Gemfile +12 -0
  7. data/LICENSE.txt +23 -0
  8. data/README.md +494 -0
  9. data/Rakefile +29 -0
  10. data/lib/trailblazer/finder/adapters/active_record/paging.rb +20 -0
  11. data/lib/trailblazer/finder/adapters/active_record/sorting.rb +20 -0
  12. data/lib/trailblazer/finder/adapters/active_record.rb +30 -0
  13. data/lib/trailblazer/finder/adapters/data_mapper/paging.rb +20 -0
  14. data/lib/trailblazer/finder/adapters/data_mapper/sorting.rb +25 -0
  15. data/lib/trailblazer/finder/adapters/data_mapper.rb +30 -0
  16. data/lib/trailblazer/finder/adapters/friendly_id.rb +33 -0
  17. data/lib/trailblazer/finder/adapters/kaminari.rb +18 -0
  18. data/lib/trailblazer/finder/adapters/sequel/paging.rb +20 -0
  19. data/lib/trailblazer/finder/adapters/sequel/sorting.rb +25 -0
  20. data/lib/trailblazer/finder/adapters/sequel.rb +30 -0
  21. data/lib/trailblazer/finder/adapters/will_paginate.rb +18 -0
  22. data/lib/trailblazer/finder/adapters.rb +26 -0
  23. data/lib/trailblazer/finder/base.rb +98 -0
  24. data/lib/trailblazer/finder/errors/block_ignored.rb +11 -0
  25. data/lib/trailblazer/finder/errors/invalid_defined_by_value.rb +11 -0
  26. data/lib/trailblazer/finder/errors/invalid_number.rb +16 -0
  27. data/lib/trailblazer/finder/errors/missing_entity_type.rb +11 -0
  28. data/lib/trailblazer/finder/errors/with_ignored.rb +11 -0
  29. data/lib/trailblazer/finder/features/paging.rb +55 -0
  30. data/lib/trailblazer/finder/features/sorting.rb +66 -0
  31. data/lib/trailblazer/finder/features.rb +22 -0
  32. data/lib/trailblazer/finder/filter.rb +66 -0
  33. data/lib/trailblazer/finder/find.rb +29 -0
  34. data/lib/trailblazer/finder/utils/extra.rb +31 -0
  35. data/lib/trailblazer/finder/utils/params.rb +28 -0
  36. data/lib/trailblazer/finder/utils/parse.rb +25 -0
  37. data/lib/trailblazer/finder/utils/string.rb +35 -0
  38. data/lib/trailblazer/finder/version.rb +5 -0
  39. data/lib/trailblazer/finder.rb +29 -0
  40. data/lib/trailblazer/operation/finder.rb +61 -0
  41. data/spec/spec_helper.rb +15 -0
  42. data/spec/spec_helper_active_record.rb +50 -0
  43. data/spec/spec_helper_data_mapper.rb +35 -0
  44. data/spec/spec_helper_sequel.rb +32 -0
  45. data/spec/support/paging_shared_example.rb +65 -0
  46. data/spec/support/sorting_shared_example.rb +95 -0
  47. data/spec/trailblazer/finder/adapters/active_record/base_spec.rb +112 -0
  48. data/spec/trailblazer/finder/adapters/active_record/paging_spec.rb +64 -0
  49. data/spec/trailblazer/finder/adapters/active_record/sorting_spec.rb +82 -0
  50. data/spec/trailblazer/finder/adapters/data_mapper/base_spec.rb +112 -0
  51. data/spec/trailblazer/finder/adapters/data_mapper/paging_spec.rb +64 -0
  52. data/spec/trailblazer/finder/adapters/data_mapper/sorting_spec.rb +85 -0
  53. data/spec/trailblazer/finder/adapters/friendly_id_spec.rb +46 -0
  54. data/spec/trailblazer/finder/adapters/kaminari_spec.rb +64 -0
  55. data/spec/trailblazer/finder/adapters/sequel/base_spec.rb +112 -0
  56. data/spec/trailblazer/finder/adapters/sequel/paging_spec.rb +64 -0
  57. data/spec/trailblazer/finder/adapters/sequel/sorting_spec.rb +82 -0
  58. data/spec/trailblazer/finder/adapters/will_paginate_spec.rb +71 -0
  59. data/spec/trailblazer/finder/adapters_spec.rb +110 -0
  60. data/spec/trailblazer/finder/base_spec.rb +329 -0
  61. data/spec/trailblazer/finder/features/paging_spec.rb +104 -0
  62. data/spec/trailblazer/finder/features/sorting_spec.rb +100 -0
  63. data/spec/trailblazer/finder/features_spec.rb +55 -0
  64. data/spec/trailblazer/finder/filter_spec.rb +133 -0
  65. data/spec/trailblazer/finder/find_spec.rb +72 -0
  66. data/spec/trailblazer/finder/utils/extra_spec.rb +41 -0
  67. data/spec/trailblazer/finder/utils/params_spec.rb +39 -0
  68. data/spec/trailblazer/finder/utils/parse_spec.rb +33 -0
  69. data/spec/trailblazer/finder/utils/string_spec.rb +25 -0
  70. data/spec/trailblazer/operation/finder_spec.rb +103 -0
  71. data/spec/trailblazer/operation/paging_spec.rb +68 -0
  72. data/spec/trailblazer/operation/sorting_spec.rb +80 -0
  73. data/trailblazer-finder.gemspec +41 -0
  74. metadata +402 -0
@@ -0,0 +1,112 @@
1
+ require 'spec_helper_active_record'
2
+
3
+ module Trailblazer
4
+ class Finder
5
+ module Adapters
6
+ describe ActiveRecord do
7
+ # it_behaves_like 'a base orm adapter'
8
+
9
+ after do
10
+ Product.delete_all
11
+ end
12
+
13
+ def define_finder_class(&block)
14
+ Class.new(Trailblazer::Finder) do
15
+ class_eval(&block)
16
+ end
17
+ end
18
+
19
+ def finder_class(&block) # rubocop:disable Metrics/MethodLength
20
+ define_finder_class do
21
+ adapters ActiveRecord
22
+
23
+ entity_type { Product }
24
+
25
+ filter_by :id
26
+ filter_by :name
27
+ filter_by :slug
28
+
29
+ if block.nil?
30
+ filter_by :value do |entity_type, value|
31
+ entity_type.where(slug: value)
32
+ end
33
+ else
34
+ class_eval(&block)
35
+ end
36
+ end
37
+ end
38
+
39
+ def finder_with_filter(key = nil, name = nil, &block)
40
+ finder_class(&block).new filter: { key => name }
41
+ end
42
+
43
+ describe 'filter_by' do
44
+ it 'has a default filter' do
45
+ 10.times { |i| Product.create name: "product_#{i}" }
46
+ finder = finder_with_filter :name, 'product_2'
47
+
48
+ expect(finder.results.first.name).to eq 'product_2'
49
+ end
50
+
51
+ it 'has another default filter' do
52
+ 10.times { |i| Product.create slug: "product_#{i}" }
53
+ finder = finder_with_filter :value, 'product_2'
54
+
55
+ expect(finder.results.first.slug).to eq 'product_2'
56
+ end
57
+ end
58
+
59
+ it 'can use methods from the object' do
60
+ 2.times { |i| Product.create name: "product_#{i}" }
61
+ finder1 = finder_with_filter :id, 1 do
62
+ filter_by :id do |entity_type, value|
63
+ some_instance_method(entity_type, value)
64
+ end
65
+
66
+ private
67
+
68
+ def some_instance_method(entity_type, value)
69
+ entity_type.where(id: value)
70
+ end
71
+ end
72
+
73
+ expect(finder1.results.first.id).to eq 1
74
+ end
75
+
76
+ it 'can dispatch with instance methods' do
77
+ 2.times { |i| Product.create name: "product_#{i}" }
78
+ finder = finder_with_filter :id, 3 do
79
+ filter_by :id, with: :some_instance_method
80
+
81
+ private
82
+
83
+ def some_instance_method(entity_type, value)
84
+ entity_type.where(id: value)
85
+ end
86
+ end
87
+
88
+ expect(finder.results.first.id).to eq 3
89
+ end
90
+
91
+ describe 'filter_by attributes' do
92
+ it 'accesses filter values' do
93
+ finder = finder_with_filter :value, 1
94
+ expect(finder.value).to eq 1
95
+ end
96
+
97
+ it 'returns default filter value if filter_by is not specified' do
98
+ finder = finder_with_filter do
99
+ filter_by :value, 1
100
+ end
101
+ expect(finder.value).to eq 1
102
+ end
103
+
104
+ it 'does not include invalid filters' do
105
+ finder = finder_with_filter invalid: 'option'
106
+ expect { finder.invalid }.to raise_error NoMethodError
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper_active_record'
2
+
3
+ module Trailblazer
4
+ class Finder
5
+ module Adapters
6
+ module ActiveRecord
7
+ describe Paging do
8
+ it_behaves_like 'a paging feature'
9
+
10
+ after do
11
+ Product.delete_all
12
+ end
13
+
14
+ def define_finder_class(&block)
15
+ Class.new do
16
+ include Trailblazer::Finder::Base
17
+ include Trailblazer::Finder::Features::Paging
18
+ include Trailblazer::Finder::Adapters::ActiveRecord
19
+
20
+ instance_eval(&block) if block_given?
21
+ end
22
+ end
23
+
24
+ def finder_class
25
+ define_finder_class do
26
+ entity_type { Product }
27
+
28
+ per_page 2
29
+
30
+ min_per_page 2
31
+ max_per_page 10
32
+ end
33
+ end
34
+
35
+ def finder_with_page(page = nil, per_page = nil)
36
+ finder_class.new page: page, per_page: per_page
37
+ end
38
+
39
+ it 'can be inherited' do
40
+ child_class = Class.new(finder_class)
41
+ expect(child_class.new.per_page).to eq 2
42
+ end
43
+
44
+ describe '#results' do
45
+ it 'paginates results' do
46
+ 6.times { |i| Product.create name: "product_#{i}" }
47
+ finder = finder_with_page 2, 2
48
+
49
+ expect(finder.results.map(&:name)).to eq %w[product_2 product_3]
50
+ end
51
+ end
52
+
53
+ describe '#count' do
54
+ it 'gives the real count' do
55
+ 10.times { |i| Product.create name: "product_#{i}" }
56
+ finder = finder_with_page 1
57
+ expect(finder.count).to eq 10
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper_active_record'
2
+
3
+ module Trailblazer
4
+ class Finder
5
+ module Adapters
6
+ module ActiveRecord
7
+ describe Sorting do
8
+ def finder_class
9
+ Class.new do
10
+ include Trailblazer::Finder::Base
11
+ include Trailblazer::Finder::Features::Sorting
12
+ include Trailblazer::Finder::Adapters::ActiveRecord
13
+
14
+ entity_type { Product.all }
15
+
16
+ sortable_by :name, :price, :created_at
17
+
18
+ filter_by :name
19
+ filter_by :price
20
+ filter_by(:category) { |entity_type, _| entity_type.joins(:category) }
21
+ end
22
+ end
23
+
24
+ def finder_with_sort(sort = nil, filters = {})
25
+ finder_class.new filter: { sort: sort }.merge(filters)
26
+ end
27
+
28
+ it 'can be inherited' do
29
+ child_class = Class.new(finder_class)
30
+ expect(child_class.new.sort_attribute).to eq 'name'
31
+ end
32
+
33
+ describe 'sorting' do
34
+ after do
35
+ Product.delete_all
36
+ end
37
+
38
+ it 'sorts results based on the sort option desc' do
39
+ 5.times { |i| Product.create! price: i }
40
+
41
+ finder = finder_with_sort 'price desc'
42
+ expect(finder.results.map(&:price)).to eq [4, 3, 2, 1, 0]
43
+ end
44
+
45
+ it 'sorts results based on the sort option asc' do
46
+ 5.times { |i| Product.create! price: i }
47
+
48
+ finder = finder_with_sort 'price asc'
49
+ expect(finder.results.map(&:price)).to eq [0, 1, 2, 3, 4]
50
+ end
51
+
52
+ it 'defaults to first sort by option' do
53
+ 5.times { |i| Product.create! name: "Name#{i}" }
54
+
55
+ finder = finder_with_sort
56
+ expect(finder.results.map(&:name)).to eq %w[Name4 Name3 Name2 Name1 Name0]
57
+ end
58
+
59
+ it 'ignores invalid sort values' do
60
+ finder = finder_with_sort 'invalid attribute'
61
+ expect { finder.results.to_a }.not_to raise_error
62
+ end
63
+
64
+ it 'can handle renames of sorting in joins' do
65
+ older_category = Category.create! title: 'older'
66
+ newer_category = Category.create! title: 'newer'
67
+
68
+ product_of_newer_category = Product.create! name: 'older product', category: newer_category
69
+ product_of_older_category = Product.create! name: 'newer product', category: older_category
70
+
71
+ finder = finder_with_sort 'created_at desc', category: ''
72
+
73
+ expect(finder.results.map(&:name)).to eq [product_of_older_category.name, product_of_newer_category.name]
74
+ end
75
+ end
76
+
77
+ it_behaves_like 'a sorting feature'
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,112 @@
1
+ require 'spec_helper_data_mapper'
2
+
3
+ module Trailblazer
4
+ class Finder
5
+ module Adapters
6
+ describe DataMapper do
7
+ # it_behaves_like 'a base orm adapter'
8
+
9
+ after do
10
+ DProduct.all.destroy
11
+ end
12
+
13
+ def define_finder_class(&block)
14
+ Class.new(Trailblazer::Finder) do
15
+ class_eval(&block)
16
+ end
17
+ end
18
+
19
+ def finder_class(&block) # rubocop:disable Metrics/MethodLength
20
+ define_finder_class do
21
+ adapters DataMapper
22
+
23
+ entity_type { DProduct }
24
+
25
+ filter_by :id
26
+ filter_by :name
27
+ filter_by :slug
28
+
29
+ if block.nil?
30
+ filter_by :value do |entity_type, value|
31
+ entity_type.all(slug: value)
32
+ end
33
+ else
34
+ class_eval(&block)
35
+ end
36
+ end
37
+ end
38
+
39
+ def finder_with_filter(key = nil, name = nil, &block)
40
+ finder_class(&block).new filter: { key => name }
41
+ end
42
+
43
+ describe 'filter_by' do
44
+ it 'has a default filter' do
45
+ 10.times { |i| DProduct.create name: "product_#{i}" }
46
+ finder = finder_with_filter :name, 'product_2'
47
+
48
+ expect(finder.results.first.name).to eq 'product_2'
49
+ end
50
+
51
+ it 'has another default filter' do
52
+ 10.times { |i| DProduct.create slug: "product_#{i}" }
53
+ finder = finder_with_filter :value, 'product_2'
54
+
55
+ expect(finder.results.first.slug).to eq 'product_2'
56
+ end
57
+ end
58
+
59
+ it 'can use methods from the object' do
60
+ 2.times { |i| DProduct.create name: "product_#{i}" }
61
+ finder1 = finder_with_filter :id, 1 do
62
+ filter_by :id do |entity_type, value|
63
+ some_instance_method(entity_type, value)
64
+ end
65
+
66
+ private
67
+
68
+ def some_instance_method(entity_type, value)
69
+ entity_type.all(id: value)
70
+ end
71
+ end
72
+
73
+ expect(finder1.results.first.id).to eq 1
74
+ end
75
+
76
+ it 'can dispatch with instance methods' do
77
+ 2.times { |i| DProduct.create name: "product_#{i}" }
78
+ finder = finder_with_filter :id, 3 do
79
+ filter_by :id, with: :some_instance_method
80
+
81
+ private
82
+
83
+ def some_instance_method(entity_type, value)
84
+ entity_type.all(id: value)
85
+ end
86
+ end
87
+
88
+ expect(finder.results.first.id).to eq 3
89
+ end
90
+
91
+ describe 'filter_by attributes' do
92
+ it 'accesses filter values' do
93
+ finder = finder_with_filter :value, 1
94
+ expect(finder.value).to eq 1
95
+ end
96
+
97
+ it 'returns default filter value if filter_by is not specified' do
98
+ finder = finder_with_filter do
99
+ filter_by :value, 1
100
+ end
101
+ expect(finder.value).to eq 1
102
+ end
103
+
104
+ it 'does not include invalid filters' do
105
+ finder = finder_with_filter invalid: 'option'
106
+ expect { finder.invalid }.to raise_error NoMethodError
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper_data_mapper'
2
+
3
+ module Trailblazer
4
+ class Finder
5
+ module Adapters
6
+ module DataMapper
7
+ describe Paging do
8
+ it_behaves_like 'a paging feature'
9
+
10
+ after do
11
+ DProduct.all.destroy
12
+ end
13
+
14
+ def define_finder_class(&block)
15
+ Class.new do
16
+ include Trailblazer::Finder::Base
17
+ include Trailblazer::Finder::Features::Paging
18
+ include Trailblazer::Finder::Adapters::DataMapper
19
+
20
+ instance_eval(&block) if block_given?
21
+ end
22
+ end
23
+
24
+ def finder_class
25
+ define_finder_class do
26
+ entity_type { DProduct }
27
+
28
+ per_page 2
29
+
30
+ min_per_page 2
31
+ max_per_page 10
32
+ end
33
+ end
34
+
35
+ def finder_with_page(page = nil, per_page = nil)
36
+ finder_class.new page: page, per_page: per_page
37
+ end
38
+
39
+ it 'can be inherited' do
40
+ child_class = Class.new(finder_class)
41
+ expect(child_class.new.per_page).to eq 2
42
+ end
43
+
44
+ describe '#results' do
45
+ it 'paginates results' do
46
+ 6.times { |i| DProduct.create name: "product_#{i}" }
47
+ finder = finder_with_page 2, 2
48
+
49
+ expect(finder.results.map(&:name)).to eq %w[product_2 product_3]
50
+ end
51
+ end
52
+
53
+ describe '#count' do
54
+ it 'gives the real count' do
55
+ 10.times { |i| DProduct.create name: "product_#{i}" }
56
+ finder = finder_with_page 1
57
+ expect(finder.count).to eq 10
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper_data_mapper'
2
+
3
+ module Trailblazer
4
+ class Finder
5
+ module Adapters
6
+ module DataMapper
7
+ describe Sorting do
8
+ def finder_class
9
+ Class.new do
10
+ include Trailblazer::Finder::Base
11
+ include Trailblazer::Finder::Features::Sorting
12
+ include Trailblazer::Finder::Adapters::DataMapper
13
+
14
+ entity_type { DProduct }
15
+
16
+ sortable_by :name, :price, :created_at
17
+
18
+ filter_by :name
19
+ filter_by :price
20
+
21
+ # # Need to find a fix for this, not sure how to handle joins with data mapper properly
22
+ # filter_by(:d_category) { |entity_type, _| entity_type }
23
+ end
24
+ end
25
+
26
+ def finder_with_sort(sort = nil, filters = {})
27
+ finder_class.new filter: { sort: sort }.merge(filters)
28
+ end
29
+
30
+ it 'can be inherited' do
31
+ child_class = Class.new(finder_class)
32
+ expect(child_class.new.sort_attribute).to eq 'name'
33
+ end
34
+
35
+ describe 'sorting' do
36
+ after do
37
+ DProduct.all.destroy
38
+ end
39
+
40
+ it 'sorts results based on the sort option desc' do
41
+ 5.times { |i| DProduct.create price: i }
42
+
43
+ finder = finder_with_sort 'price desc'
44
+ expect(finder.results.map(&:price)).to eq [4, 3, 2, 1, 0]
45
+ end
46
+
47
+ it 'sorts results based on the sort option asc' do
48
+ 5.times { |i| DProduct.create price: i }
49
+
50
+ finder = finder_with_sort 'price asc'
51
+ expect(finder.results.map(&:price)).to eq [0, 1, 2, 3, 4]
52
+ end
53
+
54
+ it 'defaults to first sort by option' do
55
+ 5.times { |i| DProduct.create name: "Name#{i}" }
56
+
57
+ finder = finder_with_sort
58
+ expect(finder.results.map(&:name)).to eq %w[Name4 Name3 Name2 Name1 Name0]
59
+ end
60
+
61
+ it 'ignores invalid sort values' do
62
+ finder = finder_with_sort 'invalid attribute'
63
+ expect { finder.results.to_a }.not_to raise_error
64
+ end
65
+
66
+ # TODO: Need to find a fix for this, not sure how to handle joins with data mapper properly
67
+ it 'can handle renames of sorting in joins' do
68
+ # older_category = DCategory.create title: 'older'
69
+ # newer_category = DCategory.create title: 'newer'
70
+ #
71
+ # product_of_newer_category = DProduct.create name: 'older product', d_category: newer_category
72
+ # product_of_older_category = DProduct.create name: 'newer product', d_category: older_category
73
+ #
74
+ # finder = finder_with_sort 'created_at desc', d_category: ''
75
+ #
76
+ # expect(finder.results.map(&:name)).to eq [product_of_older_category.name, product_of_newer_category.name]
77
+ end
78
+ end
79
+
80
+ it_behaves_like 'a sorting feature'
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper_active_record'
2
+
3
+ module Trailblazer
4
+ class Finder
5
+ module Adapters
6
+ describe FriendlyId do
7
+ after do
8
+ Product.delete_all
9
+ end
10
+
11
+ def finder_class
12
+ Class.new(Trailblazer::Finder) do
13
+ adapters ActiveRecord, FriendlyId
14
+
15
+ entity_type { Product }
16
+
17
+ filter_by :name
18
+ filter_by :price
19
+ end
20
+ end
21
+
22
+ def finder_with_slug(slug = nil, filters = {})
23
+ finder_class.new filter: { id: slug }.merge(filters)
24
+ end
25
+
26
+ it 'filters by slug' do
27
+ 2.times { |i| Product.create name: "Product #{i}", price: i, slug: "product_#{i}" }
28
+ finder = finder_with_slug 'product_1'
29
+ expect(finder.results.map(&:name)).to eq ['Product 1']
30
+ end
31
+
32
+ it 'filters by id' do
33
+ 2.times { |i| Product.create name: "Product #{i}", price: i, slug: "product_#{i}" }
34
+ finder = finder_with_slug Product.last.id
35
+ expect(finder.results.map(&:name)).to match_array([Product.last.name])
36
+ end
37
+
38
+ it 'returns no records when slug is not found' do
39
+ 2.times { |i| Product.create name: "Product #{i}", price: i, slug: "product_#{i}" }
40
+ finder = finder_with_slug 'unknown_1'
41
+ expect(finder.count).to eq 0
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper_active_record'
2
+ require 'kaminari'
3
+
4
+ module Trailblazer
5
+ class Finder
6
+ module Adapters
7
+ describe Kaminari do
8
+ it_behaves_like 'a paging feature'
9
+
10
+ after do
11
+ Product.delete_all
12
+ end
13
+
14
+ def define_finder_class(&block)
15
+ Class.new do
16
+ include Trailblazer::Finder::Base
17
+ include Trailblazer::Finder::Features::Paging
18
+ include Trailblazer::Finder::Adapters::ActiveRecord
19
+ include Trailblazer::Finder::Adapters::Kaminari
20
+
21
+ instance_eval(&block) if block_given?
22
+ end
23
+ end
24
+
25
+ def finder_class
26
+ define_finder_class do
27
+ entity_type { Product }
28
+
29
+ per_page 2
30
+
31
+ min_per_page 2
32
+ max_per_page 10
33
+ end
34
+ end
35
+
36
+ def finder_with_page(page = nil, per_page = nil)
37
+ finder_class.new page: page, per_page: per_page
38
+ end
39
+
40
+ it 'can be inherited' do
41
+ child_class = Class.new(finder_class)
42
+ expect(child_class.new.per_page).to eq 2
43
+ end
44
+
45
+ describe '#results' do
46
+ it 'paginates results' do
47
+ 6.times { |i| Product.create name: "product_#{i}" }
48
+ finder = finder_with_page 2, 2
49
+
50
+ expect(finder.results.map(&:name)).to eq %w[product_2 product_3]
51
+ end
52
+ end
53
+
54
+ describe '#count' do
55
+ it 'gives the real count' do
56
+ 10.times { |i| Product.create name: "product_#{i}" }
57
+ finder = finder_with_page 1
58
+ expect(finder.count).to eq 10
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end