doure 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 699a3e3244c2fe33d075967a17478c02b176e9b8
4
- data.tar.gz: 837ef221bb0e702fac32a3a7a6c6429b561a1da9
2
+ SHA256:
3
+ metadata.gz: 1e7be98ed2e9fdd3c91182ac61d8a81089bb9e112849e6bc24579c2a6e3d1063
4
+ data.tar.gz: e5441b9cab833029ef3f08b8027a9cc46be1d27d8b3d4be0aae7c4e163a82971
5
5
  SHA512:
6
- metadata.gz: 36b4859bbe22a9baf42ad38da0c49dd49c8e52309d880886fb5e985d69886cee9f68ed8e0e2864cad5208786cd8690a85345ee494b17c6e25bf0fb6fb1ef6eeb
7
- data.tar.gz: 788e22ff0aa88d28892f3aa3cce3c6b0651f685a88e02dd43f87ff9d3b7605b22a97f83a13558fa5010cb06b53466902ba9b8f3371917aed018a34be54668e3d
6
+ metadata.gz: 678dcc5b765633a84bdc73771698c3d5fc722f87b67b9b1175063762fc9f11a81d6d17fe4df46ed7f522112760aecdf9917641785fca43fcd08831c4f9f7c8b2
7
+ data.tar.gz: 1096d1763f9bfa55d6a1a5202bd68efa349908a71f6fb60b4eb66e4d2a28e68d6af76794b774b45e88b45d774c99ddbe28a80482f85cf40c9b50baf00f6b68c0
data/README.md CHANGED
@@ -1,16 +1,23 @@
1
1
  # Doure
2
2
 
3
- Doure is a minimal abstraction to write parameterized filters for ActiveRecord models. It allows you to write named filters that accept one parameter, and use those later with `filter`, ex:
3
+ Doure is a minimal abstraction to write parameterized filters for ActiveRecord models. It allows you to write named filters that accept one parameter, and use those later with `doure_filter`, ex:
4
4
 
5
5
  ```ruby
6
+ class Post < ApplicationRecord
7
+ include Doure::Filterable
8
+
9
+ filter_class PostFilter
10
+ end
11
+
6
12
  class PostFilter < Doure::Filter
7
13
  cont_filter(:title)
8
14
  filter(:author_role_in) { |s, v| s.joins(:author).where(authors: { role: v }) }
9
15
  end
10
16
 
11
- Post.filter(title_cont: "Dev", author_role_in: ["editor", "admin"])
17
+ Post.doure_filter(title_cont: "Dev", author_role_in: ["editor", "admin"])
12
18
  ```
13
19
 
20
+ This allows for a simple implementation of search features in a controller, by passing the "search" parameters (like a `q` parameter) directly to `#doure_filter`.
14
21
 
15
22
  ## Installation
16
23
 
@@ -36,7 +43,7 @@ Given you have an ActiveRecord model, you need to extend the filterable module a
36
43
  # app/models/post.rb
37
44
 
38
45
  class Post < ApplicationRecord
39
- extend Doure::Filterable
46
+ include Doure::Filterable
40
47
 
41
48
  filter_class PostFilter
42
49
  end
