queryko 1.2.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2344233fdafe42b76d1fbcef79137fc5506b0cd363fc8419e039da3b89bf62b0
4
- data.tar.gz: f3675c95e31ef885e50309ccae71415e37895f75969db69d0546c27448aa7a55
3
+ metadata.gz: abb6e5b750a802a5aa0838bca55feed2fc57fd0fa2b5e4ffe5d8bdd15d226079
4
+ data.tar.gz: 4dd022ad40ac529ad3b5b9303bf8e20013bebeb70810738f7958b89076a11b25
5
5
  SHA512:
6
- metadata.gz: b8bcabb4606be9cb25ada2e95819276b766e926fb6024d7c945d4189ad94e99fd6183b6377c6f73fb1050dc53218f949beb3e343b7482f379e47d96ffe6589fb
7
- data.tar.gz: 8b38c51f4e7950f4131625259290ef7f78b3123bbaf9498a18fbb55302e584a0df20896261542054a2ab287ac35beb9f74108584df64192aea09f8ce4a551b75
6
+ metadata.gz: b5691585e6b1885c7ffb23138f996c77aad1f6fffc6c76ba8136c9458c80db18ddf0a9f94044f4a288be0e343dc7670b2dcabeb1fc9a317d82e1b4b9a84db3d4
7
+ data.tar.gz: 70d4ed989265d73ad5310727251cb1df113bd81facb5cbee091bed6a5a7b38b416650b1506d87adadb2d8a2e41065d4e210bf47b958fc73422bc90628944d9e9
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- queryko (1.2.3)
4
+ queryko (1.2.2)
5
5
  activerecord (>= 4.0)
6
6
  activesupport (>= 4.0)
7
7
 
@@ -27,6 +27,7 @@ GEM
27
27
  tzinfo (~> 1.1)
28
28
  arel (9.0.0)
29
29
  builder (3.2.3)
30
+ byebug (11.0.1)
30
31
  concurrent-ruby (1.1.3)
31
32
  crass (1.0.4)
32
33
  diff-lcs (1.3)
@@ -82,6 +83,7 @@ PLATFORMS
82
83
 
83
84
  DEPENDENCIES
84
85
  bundler (~> 1.16)
86
+ byebug
85
87
  kaminari
86
88
  queryko!
87
89
  rake (~> 10.0)
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  This gem provides additional functionality on your query objects. It will filter and paginate your query by supplying arguments directly from controller params
4
4
 
5
5
  ## Installation
6
+
6
7
  ```ruby
7
8
  # Pagination
8
9
  gem 'kaminari'
@@ -22,33 +23,40 @@ Or install it yourself as:
22
23
  $ gem install queryko
23
24
 
24
25
  ## Usage
26
+
25
27
  ### Create a query object
28
+
26
29
  ``` ruby
27
30
  class ProductsQuery < Queryko::QueryObject
28
- add_range_attributes :created_at, :price
29
- add_searchables :name, :vendor
30
-
31
- table_name 'my_products' # optional
32
-
33
- def initialize params={}, relation = Product.all
34
- super(params, relation)
35
- end
31
+ feature :created_at, :min
32
+ feature :created_at, :max
33
+ feature :price, :min
34
+ feature :price, :max
35
+ feature :name, :search, as: :name
36
+ feature :vendor, :search, as: :vendor
37
+ feature :id, :after, as: :since_id
38
+ feature :id, :batch, as: :by_ids
36
39
  end
37
40
  ```
38
41
 
39
42
  ### Using your query object
40
- Filter your query by appending `_min` or `_max` on your defined attributes. You can also filter searc3h by attribute.
41
- As long as you defined it in your query object definition.
43
+ Filter your query by appending `_min` or `_max` on your defined attributes. You can also filter results by attribute with your defined feature.
44
+
42
45
  ``` ruby
43
46
  # Collection
44
47
  products = ProductsQuery.new(price_min: 100, price_max: 150, name: 'Milk').call
45
48
  products = ProductsQuery.new(since_id: 26).call
46
49
 
47
- # Count
50
+ # Count - Counts items on current page. Default page is 1
48
51
  products = ProductsQuery.new(created_at_min: 'Jan 1, 2019').count
49
52
  products = ProductsQuery.new(name: 'Bag').count
