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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml +101 -0
  4. data/.rubocop.yml +3 -43
  5. data/.rubocop_todo.yml +42 -196
  6. data/.travis.yml +5 -8
  7. data/Gemfile +2 -2
  8. data/LICENSE.txt +7 -21
  9. data/README.md +177 -292
  10. data/Rakefile +12 -12
  11. data/lib/trailblazer/finder.rb +48 -23
  12. data/lib/trailblazer/finder/activity/find.rb +57 -0
  13. data/lib/trailblazer/finder/activity/prepare.rb +29 -0
  14. data/lib/trailblazer/finder/activity/prepare/adapters.rb +66 -0
  15. data/lib/trailblazer/finder/activity/prepare/entity.rb +32 -0
  16. data/lib/trailblazer/finder/activity/prepare/filters.rb +36 -0
  17. data/lib/trailblazer/finder/activity/prepare/paging.rb +49 -0
  18. data/lib/trailblazer/finder/activity/prepare/params.rb +33 -0
  19. data/lib/trailblazer/finder/activity/prepare/properties.rb +47 -0
  20. data/lib/trailblazer/finder/activity/prepare/sorting.rb +57 -0
  21. data/lib/trailblazer/finder/activity/process.rb +18 -0
  22. data/lib/trailblazer/finder/activity/process/adapters.rb +48 -0
  23. data/lib/trailblazer/finder/activity/process/filters.rb +28 -0
  24. data/lib/trailblazer/finder/activity/process/paging.rb +26 -0
  25. data/lib/trailblazer/finder/activity/process/predicates.rb +30 -0
  26. data/lib/trailblazer/finder/activity/process/sorting.rb +26 -0
  27. data/lib/trailblazer/finder/adapters/active_record/paging.rb +9 -8
  28. data/lib/trailblazer/finder/adapters/active_record/predicates.rb +78 -17
  29. data/lib/trailblazer/finder/adapters/active_record/sorting.rb +14 -12
  30. data/lib/trailblazer/finder/adapters/basic/paging.rb +21 -0
  31. data/lib/trailblazer/finder/adapters/basic/predicates.rb +115 -0
  32. data/lib/trailblazer/finder/adapters/basic/sorting.rb +40 -0
  33. data/lib/trailblazer/finder/adapters/kaminari/paging.rb +21 -0
  34. data/lib/trailblazer/finder/adapters/sequel/paging.rb +9 -8
  35. data/lib/trailblazer/finder/adapters/sequel/predicates.rb +78 -17
  36. data/lib/trailblazer/finder/adapters/sequel/sorting.rb +17 -15
  37. data/lib/trailblazer/finder/adapters/will_paginate/paging.rb +21 -0
  38. data/lib/trailblazer/finder/base.rb +20 -83
  39. data/lib/trailblazer/finder/dsl.rb +56 -0
  40. data/lib/trailblazer/finder/find.rb +28 -15
  41. data/lib/trailblazer/finder/helpers/basic.rb +44 -0
  42. data/lib/trailblazer/finder/helpers/sorting.rb +54 -0
  43. data/lib/trailblazer/finder/utils/array.rb +20 -0
  44. data/lib/trailblazer/finder/utils/extra.rb +10 -20
  45. data/lib/trailblazer/finder/utils/hash.rb +36 -0
  46. data/lib/trailblazer/finder/utils/splitter.rb +16 -17
  47. data/lib/trailblazer/finder/utils/string.rb +20 -10
  48. data/lib/trailblazer/finder/version.rb +3 -1
  49. data/lib/trailblazer/operation/finder.rb +20 -19
  50. data/spec/spec_helper.rb +5 -11
  51. data/spec/spec_helper_active_record.rb +11 -12
  52. data/spec/spec_helper_sequel.rb +4 -4
  53. data/spec/spec_helper_will_paginate.rb +13 -0
  54. data/spec/trailblazer/finder/adapters/active_record_spec.rb +267 -0
  55. data/spec/trailblazer/finder/adapters/basic_spec.rb +251 -0
  56. data/spec/trailblazer/finder/adapters/kaminari_spec.rb +78 -32
  57. data/spec/trailblazer/finder/adapters/sequel_spec.rb +267 -0
  58. data/spec/trailblazer/finder/adapters/will_paginate_spec.rb +81 -40
  59. data/spec/trailblazer/finder/base_spec.rb +292 -204
  60. data/spec/trailblazer/finder/dsl_spec.rb +213 -0
  61. data/spec/trailblazer/finder/utils/hash_spec.rb +26 -0
  62. data/spec/trailblazer/finder/utils/splitter_spec.rb +39 -0
  63. data/spec/trailblazer/finder/utils/string_spec.rb +52 -9
  64. data/spec/trailblazer/operation/finder_spec.rb +35 -32
  65. data/trailblazer-finder.gemspec +31 -30
  66. metadata +119 -137
  67. data/lib/trailblazer/finder/adapters.rb +0 -26
  68. data/lib/trailblazer/finder/adapters/active_record.rb +0 -32
  69. data/lib/trailblazer/finder/adapters/data_mapper.rb +0 -32
  70. data/lib/trailblazer/finder/adapters/data_mapper/paging.rb +0 -20
  71. data/lib/trailblazer/finder/adapters/data_mapper/predicates.rb +0 -42
  72. data/lib/trailblazer/finder/adapters/data_mapper/sorting.rb +0 -38
  73. data/lib/trailblazer/finder/adapters/friendly_id.rb +0 -31
  74. data/lib/trailblazer/finder/adapters/kaminari.rb +0 -18
  75. data/lib/trailblazer/finder/adapters/sequel.rb +0 -32
  76. data/lib/trailblazer/finder/adapters/will_paginate.rb +0 -18
  77. data/lib/trailblazer/finder/errors/block_ignored.rb +0 -11
  78. data/lib/trailblazer/finder/errors/invalid_defined_by_value.rb +0 -11
  79. data/lib/trailblazer/finder/errors/invalid_number.rb +0 -16
  80. data/lib/trailblazer/finder/errors/missing_entity_type.rb +0 -11
  81. data/lib/trailblazer/finder/errors/with_ignored.rb +0 -11
  82. data/lib/trailblazer/finder/features.rb +0 -23
  83. data/lib/trailblazer/finder/features/paging.rb +0 -55
  84. data/lib/trailblazer/finder/features/predicate.rb +0 -32
  85. data/lib/trailblazer/finder/features/sorting.rb +0 -108
  86. data/lib/trailblazer/finder/filter.rb +0 -66
  87. data/lib/trailblazer/finder/predicates.rb +0 -39
  88. data/lib/trailblazer/finder/utils/deep_locate.rb +0 -30
  89. data/lib/trailblazer/finder/utils/params.rb +0 -28
  90. data/lib/trailblazer/finder/utils/parse.rb +0 -25
  91. data/spec/spec_helper_data_mapper.rb +0 -35
  92. data/spec/support/paging_shared_example.rb +0 -65
  93. data/spec/support/sorting_shared_example.rb +0 -125
  94. data/spec/trailblazer/finder/adapters/active_record/base_spec.rb +0 -112
  95. data/spec/trailblazer/finder/adapters/active_record/paging_spec.rb +0 -64
  96. data/spec/trailblazer/finder/adapters/active_record/predicates_spec.rb +0 -101
  97. data/spec/trailblazer/finder/adapters/active_record/sorting_spec.rb +0 -99
  98. data/spec/trailblazer/finder/adapters/data_mapper/base_spec.rb +0 -112
  99. data/spec/trailblazer/finder/adapters/data_mapper/paging_spec.rb +0 -64
  100. data/spec/trailblazer/finder/adapters/data_mapper/predicates_spec.rb +0 -100
  101. data/spec/trailblazer/finder/adapters/data_mapper/sorting_spec.rb +0 -97
  102. data/spec/trailblazer/finder/adapters/friendly_id_spec.rb +0 -46
  103. data/spec/trailblazer/finder/adapters/sequel/base_spec.rb +0 -125
  104. data/spec/trailblazer/finder/adapters/sequel/paging_spec.rb +0 -64
  105. data/spec/trailblazer/finder/adapters/sequel/predicates_spec.rb +0 -89
  106. data/spec/trailblazer/finder/adapters/sequel/sorting_spec.rb +0 -110
  107. data/spec/trailblazer/finder/adapters_spec.rb +0 -110
  108. data/spec/trailblazer/finder/features/paging_spec.rb +0 -104
  109. data/spec/trailblazer/finder/features/predicates_spec.rb +0 -99
  110. data/spec/trailblazer/finder/features/sorting_spec.rb +0 -96
  111. data/spec/trailblazer/finder/features_spec.rb +0 -55
  112. data/spec/trailblazer/finder/filter_spec.rb +0 -133
  113. data/spec/trailblazer/finder/find_spec.rb +0 -72
  114. data/spec/trailblazer/finder/utils/extra_spec.rb +0 -41
  115. data/spec/trailblazer/finder/utils/params_spec.rb +0 -39
  116. data/spec/trailblazer/finder/utils/parse_spec.rb +0 -33
  117. data/spec/trailblazer/operation/paging_spec.rb +0 -68
  118. data/spec/trailblazer/operation/predicates_spec.rb +0 -127
  119. data/spec/trailblazer/operation/sorting_spec.rb +0 -80
  120. data/spec/trailblazer/test_spec.rb +0 -41
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'coveralls', require: false
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 and contributors, released under the MIT
2
- license.
1
+ Copyright (c) 2018 Trailblazer GmbH
3
2
 
