cancancan-squeel 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/lib/cancancan/squeel/attribute_mapper.rb +79 -12
- data/lib/cancancan/squeel/expression_builder.rb +38 -7
- data/lib/cancancan/squeel/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee0d8f0d270a3449f4c1373eb89857cc047553ea
|
4
|
+
data.tar.gz: ddc057b7c68e47e087dbed2b707005ccf581b6f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0756bbd6699c2eea5eee163425bcc389180028edfcad1b0c839e19bcfea821f0644987083d77069e3235e8db4d103143cb8125d1a5b897a360b669438f89a72d
|
7
|
+
data.tar.gz: 0db5510c60e8cfe778e6e6cd709ae95fd63ba47467c1b4f0a374561d749fc3a2dcd281530ef5f23020ca604dffaccce0968bc9bda86e7a839f8472fb174fb105
|
data/CHANGELOG.md
CHANGED
@@ -11,20 +11,34 @@ module CanCanCan::Squeel::AttributeMapper
|
|
11
11
|
# Picks the appropriate column, comparator, and value to use in the Squeel expression.
|
12
12
|
#
|
13
13
|
# This checks for association references: this will use the appropriate column name.
|
14
|
-
#
|
15
14
|
# Array values are interpreted as alternative choices allowed or disallowed.
|
15
|
+
# Ranges are converted to appropriate comparator pairs.
|
16
|
+
#
|
17
|
+
# The return value is a tuple:
|
18
|
+
#
|
19
|
+
# - The first element is a combinator to be used on the comparisons.
|
20
|
+
# - The second element is an array of comparisons: each comparison is a tuple of
|
21
|
+
# (key, comparator, value)
|
22
|
+
#
|
23
|
+
# The appropriate expression is the combination of all the comparisons, using the combinator
|
24
|
+
# returned.
|
25
|
+
#
|
26
|
+
# @example Attribute Ranges
|
27
|
+
# squeel_comparison_for(User, :id, :==, 1..5) #=> [:&, [[:id, :>=, 1], [:id, :<=, 5]]]
|
28
|
+
# @example Association Objects
|
29
|
+
# squeel_comparison_for(Post, :comment, :==, comment) #=> [:&, [[:comment_id, :==, 1]]]
|
16
30
|
#
|
17
31
|
# @param [Class] model_class The model class which the key references.
|
18
32
|
# @param [Symbol] key The column being compared.
|
19
33
|
# @param [Symbol] comparator The comparator to get the appropriate Squeel comparator for.
|
20
34
|
# @param value The value to be comparing against.
|
21
|
-
# @return [Array<(Symbol, Symbol, Object)>] A
|
22
|
-
#
|
35
|
+
# @return [Array<(Symbol, Array<(Symbol, Symbol, Object)>)>] A tuple containing the combinator for
|
36
|
+
# the comparisons, and a sequence of comparisons.
|
23
37
|
def squeel_comparison_for(model_class, key, comparator, value)
|
24
38
|
key, value = map_association(model_class, key, value)
|
25
39
|
|
26
|
-
|
27
|
-
[
|
40
|
+
combinator, comparisons = squeel_comparator_for(comparator, value)
|
41
|
+
[combinator, comparisons.map { |comp| comp.unshift(key) }]
|
28
42
|
end
|
29
43
|
|
30
44
|
# Picks the table column to compare the value against for the given key.
|
@@ -48,17 +62,70 @@ module CanCanCan::Squeel::AttributeMapper
|
|
48
62
|
#
|
49
63
|
# Array values are interpreted as alternative choices allowed or disallowed.
|
50
64
|
#
|
65
|
+
# Ranges are interpreted as start/end pairs, respecting the exclusion of the end point.
|
66
|
+
#
|
51
67
|
# @param [Symbol] comparator The comparator to get the appropriate Squeel comparator for.
|
52
68
|
# @param value The value to be comparing against.
|
53
|
-
# @return [Symbol]
|
69
|
+
# @return [Array<Array<(Symbol, Object)>>] An array of comparisons, each with the comparator
|
70
|
+
# to use, and the value to compare against.
|
54
71
|
def squeel_comparator_for(comparator, value)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
72
|
+
case value
|
73
|
+
when Array then comparator_for_array(comparator, value)
|
74
|
+
when Range then comparator_for_range(comparator, value)
|
75
|
+
else [:&, [[comparator, value]]]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Maps the given comparator to the IN/NOT IN operator.
|
80
|
+
#
|
81
|
+
# @param [Symbol] comparator The comparator to get the SqueeL comparator for.
|
82
|
+
# @param [Array] value The acceptable/rejected values.
|
83
|
+
# @return [Array<(Symbol, Array<(Symbol, Object)>)>] The combinator, and an array of comparisons,
|
84
|
+
# each with the comparator to use, and the value to compare against.
|
85
|
+
def comparator_for_array(comparator, value)
|
86
|
+
case comparator
|
87
|
+
when :== then [:&, [[:>>, value]]]
|
88
|
+
when :!= then [:&, [[:<<, value]]]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Maps the given comparator to a range comparison.
|
93
|
+
#
|
94
|
+
# @param [Symbol] comparator The comparator to get the Squeel comparator for.
|
95
|
+
# @param [Range] value The acceptable/rejected values.
|
96
|
+
# @return [Array<(Symbol, Array<(Symbol, Object)>)>] The combinator, and an array of comparisons,
|
97
|
+
# each with the comparator to use, and the value to compare against.
|
98
|
+
def comparator_for_range(comparator, value)
|
99
|
+
if value.exclude_end?
|
100
|
+
comparator_for_exclusive_range(comparator, value)
|
60
101
|
else
|
61
|
-
comparator
|
102
|
+
comparator_for_inclusive_range(comparator, value)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Maps the given comparator to a range comparison.
|
107
|
+
#
|
108
|
+
# @param [Symbol] comparator The comparator to get the Squeel comparator for.
|
109
|
+
# @param [Range] value The acceptable/rejected values.
|
110
|
+
# @return [Array<Array<(Symbol, Object)>>] An array of comparisons, each with the comparator
|
111
|
+
# to use, and the value to compare against.
|
112
|
+
def comparator_for_exclusive_range(comparator, value)
|
113
|
+
case comparator
|
114
|
+
when :== then [:&, [[:>=, value.first], [:<, value.last]]]
|
115
|
+
when :!= then [:|, [[:<, value.first], [:>=, value.last]]]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Maps the given comparator to a range comparison.
|
120
|
+
#
|
121
|
+
# @param [Symbol] comparator The comparator to get the Squeel comparator for.
|
122
|
+
# @param [Range] value The acceptable/rejected values.
|
123
|
+
# @return [Array<Array<(Symbol, Object)>>] An array of comparisons, each with the comparator
|
124
|
+
# to use, and the value to compare against.
|
125
|
+
def comparator_for_inclusive_range(comparator, value)
|
126
|
+
case comparator
|
127
|
+
when :== then [:&, [[:>=, value.first], [:<=, value.last]]]
|
128
|
+
when :!= then [:|, [[:<, value.first], [:>, value.last]]]
|
62
129
|
end
|
63
130
|
end
|
64
131
|
end
|
@@ -51,14 +51,45 @@ module CanCanCan::Squeel::ExpressionBuilder
|
|
51
51
|
# @param value The value to compare the column against.
|
52
52
|
def build_comparison_node(node, model_class, key, comparator, value)
|
53
53
|
if value.is_a?(Hash)
|
54
|
-
|
55
|
-
expression, joins = build_expression_node(node.__send__(key), reflection_class, comparator,
|
56
|
-
value)
|
57
|
-
[expression, joins.map { |join| join.unshift(key) }.unshift([key])]
|
54
|
+
build_association_comparison_node(node, model_class, key, comparator, value)
|
58
55
|
else
|
59
|
-
key, comparator, value
|
60
|
-
squeel_comparison_for(model_class, key, comparator, value)
|
61
|
-
[node.__send__(key).public_send(comparator, value), []]
|
56
|
+
build_scalar_comparison_node(node, model_class, key, comparator, value)
|
62
57
|
end
|
63
58
|
end
|
59
|
+
|
60
|
+
# Builds a comparison node for the given association and association attributes.
|
61
|
+
#
|
62
|
+
# @param node The node context to build the comparison.
|
63
|
+
# @param [Class] model_class The model class which the conditions reference.
|
64
|
+
# @param [Symbol] key The association to compare against.
|
65
|
+
# @param [Symbol] comparator The comparator to compare the column against the value.
|
66
|
+
# @param [Hash] value The attributes to compare the column against.
|
67
|
+
def build_association_comparison_node(node, model_class, key, comparator, value)
|
68
|
+
reflection_class = model_class.reflect_on_association(key).klass
|
69
|
+
expression, joins = build_expression_node(node.__send__(key), reflection_class, comparator,
|
70
|
+
value)
|
71
|
+
[expression, joins.map { |join| join.unshift(key) }.unshift([key])]
|
72
|
+
end
|
73
|
+
|
74
|
+
# Builds a comparison node for the given attribute and value.
|
75
|
+
#
|
76
|
+
# @param node The node context to build the comparison.
|
77
|
+
# @param [Class] model_class The model class which the conditions reference.
|
78
|
+
# @param [Symbol] key The column to compare against.
|
79
|
+
# @param [Symbol] comparator The comparator to compare the column against the value.
|
80
|
+
# @param value The value to compare the column against.
|
81
|
+
def build_scalar_comparison_node(node, model_class, key, comparator, value)
|
82
|
+
combinator, comparisons = CanCanCan::Squeel::AttributeMapper.
|
83
|
+
squeel_comparison_for(model_class, key, comparator, value)
|
84
|
+
attribute = node.__send__(comparisons.first.first)
|
85
|
+
|
86
|
+
expression = comparisons.reduce(nil) do |left_expression, (_, comparator, value)|
|
87
|
+
right_expression = attribute.dup.public_send(comparator, value)
|
88
|
+
next right_expression unless left_expression
|
89
|
+
|
90
|
+
left_expression.public_send(combinator, right_expression)
|
91
|
+
end
|
92
|
+
|
93
|
+
[expression, []]
|
94
|
+
end
|
64
95
|
end
|