53
+
54
+ # Total Count - Counts all items matching defined conditions
55
+ products = ProductsQuery.new(created_at_min: 'Jan 1, 2019').total_count
56
+ products = ProductsQuery.new(name: 'Bag').total_count
50
57
  ```
51
58
 
59
+
52
60
  #### Object Methods
53
61
  - **count** - Returns the filtered count including pagination filter or the size of return object.
54
62
  - **total_count** - Returns the overall count of the filtered total records.
@@ -62,19 +70,84 @@ query = ProductsQuery.new(page: 5, limit: 5)
62
70
  query.count # 1
63
71
  query.total_count # 21
64
72
  ```
73
+ ### Pagination
74
+ Override these methods to customize pagination limits
75
+
76
+ ``` ruby
77
+ ...
78
+
79
+ def upper_limit
80
+ 20 # default is 100
81
+ end
82
+
83
+ def lower_limit
84
+ 5 # default is 10
85
+ end
86
+
87
+ def default_limit
88
+ 10 # default is 50
89
+ end
90
+
91
+ ...
92
+ ```
93
+
94
+ ### Custom Filters
95
+ Create a custom filter class using `Queryko::Filters::Base`
96
+
97
+ ``` ruby
98
+ class CustomFilters::CoolSearch < Queryko::Filters::Base
99
+
100
+ # Optional.
101
+ # Some `options` keys are reserved for basic functionality
102
+ # Use `options` to get data from feature definition
103
+ def intialize(options = {}, feature)
104
+ super options, feature
105
+ end
106
+
107
+ # Required. This method is called by query object. Always return the result of
108
+ # the collection
109
+ def perform(collection, token)
110
+ collection.where("#{table_name}.#{column_name} < ?", "Cool-#{token}")
111
+ end
112
+ end
113
+ ```
114
+
115
+ Then add the filter class to your Queryko::Base object
116
+ ``` ruby
117
+ class QueryObject < Queryko::Base
118
+ filter_class :cool_search, CustomFilters::CoolSearch
119
+ # or
120
+ filter_class :cool_search, "CustomFilters::CoolSearch"
121
+
122
+
123
+ feature :name, :cool_search
124
+ # the :name will be scoped using params[:name_cool_search]
125
+ end
126
+ ```
65
127
 
66
128
  ### Other available options
67
129
  | Option | description |
68
130
  |:---------|:-----------------------------|
69
131
  | since_id | retrieves records after `id` |
70
132
  | page | page to retrieve |
71
- | limit | number of records per page |
133
+
134
+
135
+ ### File structure
136
+ You are free to structure your query objects and custom filters. Or group them
137
+ in one folder
138
+ ```
139
+ app/
140
+ └─ queries/
141
+ ├─ filters/
142
+ │ └─ cool_search.rb
143
+ ├─ products_query.rb
144
+ └─ query_base.rb
145
+ ```
72
146
 
73
147
  ## Contributing
74
148
 
75
149
  Bug reports and pull requests are welcome on GitHub at https://github.com/neume/queryko. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
76
150
 
77
-
78
151
  ## License
79
152
 
80
153
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,78 @@
1
+ require "active_support/core_ext/class/attribute"
2
+ require "queryko/naming"
3
+ require "queryko/able"
4
+ require "queryko/filterer"
5
+ require "queryko/filter_classes"
6
+ require "byebug"
7
+
8
+ module Queryko
9
+
10
+ class Base
11
+ attr_reader :countable_resource
12
+ include Queryko::FilterClasses
13
+ include Queryko::Naming
14
+ include Queryko::Able
15
+ include Queryko::Filterer
16
+
17
+ attr_reader :params
18
+
19
+ def initialize(params = {}, rel=nil)
20
+ @relation = @original_relation = rel || self.class.model_class.all
21
+ @params = self.defaults.merge(params)
22
+ end
23
+
24
+ def self.call(params = {}, rel)
25
+ new(params, rel).call
26
+ end
27
+
28
+ def call
29
+ perform
30
+ return relation
31
+ end
32
+
33
+ def perform
34
+ return if @performed
35
+
36
+ @performed = true
37
+ filter
38
+ filter_by_filters
39
+ @countable_resource = relation
40
+ end
41
+
42
+
43
+ def self.total_count(params = {}, rel)
44
+ new(params, rel).total_count
45
+ end
46
+
47
+ def total_count
48
+ perform
49
+ countable_resource.count
50
+ end
51
+
52
+ def self.count(params = {}, rel)
53
+ new(params, rel).count
54
+ end
55
+
56
+ def count
57
+ call.to_a.count
58
+ end
59
+
60
+ private
61
+
62
+ attr_accessor :relation
63
+
64
+ def config
65
+ @config ||= {
66
+ }
67
+ end
68
+
69
+ def filter
70
+ # overridable method
71
+ end
72
+
73
+ class_attribute :defaults, default: {}
74
+ def self.default(sym, value)
75
+ self.defaults[sym] = value
76
+ end
77
+ end
78
+ end
@@ -4,6 +4,9 @@ require "queryko/filters/before"
4
4
  require "queryko/filters/min"
