super 0.0.14 → 0.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/app/assets/javascripts/super/application.js +148 -15
- data/app/assets/stylesheets/super/application.css +15 -22
- data/app/controllers/super/application_controller.rb +44 -42
- data/app/controllers/super/substructure_controller.rb +313 -0
- data/app/helpers/super/form_builder_helper.rb +7 -0
- data/app/views/layouts/super/application.html.erb +3 -21
- data/app/views/super/application/_collection_header.html.erb +2 -2
- data/app/views/super/application/_display_actions.html.erb +1 -1
- data/app/views/super/application/_display_index.html.erb +2 -2
- data/app/views/super/application/_display_show.html.erb +1 -1
- data/app/views/super/application/_filter.html.erb +62 -2
- data/app/views/super/application/_form_field.html.erb +5 -0
- data/app/views/super/application/_member_header.html.erb +2 -2
- data/app/views/super/application/_pagination.html.erb +1 -1
- data/app/views/super/application/_site_footer.html.erb +3 -0
- data/app/views/super/application/_site_header.html.erb +17 -0
- data/app/views/super/application/_sort_expression.html.erb +2 -2
- data/app/views/super/application/index.csv.erb +14 -0
- data/app/views/super/feather/README.md +0 -1
- data/frontend/super-frontend/dist/application.css +15 -22
- data/frontend/super-frontend/dist/application.js +148 -15
- data/lib/generators/super/install/install_generator.rb +0 -16
- data/lib/generators/super/install/templates/base_controller.rb.tt +0 -8
- data/lib/generators/super/resource/templates/resources_controller.rb.tt +4 -4
- data/lib/super/action_inquirer.rb +18 -3
- data/lib/super/badge.rb +60 -0
- data/lib/super/cheat.rb +6 -6
- data/lib/super/display/guesser.rb +1 -1
- data/lib/super/display/schema_types.rb +49 -1
- data/lib/super/display.rb +2 -1
- data/lib/super/error.rb +3 -0
- data/lib/super/filter/form_object.rb +74 -48
- data/lib/super/filter/guesser.rb +2 -0
- data/lib/super/filter/operator.rb +90 -64
- data/lib/super/filter/schema_types.rb +63 -80
- data/lib/super/filter.rb +1 -1
- data/lib/super/form/builder.rb +30 -39
- data/lib/super/form/field_transcript.rb +43 -0
- data/lib/super/form/guesser.rb +4 -4
- data/lib/super/form/schema_types.rb +66 -22
- data/lib/super/link.rb +2 -2
- data/lib/super/pagination.rb +2 -44
- data/lib/super/reset.rb +25 -0
- data/lib/super/schema.rb +4 -0
- data/lib/super/useful/builder.rb +4 -4
- data/lib/super/version.rb +1 -1
- data/lib/super.rb +3 -1
- data/lib/tasks/super/cheat.rake +1 -1
- metadata +25 -19
- data/app/views/super/application/_filter_type_select.html.erb +0 -21
- data/app/views/super/application/_filter_type_text.html.erb +0 -18
- data/app/views/super/application/_filter_type_timestamp.html.erb +0 -24
- data/app/views/super/application/_form_field_checkbox.html.erb +0 -1
- data/app/views/super/application/_form_field_flatpickr_date.html.erb +0 -8
- data/app/views/super/application/_form_field_flatpickr_datetime.html.erb +0 -8
- data/app/views/super/application/_form_field_flatpickr_time.html.erb +0 -8
- data/app/views/super/application/_form_field_rich_text_area.html.erb +0 -1
- data/app/views/super/application/_form_field_select.html.erb +0 -1
- data/app/views/super/application/_form_field_text.html.erb +0 -1
- data/app/views/super/feather/_chevron_down.html +0 -1
- data/docs/cheat.md +0 -41
- data/lib/super/controls/optional.rb +0 -113
- data/lib/super/controls/steps.rb +0 -106
- data/lib/super/controls/view.rb +0 -55
- data/lib/super/controls.rb +0 -22
@@ -19,12 +19,27 @@ module Super
|
|
19
19
|
#
|
20
20
|
def self.default_for_resources
|
21
21
|
{
|
22
|
-
read
|
23
|
-
write
|
24
|
-
delete
|
22
|
+
"read" => %w[index show new edit],
|
23
|
+
"write" => %w[create update destroy],
|
24
|
+
"delete" => %w[destroy],
|
25
25
|
}
|
26
26
|
end
|
27
27
|
|
28
|
+
# @return [ActionInquirer]
|
29
|
+
def self.index!; new(default_for_resources, "index"); end
|
30
|
+
# @return [ActionInquirer]
|
31
|
+
def self.show!; new(default_for_resources, "show"); end
|
32
|
+
# @return [ActionInquirer]
|
33
|
+
def self.new!; new(default_for_resources, "new"); end
|
34
|
+
# @return [ActionInquirer]
|
35
|
+
def self.edit!; new(default_for_resources, "edit"); end
|
36
|
+
# @return [ActionInquirer]
|
37
|
+
def self.create!; new(default_for_resources, "create"); end
|
38
|
+
# @return [ActionInquirer]
|
39
|
+
def self.update!; new(default_for_resources, "update"); end
|
40
|
+
# @return [ActionInquirer]
|
41
|
+
def self.destroy!; new(default_for_resources, "destroy"); end
|
42
|
+
|
28
43
|
def initialize(categories_and_their_actions, action)
|
29
44
|
@categories = categories_and_their_actions.keys.map(&:to_s)
|
30
45
|
@actions = categories_and_their_actions.values.flatten.uniq.map(&:to_s)
|
data/lib/super/badge.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Super
|
4
|
+
class Badge
|
5
|
+
STYLES = {
|
6
|
+
light: "bg-gray-100 text-black",
|
7
|
+
dark: "bg-gray-900 text-white",
|
8
|
+
red: "bg-red-700 text-white",
|
9
|
+
yellow: "bg-yellow-400 text-black",
|
10
|
+
green: "bg-green-700 text-white",
|
11
|
+
blue: "bg-blue-700 text-white",
|
12
|
+
purple: "bg-purple-800 text-white",
|
13
|
+
}
|
14
|
+
|
15
|
+
def initialize(text, styles: nil)
|
16
|
+
@text = text
|
17
|
+
@requested_styles = Array(styles.presence).flatten
|
18
|
+
end
|
19
|
+
|
20
|
+
def styles
|
21
|
+
return @styles if instance_variable_defined?(:@styles)
|
22
|
+
@styles =
|
23
|
+
if requested_styles.delete(:reset)
|
24
|
+
[]
|
25
|
+
else
|
26
|
+
COMMON_STYLES
|
27
|
+
end
|
28
|
+
|
29
|
+
if requested_styles.empty?
|
30
|
+
@styles += [STYLES[:light]]
|
31
|
+
else
|
32
|
+
requested_styles.each do |style|
|
33
|
+
@styles +=
|
34
|
+
if STYLES.key?(style)
|
35
|
+
[STYLES[style]]
|
36
|
+
else
|
37
|
+
[style]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
@styles
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
ActionController::Base.helpers.content_tag(
|
47
|
+
:span,
|
48
|
+
@text,
|
49
|
+
class: styles.join(" ")
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
COMMON_STYLES = %w[rounded px-2 py-1 text-xs leading-none font-bold]
|
56
|
+
private_constant :COMMON_STYLES
|
57
|
+
|
58
|
+
attr_reader :requested_styles
|
59
|
+
end
|
60
|
+
end
|
data/lib/super/cheat.rb
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
module Super
|
4
4
|
class Cheat
|
5
|
-
def
|
6
|
-
paths = %w[
|
5
|
+
def controller
|
6
|
+
paths = %w[../../app/controllers/super/substructure_controller.rb]
|
7
7
|
methods =
|
8
8
|
paths
|
9
|
-
.map { |f| File.read(File.
|
10
|
-
.flat_map { |content| content.scan(/^\s+def .*$/) }
|
11
|
-
.map { |method| method.strip.sub(/^def /, "#") }
|
9
|
+
.map { |f| File.read(File.expand_path(f, __dir__)) }
|
10
|
+
.flat_map { |content| content.scan(/^\s+(?:helper_method )?def .*$/) }
|
11
|
+
.map { |method| method.strip.sub(/^(?:helper_method )?def /, "#") }
|
12
12
|
|
13
|
-
puts "== Super::
|
13
|
+
puts "== Super::ApplicationController"
|
14
14
|
puts methods.join("\n")
|
15
15
|
end
|
16
16
|
end
|
@@ -61,6 +61,47 @@ module Super
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
+
class Badge
|
65
|
+
extend Useful::Builder
|
66
|
+
|
67
|
+
def initialize(builder)
|
68
|
+
@builder = builder
|
69
|
+
@whens = {}
|
70
|
+
format_for_lookup(&:itself)
|
71
|
+
format_for_display(&:itself)
|
72
|
+
end
|
73
|
+
|
74
|
+
builder_with_block def when(*patterns, &block)
|
75
|
+
patterns.each do |pattern|
|
76
|
+
@whens[pattern] = block
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
builder_with_block def else(&block)
|
81
|
+
@else = block
|
82
|
+
end
|
83
|
+
|
84
|
+
builder_with_block def format_for_lookup(&block)
|
85
|
+
@format_for_lookup = block
|
86
|
+
end
|
87
|
+
|
88
|
+
builder_with_block def format_for_display(&block)
|
89
|
+
@format_for_display = block
|
90
|
+
end
|
91
|
+
|
92
|
+
def build
|
93
|
+
@builder.transform do |value|
|
94
|
+
lookup_value = @format_for_lookup.call(value)
|
95
|
+
block = @whens[lookup_value] || @else
|
96
|
+
Super::Badge.new(
|
97
|
+
@format_for_display.call(value),
|
98
|
+
styles: block&.call
|
99
|
+
)
|
100
|
+
end
|
101
|
+
@builder.build
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
64
105
|
def initialize(fields:)
|
65
106
|
@actions_called = false
|
66
107
|
@fields = fields
|
@@ -89,7 +130,6 @@ module Super
|
|
89
130
|
end
|
90
131
|
|
91
132
|
def string; real(&:to_s); end
|
92
|
-
alias text string
|
93
133
|
|
94
134
|
def timestamp; real(&:to_s); end
|
95
135
|
def time; real { |value| value.strftime("%H:%M:%S") }; end
|
@@ -100,6 +140,14 @@ module Super
|
|
100
140
|
end
|
101
141
|
end
|
102
142
|
|
143
|
+
def badge(*builder_methods)
|
144
|
+
builder_methods = %i[real ignore_nil column] if builder_methods.empty?
|
145
|
+
builder = builder_methods.each_with_object(Builder.new) do |builder_method, builder|
|
146
|
+
builder.public_send(builder_method)
|
147
|
+
end
|
148
|
+
Badge.new(builder)
|
149
|
+
end
|
150
|
+
|
103
151
|
def actions
|
104
152
|
@actions_called = true
|
105
153
|
Builder.new.computed.none.transform do
|
data/lib/super/display.rb
CHANGED
@@ -32,10 +32,11 @@ module Super
|
|
32
32
|
yield(@fields, @schema_types)
|
33
33
|
end
|
34
34
|
|
35
|
-
def apply(action:)
|
35
|
+
def apply(action:, format:)
|
36
36
|
@action_inquirer = action
|
37
37
|
return self if !@action_inquirer.index?
|
38
38
|
return self if @schema_types.actions_called?
|
39
|
+
return self if !format.html?
|
39
40
|
@fields[:actions] = @schema_types.actions
|
40
41
|
self
|
41
42
|
end
|
data/lib/super/error.rb
CHANGED
@@ -28,6 +28,9 @@ module Super
|
|
28
28
|
# a more specific error
|
29
29
|
class Initalization < Error; end
|
30
30
|
class ArgumentError < Error; end
|
31
|
+
class AlreadyRegistered < Error; end
|
32
|
+
class AlreadyTranscribed < Error; end
|
33
|
+
class NotImplementedError < Error; end
|
31
34
|
|
32
35
|
class Enum < Error
|
33
36
|
class ImpossibleValue < Enum; end
|
@@ -3,58 +3,95 @@
|
|
3
3
|
module Super
|
4
4
|
class Filter
|
5
5
|
class FormObject
|
6
|
-
class
|
7
|
-
def initialize(
|
8
|
-
@
|
6
|
+
class AttributeForm
|
7
|
+
def initialize(model:, field_name:, operators:, params:)
|
8
|
+
@model = model
|
9
9
|
@field_name = field_name
|
10
|
-
@
|
11
|
-
@params = params
|
10
|
+
@operators = operators
|
11
|
+
@params = params || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :model
|
15
|
+
attr_reader :field_name
|
16
|
+
attr_reader :operators
|
17
|
+
attr_reader :params
|
18
|
+
|
19
|
+
def each_operator
|
20
|
+
return enum_for(:each_operator) if !block_given?
|
21
|
+
|
22
|
+
@operators.each do |operator|
|
23
|
+
operator_form = OperatorForm.new(
|
24
|
+
operator: operator,
|
25
|
+
params: @params[operator.identifier]
|
26
|
+
)
|
27
|
+
|
28
|
+
yield(operator_form)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def humanized_attribute_name
|
33
|
+
@model.human_attribute_name(@field_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class OperatorForm
|
38
|
+
NULLARY = :_apply
|
39
|
+
|
40
|
+
def initialize(operator:, params:)
|
41
|
+
@operator = operator
|
42
|
+
@params = params || {}
|
43
|
+
query_parameter_keys = operator.query_parameter_keys
|
44
|
+
query_parameter_keys = [NULLARY] if query_parameter_keys.empty?
|
12
45
|
@specified_values =
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
query_field_name,
|
17
|
-
(params || {})[query_field_name],
|
18
|
-
]
|
19
|
-
end
|
20
|
-
.to_h
|
46
|
+
query_parameter_keys
|
47
|
+
.map { |key| [key, @params[key].presence&.strip] }
|
48
|
+
.to_h
|
21
49
|
|
22
50
|
@specified_values.each do |key, value|
|
23
51
|
define_singleton_method(key) { value }
|
24
52
|
end
|
25
53
|
end
|
26
54
|
|
27
|
-
|
28
|
-
|
29
|
-
|
55
|
+
def specified?
|
56
|
+
@specified_values.any? { |_key, value| value }
|
57
|
+
end
|
58
|
+
|
59
|
+
attr_reader :operator
|
30
60
|
attr_reader :specified_values
|
31
61
|
|
32
|
-
def
|
33
|
-
|
62
|
+
def identifier
|
63
|
+
@operator.identifier
|
34
64
|
end
|
35
65
|
|
36
|
-
def
|
37
|
-
|
38
|
-
.map { |o| [o.name, o.identifier] }
|
39
|
-
.to_h
|
40
|
-
end
|
66
|
+
def each_field
|
67
|
+
return enum_for(:each_field) if !block_given?
|
41
68
|
|
42
|
-
|
43
|
-
|
69
|
+
@specified_values.each do |key, _value|
|
70
|
+
yield(key)
|
71
|
+
end
|
44
72
|
end
|
45
73
|
end
|
46
74
|
|
47
75
|
def initialize(model:, params:, schema:)
|
48
76
|
@model = model
|
49
|
-
@params = params
|
77
|
+
@params = params || {}
|
50
78
|
@schema = schema
|
51
79
|
|
52
80
|
@form_fields = {}
|
53
81
|
end
|
54
82
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
83
|
+
def each_attribute
|
84
|
+
return enum_for(:each_attribute) if !block_given?
|
85
|
+
|
86
|
+
@schema.fields.each do |field_name, field_operators|
|
87
|
+
attribute_form = AttributeForm.new(
|
88
|
+
model: @model,
|
89
|
+
field_name: field_name,
|
90
|
+
operators: field_operators,
|
91
|
+
params: @params[field_name]
|
92
|
+
)
|
93
|
+
|
94
|
+
yield(attribute_form)
|
58
95
|
end
|
59
96
|
end
|
60
97
|
|
@@ -63,32 +100,21 @@ module Super
|
|
63
100
|
end
|
64
101
|
|
65
102
|
def apply_changes(relation)
|
66
|
-
|
67
|
-
|
68
|
-
|
103
|
+
each_attribute do |attribute_form|
|
104
|
+
attribute_form.each_operator do |operator_form|
|
105
|
+
next if operator_form.specified_values.values.map(&:to_s).map(&:presence).none?
|
69
106
|
|
70
|
-
|
71
|
-
|
107
|
+
operator_behavior = operator_form.operator.behavior
|
108
|
+
updated_relation = operator_behavior.call(relation, attribute_form.field_name, **operator_form.specified_values)
|
72
109
|
|
73
|
-
|
74
|
-
|
110
|
+
if updated_relation.is_a?(ActiveRecord::Relation)
|
111
|
+
relation = updated_relation
|
112
|
+
end
|
75
113
|
end
|
76
114
|
end
|
77
115
|
|
78
116
|
relation
|
79
117
|
end
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
def form_field_for(field_name)
|
84
|
-
@form_fields[field_name] ||=
|
85
|
-
FilterFormField.new(
|
86
|
-
humanized_field_name: @model.human_attribute_name(field_name),
|
87
|
-
field_name: field_name,
|
88
|
-
type: @schema.fields[field_name],
|
89
|
-
params: (@params || {})[field_name]
|
90
|
-
)
|
91
|
-
end
|
92
118
|
end
|
93
119
|
end
|
94
120
|
end
|
data/lib/super/filter/guesser.rb
CHANGED
@@ -2,100 +2,126 @@
|
|
2
2
|
|
3
3
|
module Super
|
4
4
|
class Filter
|
5
|
-
|
6
|
-
class Definition
|
7
|
-
def initialize(identifier, name, filter)
|
8
|
-
@identifier = identifier
|
9
|
-
@name = name
|
10
|
-
@filter = filter
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_reader :identifier
|
14
|
-
attr_reader :name
|
15
|
-
|
16
|
-
def filter(*args)
|
17
|
-
@filter.call(args)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
5
|
+
class Operator
|
21
6
|
class << self
|
22
7
|
def registry
|
23
8
|
@registry ||= {}
|
24
9
|
end
|
25
10
|
|
26
|
-
def
|
27
|
-
|
28
|
-
registry["between"],
|
29
|
-
]
|
11
|
+
def [](key)
|
12
|
+
registry.fetch(key.to_s)
|
30
13
|
end
|
31
14
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
15
|
+
def register(identifier, operator)
|
16
|
+
identifier = identifier.to_s
|
17
|
+
if registry.key?(identifier)
|
18
|
+
raise Error::AlreadyRegistered, "Already registered: #{identifier}"
|
19
|
+
end
|
20
|
+
|
21
|
+
registry[identifier] = operator
|
37
22
|
end
|
38
23
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
registry["contain"],
|
44
|
-
registry["ncontain"],
|
45
|
-
registry["start"],
|
46
|
-
registry["end"],
|
47
|
-
]
|
24
|
+
def define(identifier, display, &block)
|
25
|
+
operator = new(identifier, display, &block).freeze
|
26
|
+
register(identifier, operator)
|
27
|
+
operator
|
48
28
|
end
|
29
|
+
end
|
49
30
|
|
50
|
-
|
51
|
-
|
52
|
-
|
31
|
+
def initialize(identifier, display, &behavior)
|
32
|
+
@identifier = identifier.to_s
|
33
|
+
@humanized_operator_name = display
|
34
|
+
self.behavior = behavior
|
35
|
+
end
|
36
|
+
|
37
|
+
def behavior=(behavior)
|
38
|
+
behavior_params = behavior.parameters
|
39
|
+
if behavior_params.size < 2
|
40
|
+
raise Error::ArgumentError, "Operator behavior must include `column_name` and `relation`"
|
41
|
+
end
|
42
|
+
if behavior_params[0][0] != :req && behavior_params[0][0] != :opt
|
43
|
+
raise Error::ArgumentError, "First argument `relation` must be a required, positional argument"
|
44
|
+
end
|
45
|
+
if behavior_params[1][0] != :req && behavior_params[1][0] != :opt
|
46
|
+
raise Error::ArgumentError, "Second argument `column_name` must be a required, positional argument"
|
47
|
+
end
|
48
|
+
if !behavior_params[2..-1].all? { |(type, _name)| type == :keyreq }
|
49
|
+
raise Error::ArgumentError, "All query parameter keys must be required, keyword arguments"
|
50
|
+
end
|
51
|
+
@behavior = behavior
|
52
|
+
@query_parameter_keys = behavior_params[2..-1].map(&:last)
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
+
attr_reader :identifier
|
56
|
+
attr_reader :query_parameter_keys
|
57
|
+
attr_reader :humanized_operator_name
|
55
58
|
|
56
|
-
|
59
|
+
def behavior(&block)
|
60
|
+
self.behavior = block if block_given?
|
61
|
+
@behavior
|
62
|
+
end
|
57
63
|
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
64
|
+
define("eq", "Equals") do |relation, field, q:|
|
65
|
+
relation.where(field => q)
|
62
66
|
end
|
63
67
|
|
64
|
-
define("
|
65
|
-
relation.where(field =>
|
68
|
+
define("neq", "Doesn't equal") do |relation, field, q:|
|
69
|
+
relation.where.not(field => q)
|
66
70
|
end
|
67
71
|
|
68
|
-
define("
|
69
|
-
relation.where
|
72
|
+
define("null", "Is NULL") do |relation, field|
|
73
|
+
relation.where(field => nil)
|
70
74
|
end
|
71
75
|
|
72
|
-
define("
|
73
|
-
|
74
|
-
relation.where("#{field} LIKE ?", "%#{query}%")
|
76
|
+
define("nnull", "Isn't NULL") do |relation, field|
|
77
|
+
relation.where.not(field => nil)
|
75
78
|
end
|
76
79
|
|
77
|
-
define("
|
78
|
-
|
79
|
-
|
80
|
+
define("true", "Is true") do |relation, field|
|
81
|
+
relation.where(field => true)
|
82
|
+
end
|
83
|
+
|
84
|
+
define("false", "Is false") do |relation, field|
|
85
|
+
relation.where(field => false)
|
86
|
+
end
|
87
|
+
|
88
|
+
define("empty", "Is empty") do |relation, field|
|
89
|
+
relation.where(field => "")
|
80
90
|
end
|
81
91
|
|
82
|
-
define("
|
83
|
-
|
84
|
-
relation.where("#{field} LIKE ?", query)
|
92
|
+
define("nempty", "Isn't empty") do |relation, field|
|
93
|
+
relation.where.not(field => "")
|
85
94
|
end
|
86
95
|
|
87
|
-
define("
|
88
|
-
|
89
|
-
|
96
|
+
define("blank", "Is blank") do |relation, field|
|
97
|
+
relation.where(field => [nil, ""])
|
98
|
+
end
|
99
|
+
|
100
|
+
define("nblank", "Isn't blank") do |relation, field|
|
101
|
+
relation.where.not(field => [nil, ""])
|
102
|
+
end
|
103
|
+
|
104
|
+
define("contain", "Contains") do |relation, field, q:|
|
105
|
+
query = "%#{Compatability.sanitize_sql_like(q)}%"
|
106
|
+
if relation.connection.adapter_name == "PostgreSQL"
|
107
|
+
relation.where("#{field} ILIKE ?", query)
|
108
|
+
else
|
109
|
+
relation.where("#{field} LIKE ?", query)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
define("ncontain", "Doesn't contain") do |relation, field, q:|
|
114
|
+
query = "%#{Compatability.sanitize_sql_like(q)}%"
|
115
|
+
relation.where("#{field} NOT LIKE ?", query)
|
90
116
|
end
|
91
117
|
|
92
|
-
define("between", "
|
93
|
-
if
|
94
|
-
relation = relation.where("#{field} >= ?",
|
118
|
+
define("between", "Between") do |relation, field, q0:, q1:|
|
119
|
+
if q0.present?
|
120
|
+
relation = relation.where("#{field} >= ?", q0)
|
95
121
|
end
|
96
122
|
|
97
|
-
if
|
98
|
-
relation = relation.where("#{field} <= ?",
|
123
|
+
if q1.present?
|
124
|
+
relation = relation.where("#{field} <= ?", q1)
|
99
125
|
end
|
100
126
|
|
101
127
|
relation
|