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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +45 -0
- data/.rubocop_todo.yml +52 -0
- data/.travis.yml +15 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +23 -0
- data/README.md +494 -0
- data/Rakefile +29 -0
- data/lib/trailblazer/finder/adapters/active_record/paging.rb +20 -0
- data/lib/trailblazer/finder/adapters/active_record/sorting.rb +20 -0
- data/lib/trailblazer/finder/adapters/active_record.rb +30 -0
- data/lib/trailblazer/finder/adapters/data_mapper/paging.rb +20 -0
- data/lib/trailblazer/finder/adapters/data_mapper/sorting.rb +25 -0
- data/lib/trailblazer/finder/adapters/data_mapper.rb +30 -0
- data/lib/trailblazer/finder/adapters/friendly_id.rb +33 -0
- data/lib/trailblazer/finder/adapters/kaminari.rb +18 -0
- data/lib/trailblazer/finder/adapters/sequel/paging.rb +20 -0
- data/lib/trailblazer/finder/adapters/sequel/sorting.rb +25 -0
- data/lib/trailblazer/finder/adapters/sequel.rb +30 -0
- data/lib/trailblazer/finder/adapters/will_paginate.rb +18 -0
- data/lib/trailblazer/finder/adapters.rb +26 -0
- data/lib/trailblazer/finder/base.rb +98 -0
- data/lib/trailblazer/finder/errors/block_ignored.rb +11 -0
- data/lib/trailblazer/finder/errors/invalid_defined_by_value.rb +11 -0
- data/lib/trailblazer/finder/errors/invalid_number.rb +16 -0
- data/lib/trailblazer/finder/errors/missing_entity_type.rb +11 -0
- data/lib/trailblazer/finder/errors/with_ignored.rb +11 -0
- data/lib/trailblazer/finder/features/paging.rb +55 -0
- data/lib/trailblazer/finder/features/sorting.rb +66 -0
- data/lib/trailblazer/finder/features.rb +22 -0
- data/lib/trailblazer/finder/filter.rb +66 -0
- data/lib/trailblazer/finder/find.rb +29 -0
- data/lib/trailblazer/finder/utils/extra.rb +31 -0
- data/lib/trailblazer/finder/utils/params.rb +28 -0
- data/lib/trailblazer/finder/utils/parse.rb +25 -0
- data/lib/trailblazer/finder/utils/string.rb +35 -0
- data/lib/trailblazer/finder/version.rb +5 -0
- data/lib/trailblazer/finder.rb +29 -0
- data/lib/trailblazer/operation/finder.rb +61 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/spec_helper_active_record.rb +50 -0
- data/spec/spec_helper_data_mapper.rb +35 -0
- data/spec/spec_helper_sequel.rb +32 -0
- data/spec/support/paging_shared_example.rb +65 -0
- data/spec/support/sorting_shared_example.rb +95 -0
- data/spec/trailblazer/finder/adapters/active_record/base_spec.rb +112 -0
- data/spec/trailblazer/finder/adapters/active_record/paging_spec.rb +64 -0
- data/spec/trailblazer/finder/adapters/active_record/sorting_spec.rb +82 -0
- data/spec/trailblazer/finder/adapters/data_mapper/base_spec.rb +112 -0
- data/spec/trailblazer/finder/adapters/data_mapper/paging_spec.rb +64 -0
- data/spec/trailblazer/finder/adapters/data_mapper/sorting_spec.rb +85 -0
- data/spec/trailblazer/finder/adapters/friendly_id_spec.rb +46 -0
- data/spec/trailblazer/finder/adapters/kaminari_spec.rb +64 -0
- data/spec/trailblazer/finder/adapters/sequel/base_spec.rb +112 -0
- data/spec/trailblazer/finder/adapters/sequel/paging_spec.rb +64 -0
- data/spec/trailblazer/finder/adapters/sequel/sorting_spec.rb +82 -0
- data/spec/trailblazer/finder/adapters/will_paginate_spec.rb +71 -0
- data/spec/trailblazer/finder/adapters_spec.rb +110 -0
- data/spec/trailblazer/finder/base_spec.rb +329 -0
- data/spec/trailblazer/finder/features/paging_spec.rb +104 -0
- data/spec/trailblazer/finder/features/sorting_spec.rb +100 -0
- data/spec/trailblazer/finder/features_spec.rb +55 -0
- data/spec/trailblazer/finder/filter_spec.rb +133 -0
- data/spec/trailblazer/finder/find_spec.rb +72 -0
- data/spec/trailblazer/finder/utils/extra_spec.rb +41 -0
- data/spec/trailblazer/finder/utils/params_spec.rb +39 -0
- data/spec/trailblazer/finder/utils/parse_spec.rb +33 -0
- data/spec/trailblazer/finder/utils/string_spec.rb +25 -0
- data/spec/trailblazer/operation/finder_spec.rb +103 -0
- data/spec/trailblazer/operation/paging_spec.rb +68 -0
- data/spec/trailblazer/operation/sorting_spec.rb +80 -0
- data/trailblazer-finder.gemspec +41 -0
- 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
|