5
5
  require "queryko/filters/max"
6
6
  require "queryko/filters/search"
7
+ require "queryko/filters/order"
8
+ require "queryko/filters/batch"
9
+ require "queryko/filters/paginate"
7
10
 
8
11
  module Queryko
9
12
  module FilterClasses
@@ -22,7 +25,10 @@ module Queryko
22
25
  before: Queryko::Filters::Before,
23
26
  min: Queryko::Filters::Min,
24
27
  max: Queryko::Filters::Max,
25
- search: Queryko::Filters::Search
28
+ search: Queryko::Filters::Search,
29
+ order: Queryko::Filters::Order,
30
+ batch: Queryko::Filters::Batch,
31
+ paginate: Queryko::Filters::Paginate
26
32
  }
27
33
  end
28
34
 
@@ -2,10 +2,17 @@ module Queryko
2
2
  module Filterer
3
3
  def filter_by_filters
4
4
  fields.each do |field, filter|
5
- # puts field
6
- # puts filter, filter.first.class.name
5
+ if field == 'limit' || field == 'page'
6
+ paginate(filter, )
7
+ end
7
8
  self.relation = filter.first.call(relation, params[field], self) if params[field]
8
9
  end
9
10
  end
11
+
12
+ def paginate(filter)
13
+ unless @paginated
14
+ end
15
+ @paginated ||= true
16
+ end
10
17
  end
11
18
  end
@@ -1,11 +1,7 @@
1
1
  require "queryko/filters/base"
2
2
 
3
3
  class Queryko::Filters::After < Queryko::Filters::Base
4
- def intialize(options = {}, feature)
5
- super options, feature
6
- end
7
-
8
- def perform(collection, token, query_object)
4
+ def perform(collection, token, query_object = nil)
9
5
  collection.where("#{table_name}.#{column_name} > ?", token)
10
6
  end
11
7
  end
@@ -5,7 +5,7 @@ module Queryko
5
5
 
6
6
  def initialize(options = {}, feature)
7
7
  @feature = feature
8
- @table_name = options.fetch(:table_name) { @feature.query_object.defined_table_name }
8
+ @table_name = options[:table_name]
9
9
  @column_name = options.fetch(:column_name) { @feature.name }
10
10
  @as = options[:as]
11
11
  end
@@ -18,11 +18,25 @@ module Queryko
18
18
  end
19
19
 
20
20
  def field
21
- @field ||= as || build_field_from_column
21
+ @field ||= as || build_param_key
22
22
  end
23
23
 
24
- def build_field_from_column
25
- "#{column_name}_#{self.class.name.split('::').last.underscore}"
24
+ def param_key_format
25
+ nil
26
+ end
27
+
28
+ private
29
+
30
+ def build_param_key
31
+ param_key_format || default_param_key_format
32
+ end
33
+
34
+ def default_param_key_format
35
+ "#{column_name}_#{parameterized_name}"
36
+ end
37
+
38
+ def parameterized_name
39
+ self.class.name.split('::').last.underscore
26
40
  end
27
41
  end
28
42
  end
@@ -0,0 +1,11 @@
1
+ require "queryko/filters/base"
2
+
3
+ class Queryko::Filters::Batch < Queryko::Filters::Base
4
+ def perform(collection, token, query_object = nil)
5
+ collection.where("#{table_name}.#{column_name} IN (?)", token.split(','))
6
+ end
7
+
8
+ def param_key_format
9
+ "by_#{column_name.pluralize}"
10
+ end
11
+ end
@@ -1,11 +1,7 @@
1
1
  require "queryko/filters/base"
2
2
 
3
3
  class Queryko::Filters::Before < Queryko::Filters::Base