@@ -64,7 +71,7 @@ You can also use the additional argument `:as` to `filter` (or any of the other
64
71
  ```ruby
65
72
  class PostFilter < Doure::Filter
66
73
  filter(:is_visible, as: :boolean) { |s, v|
67
- # 'v' is a boolean here even if used as `Post.filter(is_visible: 'true')`
74
+ # 'v' is a boolean here even if used as `Post.doure_filter(is_visible: 'true')`
68
75
  s.where(active: v)
69
76
  }
70
77
  end
@@ -100,26 +107,26 @@ end
100
107
 
101
108
  Some of the most commonly used filters are already provided. The name of the resulting filter is always <filter_name>_<prefix>, for example "title_cont" for a filter like "cont_filter(:title)". In particular the provided filters are:
102
109
 
103
- - `cont_filter(name)`: Implements `ILIKE '%#{value}%'`. Ex: `Post.filter(title_cont: 'dev')`
104
- - `eq_filter(name)`: Implements equality. Ex: `Post.filter(id_eq: 12)`
105
- - `not_eq_filter(name)`: Non-equality. Ex: `Post.filter(id_not_eq: 12)`
106
- - `present_filter(name)`: This is a boolean filter by default. Implements equality / non-equality against NULL. Ex: `Post.filter(slug_present: false)`
107
- - Numerical comparators, `gt_filter, lt_filter, gteq_filter, lteq_filter`: Implements numerical comparators, the passed value is left as-is. Ex: `Post.filter(views_count_gt: 10)`
110
+ - `cont_filter(name)`: Implements `ILIKE '%#{value}%'`. Ex: `Post.doure_filter(title_cont: 'dev')`
111
+ - `eq_filter(name)`: Implements equality. Ex: `Post.doure_filter(id_eq: 12)`
112
+ - `not_eq_filter(name)`: Non-equality. Ex: `Post.doure_filter(id_not_eq: 12)`
113
+ - `present_filter(name)`: This is a boolean filter by default. Implements equality / non-equality against NULL. Ex: `Post.doure_filter(slug_present: false)`
114
+ - Numerical comparators, `gt_filter, lt_filter, gteq_filter, lteq_filter`: Implements numerical comparators, the passed value is left as-is. Ex: `Post.doure_filter(views_count_gt: 10)`
108
115
 
109
116
 
110
117
  ### Using Model#filter
111
118
 
112
119
  The `#filter` method is chainable with other scopes, for example:
113
120
 
114
- `Post.where(category_id: 12).filter(title_cont: "Dev")`
121
+ `Post.where(category_id: 12).doure_filter(title_cont: "Dev")`
115
122
 
116
123
  Or with named scopes you have declared in the model:
117
124
 
118
- `Post.not_deleted.visible.filter(title_cont: "Dev", category_id_eq: '88')`
125
+ `Post.not_deleted.visible.doure_filter(title_cont: "Dev", category_id_eq: '88')`
119
126
 
120
127
  The expected use case for Doure is to implement search features. Since it's a common scenario to use `Model#filter` passing a hash of values coming from a view form, the hash will usually have most of their keys with nil values or empty strings. In order to not give incorrect results, then, `nil` and the empty string (`""`) values are ignored by default. For example:
121
128
 
122
- `Post.filter(title_cont: "", is_visible: "f")`
129
+ `Post.doure_filter(title_cont: "", is_visible: "f")`
123
130
 
124
131
  Will only apply the `is_visible` filter but not the `title_cont`.
125
132
 
data/doure.gemspec CHANGED
@@ -20,9 +20,9 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
- spec.add_dependency "activerecord", ">= 4.0.0"
24
- spec.add_dependency "activesupport", ">= 4.0.0"
25
- spec.add_development_dependency "bundler", "~> 1.15"
26
- spec.add_development_dependency "rake", "~> 10.0"
27
- spec.add_development_dependency "minitest", "~> 5.0"
23
+ spec.add_dependency "activerecord", ">= 6.0.0"
24
+ spec.add_dependency "activesupport", ">= 6.0.0"
25
+ spec.add_development_dependency "bundler", "~> 2.0"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "minitest"
28
28
  end
data/lib/doure.rb CHANGED
@@ -1,8 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/class/attribute'
4
+ require 'active_support/concern'
5
+ require 'active_support/core_ext/hash/indifferent_access'
6
+
1
7
  require "doure/version"
2
8
 
3
9
  require 'doure/filter'
4
10
  require 'doure/filterable'
5
11
 
12
+
6
13
  module Doure
7
14
  # Your code goes here...
8
15
  end
data/lib/doure/filter.rb CHANGED
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doure
2
4
  class Filter
3
5
  class_attribute :mapping
4
6
  self.mapping = ActiveSupport::HashWithIndifferentAccess.new
7
+ VALID_CASTINGS = %i(boolean date datetime)
8
+ InvalidCasting = Class.new(StandardError)
5
9
 
6
10
  class << self
7
11
  def inherited(subclass)
@@ -47,8 +51,7 @@ module Doure
47
51
  def apply(params = {})
48
52
  params.each do |key, value|
49
53
  if !value.nil? && value != "" && mapping.key?(key)
50
- casted_value = mapping[key][0].key?(:as) ? cast_value(mapping[key][0][:as], value) : value
51
- @scope = mapping[key][1].call(@scope, casted_value)
54
+ @scope = instance_exec(@scope, cast_value(mapping[key][0], value), &mapping[key][1])
52
55
  end
53
56
  end
54
57
 
@@ -57,8 +60,10 @@ module Doure
57
60
 
58
61
  private
59
62
 
60
- def cast_value(type, value)
61
- case type
63
+ def cast_value(opts, value)
64
+ raise InvalidCasting, "Invalid casting type #{opts[:as]}" if opts[:as] && !VALID_CASTINGS.include?(opts[:as])
65
+
66
+ case opts[:as]
62
67
  when :boolean
63
68
  ActiveRecord::Type::Boolean.new.cast(value)
64
69
  when :date
@@ -1,12 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doure
2
4
  module Filterable
3
- def filter_class(klass)
4
- @filter_class = klass
5
+ NoFilter = Class.new(StandardError)
6
+ extend ActiveSupport::Concern
7
+
8
+ class_methods do
9
+ def filter_class(klass)
10
+ self.doure_filter_klass = klass
11
+ end
5
12
  end
6
13
 
7
- def filter(params = {})
8
- @filter_class or raise "No filter model specified"
9
- @filter_class.new(self).apply(params)
14
+ included do
15
+ cattr_accessor :doure_filter_klass
16
+
17
+ scope :doure_filter, lambda { |params = {}|
18
+ doure_filter_klass || raise(NoFilter, "No filter model specified")
19
+ doure_filter_klass.new(self).apply(params)
20
+ }
10
21
  end
11
22
  end
12
- end
23
+ end
data/lib/doure/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doure
2
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
3
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doure
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roger Campos
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-08-24 00:00:00.000000000 Z
11
+ date: 2021-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,70 +16,70 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.0
19
+ version: 6.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 4.0.0
26
+ version: 6.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 4.0.0
33
+ version: 6.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 4.0.0
40
+ version: 6.0.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.15'
47
+ version: '2.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.15'
54
+ version: '2.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: minitest
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '5.0'
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '5.0'
82
+ version: '0'
83
83
  description: Minimal abstraction to write parameterized filters for ActiveRecord models
84
84
  email:
85
85
  - roger@rogercampos.com
@@ -117,8 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
117
  - !ruby/object:Gem::Version
118
118
  version: '0'
119
119
  requirements: []
120
- rubyforge_project:
121
- rubygems_version: 2.5.2
120
+ rubygems_version: 3.0.3
122
121
  signing_key:
123
122
  specification_version: 4
124
123
  summary: Minimal abstraction to write parameterized filters for ActiveRecord models