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 +5 -5
- data/README.md +19 -12
- data/doure.gemspec +5 -5
- data/lib/doure.rb +7 -0
- data/lib/doure/filter.rb +9 -4
- data/lib/doure/filterable.rb +17 -6
- data/lib/doure/version.rb +3 -1
- metadata +17 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1e7be98ed2e9fdd3c91182ac61d8a81089bb9e112849e6bc24579c2a6e3d1063
|
4
|
+
data.tar.gz: e5441b9cab833029ef3f08b8027a9cc46be1d27d8b3d4be0aae7c4e163a82971
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 `
|
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.
|
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
|
-
|
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.
|
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.
|
104
|
-
- `eq_filter(name)`: Implements equality. Ex: `Post.
|
105
|
-
- `not_eq_filter(name)`: Non-equality. Ex: `Post.
|
106
|
-
- `present_filter(name)`: This is a boolean filter by default. Implements equality / non-equality against NULL. Ex: `Post.
|
107
|
-
- Numerical comparators, `gt_filter, lt_filter, gteq_filter, lteq_filter`: Implements numerical comparators, the passed value is left as-is. Ex: `Post.
|
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).
|
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.
|
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.
|
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", ">=
|
24
|
-
spec.add_dependency "activesupport", ">=
|
25
|
-
spec.add_development_dependency "bundler", "~>
|
26
|
-
spec.add_development_dependency "rake"
|
27
|
-
spec.add_development_dependency "minitest"
|
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
|
-
|
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(
|
61
|
-
|
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
|
data/lib/doure/filterable.rb
CHANGED
@@ -1,12 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doure
|
2
4
|
module Filterable
|
3
|
-
|
4
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
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
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.
|
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:
|
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:
|
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:
|
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:
|
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:
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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
|
-
|
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
|