4
- def intialize(options = {}, feature)
5
- super options, feature
6
- end
7
-
8
- def perform(collection, token, query_object)
4
+ def perform(collection, token, query_object = nil)
9
5
  collection.where("#{table_name}.#{column_name} < ?", token)
10
6
  end
11
7
  end
@@ -1,11 +1,7 @@
1
1
  require "queryko/filters/base"
2
2
 
3
3
  class Queryko::Filters::Max < Queryko::Filters::Base
4
- def intialize(options = {}, feature)
5
- super options, feature
6
- end
7
-
8
- def perform(collection, token, query_object)
4
+ def perform(collection, token, query_object = nil)
9
5
  collection.where("#{table_name}.#{column_name} <= ?", token)
10
6
  end
11
7
  end
@@ -1,15 +1,10 @@
1
1
  require "queryko/filters/base"
2
2
 
3
3
  class Queryko::Filters::Min < Queryko::Filters::Base
4
- def intialize(options = {}, feature)
5
- super options, feature
6
- end
7
-
8
- def perform(collection, token, query_object)
4
+ def perform(collection, token, query_object = nil)
9
5
  collection.where("#{table_name}.#{column_name} >= ?", token)
10
6
  end
11
7
 
12
-
13
8
  def build_field_from_column
14
9
  "#{column_name}_min"
15
10
  end
@@ -0,0 +1,17 @@
1
+ require "queryko/filters/base"
2
+
3
+ class Queryko::Filters::Order < Queryko::Filters::Base
4
+
5
+ def perform(collection, token, query_object = nil)
6
+ collection.order("#{table_name}.#{column_name} #{filter_input(token)}", )
7
+ end
8
+
9
+ def filter_input(token)
10
+ return 'DESC' if token.to_s.downcase == 'desc'
11
+ return 'ASC'
12
+ end
13
+
14
+ def param_key_format
15
+ "order_by_#{column_name}"
16
+ end
17
+ end
@@ -0,0 +1,49 @@
1
+ require "queryko/filters/base"
2
+
3
+ class Queryko::Filters::Paginate < Queryko::Filters::Base
4
+ attr_reader :upper_limit, :lower_limit, :default_limit, :params
5
+
6
+ def initialize(options = {}, feature)
7
+ @upper_limit = options.fetch(:upper) { 100 }
8
+ @lower_limit = options.fetch(:lower) { 10 }
9
+
10
+ super(options, feature)
11
+ end
12
+
13
+ def perform(collection, paginate, query_object)
14
+ if paginate
15
+ @params = query_object.params
16
+
17
+ if defined?(WillPaginate)
18
+ collection.paginate(page: page, per_page: limit)
19
+ elsif defined?(Kaminari)
20
+ collection.page(page).per(limit)
21
+ else
22
+ raise 'Only kaminari and wil_paginate are supported'
23
+ end
24
+ end
25
+ end
26
+
27
+ def page
28
+ params[:page] || 1
29
+ end
30
+
31
+ def limit
32
+ get_limit
33
+ end
34
+
35
+ def get_limit
36
+ lim = params[:limit].to_i
37
+ if lower_limit > lim
38
+ lower_limit
39
+ elsif lim > upper_limit
40
+ upper_limit
41
+ else
42
+ lim
43
+ end
44
+ end
45
+
46
+ def param_key_format
47
+ "paginate"
48
+ end
49
+ end
@@ -5,10 +5,10 @@ class Queryko::Filters::Search < Queryko::Filters::Base
5
5
  def initialize(options = {}, feature)
6
6
  @cond = options.fetch(:cond) { :like }
7
7
  @token_format = options[:token_format] || '%token%'
8
- super options, feature
8
+ super(options, feature)
9
9
  end
10
10
 
11
- def perform(collection, token, query_object)
11
+ def perform(collection, token, query_object = nil)
12
12
  query_cond, query_token = format_query_params(token)
13
13
  table_property = "#{table_name}.#{column_name}"
14
14
 
@@ -3,8 +3,9 @@ module Queryko
3
3
  def self.included(base)
4
4
  base.extend(ClassMethods)
5
5
  base.class_eval do