4
- MIT License
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
- Permission is hereby granted, free of charge, to any person obtaining
7
- a copy of this software and associated documentation files (the
8
- "Software"), to deal in the Software without restriction, including
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
- Description should come here
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) [![Build Status](https://secure.travis-ci.org/trailblazer/trailblazer-finder.svg)](https://travis-ci.org/trailblazer/trailblazer-finder) [![Coverage Status](https://coveralls.io/repos/github/trailblazer/trailblazer-finder/badge.svg?branch=master)](https://coveralls.io/github/trailblazer/trailblazer-finder?branch=master)
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
- * [Dependencies](#dependencies)
15
+ * [Dependencies](#dependencies)
12
16
  * [Usage](#usage)
13
- * [Finder](#finder)
14
- * [Finder Example](#finder-example)
15
- * [Operation](#operation)
16
- * [Operation Example](#operation-example)
17
- * [Usable without Trailblazer](#usable-without-trailblazer)
18
- * [Example without Trailblazer](#example-without-trailblazer)
19
- * [Example Project](#example-project)
20
- * [Features](#features)
21
- * [Predicate](#predicate)
22
- * [Predicate Example](#predicate-example)
23
- * [Paging](#paging)
24
- * [Paging Example](#paging-example)
25
- * [Sorting](#sorting)
26
- * [Sorting Example](#sorting-example)
27
- * [Adapters](#adapters)
28
- * [Adapters Example](#adapters-example)
29
- * [ActiveRecord](#active_record)
30
- * [Active Record Example](#active-record-example)
31
- * [DataMapper](#data_mapper)
32
- * [Data Mapper Example](#data-mapper-example)
33
- * [Sequel](#sequel)
34
- * [Sequel Example](#sequel-example)
35
- * [Kaminari](#kaminari)
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](#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 work if they're specified on top of your Finder class
70
+ NOTE: features are only applied if their options are specified in your finder
74
71
 
75
- An Entity Type is required, but can:
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
- Basically for most use cases, Entity Type is the entity/model/array of hashes you wish to use finder on
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
- # Optional features
86
- features Paging, Sorting
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
- entity_type { Post }
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 (remove if not using the Paging feature)
96
- per_page 25
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
- # Sortable attributes (remove if not using the Sorting feature)
101
- sortable_by :id, :title, :created_at
102
-
103
- # Runs filter_by to filter results
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
- # * +attribute+:: The attribute to be filtered on
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 :created_before, with: :apply_created_before
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 apply_body_filter(entity_type, value)
126
- return unless value.present?
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
- # +entity_type+:: Entity/Model or array (optional if specified in Finder Class, overwrites Finder class entity_type)
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(filter: params['f'], page: params['page'], per_page: params['per_page'])
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(filter: params['f']).results.first
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[:f] = {} unless params.key?('f')
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
- .results? # => are there any results found
201
- .results # => fetched results
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
- result = Post::Finder.new(filter: params[:f], page: params[:page], per_page: params[:per_page])
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
- .results? # => are there any results found
227
- .results # => fetched results
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
- ### Predicate
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
- #### Predicate Example
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
- features Predicate
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
- # per page defaults to 25 (so not required)
273
- per_page 10
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
- # accessing filters
286
- .name # => name filter
287
- .created_at # => created at filter
288
-
289
- # Predicate filters
290
- .name_eq # => name equals filter
291
- .name_not_eq # => name not equals filter
292
- .name_blank # => name blank filter
293
- .name_not_blank # => name not blank filter
294
- .name_lt # => name less than filter (converts value to float)
295
- .name_lte # => name less than or equal to filter (converts value to float)
296
- .name_gt # => name greater than filter (converts value to float)
297
- .name_gte # => name greater than or equal to filter (converts value to float)
298
- .category_name_eq # => category name equals filter
299
- .category_name_not_eq # => category name not equals filter
300
- .category_name_blank # => category name blank filter
301
- .category_name_not_blank # => category name not blank filter
302
- .category_name_lt # => category name less than filter (converts value to float)
303
- .category_name_lte # => category name less than or equal to filter (converts value to float)
304
- .category_name_gt # => category name greater than filter (converts value to float)
305
- .category_name_gte # => category name greater than or equal to filter (converts value to float)
306
-
307
- # accessing results
308
- .count # => number of found results
309
- .results? # => are there any results found
310
- .results # => fetched results
311
- .all # => if needed, use it to get dataset (sequel for example requires you use it in some cases)
312
-
313
- # params for url generations
314
- .params # => filter values
315
- .params published: false # => overwrites the 'published' filter
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
- features Paging
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
- # Minimum items per page (not required)
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
- features Sorting
312
+ entity { Post }
354
313
 
355
- sortable_by :name, :body
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
- .results # => Posts sorted by title DESC
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. Adapters are not just tied to the ORM's, we also have a few adapters included that make it easier to work along with existing gems such as [Kaminari](https://github.com/kaminari/kaminari), [WillPaginate](https://github.com/mislav/will_paginate/) and [FriendlyId](https://github.com/norman/friendly_id).
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
- # Features, in case you use any, need to be specified before adapters
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
- # Features, in case you use any, need to be specified before adapters
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
- # Features, in case you use any, need to be specified before adapters
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
- **Note**
462
- Not usable without the Paging feature enabled, and requires an ORM that's supported by [WillPaginate](https://github.com/mislav/will_paginate/), directly or by using additional gems.
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
- features Paging
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
- #### Friendly Id Example
487
- ```ruby
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
- ## Tips & Tricks
495
- ### ORM's are not required
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
- # Features, in case you use any, need to be specified before adapters
501
- entity_type { fetch_product_as_hashes }
413
+ property :name, type: Types::String
502
414
 
503
- filter_by(:name) { |entity_type, value| entity_type.select { |product| product[:name] == value } }
504
- filter_by(:category) { |entity_type, value| entity_type.select { |product| product[:category] == value } }
415
+ def initialize(options = {})
416
+ super options.merge(entity: Product.visible_to(user))
417
+ end
505
418
  end
506
419
  ```
507
420
 
508
- ### Overwriting Methods
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
- # Features, in case you use any, need to be specified before adapters
425
+ property :name, type: Types::String
514
426
 
515
- filter_by :name
516
- filter_by :category_name
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.