doure 0.1.0 → 0.1.2

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
- 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