6
- class_attribute :defined_table_name, default: nil, instance_writer: false
7
- class_attribute :defined_model_class, default: nil, instance_writer: false
6
+ class_attribute :defined_table_name, default: :table, instance_writer: false
7
+ class_attribute :defined_model_class, default: :model, instance_writer: false
8
+ # class_attribute :abstract_class, default: false, instance_writer: false
8
9
 
9
10
  def table_name
10
11
  self.class.table_name
@@ -20,7 +21,7 @@ module Queryko
20
21
  def table_name(name = nil)
21
22
  if name
22
23
  self.defined_table_name = name.to_s
23
- elsif self.defined_table_name.nil?
24
+ elsif self.defined_table_name == :table
24
25
  self.defined_table_name = inferred_from_class_name(self)
25
26
  end
26
27
 
@@ -30,13 +31,19 @@ module Queryko
30
31
  def model_class(name = nil)
31
32
  if name
32
33
  self.defined_model_class = name.to_s.constantize
33
- elsif self.defined_model_class.nil?
34
+ elsif self.defined_model_class == :model
34
35
  self.defined_model_class = inferred_model(self)
35
36
  end
36
37
 
38
+ # require 'byebug'
39
+ # byebug
37
40
  return self.defined_model_class
38
41
  end
39
42
 
43
+ def abstract_class
44
+ @abstract_class = true
45
+ end
46
+
40
47
  def inferred_from_class_name(klass)
41
48
  # class names should be in plural form by default. No need to tableize
42
49
  klass.name.chomp('Query').split('::').last.underscore
@@ -1,3 +1,3 @@
1
1
  module Queryko
2
- VERSION = "1.2.4"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/queryko.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require "queryko/version"
2
- require "queryko/query_object"
2
+ require "queryko/base"
3
3
  require "queryko/feature"
4
4
  require "queryko/able"
5
5
  require "queryko/filterer"
data/queryko.gemspec CHANGED
@@ -41,4 +41,5 @@ Gem::Specification.new do |spec|
41
41
  spec.add_development_dependency 'sqlite3'
42
42
  spec.add_development_dependency 'kaminari'
43
43
  spec.add_development_dependency 'will_paginate', '~> 3.1.0'
44
+ spec.add_development_dependency 'byebug'
44
45
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: queryko
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Nelson Valeros
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-11 00:00:00.000000000 Z
11
+ date: 2019-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 3.1.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: byebug
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  description: " This gem provides additional functionality on your query objects. It
126
140
  will filter and paginate your query by supplying an option "
127
141
  email:
@@ -144,23 +158,22 @@ files:
144
158
  - bin/setup
145
159
  - lib/queryko.rb
146
160
  - lib/queryko/able.rb
147
- - lib/queryko/after_attributes.rb
161
+ - lib/queryko/base.rb
148
162
  - lib/queryko/feature.rb
149
163
  - lib/queryko/filter_classes.rb
150
164
  - lib/queryko/filterer.rb
151
165
  - lib/queryko/filters/after.rb
152
166
  - lib/queryko/filters/base.rb
167
+ - lib/queryko/filters/batch.rb
153
168
  - lib/queryko/filters/before.rb
154
169
  - lib/queryko/filters/max.rb
155
170
  - lib/queryko/filters/min.rb
171
+ - lib/queryko/filters/order.rb
172
+ - lib/queryko/filters/paginate.rb
156
173
  - lib/queryko/filters/search.rb
157
174
  - lib/queryko/naming.rb
158
- - lib/queryko/query_object.rb
159
- - lib/queryko/range_attributes.rb
160
- - lib/queryko/searchables.rb
161
175
  - lib/queryko/version.rb
162
176
  - queryko.gemspec
163
- - test.html
164
177
  homepage: https://github.com/neume/queryko
165
178
  licenses:
166
179
  - MIT
@@ -1,19 +0,0 @@
1
- module Queryko
2
- module AfterAttributes
3
- def self.included(base)
4
- base.extend(ClassMethods)
5
- end
6
-
7
- module ClassMethods
8
- def add_after_attributes(*args)
9
- suggestion = []
10
- args.each do |arg|
11
- feature arg.to_sym, :after, as: "after_#{arg}"
12
- suggestion << "feature :#{arg}, :after, as: 'after_#{arg}'"
13
-
14
- end
15
- warn "[DEPRECATION] `add_after_attributes` is deprecated. Please use `feature` instead.\nExample:\n#{suggestion.join("\n")}"
16
- end
17
- end
18
- end
19
- end