restme 0.0.37
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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/Dockerfile +28 -0
- data/LICENSE.txt +21 -0
- data/README.md +350 -0
- data/Rakefile +12 -0
- data/docker-compose.yml +13 -0
- data/lib/restme/authorize/rules.rb +35 -0
- data/lib/restme/create/rules.rb +110 -0
- data/lib/restme/restme.rb +30 -0
- data/lib/restme/scope/field/attachable.rb +51 -0
- data/lib/restme/scope/field/rules.rb +124 -0
- data/lib/restme/scope/filter/rules.rb +102 -0
- data/lib/restme/scope/filter/types/bigger_than_filterable.rb +38 -0
- data/lib/restme/scope/filter/types/bigger_than_or_equal_to_filterable.rb +38 -0
- data/lib/restme/scope/filter/types/equal_filterable.rb +38 -0
- data/lib/restme/scope/filter/types/in_filterable.rb +46 -0
- data/lib/restme/scope/filter/types/less_than_filterable.rb +38 -0
- data/lib/restme/scope/filter/types/less_than_or_equal_to_filterable.rb +38 -0
- data/lib/restme/scope/filter/types/like_filterable.rb +40 -0
- data/lib/restme/scope/paginate/rules.rb +53 -0
- data/lib/restme/scope/rules.rb +100 -0
- data/lib/restme/scope/sort/rules.rb +67 -0
- data/lib/restme/shared/controller_params.rb +24 -0
- data/lib/restme/shared/current_model.rb +27 -0
- data/lib/restme/shared/user_role.rb +12 -0
- data/lib/restme/update/rules.rb +116 -0
- data/lib/restme/version.rb +5 -0
- data/lib/restme.rb +9 -0
- data/sig/restme.rbs +4 -0
- metadata +75 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../shared/user_role"
|
4
|
+
require_relative "../shared/current_model"
|
5
|
+
require_relative "../shared/controller_params"
|
6
|
+
|
7
|
+
module Restme
|
8
|
+
module Create
|
9
|
+
# Defines create restrictions rules for a record.
|
10
|
+
module Rules
|
11
|
+
include ::Restme::Shared::ControllerParams
|
12
|
+
include ::Restme::Shared::CurrentModel
|
13
|
+
include ::Restme::Shared::UserRole
|
14
|
+
|
15
|
+
attr_reader :create_temp_record
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def creatable_record
|
20
|
+
@creatable_record ||= begin
|
21
|
+
@create_temp_record = klass.new(controller_params)
|
22
|
+
|
23
|
+
set_create_temp_record_current_user
|
24
|
+
|
25
|
+
create_record_errors.presence || create_temp_record
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_create_temp_record_current_user
|
30
|
+
return unless create_temp_record.respond_to?(:current_user)
|
31
|
+
return unless restme_current_user
|
32
|
+
|
33
|
+
create_temp_record.current_user = restme_current_user
|
34
|
+
end
|
35
|
+
|
36
|
+
def restme_create_status
|
37
|
+
return :unprocessable_entity if create_record_errors
|
38
|
+
|
39
|
+
:created
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_record_errors
|
43
|
+
return unless creatable_current_action
|
44
|
+
|
45
|
+
return createable_unscoped_error_response unless createable_scope?
|
46
|
+
|
47
|
+
create_object! unless create_temp_record.persisted?
|
48
|
+
|
49
|
+
createable_object_errors_messages
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_object!
|
53
|
+
ActiveRecord::Base.transaction do
|
54
|
+
create_temp_record.save!
|
55
|
+
end
|
56
|
+
rescue StandardError
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def createable_unscoped_error_response
|
61
|
+
{ message: "Unscoped", body: controller_params }
|
62
|
+
end
|
63
|
+
|
64
|
+
def createable_scope?
|
65
|
+
return true unless restme_current_user
|
66
|
+
|
67
|
+
method_scope = "#{creatable_current_action}_#{user_role}_scope?"
|
68
|
+
|
69
|
+
createable_super_admin_scope? || create_rules_class.try(method_scope) || false
|
70
|
+
end
|
71
|
+
|
72
|
+
def createable_super_admin_scope?
|
73
|
+
restme_current_user.super_admin?
|
74
|
+
end
|
75
|
+
|
76
|
+
def createable_object_errors_messages
|
77
|
+
return if create_temp_record.errors.blank?
|
78
|
+
|
79
|
+
"#{current_action}_error_scope?".constantize
|
80
|
+
rescue StandardError
|
81
|
+
createable_default_error_response
|
82
|
+
end
|
83
|
+
|
84
|
+
def creatable_current_action
|
85
|
+
return true unless restme_current_user
|
86
|
+
|
87
|
+
current_action.presence_in create_rules_class.class::CREATABLE_ACTIONS_RULES
|
88
|
+
rescue StandardError
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
|
92
|
+
def current_action
|
93
|
+
action_name.to_sym
|
94
|
+
end
|
95
|
+
|
96
|
+
def createable_default_error_response
|
97
|
+
{
|
98
|
+
message: "Error #{create_temp_record.errors.full_messages.to_sentence}",
|
99
|
+
body: controller_params
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def create_rules_class
|
104
|
+
@create_rules_class ||=
|
105
|
+
"#{controller_class.to_s.split("::").last}::Create::Rules"
|
106
|
+
.constantize.new(create_temp_record, restme_current_user)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "authorize/rules"
|
4
|
+
require_relative "scope/rules"
|
5
|
+
require_relative "create/rules"
|
6
|
+
require_relative "update/rules"
|
7
|
+
|
8
|
+
module Restme
|
9
|
+
# Defines the initialization rules for Restme.
|
10
|
+
module Restme
|
11
|
+
include ::Restme::Update::Rules
|
12
|
+
include ::Restme::Create::Rules
|
13
|
+
include ::Restme::Scope::Rules
|
14
|
+
include ::Restme::Authorize::Rules
|
15
|
+
|
16
|
+
attr_reader :restme_current_user
|
17
|
+
|
18
|
+
def initialize_restme
|
19
|
+
use_current_user
|
20
|
+
|
21
|
+
user_authorize
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def use_current_user
|
27
|
+
@restme_current_user = try(:current_user)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Restme
|
4
|
+
module Scope
|
5
|
+
module Field
|
6
|
+
# Defines the rules that determine which attachable fields can be attached.
|
7
|
+
module Attachable
|
8
|
+
def insert_attachments(scope)
|
9
|
+
unallowed_attachment_fields_error
|
10
|
+
|
11
|
+
return scope.uniq if attachment_fields_select.blank?
|
12
|
+
|
13
|
+
scope = scope.includes(attachment_fields_select_includes).uniq
|
14
|
+
|
15
|
+
scope.map do |record|
|
16
|
+
attachment_fields_select.each do |field|
|
17
|
+
@record = record.as_json.merge({ "#{field}": record.send(field).url })
|
18
|
+
end
|
19
|
+
|
20
|
+
@record
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def attachment_fields_select_includes
|
25
|
+
attachment_fields_select.map { |field| { "#{field}_attachment": :blob } }
|
26
|
+
end
|
27
|
+
|
28
|
+
def model_attachment_fields
|
29
|
+
@model_attachment_fields ||= klass.attachment_reflections.map do |attachment|
|
30
|
+
attachment.last.name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def unallowed_attachment_fields_error
|
35
|
+
return if unallowed_attachment_fields.blank?
|
36
|
+
|
37
|
+
render json: {
|
38
|
+
body: unallowed_attachment_fields,
|
39
|
+
message: "Selected not allowed attachment fields"
|
40
|
+
}, status: :bad_request
|
41
|
+
end
|
42
|
+
|
43
|
+
def unallowed_attachment_fields
|
44
|
+
return if attachment_fields_select.blank?
|
45
|
+
|
46
|
+
attachment_fields_select - model_attachment_fields
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "attachable"
|
4
|
+
|
5
|
+
module Restme
|
6
|
+
module Scope
|
7
|
+
module Field
|
8
|
+
# Defines the rules that determine which fields can be attached.
|
9
|
+
module Rules
|
10
|
+
include Restme::Scope::Field::Attachable
|
11
|
+
|
12
|
+
def fieldable_scope(user_scope)
|
13
|
+
unallowed_select_fields_error
|
14
|
+
|
15
|
+
return user_scope unless select_any_field?
|
16
|
+
|
17
|
+
scoped = user_scope
|
18
|
+
|
19
|
+
scoped = user_scope.select(model_fields_select) if model_fields_select
|
20
|
+
|
21
|
+
scoped = select_nested_scope(scoped) if valid_nested_fields_select
|
22
|
+
|
23
|
+
insert_attachments(scoped)
|
24
|
+
end
|
25
|
+
|
26
|
+
def select_nested_scope(scoped)
|
27
|
+
scoped.joins(nested_fields_joins)
|
28
|
+
.left_joins(nested_fields_left_joins)
|
29
|
+
.preload(valid_nested_fields_select)
|
30
|
+
.select(nesteds_table)
|
31
|
+
end
|
32
|
+
|
33
|
+
def select_any_field?
|
34
|
+
fields_select || nested_fields_select || attachment_fields_select
|
35
|
+
end
|
36
|
+
|
37
|
+
def nesteds_table
|
38
|
+
valid_nested_fields_select&.map do |field|
|
39
|
+
table = nested_selectable_fields_keys.dig(field, :table_name)
|
40
|
+
table.present? ? "#{table}::text AS #{field}" : nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def model_fields_select
|
45
|
+
@model_fields_select ||= begin
|
46
|
+
fields = fields_select&.split(",")
|
47
|
+
fields = fields&.map { |field| "#{klass.table_name}.#{field}" }&.join(",")
|
48
|
+
fields || model_attributes
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def model_attributes
|
53
|
+
@model_attributes ||= klass.new.attributes.keys
|
54
|
+
end
|
55
|
+
|
56
|
+
def nested_fields_joins
|
57
|
+
@nested_fields_joins ||= valid_nested_fields_select.select do |field|
|
58
|
+
nested_selectable_fields_keys[field.to_sym][:join_type].blank?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def nested_fields_left_joins
|
63
|
+
@nested_fields_left_joins ||= valid_nested_fields_select.select do |field|
|
64
|
+
nested_selectable_fields_keys[field.to_sym][:join_type] == :left_joins
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def valid_nested_fields_select
|
69
|
+
@valid_nested_fields_select ||=
|
70
|
+
nested_fields_select&.split(",")&.select do |field|
|
71
|
+
nested_selectable_fields_keys[field.to_sym].present?
|
72
|
+
end&.map(&:to_sym)
|
73
|
+
end
|
74
|
+
|
75
|
+
def unallowed_select_fields_error
|
76
|
+
return if unallowed_fields_selected.blank?
|
77
|
+
|
78
|
+
restme_scope_errors({ body: unallowed_fields_selected, message: "Selected not allowed fields" })
|
79
|
+
|
80
|
+
restme_scope_status(:bad_request)
|
81
|
+
end
|
82
|
+
|
83
|
+
def unallowed_fields_selected
|
84
|
+
unallowed_nested_fields_select + unallowed_fields_select
|
85
|
+
end
|
86
|
+
|
87
|
+
def unallowed_nested_fields_select
|
88
|
+
return [] if nested_fields_select.blank?
|
89
|
+
|
90
|
+
nested_fields_select.split(",").map(&:to_sym) - valid_nested_fields_select
|
91
|
+
end
|
92
|
+
|
93
|
+
def unallowed_fields_select
|
94
|
+
return [] if fields_select.blank?
|
95
|
+
|
96
|
+
fields_select.split(",").map(&:to_sym) - model_attributes.map(&:to_sym)
|
97
|
+
end
|
98
|
+
|
99
|
+
def fields_select
|
100
|
+
@fields_select ||= controller_query_params[:fields_select]
|
101
|
+
end
|
102
|
+
|
103
|
+
def nested_fields_select
|
104
|
+
@nested_fields_select ||= controller_query_params[:nested_fields_select]
|
105
|
+
end
|
106
|
+
|
107
|
+
def attachment_fields_select
|
108
|
+
@attachment_fields_select ||= controller_query_params[:attachment_fields_select]
|
109
|
+
&.split(",")&.map(&:to_sym)
|
110
|
+
end
|
111
|
+
|
112
|
+
def nested_selectable_fields_keys
|
113
|
+
@nested_selectable_fields_keys ||= field_class_rules::NESTED_SELECTABLE_FIELDS
|
114
|
+
rescue StandardError
|
115
|
+
{}
|
116
|
+
end
|
117
|
+
|
118
|
+
def field_class_rules
|
119
|
+
"#{controller_class.to_s.split("::").last}::Field::Rules".constantize
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "types/equal_filterable"
|
4
|
+
require_relative "types/like_filterable"
|
5
|
+
require_relative "types/bigger_than_filterable"
|
6
|
+
require_relative "types/less_than_filterable"
|
7
|
+
require_relative "types/bigger_than_or_equal_to_filterable"
|
8
|
+
require_relative "types/less_than_or_equal_to_filterable"
|
9
|
+
require_relative "types/in_filterable"
|
10
|
+
|
11
|
+
module Restme
|
12
|
+
module Scope
|
13
|
+
module Filter
|
14
|
+
# Defines filter rules
|
15
|
+
module Rules
|
16
|
+
include ::Scope::Filter::Types::InFilterable
|
17
|
+
include ::Scope::Filter::Types::LessThanOrEqualToFilterable
|
18
|
+
include ::Scope::Filter::Types::BiggerThanOrEqualToFilterable
|
19
|
+
include ::Scope::Filter::Types::LessThanFilterable
|
20
|
+
include ::Scope::Filter::Types::BiggerThanFilterable
|
21
|
+
include ::Scope::Filter::Types::LikeFilterable
|
22
|
+
include ::Scope::Filter::Types::EqualFilterable
|
23
|
+
|
24
|
+
ID = :id
|
25
|
+
|
26
|
+
FILTERS_TYPES = %i[equal like bigger_than less_than
|
27
|
+
bigger_than_or_equal_to less_than_or_equal_to in].freeze
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def filterable_scope(user_scope)
|
32
|
+
return unallowed_filter_fields_response if unallowed_fields_to_filter?
|
33
|
+
return user_scope unless filterable_scope?
|
34
|
+
|
35
|
+
next_scope = where_equal(user_scope)
|
36
|
+
next_scope = where_like(next_scope)
|
37
|
+
next_scope = where_bigger_than(next_scope)
|
38
|
+
next_scope = where_less_than(next_scope)
|
39
|
+
next_scope = where_bigger_than_or_equal_to(next_scope)
|
40
|
+
next_scope = where_less_than_or_equal_to(next_scope)
|
41
|
+
where_in(next_scope)
|
42
|
+
end
|
43
|
+
|
44
|
+
def allowed_fields
|
45
|
+
@allowed_fields ||= controller_params_filters_fields.map do |param_key|
|
46
|
+
filter_type = FILTERS_TYPES.find do |filter_type|
|
47
|
+
param_key.to_s.end_with?(filter_type.to_s)
|
48
|
+
end
|
49
|
+
|
50
|
+
record_field = param_key.to_s.gsub("_#{filter_type}", "")&.to_sym
|
51
|
+
|
52
|
+
next unless filter_type
|
53
|
+
next unless filteable_fields.include?(record_field)
|
54
|
+
|
55
|
+
send(:"add_#{filter_type}_field", record_field)
|
56
|
+
end.compact.flatten
|
57
|
+
end
|
58
|
+
|
59
|
+
def params_filters
|
60
|
+
@params_filters ||= {}
|
61
|
+
end
|
62
|
+
|
63
|
+
def filteable_fields
|
64
|
+
@filteable_fields ||= Array.new(klass::FILTERABLE_FIELDS).push(ID)
|
65
|
+
rescue StandardError
|
66
|
+
[ID]
|
67
|
+
end
|
68
|
+
|
69
|
+
def unallowed_fields_to_filter?
|
70
|
+
try_insert_id_equal
|
71
|
+
|
72
|
+
filterable_scope? && unallowed_fields_to_filter.present?
|
73
|
+
end
|
74
|
+
|
75
|
+
def filterable_scope?
|
76
|
+
request.get? && controller_params_filters_fields.present?
|
77
|
+
end
|
78
|
+
|
79
|
+
def unallowed_fields_to_filter
|
80
|
+
@unallowed_fields_to_filter ||= controller_params_filters_fields - allowed_fields
|
81
|
+
end
|
82
|
+
|
83
|
+
def try_insert_id_equal
|
84
|
+
return if params[:id].blank?
|
85
|
+
|
86
|
+
controller_params_filters_fields.push(:id_equal)
|
87
|
+
end
|
88
|
+
|
89
|
+
def unallowed_filter_fields_response
|
90
|
+
render json: { message: "Unknown Filter Fields", body: unallowed_fields_to_filter },
|
91
|
+
status: :bad_request
|
92
|
+
end
|
93
|
+
|
94
|
+
def controller_params_filters_fields
|
95
|
+
@controller_params_filters_fields ||= controller_query_params.keys.select do |item|
|
96
|
+
FILTERS_TYPES.any? { |filter| item.to_s.end_with?(filter.to_s) }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scope
|
4
|
+
module Filter
|
5
|
+
module Types
|
6
|
+
# Defines the behavior of the "bigger than" filter in queries.
|
7
|
+
module BiggerThanFilterable
|
8
|
+
FIELD_SUFFIX = :bigger_than
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def where_bigger_than(scope)
|
13
|
+
return scope if bigger_than_fields.blank?
|
14
|
+
|
15
|
+
scope.where(bigger_than_sql, bigger_than_fields)
|
16
|
+
end
|
17
|
+
|
18
|
+
def bigger_than_sql
|
19
|
+
bigger_than_fields.keys.map do |param|
|
20
|
+
"#{klass.table_name}.#{param} > :#{param}"
|
21
|
+
end.join(" AND ")
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_bigger_than_field(field)
|
25
|
+
field_key = :"#{field}_#{FIELD_SUFFIX}"
|
26
|
+
field_value = controller_query_params[field_key]
|
27
|
+
bigger_than_fields[field] = field_value if field_value
|
28
|
+
|
29
|
+
field_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def bigger_than_fields
|
33
|
+
params_filters[FIELD_SUFFIX] ||= {}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scope
|
4
|
+
module Filter
|
5
|
+
module Types
|
6
|
+
# Defines the behavior of the "bigger than or equal to" filter in queries.
|
7
|
+
module BiggerThanOrEqualToFilterable
|
8
|
+
FIELD_SUFFIX = :bigger_than_or_equal_to
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def where_bigger_than_or_equal_to(scope)
|
13
|
+
return scope if bigger_than_or_equal_to_fields.blank?
|
14
|
+
|
15
|
+
scope.where(bigger_than_or_equal_to_sql, bigger_than_or_equal_to_fields)
|
16
|
+
end
|
17
|
+
|
18
|
+
def bigger_than_or_equal_to_sql
|
19
|
+
bigger_than_or_equal_to_fields.keys.map do |param|
|
20
|
+
"#{klass.table_name}.#{param} >= :#{param}"
|
21
|
+
end.join(" AND ")
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_bigger_than_or_equal_to_field(field)
|
25
|
+
field_key = :"#{field}_#{FIELD_SUFFIX}"
|
26
|
+
field_value = controller_query_params[field_key]
|
27
|
+
bigger_than_or_equal_to_fields[field] = field_value if field_value
|
28
|
+
|
29
|
+
field_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def bigger_than_or_equal_to_fields
|
33
|
+
params_filters[FIELD_SUFFIX] ||= {}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scope
|
4
|
+
module Filter
|
5
|
+
module Types
|
6
|
+
# Defines the behavior of the "equal" filter in queries.
|
7
|
+
module EqualFilterable
|
8
|
+
FIELD_SUFFIX = :equal
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def where_equal(scope)
|
13
|
+
return scope if equal_fields.blank?
|
14
|
+
|
15
|
+
scope.where(equal_sql, equal_fields)
|
16
|
+
end
|
17
|
+
|
18
|
+
def equal_sql
|
19
|
+
equal_fields.keys.map do |param|
|
20
|
+
"#{klass.table_name}.#{param} = :#{param}"
|
21
|
+
end.join(" AND ")
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_equal_field(field)
|
25
|
+
field_key = :"#{field}_#{FIELD_SUFFIX}"
|
26
|
+
field_value = controller_query_params[field_key] || params[field]
|
27
|
+
equal_fields[field] = field_value if field_value
|
28
|
+
|
29
|
+
field_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def equal_fields
|
33
|
+
params_filters[FIELD_SUFFIX] ||= {}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scope
|
4
|
+
module Filter
|
5
|
+
module Types
|
6
|
+
# Defines the behavior of the "in" filter in queries.
|
7
|
+
module InFilterable
|
8
|
+
FIELD_SUFFIX = :in
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def where_in(scope)
|
13
|
+
return scope if in_fields.blank?
|
14
|
+
|
15
|
+
serialize_in_fields
|
16
|
+
|
17
|
+
scope.where(in_sql, in_fields)
|
18
|
+
end
|
19
|
+
|
20
|
+
def in_sql
|
21
|
+
in_fields.keys.map do |param|
|
22
|
+
"#{klass.table_name}.#{param} IN (:#{param})"
|
23
|
+
end.join(" AND ")
|
24
|
+
end
|
25
|
+
|
26
|
+
def serialize_in_fields
|
27
|
+
in_fields.each do |key, value|
|
28
|
+
in_fields[key] = value.split(",")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_in_field(field)
|
33
|
+
field_key = :"#{field}_#{FIELD_SUFFIX}"
|
34
|
+
field_value = controller_query_params[field_key]
|
35
|
+
in_fields[field] = field_value if field_value
|
36
|
+
|
37
|
+
field_key
|
38
|
+
end
|
39
|
+
|
40
|
+
def in_fields
|
41
|
+
params_filters[FIELD_SUFFIX] ||= {}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scope
|
4
|
+
module Filter
|
5
|
+
module Types
|
6
|
+
# Defines the behavior of the "less than" filter in queries.
|
7
|
+
module LessThanFilterable
|
8
|
+
FIELD_SUFFIX = :less_than
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def where_less_than(scope)
|
13
|
+
return scope if less_than_fields.blank?
|
14
|
+
|
15
|
+
scope.where(less_than_sql, less_than_fields)
|
16
|
+
end
|
17
|
+
|
18
|
+
def less_than_sql
|
19
|
+
less_than_fields.keys.map do |param|
|
20
|
+
"#{klass.table_name}.#{param} < :#{param}"
|
21
|
+
end.join(" AND ")
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_less_than_field(field)
|
25
|
+
field_key = :"#{field}_#{FIELD_SUFFIX}"
|
26
|
+
field_value = controller_query_params[field_key]
|
27
|
+
less_than_fields[field] = field_value if field_value
|
28
|
+
|
29
|
+
field_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def less_than_fields
|
33
|
+
params_filters[FIELD_SUFFIX] ||= {}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scope
|
4
|
+
module Filter
|
5
|
+
module Types
|
6
|
+
# Defines the behavior of the "less than or equal to" filter in queries.
|
7
|
+
module LessThanOrEqualToFilterable
|
8
|
+
FIELD_SUFFIX = :less_than_or_equal_to
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def where_less_than_or_equal_to(scope)
|
13
|
+
return scope if less_than_or_equal_to_fields.blank?
|
14
|
+
|
15
|
+
scope.where(less_than_or_equal_to_sql, less_than_or_equal_to_fields)
|
16
|
+
end
|
17
|
+
|
18
|
+
def less_than_or_equal_to_sql
|
19
|
+
less_than_or_equal_to_fields.keys.map do |param|
|
20
|
+
"#{klass.table_name}.#{param} <= :#{param}"
|
21
|
+
end.join(" AND ")
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_less_than_or_equal_to_field(field)
|
25
|
+
field_key = :"#{field}_#{FIELD_SUFFIX}"
|
26
|
+
field_value = controller_query_params[field_key]
|
27
|
+
less_than_or_equal_to_fields[field] = field_value if field_value
|
28
|
+
|
29
|
+
field_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def less_than_or_equal_to_fields
|
33
|
+
params_filters[FIELD_SUFFIX] ||= {}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scope
|
4
|
+
module Filter
|
5
|
+
module Types
|
6
|
+
# Defines the behavior of "like" filters used for partial matching in queries.
|
7
|
+
module LikeFilterable
|
8
|
+
FIELD_SUFFIX = :like
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def where_like(scope)
|
13
|
+
return scope if like_fields.blank?
|
14
|
+
|
15
|
+
scope.where(like_sql, like_fields)
|
16
|
+
end
|
17
|
+
|
18
|
+
def like_sql
|
19
|
+
like_fields.keys.map do |param|
|
20
|
+
"CAST(#{klass.table_name}.#{param} AS TEXT) ILIKE :#{param}"
|
21
|
+
end.join(" AND ")
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_like_field(field)
|
25
|
+
field_key = :"#{field}_#{FIELD_SUFFIX}"
|
26
|
+
field_value = controller_query_params[field_key].to_s
|
27
|
+
|
28
|
+
field_value = "%#{field_value}%" if field_value.present?
|
29
|
+
like_fields[field] = field_value if field_value.present?
|
30
|
+
|
31
|
+
field_key
|
32
|
+
end
|
33
|
+
|
34
|
+
def like_fields
|
35
|
+
params_filters[FIELD_SUFFIX] ||= {}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|