trailblazer-finder 0.1.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml +101 -0
- data/.rubocop.yml +3 -43
- data/.rubocop_todo.yml +42 -196
- data/.travis.yml +5 -8
- data/Gemfile +2 -2
- data/LICENSE.txt +7 -21
- data/README.md +177 -292
- data/Rakefile +12 -12
- data/lib/trailblazer/finder.rb +48 -23
- data/lib/trailblazer/finder/activity/find.rb +57 -0
- data/lib/trailblazer/finder/activity/prepare.rb +29 -0
- data/lib/trailblazer/finder/activity/prepare/adapters.rb +66 -0
- data/lib/trailblazer/finder/activity/prepare/entity.rb +32 -0
- data/lib/trailblazer/finder/activity/prepare/filters.rb +36 -0
- data/lib/trailblazer/finder/activity/prepare/paging.rb +49 -0
- data/lib/trailblazer/finder/activity/prepare/params.rb +33 -0
- data/lib/trailblazer/finder/activity/prepare/properties.rb +47 -0
- data/lib/trailblazer/finder/activity/prepare/sorting.rb +57 -0
- data/lib/trailblazer/finder/activity/process.rb +18 -0
- data/lib/trailblazer/finder/activity/process/adapters.rb +48 -0
- data/lib/trailblazer/finder/activity/process/filters.rb +28 -0
- data/lib/trailblazer/finder/activity/process/paging.rb +26 -0
- data/lib/trailblazer/finder/activity/process/predicates.rb +30 -0
- data/lib/trailblazer/finder/activity/process/sorting.rb +26 -0
- data/lib/trailblazer/finder/adapters/active_record/paging.rb +9 -8
- data/lib/trailblazer/finder/adapters/active_record/predicates.rb +78 -17
- data/lib/trailblazer/finder/adapters/active_record/sorting.rb +14 -12
- data/lib/trailblazer/finder/adapters/basic/paging.rb +21 -0
- data/lib/trailblazer/finder/adapters/basic/predicates.rb +115 -0
- data/lib/trailblazer/finder/adapters/basic/sorting.rb +40 -0
- data/lib/trailblazer/finder/adapters/kaminari/paging.rb +21 -0
- data/lib/trailblazer/finder/adapters/sequel/paging.rb +9 -8
- data/lib/trailblazer/finder/adapters/sequel/predicates.rb +78 -17
- data/lib/trailblazer/finder/adapters/sequel/sorting.rb +17 -15
- data/lib/trailblazer/finder/adapters/will_paginate/paging.rb +21 -0
- data/lib/trailblazer/finder/base.rb +20 -83
- data/lib/trailblazer/finder/dsl.rb +56 -0
- data/lib/trailblazer/finder/find.rb +28 -15
- data/lib/trailblazer/finder/helpers/basic.rb +44 -0
- data/lib/trailblazer/finder/helpers/sorting.rb +54 -0
- data/lib/trailblazer/finder/utils/array.rb +20 -0
- data/lib/trailblazer/finder/utils/extra.rb +10 -20
- data/lib/trailblazer/finder/utils/hash.rb +36 -0
- data/lib/trailblazer/finder/utils/splitter.rb +16 -17
- data/lib/trailblazer/finder/utils/string.rb +20 -10
- data/lib/trailblazer/finder/version.rb +3 -1
- data/lib/trailblazer/operation/finder.rb +20 -19
- data/spec/spec_helper.rb +5 -11
- data/spec/spec_helper_active_record.rb +11 -12
- data/spec/spec_helper_sequel.rb +4 -4
- data/spec/spec_helper_will_paginate.rb +13 -0
- data/spec/trailblazer/finder/adapters/active_record_spec.rb +267 -0
- data/spec/trailblazer/finder/adapters/basic_spec.rb +251 -0
- data/spec/trailblazer/finder/adapters/kaminari_spec.rb +78 -32
- data/spec/trailblazer/finder/adapters/sequel_spec.rb +267 -0
- data/spec/trailblazer/finder/adapters/will_paginate_spec.rb +81 -40
- data/spec/trailblazer/finder/base_spec.rb +292 -204
- data/spec/trailblazer/finder/dsl_spec.rb +213 -0
- data/spec/trailblazer/finder/utils/hash_spec.rb +26 -0
- data/spec/trailblazer/finder/utils/splitter_spec.rb +39 -0
- data/spec/trailblazer/finder/utils/string_spec.rb +52 -9
- data/spec/trailblazer/operation/finder_spec.rb +35 -32
- data/trailblazer-finder.gemspec +31 -30
- metadata +119 -137
- data/lib/trailblazer/finder/adapters.rb +0 -26
- data/lib/trailblazer/finder/adapters/active_record.rb +0 -32
- data/lib/trailblazer/finder/adapters/data_mapper.rb +0 -32
- data/lib/trailblazer/finder/adapters/data_mapper/paging.rb +0 -20
- data/lib/trailblazer/finder/adapters/data_mapper/predicates.rb +0 -42
- data/lib/trailblazer/finder/adapters/data_mapper/sorting.rb +0 -38
- data/lib/trailblazer/finder/adapters/friendly_id.rb +0 -31
- data/lib/trailblazer/finder/adapters/kaminari.rb +0 -18
- data/lib/trailblazer/finder/adapters/sequel.rb +0 -32
- data/lib/trailblazer/finder/adapters/will_paginate.rb +0 -18
- data/lib/trailblazer/finder/errors/block_ignored.rb +0 -11
- data/lib/trailblazer/finder/errors/invalid_defined_by_value.rb +0 -11
- data/lib/trailblazer/finder/errors/invalid_number.rb +0 -16
- data/lib/trailblazer/finder/errors/missing_entity_type.rb +0 -11
- data/lib/trailblazer/finder/errors/with_ignored.rb +0 -11
- data/lib/trailblazer/finder/features.rb +0 -23
- data/lib/trailblazer/finder/features/paging.rb +0 -55
- data/lib/trailblazer/finder/features/predicate.rb +0 -32
- data/lib/trailblazer/finder/features/sorting.rb +0 -108
- data/lib/trailblazer/finder/filter.rb +0 -66
- data/lib/trailblazer/finder/predicates.rb +0 -39
- data/lib/trailblazer/finder/utils/deep_locate.rb +0 -30
- data/lib/trailblazer/finder/utils/params.rb +0 -28
- data/lib/trailblazer/finder/utils/parse.rb +0 -25
- data/spec/spec_helper_data_mapper.rb +0 -35
- data/spec/support/paging_shared_example.rb +0 -65
- data/spec/support/sorting_shared_example.rb +0 -125
- data/spec/trailblazer/finder/adapters/active_record/base_spec.rb +0 -112
- data/spec/trailblazer/finder/adapters/active_record/paging_spec.rb +0 -64
- data/spec/trailblazer/finder/adapters/active_record/predicates_spec.rb +0 -101
- data/spec/trailblazer/finder/adapters/active_record/sorting_spec.rb +0 -99
- data/spec/trailblazer/finder/adapters/data_mapper/base_spec.rb +0 -112
- data/spec/trailblazer/finder/adapters/data_mapper/paging_spec.rb +0 -64
- data/spec/trailblazer/finder/adapters/data_mapper/predicates_spec.rb +0 -100
- data/spec/trailblazer/finder/adapters/data_mapper/sorting_spec.rb +0 -97
- data/spec/trailblazer/finder/adapters/friendly_id_spec.rb +0 -46
- data/spec/trailblazer/finder/adapters/sequel/base_spec.rb +0 -125
- data/spec/trailblazer/finder/adapters/sequel/paging_spec.rb +0 -64
- data/spec/trailblazer/finder/adapters/sequel/predicates_spec.rb +0 -89
- data/spec/trailblazer/finder/adapters/sequel/sorting_spec.rb +0 -110
- data/spec/trailblazer/finder/adapters_spec.rb +0 -110
- data/spec/trailblazer/finder/features/paging_spec.rb +0 -104
- data/spec/trailblazer/finder/features/predicates_spec.rb +0 -99
- data/spec/trailblazer/finder/features/sorting_spec.rb +0 -96
- data/spec/trailblazer/finder/features_spec.rb +0 -55
- data/spec/trailblazer/finder/filter_spec.rb +0 -133
- data/spec/trailblazer/finder/find_spec.rb +0 -72
- data/spec/trailblazer/finder/utils/extra_spec.rb +0 -41
- data/spec/trailblazer/finder/utils/params_spec.rb +0 -39
- data/spec/trailblazer/finder/utils/parse_spec.rb +0 -33
- data/spec/trailblazer/operation/paging_spec.rb +0 -68
- data/spec/trailblazer/operation/predicates_spec.rb +0 -127
- data/spec/trailblazer/operation/sorting_spec.rb +0 -80
- data/spec/trailblazer/test_spec.rb +0 -41
data/Gemfile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
gem
|
5
|
+
gem "pry-byebug"
|
6
6
|
|
7
7
|
# Had to add this for a bit, since none of the latest changes have been pushed to gems yet
|
8
8
|
# gem "trailblazer", github: "trailblazer/trailblazer"
|
data/LICENSE.txt
CHANGED
@@ -1,23 +1,9 @@
|
|
1
|
-
Copyright (c) 2018 Trailblazer GmbH
|
2
|
-
license.
|
1
|
+
Copyright (c) 2018 Trailblazer GmbH
|
3
2
|
|
4
|
-
|
3
|
+
Trailblazer is an Open Source project licensed under the terms of
|
4
|
+
the LGPLv3 license. Please see <http://www.gnu.org/licenses/lgpl-3.0.html>
|
5
|
+
for license text.
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
-
permit persons to whom the Software is furnished to do so, subject to
|
12
|
-
the following conditions:
|
13
|
-
|
14
|
-
The above copyright notice and this permission notice shall be
|
15
|
-
included in all copies or substantial portions of the Software.
|
16
|
-
|
17
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
7
|
+
Trailblazer Enterprise has a commercial-friendly license allowing private forks
|
8
|
+
and modifications of Trailblazer. Please see http://trailblazer.to/enterprise/ for
|
9
|
+
more detail. You can find the commercial license terms in COMM-LICENSE.
|
data/README.md
CHANGED
@@ -1,48 +1,44 @@
|
|
1
|
+
# THIS IS MOSTLY OUT OF DATE
|
2
|
+
|
3
|
+
# NEW README AND RELEASE COMING NEXT WEEK
|
1
4
|
|
2
5
|
# Trailblazer Finder
|
3
6
|
|
4
|
-
|
7
|
+
Provides DSL for creating [Trailblazer](https://github.com/trailblazer/trailblazer) based Finder Objects. But it is designed to be used on its own as a separate gem. It was influenced by popular [Ransack](https://github.com/activerecord-hackery/ransack) gem, but in addition to [ActiveRecord](https://github.com/rails/rails/tree/master/activerecord), it can be used with [DataMapper](https://github.com/datamapper) or [Sequel](https://github.com/jeremyevans/sequel). It also integrates with [Kaminari](https://github.com/kaminari/kaminari) or [Will Paginate](https://github.com/mislav/will_paginate), as well as [FriendlyId](https://github.com/norman/friendly_id)
|
5
8
|
|
6
|
-
[![Gitter Chat](https://badges.gitter.im/trailblazer/chat.svg)](https://gitter.im/trailblazer/chat)
|
9
|
+
[![Gitter Chat](https://badges.gitter.im/trailblazer/chat.svg)](https://gitter.im/trailblazer/chat)
|
10
|
+
[![Build Status](https://secure.travis-ci.org/trailblazer/trailblazer-finder.svg)](https://travis-ci.org/trailblazer/trailblazer-finder)
|
7
11
|
|
8
12
|
## Table of Contents
|
9
13
|
|
10
14
|
* [Installation](#installation)
|
11
|
-
|
15
|
+
* [Dependencies](#dependencies)
|
12
16
|
* [Usage](#usage)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
* [Kaminari Example](#kaminari-example)
|
37
|
-
* [WillPaginate](#will_paginate)
|
38
|
-
* [Will Paginate Example](#will-paginate-example)
|
39
|
-
* [FriendlyId](#friendly_id)
|
40
|
-
* [Friendly Id Example](#friendly-id-example)
|
41
|
-
* [Tips & Tricks](#tips--tricks)
|
42
|
-
* [ORM's are not required](#results-shortcut)
|
43
|
-
* [Passing Entity Type as Argument](#passing-entity_type-as-argument)
|
17
|
+
* [Finder](#finder)
|
18
|
+
* [Finder Example](#finder-example)
|
19
|
+
* [Operation](#operation)
|
20
|
+
* [Operation Example](#operation-example)
|
21
|
+
* [Usable without Trailblazer](#usable-without-trailblazer)
|
22
|
+
* [Example without Trailblazer](#example-without-trailblazer)
|
23
|
+
* [Example Project](#example-project)
|
24
|
+
* [Features](#features)
|
25
|
+
* [Predicates](#predicate)
|
26
|
+
* [Predicates Example](#predicates-example)
|
27
|
+
* [Paging](#paging)
|
28
|
+
* [Paging Example](#paging-example)
|
29
|
+
* [Sorting](#sorting)
|
30
|
+
* [Sorting Example](#sorting-example)
|
31
|
+
* [Adapters](#adapters)
|
32
|
+
* [Adapters Example](#adapters-example)
|
33
|
+
* [ActiveRecord](#active_record)
|
34
|
+
* [Active Record Example](#active-record-example)
|
35
|
+
* [Sequel](#sequel)
|
36
|
+
* [Sequel Example](#sequel-example)
|
37
|
+
* [Tips & Tricks](#tips--tricks)
|
38
|
+
* [ORM's are not required](#results-shortcut)
|
39
|
+
* [Passing Entity as Argument](#passing-entity-as-argument)
|
44
40
|
* [Contributing](#contributing)
|
45
|
-
* [License](
|
41
|
+
* [License](LICENSE.txt)
|
46
42
|
|
47
43
|
## Installation
|
48
44
|
|
@@ -61,6 +57,7 @@ Or install it yourself as:
|
|
61
57
|
$ gem install trailblazer-finder
|
62
58
|
|
63
59
|
### Dependencies
|
60
|
+
* [Trailblazer-Activity](https://github.com/trailblazer/trailblazer-activity) - required
|
64
61
|
* [Trailblazer](https://github.com/trailblazer/trailblazer) - [actually optional, but requires 2.1+](https://github.com/trailblazer/trailblazer-finder#usable-without-trailblazer)
|
65
62
|
|
66
63
|
## Usage
|
@@ -70,77 +67,60 @@ Just inherit from the ```Trailblazer::Finder``` class.
|
|
70
67
|
|
71
68
|
Features and adapters are optional. However.
|
72
69
|
|
73
|
-
NOTE: features only
|
70
|
+
NOTE: features are only applied if their options are specified in your finder
|
74
71
|
|
75
|
-
An Entity
|
72
|
+
An Entity (model) is required, but can:
|
76
73
|
* be defined in the inherited Finder class
|
77
74
|
* be given as an option in the call
|
78
75
|
|
79
|
-
|
76
|
+
Be sure to specify features you wish to use in your finder, before specifying adapters.
|
77
|
+
|
78
|
+
Basically for most use cases, Entity is the entity/model/array of hashes you wish to use finder on
|
80
79
|
|
81
80
|
#### Finder Example
|
82
81
|
|
83
82
|
```ruby
|
84
83
|
class Post::Finder < Trailblazer::Finder
|
85
|
-
|
86
|
-
|
84
|
+
# Without defining an ORM everything defaults to dealing with hash objects
|
85
|
+
adapters :ActiveRecord
|
87
86
|
|
88
87
|
# Optional if you use it as option in the caller, Model/Entity or Array with Hashes
|
89
|
-
|
90
|
-
|
91
|
-
# Without defining an ORM everything defaults to dealing with an
|
92
|
-
# array with Hashes
|
93
|
-
adapters ActiveRecord, Kaminari
|
88
|
+
entity { Post }
|
94
89
|
|
95
|
-
# Pagination settings (
|
96
|
-
per_page
|
97
|
-
min_per_page 10
|
98
|
-
max_per_page 100
|
90
|
+
# Pagination settings (don't use it if you don't wish to use paging)
|
91
|
+
paging per_page: 5, min_per_page: 1, max_per_page: 100
|
99
92
|
|
100
|
-
#
|
101
|
-
|
102
|
-
|
103
|
-
#
|
93
|
+
# Property
|
94
|
+
# Set the properties with their respective options
|
95
|
+
#
|
96
|
+
# Params:
|
97
|
+
# * +name+:: The property name (attribute /column / field - name) (required)
|
98
|
+
# * +type:+:: Dry Types type, for future validations (required)
|
99
|
+
#
|
100
|
+
# * Following is optional (don't use it if you do not wish to use sorting)
|
101
|
+
# * +sortable:+:: Can this property be sorted on? (default: false)
|
102
|
+
# * +sort_direction:+:: Specify default sort direction (only usable if sortable is true)
|
103
|
+
# (default: :desc)
|
104
|
+
property :id, type: Types::Integer
|
105
|
+
property :body, type: Types::String, sortable: true
|
106
|
+
property :title, type: Types::String, sortable: true, sort_direction: :asc
|
107
|
+
|
108
|
+
# Filter By
|
109
|
+
# A simple way to make custom filter methods
|
104
110
|
#
|
105
111
|
# Params:
|
106
|
-
# * +
|
112
|
+
# * +parameter+:: The parameter to use to call this filter (required)
|
107
113
|
#
|
108
114
|
# * Following is optional, matches exact value if not specified
|
109
115
|
# * +with:+:: Filter method defined in Finder class
|
110
|
-
# * +defined_by:+:: Array of filter Methods defined in Finder class
|
111
|
-
# method name: apply_filter_name_with_array_value
|
112
116
|
# * block:: A block can be given with the code to filter with
|
113
|
-
filter_by :id
|
114
|
-
filter_by :body, with: :apply_body_filter
|
115
117
|
filter_by :created_after, with: :apply_created_after
|
116
|
-
filter_by
|
117
|
-
filter_by :is_hot, defined_by: %i[true false]
|
118
|
-
filter_by(:title) { |entity_type, value| entity_type.where title: value }
|
119
|
-
filter_by(:published, false) do |entity_type, value|
|
120
|
-
value ? entity_type.where('published = false') : entity_type.where('published = true')
|
121
|
-
end
|
118
|
+
filter_by(:created_before) { |entity, _attribute, value| entity.where('DATE(created_at) <= ?', value) if value.present? }
|
122
119
|
|
123
120
|
private
|
124
121
|
|
125
|
-
def
|
126
|
-
|
127
|
-
entity_type.where 'lower(body) LIKE ?', Utils::Parse.term(value.downcase)
|
128
|
-
end
|
129
|
-
|
130
|
-
def apply_created_after(entity_type, value)
|
131
|
-
entity_type.where('DATE(created_at) >= ?', value) if value.present?
|
132
|
-
end
|
133
|
-
|
134
|
-
def apply_created_before(entity_type, value)
|
135
|
-
entity_type.where('DATE(created_at) <= ?', value) if value.present?
|
136
|
-
end
|
137
|
-
|
138
|
-
def apply_is_hot_with_true(entity_type)
|
139
|
-
entity_type.where 'views > 100'
|
140
|
-
end
|
141
|
-
|
142
|
-
def apply_is_hot_with_false(entity_type)
|
143
|
-
entity_type.where 'views < 100'
|
122
|
+
def apply_created_after(entity, _attribute, value)
|
123
|
+
entity.where('DATE(created_at) >= ?', value) if value.present?
|
144
124
|
end
|
145
125
|
end
|
146
126
|
```
|
@@ -155,7 +135,7 @@ class Post::Index < Trailblazer::Operation
|
|
155
135
|
# Params:
|
156
136
|
# +finder_class+:: Finder class to be used
|
157
137
|
# +action+:: :all, :single (optional, defaults to :all)
|
158
|
-
# +
|
138
|
+
# +entity+:: Entity/Model or array (optional if specified in Finder Class, overwrites Finder class entity)
|
159
139
|
step Finder(Post::Finder, :all, Post)
|
160
140
|
end
|
161
141
|
```
|
@@ -167,7 +147,7 @@ class Post::Index < Trailblazer::Operation
|
|
167
147
|
|
168
148
|
# Find all matching results and extend model object with required methods
|
169
149
|
def finder!(options, params:, **)
|
170
|
-
options[:finder] = Post::Finder.new(
|
150
|
+
options[:finder] = Post::Finder.new(params: params)
|
171
151
|
end
|
172
152
|
|
173
153
|
# Find first matching row, no method extension on model object
|
@@ -177,32 +157,26 @@ class Post::Index < Trailblazer::Operation
|
|
177
157
|
apply_id(params)
|
178
158
|
|
179
159
|
# No paging, sorting, no methods and only returns the first matched result
|
180
|
-
options[:finder] = Post::Finder.new(
|
160
|
+
options[:finder] = Post::Finder.new(params: params).result.first
|
181
161
|
end
|
182
162
|
|
183
163
|
# Since ID's are usually given directly, patch it into filter
|
184
164
|
def apply_id(params)
|
185
165
|
return if params[:id].nil?
|
186
|
-
params[:
|
187
|
-
params[:f][:id] = params[:id] unless params[:f].key?('id')
|
166
|
+
params[:id_eq] = params[:id] unless params.key?("id")
|
188
167
|
end
|
189
168
|
end
|
190
169
|
```
|
191
170
|
|
192
171
|
When using this, result[:finder] will be extended with (not available for :single row)
|
193
172
|
```ruby
|
194
|
-
# accessing filters
|
195
|
-
.name # => name filter
|
196
|
-
.created_at # => created at filter
|
197
|
-
|
198
173
|
# accessing results
|
199
174
|
.count # => number of found results
|
200
|
-
.
|
201
|
-
.
|
175
|
+
.result? # => are there any results found
|
176
|
+
.result # => fetched results
|
202
177
|
|
203
178
|
# params for url generations
|
204
179
|
.params # => filter values
|
205
|
-
.params published: false # => overwrites the 'published' filter
|
206
180
|
```
|
207
181
|
|
208
182
|
|
@@ -212,23 +186,22 @@ If Trailblazer isn't loaded, the ties to [Trailblazer](https://github.com/trailb
|
|
212
186
|
|
213
187
|
#### Example without Trailblazer
|
214
188
|
```ruby
|
215
|
-
|
189
|
+
# If entity is specified in your finder
|
190
|
+
result = Post::Finder.new(params: params)
|
191
|
+
|
192
|
+
# If entity ism't specified in your finder
|
193
|
+
result = Post::Finder.new(entity: Post, params: params)
|
216
194
|
```
|
217
195
|
|
218
196
|
When using this, result will be extended with (not available for :single row)
|
219
197
|
```ruby
|
220
|
-
# accessing filters
|
221
|
-
.name # => name filter
|
222
|
-
.created_at # => created at filter
|
223
|
-
|
224
198
|
# accessing results
|
225
199
|
.count # => number of found results
|
226
|
-
.
|
227
|
-
.
|
200
|
+
.result? # => are there any results found
|
201
|
+
.result # => fetched results
|
228
202
|
|
229
203
|
# params for url generations
|
230
204
|
.params # => filter values
|
231
|
-
.params published: false # => overwrites the 'published' filter
|
232
205
|
```
|
233
206
|
|
234
207
|
### Example Project
|
@@ -237,14 +210,9 @@ Coming soon!
|
|
237
210
|
## Features
|
238
211
|
Aside of the default filtering behavior, it offers the following optional features as well.
|
239
212
|
|
240
|
-
Just for the record, you can comma seperate features and load multiple by doing
|
241
|
-
```ruby
|
242
|
-
features Sorting, Paging, Predicate
|
243
|
-
```
|
244
|
-
|
245
213
|
NOTE: FEATURES NEED TO BE SPECIFIED ON TOP OF YOUR CLASS
|
246
214
|
|
247
|
-
###
|
215
|
+
### Predicates
|
248
216
|
Simple predicate feature, that enables you to have default predicate filters available for the specified fields.
|
249
217
|
|
250
218
|
At the moment we support:
|
@@ -256,63 +224,71 @@ At the moment we support:
|
|
256
224
|
- lte: less than or equal to (value converts to float)
|
257
225
|
- gt: greater than (value converts to float)
|
258
226
|
- gte: greater than or equal to (value converts to float)
|
259
|
-
|
260
|
-
|
227
|
+
- cont: contains specified value
|
228
|
+
- not_cont: does not contain specified value
|
229
|
+
- sw: starts with specified value
|
230
|
+
- not_sw: does not start with specified value
|
231
|
+
- ew: end with specified value
|
232
|
+
- not_ew: does not end with specified value
|
233
|
+
|
234
|
+
#### Predicates Example
|
261
235
|
```ruby
|
262
236
|
class Post::Finder < Trailblazer::Finder
|
263
|
-
|
264
|
-
|
265
|
-
# Specify the fields you want predicates enabled for, mind you these fields need to exist on your entity_type
|
266
|
-
predicates_for :name, :category_name
|
267
|
-
|
268
|
-
filter_by :name
|
269
|
-
filter_by :published
|
270
|
-
filter_by :category_name
|
237
|
+
entity { Post }
|
271
238
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
# Minimum items per page (not required)
|
276
|
-
min_per_page 5
|
277
|
-
|
278
|
-
# Maximum items per page (not required)
|
279
|
-
max_per_page 100
|
239
|
+
property :id, type: Types::Integer
|
240
|
+
property :body, type: Types::String
|
241
|
+
property :title, type: Types::String
|
280
242
|
end
|
281
243
|
```
|
282
244
|
|
283
245
|
This feature extends the result[:finder] object with the following methods
|
284
246
|
```ruby
|
285
|
-
#
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
#
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
#
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
#
|
314
|
-
|
315
|
-
|
247
|
+
# Available Predicate filters with the above example
|
248
|
+
id_eq # => id equals value
|
249
|
+
id_not_eq # => id not equals value
|
250
|
+
id_blank # => id blank value
|
251
|
+
id_not_blank # => id not blank value
|
252
|
+
id_lt # => id less than value (converts value to float)
|
253
|
+
id_lte # => id less than or equal to value (converts value to float)
|
254
|
+
id_gt # => id greater than value (converts value to float)
|
255
|
+
id_gte # => id greater than or equal to value (converts value to float)
|
256
|
+
id_cont # => id contains value
|
257
|
+
id_not_cont # => id does not contain value
|
258
|
+
id_sw # => id starts with
|
259
|
+
id_not_sw # => id does not start with
|
260
|
+
id_ew # => id ends with
|
261
|
+
id_not_ew # => id does not end with
|
262
|
+
|
263
|
+
body_eq # => body equals value
|
264
|
+
body_not_eq # => body not equals value
|
265
|
+
body_blank # => body blank value
|
266
|
+
body_not_blank # => body not blank value
|
267
|
+
body_lt # => body less than value (converts value to float)
|
268
|
+
body_lte # => body less than or equal to value (converts value to float)
|
269
|
+
body_gt # => body greater than value (converts value to float)
|
270
|
+
body_gte # => body greater than or equal to value (converts value to float)
|
271
|
+
body_cont # => body contains value
|
272
|
+
body_not_cont # => body does not contain value
|
273
|
+
body_sw # => body starts with
|
274
|
+
body_not_sw # => body does not start with
|
275
|
+
body_ew # => body ends with
|
276
|
+
body_not_ew # => body does not end with
|
277
|
+
|
278
|
+
title_eq # => title equals value
|
279
|
+
title_not_eq # => title not equals value
|
280
|
+
title_blank # => title blank value
|
281
|
+
title_not_blank # => title not blank value
|
282
|
+
title_lt # => title less than value (converts value to float)
|
283
|
+
title_lte # => title less than or equal to value (converts value to float)
|
284
|
+
title_gt # => title greater than value (converts value to float)
|
285
|
+
title_gte # => title greater than or equal to value (converts value to float)
|
286
|
+
title_cont # => title contains value
|
287
|
+
title_not_cont # => title does not contain value
|
288
|
+
title_sw # => title starts with
|
289
|
+
title_not_sw # => title does not start with
|
290
|
+
title_ew # => title ends with
|
291
|
+
title_not_ew # => title does not end with
|
316
292
|
```
|
317
293
|
|
318
294
|
### Paging
|
@@ -321,44 +297,40 @@ Really simple pagination feature, which uses the plain ```.limit``` and ```.offs
|
|
321
297
|
#### Paging Example
|
322
298
|
```ruby
|
323
299
|
class Post::Finder < Trailblazer::Finder
|
324
|
-
|
325
|
-
|
326
|
-
filter_by :name
|
327
|
-
filter_by :category_name
|
328
|
-
|
329
|
-
# per page defaults to 25 (so not required)
|
330
|
-
per_page 10
|
300
|
+
entity { Post }
|
331
301
|
|
332
|
-
|
333
|
-
min_per_page 5
|
334
|
-
|
335
|
-
# Maximum items per page (not required)
|
336
|
-
max_per_page 100
|
302
|
+
paging per_page: 5, min_per_page: 1, max_per_page: 100
|
337
303
|
end
|
338
304
|
```
|
339
305
|
|
340
|
-
This feature extends the result[:finder] object with the following methods
|
341
|
-
```ruby
|
342
|
-
.page # => page number
|
343
|
-
.per_page # => per page (10)
|
344
|
-
.results # => paginated page results
|
345
|
-
```
|
346
|
-
|
347
306
|
### Sorting
|
348
307
|
Really simple sorting feature, fixing the pain of dealing with sorting attributes and directions. Can sort by multiple columns/directions.
|
349
308
|
|
350
309
|
#### Sorting Example
|
351
310
|
```ruby
|
352
311
|
class Post::Finder < Trailblazer::Finder
|
353
|
-
|
312
|
+
entity { Post }
|
354
313
|
|
355
|
-
|
314
|
+
# Property
|
315
|
+
# Set the properties with their respective options
|
316
|
+
#
|
317
|
+
# Params:
|
318
|
+
# * +name+:: The property name (attribute /column / field - name) (required)
|
319
|
+
# * +type:+:: Dry Types type, for future validations (required)
|
320
|
+
#
|
321
|
+
# * Following is optional (don't use it if you do not wish to use sorting)
|
322
|
+
# * +sortable:+:: Can this property be sorted on? (default: false)
|
323
|
+
# * +sort_direction:+:: Specify default sort direction (only usable if sortable is true)
|
324
|
+
# (default: :desc)
|
325
|
+
property :id, type: Types::Integer
|
326
|
+
property :body, type: Types::String, sortable: true
|
327
|
+
property :title, type: Types::String, sortable: true, sort_direction: :asc
|
356
328
|
end
|
357
329
|
```
|
358
330
|
|
359
331
|
This feature extends the result[:finder] object with the following methods
|
360
332
|
```ruby
|
361
|
-
.
|
333
|
+
.result # => Posts sorted by title DESC
|
362
334
|
|
363
335
|
# Smart sort checking
|
364
336
|
.sort?('title') # => true
|
@@ -374,19 +346,21 @@ This feature extends the result[:finder] object with the following methods
|
|
374
346
|
# Params for sorting links (new if none exists, existing params if exists)
|
375
347
|
.sort_params_for('title')
|
376
348
|
|
377
|
-
# Add Params for sorting links (add to existing / replace with different direction)
|
349
|
+
# Add Params for sorting links (add to existing / replace with different direction if exists)
|
378
350
|
.add_sort_params_for('title')
|
379
351
|
|
352
|
+
# Remove Params for sorting links (remove from existing)
|
353
|
+
.remove_sort_params_for('title')
|
354
|
+
|
380
355
|
# New Params for sorting links (reset)
|
381
356
|
.new_sort_params_for('title')
|
382
357
|
```
|
383
358
|
|
384
359
|
## Adapters
|
385
|
-
By default, everything works with an array of hashes. You can change the default behaviour by using adapters.
|
360
|
+
By default, everything works with an array of hashes. You can change the default behaviour by using adapters.
|
386
361
|
|
387
362
|
Currently supported ORM's:
|
388
363
|
* [ActiveRecord](https://github.com/rails/rails/tree/master/activerecord)
|
389
|
-
* [DataMapper](https://github.com/datamapper)
|
390
364
|
* [Sequel](https://github.com/jeremyevans/sequel)
|
391
365
|
|
392
366
|
You can specify the adapters you wish to use inside your enherited Finder class.
|
@@ -394,8 +368,7 @@ You can specify the adapters you wish to use inside your enherited Finder class.
|
|
394
368
|
### Adapters Example
|
395
369
|
```ruby
|
396
370
|
class Post::Finder < Trailblazer::Finder
|
397
|
-
|
398
|
-
adapters ActiveRecord, Kaminari, FriendlyId
|
371
|
+
adapters :ActiveRecord
|
399
372
|
end
|
400
373
|
```
|
401
374
|
|
@@ -405,19 +378,7 @@ The only thing the [ActiveRecord](https://github.com/rails/rails/tree/master/act
|
|
405
378
|
#### Active Record Example
|
406
379
|
```ruby
|
407
380
|
class Post::Finder < Trailblazer::Finder
|
408
|
-
|
409
|
-
adapters ActiveRecord
|
410
|
-
end
|
411
|
-
```
|
412
|
-
|
413
|
-
### DataMapper
|
414
|
-
The only thing the [DataMapper](https://github.com/datamapper) adapter does, is overwrite one specific method for Paging (limit/offset) and Sorting (order) each, as well as change the default filter behaviour (from select to where). These are overwritten by the adapter to match the specific use case of [DataMapper](https://github.com/datamapper).
|
415
|
-
|
416
|
-
#### Data Mapper Example
|
417
|
-
```ruby
|
418
|
-
class Post::Finder < Trailblazer::Finder
|
419
|
-
# Features, in case you use any, need to be specified before adapters
|
420
|
-
adapters DataMapper
|
381
|
+
adapters :ActiveRecord
|
421
382
|
end
|
422
383
|
```
|
423
384
|
|
@@ -427,96 +388,45 @@ The only thing the [Sequel](https://github.com/jeremyevans/sequel) adapter does,
|
|
427
388
|
#### Sequel Example
|
428
389
|
```ruby
|
429
390
|
class Post::Finder < Trailblazer::Finder
|
430
|
-
|
431
|
-
adapters Sequel
|
432
|
-
end
|
433
|
-
```
|
434
|
-
|
435
|
-
### Kaminari
|
436
|
-
The only thing the [Kaminari](https://github.com/kaminari/kaminari) adapter does, is overwrite one specific method for Paging (limit/offset). These are overwritten by the adapter to match the specific use case of [Kaminari](https://github.com/kaminari/kaminari).
|
437
|
-
|
438
|
-
**Note**
|
439
|
-
Not usable without the Paging feature enabled, and requires an ORM that's supported by [Kaminari](https://github.com/kaminari/kaminari), directly or by using additional gems.
|
440
|
-
|
441
|
-
#### Kaminari Example
|
442
|
-
```ruby
|
443
|
-
class Post::Finder < Trailblazer::Finder
|
444
|
-
features Paging
|
445
|
-
adapters ActiveRecord, Kaminari
|
391
|
+
adapters :Sequel
|
446
392
|
end
|
447
393
|
```
|
448
|
-
**Note**
|
449
|
-
To use [Kaminari](https://github.com/kaminari/kaminari) in combination with [Cells](https://github.com/trailblazer/cells), you'll currently have to use [kaminari-cells](https://github.com/apotonick/kaminari-cells) and monkey-patch Kaminari by using in an initiliazer:
|
450
|
-
```ruby
|
451
|
-
Kaminari::Helpers::Paginator.class_eval do
|
452
|
-
def render(&block)
|
453
|
-
instance_eval(&block) if @options[:total_pages] > 1
|
454
|
-
end
|
455
|
-
end
|
456
|
-
```
|
457
|
-
|
458
|
-
### WillPaginate
|
459
|
-
The only thing the [WillPaginate](https://github.com/mislav/will_paginate/) adapter does, is overwrite one specific method for Paging (limit/offset). These are overwritten by the adapter to match the specific use case of [WillPaginate](https://github.com/mislav/will_paginate/).
|
460
394
|
|
461
|
-
|
462
|
-
|
395
|
+
## Tips & Tricks
|
396
|
+
### ORM's are not required
|
397
|
+
Not even for the Paging, Predicates and Sorting features.
|
463
398
|
|
464
|
-
#### Will Paginate Example
|
465
399
|
```ruby
|
466
400
|
class Post::Finder < Trailblazer::Finder
|
467
|
-
|
468
|
-
adapters ActiveRecord, WillPaginate
|
469
|
-
end
|
470
|
-
```
|
471
|
-
|
472
|
-
### FriendlyId
|
473
|
-
The [FriendlyId](https://github.com/norman/friendly_id) adapter was written cause I personally use it a lot, as well as to show an example of what kind of adapters we could potentially write in the future to compliment the filters with.
|
474
|
-
|
475
|
-
Basically the [FriendlyId](https://github.com/norman/friendly_id) adapter adds the following filter, which automatically checks wether the id is an integer or slug and makes sure the right filter is applied on the row set:
|
476
|
-
```ruby
|
477
|
-
filter_by :id, with: :apply_slug_filter
|
478
|
-
```
|
479
|
-
|
480
|
-
**Note**
|
481
|
-
Currently only tested with ActiveRecord.
|
482
|
-
|
483
|
-
**Note**
|
484
|
-
Do not set a filter_by for id or slug when using this adapter.
|
401
|
+
entity { fetch_product_as_hashes }
|
485
402
|
|
486
|
-
|
487
|
-
|
488
|
-
class Post::Finder < Trailblazer::Finder
|
489
|
-
# Features, in case you use any, need to be specified before adapters
|
490
|
-
adapters ActiveRecord, FriendlyId
|
403
|
+
filter_by(:name) { |entity, _attribute, value| entity.select { |product| product[:name] == value } }
|
404
|
+
filter_by(:category) { |entity, _attribute, value| entity.select { |product| product[:category] == value } }
|
491
405
|
end
|
492
406
|
```
|
493
407
|
|
494
|
-
|
495
|
-
|
496
|
-
Not even for the Paging and Sorting features, however using additional adapters such as Kaminari, WillPaginate and FriendlyId won't work well with this.
|
408
|
+
### Overwriting Methods
|
409
|
+
You can have fine grained entity, by overwriting ```initialize``` method:
|
497
410
|
|
498
411
|
```ruby
|
499
412
|
class Post::Finder < Trailblazer::Finder
|
500
|
-
|
501
|
-
entity_type { fetch_product_as_hashes }
|
413
|
+
property :name, type: Types::String
|
502
414
|
|
503
|
-
|
504
|
-
|
415
|
+
def initialize(options = {})
|
416
|
+
super options.merge(entity: Product.visible_to(user))
|
417
|
+
end
|
505
418
|
end
|
506
419
|
```
|
507
420
|
|
508
|
-
|
509
|
-
You can have fine grained entity_type, by overwriting ```initialize``` method:
|
421
|
+
You can have fine grained result set, by overwriting ```fetch_result``` method:
|
510
422
|
|
511
423
|
```ruby
|
512
424
|
class Post::Finder < Trailblazer::Finder
|
513
|
-
|
425
|
+
property :name, type: Types::String
|
514
426
|
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
def initialize(user, options = {})
|
519
|
-
super options.merge(entity_type: Product.visible_to(user))
|
427
|
+
def fetch_result
|
428
|
+
super
|
429
|
+
result.merge! test: "I added this"
|
520
430
|
end
|
521
431
|
end
|
522
432
|
```
|
@@ -546,28 +456,3 @@ If you are able to, it helps even more if you can fork Trailblazer-Finder on Git
|
|
546
456
|
and add a test that reproduces the error you are experiencing.
|
547
457
|
|
548
458
|
For more info on how to report bugs, please see [this article](http://yourbugreportneedsmore.info/).
|
549
|
-
|
550
|
-
## License
|
551
|
-
Copyright (c) 2018 Trailblazer GmbH and contributors, released under the MIT
|
552
|
-
license.
|
553
|
-
|
554
|
-
MIT License
|
555
|
-
|
556
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
557
|
-
a copy of this software and associated documentation files (the
|
558
|
-
"Software"), to deal in the Software without restriction, including
|
559
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
560
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
561
|
-
permit persons to whom the Software is furnished to do so, subject to
|
562
|
-
the following conditions:
|
563
|
-
|
564
|
-
The above copyright notice and this permission notice shall be
|
565
|
-
included in all copies or substantial portions of the Software.
|
566
|
-
|
567
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
568
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
569
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
570
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
571
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
572
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
573
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|