squeel 0.8.4 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +8 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/lib/squeel/adapters/active_record/3.0/join_dependency.rb +0 -4
- data/lib/squeel/adapters/active_record/3.0/relation.rb +2 -2
- data/lib/squeel/adapters/active_record/join_dependency.rb +0 -4
- data/lib/squeel/adapters/active_record/relation.rb +5 -5
- data/lib/squeel/dsl.rb +9 -1
- data/lib/squeel/nodes.rb +1 -0
- data/lib/squeel/nodes/literal.rb +70 -0
- data/lib/squeel/version.rb +1 -1
- data/lib/squeel/visitors/attribute_visitor.rb +21 -12
- data/lib/squeel/visitors/base.rb +8 -9
- data/lib/squeel/visitors/predicate_visitor.rb +72 -41
- data/lib/squeel/visitors/symbol_visitor.rb +2 -2
- data/spec/squeel/adapters/active_record/join_association_spec.rb +2 -0
- data/spec/squeel/adapters/active_record/join_dependency_spec.rb +2 -0
- data/spec/squeel/adapters/active_record/relation_spec.rb +11 -8
- data/spec/squeel/dsl_spec.rb +8 -0
- data/spec/squeel/nodes/function_spec.rb +2 -0
- data/spec/squeel/nodes/key_path_spec.rb +2 -0
- data/spec/squeel/nodes/literal_spec.rb +155 -0
- data/spec/squeel/nodes/operation_spec.rb +2 -0
- data/spec/squeel/visitors/attribute_visitor_spec.rb +2 -0
- data/spec/squeel/visitors/predicate_visitor_spec.rb +30 -0
- data/squeel.gemspec +1 -1
- metadata +117 -74
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Squeel
|
1
|
+
# Squeel [![Build Status](http://travis-ci.org/ernie/squeel.png)](http://travis-ci.org/ernie/squeel)
|
2
2
|
|
3
3
|
Squeel lets you write your ActiveRecord queries with with fewer strings, and more Ruby,
|
4
4
|
by making the ARel awesomeness that lies beneath ActiveRecord more accessible.
|
@@ -5,10 +5,6 @@ module Squeel
|
|
5
5
|
module ActiveRecord
|
6
6
|
module JoinDependency
|
7
7
|
|
8
|
-
# Yes, I'm using alias_method_chain here. No, I don't feel too
|
9
|
-
# bad about it. JoinDependency, or, to call it by its full proper
|
10
|
-
# name, ::ActiveRecord::Associations::JoinDependency, is one of the
|
11
|
-
# most "for internal use only" chunks of ActiveRecord.
|
12
8
|
def self.included(base)
|
13
9
|
base.class_eval do
|
14
10
|
alias_method_chain :build, :squeel
|
@@ -62,8 +62,8 @@ module Squeel
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def prepare_relation_for_association_merge!(r, association_name)
|
65
|
-
r.where_values.map! {|w| Squeel::Visitors::PredicateVisitor.
|
66
|
-
r.having_values.map! {|h| Squeel::Visitors::PredicateVisitor.
|
65
|
+
r.where_values.map! {|w| Squeel::Visitors::PredicateVisitor.can_visit?(w) ? {association_name => w} : w}
|
66
|
+
r.having_values.map! {|h| Squeel::Visitors::PredicateVisitor.can_visit?(h) ? {association_name => h} : h}
|
67
67
|
r.joins_values.map! {|j| [Symbol, Hash, Nodes::Stub, Nodes::Join].include?(j.class) ? {association_name => j} : j}
|
68
68
|
end
|
69
69
|
|
@@ -5,10 +5,6 @@ module Squeel
|
|
5
5
|
module ActiveRecord
|
6
6
|
module JoinDependency
|
7
7
|
|
8
|
-
# Yes, I'm using alias_method_chain here. No, I don't feel too
|
9
|
-
# bad about it. JoinDependency, or, to call it by its full proper
|
10
|
-
# name, ::ActiveRecord::Associations::JoinDependency, is one of the
|
11
|
-
# most "for internal use only" chunks of ActiveRecord.
|
12
8
|
def self.included(base)
|
13
9
|
base.class_eval do
|
14
10
|
alias_method_chain :build, :squeel
|
@@ -61,11 +61,11 @@ module Squeel
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def prepare_relation_for_association_merge!(r, association_name)
|
64
|
-
r.where_values.map! {|w| Squeel::Visitors::PredicateVisitor.
|
65
|
-
r.having_values.map! {|h| Squeel::Visitors::PredicateVisitor.
|
66
|
-
r.group_values.map! {|g| Squeel::Visitors::AttributeVisitor.
|
67
|
-
r.order_values.map! {|o| Squeel::Visitors::AttributeVisitor.
|
68
|
-
r.select_values.map! {|s| Squeel::Visitors::AttributeVisitor.
|
64
|
+
r.where_values.map! {|w| Squeel::Visitors::PredicateVisitor.can_visit?(w) ? {association_name => w} : w}
|
65
|
+
r.having_values.map! {|h| Squeel::Visitors::PredicateVisitor.can_visit?(h) ? {association_name => h} : h}
|
66
|
+
r.group_values.map! {|g| Squeel::Visitors::AttributeVisitor.can_visit?(g) ? {association_name => g} : g}
|
67
|
+
r.order_values.map! {|o| Squeel::Visitors::AttributeVisitor.can_visit?(o) ? {association_name => o} : o}
|
68
|
+
r.select_values.map! {|s| Squeel::Visitors::AttributeVisitor.can_visit?(s) ? {association_name => s} : s}
|
69
69
|
r.joins_values.map! {|j| [Symbol, Hash, Nodes::Stub, Nodes::Join, Nodes::KeyPath].include?(j.class) ? {association_name => j} : j}
|
70
70
|
r.includes_values.map! {|i| [Symbol, Hash, Nodes::Stub, Nodes::Join, Nodes::KeyPath].include?(i.class) ? {association_name => i} : i}
|
71
71
|
end
|
data/lib/squeel/dsl.rb
CHANGED
@@ -50,11 +50,19 @@ module Squeel
|
|
50
50
|
# programmer hell.
|
51
51
|
#
|
52
52
|
# @param &block A block to instance_eval against the DSL's caller.
|
53
|
-
# @return
|
53
|
+
# @return The results of evaluating the block in the instance of the DSL's caller.
|
54
54
|
def my(&block)
|
55
55
|
@caller.instance_eval &block
|
56
56
|
end
|
57
57
|
|
58
|
+
# Shorthand for creating ARel SqlLiteral nodes.
|
59
|
+
#
|
60
|
+
# @param [String] string The string to convert to an SQL literal.
|
61
|
+
# @return [Arel::Nodes::SqlLiteral] The SQL literal.
|
62
|
+
def `(string)
|
63
|
+
Nodes::Literal.new(string)
|
64
|
+
end
|
65
|
+
|
58
66
|
# Node generation inside DSL blocks.
|
59
67
|
#
|
60
68
|
# @overload node_name
|
data/lib/squeel/nodes.rb
CHANGED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'squeel/predicate_methods'
|
2
|
+
require 'squeel/nodes/operators'
|
3
|
+
require 'squeel/nodes/aliasing'
|
4
|
+
|
5
|
+
module Squeel
|
6
|
+
module Nodes
|
7
|
+
# Literal nodes are a container for raw SQL.
|
8
|
+
class Literal
|
9
|
+
include PredicateMethods
|
10
|
+
include Operators
|
11
|
+
include Aliasing
|
12
|
+
|
13
|
+
attr_reader :expr
|
14
|
+
|
15
|
+
def initialize(expr)
|
16
|
+
@expr = expr
|
17
|
+
end
|
18
|
+
|
19
|
+
alias :== :eq
|
20
|
+
alias :'^' :not_eq
|
21
|
+
alias :'!=' :not_eq if respond_to?(:'!=')
|
22
|
+
alias :>> :in
|
23
|
+
alias :<< :not_in
|
24
|
+
alias :=~ :matches
|
25
|
+
alias :'!~' :does_not_match if respond_to?(:'!~')
|
26
|
+
alias :> :gt
|
27
|
+
alias :>= :gteq
|
28
|
+
alias :< :lt
|
29
|
+
alias :<= :lteq
|
30
|
+
|
31
|
+
# Create an ascending Order node with this Literal as its expression
|
32
|
+
# @return [Order] The new Order node
|
33
|
+
def asc
|
34
|
+
Order.new self, 1
|
35
|
+
end
|
36
|
+
|
37
|
+
# Create a descending Order node with this Literal as its expression
|
38
|
+
# @return [Order] The new Order node
|
39
|
+
def desc
|
40
|
+
Order.new self, -1
|
41
|
+
end
|
42
|
+
|
43
|
+
# Object comparison
|
44
|
+
def eql?(other)
|
45
|
+
self.class == other.class &&
|
46
|
+
self.expr == other.expr
|
47
|
+
end
|
48
|
+
|
49
|
+
# To support object equality tests
|
50
|
+
def hash
|
51
|
+
expr.hash
|
52
|
+
end
|
53
|
+
|
54
|
+
# expand_hash_conditions_for_aggregates assumes our hash keys can be
|
55
|
+
# converted to symbols, so this has to be implemented, but it doesn't
|
56
|
+
# really have to do anything useful.
|
57
|
+
# @return [NilClass] Just to avoid bombing out on expand_hash_conditions_for_aggregates
|
58
|
+
def to_sym
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [String] The Literal's String equivalent.
|
63
|
+
def to_s
|
64
|
+
expr.to_s
|
65
|
+
end
|
66
|
+
alias :to_str :to_s
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/squeel/version.rb
CHANGED
@@ -31,7 +31,7 @@ module Squeel
|
|
31
31
|
# @param parent The array's parent within the context
|
32
32
|
# @return [Array] The flattened array with elements visited
|
33
33
|
def visit_Array(o, parent)
|
34
|
-
o.map { |v|
|
34
|
+
o.map { |v| can_visit?(v) ? visit(v, parent) : v }.flatten
|
35
35
|
end
|
36
36
|
|
37
37
|
# Visit a symbol. This will return an attribute named after the symbol against
|
@@ -54,6 +54,15 @@ module Squeel
|
|
54
54
|
contextualize(parent)[o.symbol]
|
55
55
|
end
|
56
56
|
|
57
|
+
# Visit a Literal by converting it to an ARel SqlLiteral
|
58
|
+
#
|
59
|
+
# @param [Nodes::Literal] o The Literal to visit
|
60
|
+
# @param parent The parent object in the context (unused)
|
61
|
+
# @return [Arel::Nodes::SqlLiteral] An SqlLiteral
|
62
|
+
def visit_Squeel_Nodes_Literal(o, parent)
|
63
|
+
Arel.sql(o.expr)
|
64
|
+
end
|
65
|
+
|
57
66
|
# Visit a keypath. This will traverse the keypath's "path", setting a new
|
58
67
|
# parent as though the keypath's endpoint was in a deeply-nested hash,
|
59
68
|
# then visit the endpoint with the new parent.
|
@@ -64,7 +73,7 @@ module Squeel
|
|
64
73
|
def visit_Squeel_Nodes_KeyPath(o, parent)
|
65
74
|
parent = traverse(o, parent)
|
66
75
|
|
67
|
-
|
76
|
+
visit(o.endpoint, parent)
|
68
77
|
end
|
69
78
|
|
70
79
|
# Visit an Order node.
|
@@ -73,10 +82,10 @@ module Squeel
|
|
73
82
|
# @param parent The node's parent within the context
|
74
83
|
# @return [Arel::Nodes::Ordering] An ascending or desending ordering
|
75
84
|
def visit_Squeel_Nodes_Order(o, parent)
|
76
|
-
|
85
|
+
visit(o.expr, parent).send(o.descending? ? :desc : :asc)
|
77
86
|
end
|
78
87
|
|
79
|
-
# Visit a Function node. Each function argument will be
|
88
|
+
# Visit a Function node. Each function argument will be visiteded or
|
80
89
|
# contextualized if appropriate. Keep in mind that this occurs with
|
81
90
|
# the current parent within the context.
|
82
91
|
#
|
@@ -92,8 +101,8 @@ module Squeel
|
|
92
101
|
def visit_Squeel_Nodes_Function(o, parent)
|
93
102
|
args = o.args.map do |arg|
|
94
103
|
case arg
|
95
|
-
when Nodes::Function, Nodes::KeyPath
|
96
|
-
|
104
|
+
when Nodes::Function, Nodes::KeyPath, Nodes::As, Nodes::Literal
|
105
|
+
visit(arg, parent)
|
97
106
|
when Symbol, Nodes::Stub
|
98
107
|
Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_sym])
|
99
108
|
else
|
@@ -114,8 +123,8 @@ module Squeel
|
|
114
123
|
def visit_Squeel_Nodes_Operation(o, parent)
|
115
124
|
args = o.args.map do |arg|
|
116
125
|
case arg
|
117
|
-
when Nodes::Function
|
118
|
-
|
126
|
+
when Nodes::Function, Nodes::KeyPath, Nodes::As, Nodes::Literal
|
127
|
+
visit(arg, parent)
|
119
128
|
when Symbol, Nodes::Stub
|
120
129
|
Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_sym])
|
121
130
|
else
|
@@ -144,7 +153,7 @@ module Squeel
|
|
144
153
|
# @param parent The parent object in the context
|
145
154
|
# @return [Arel::Nodes::As] The resulting as node.
|
146
155
|
def visit_Squeel_Nodes_As(o, parent)
|
147
|
-
|
156
|
+
visit(o.left, parent).as(o.right)
|
148
157
|
end
|
149
158
|
|
150
159
|
# Visit an ActiveRecord Relation, returning an Arel::SelectManager
|
@@ -159,7 +168,7 @@ module Squeel
|
|
159
168
|
# @return [Boolean] Whether the given value implies a context change
|
160
169
|
# @param v The value to consider
|
161
170
|
def implies_context_change?(v)
|
162
|
-
|
171
|
+
can_visit?(v)
|
163
172
|
end
|
164
173
|
|
165
174
|
# Change context (by setting the new parent to the result of a #find or
|
@@ -178,9 +187,9 @@ module Squeel
|
|
178
187
|
end
|
179
188
|
|
180
189
|
if Array === v
|
181
|
-
v.map {|val|
|
190
|
+
v.map {|val| visit(val, parent || k)}
|
182
191
|
else
|
183
|
-
|
192
|
+
can_visit?(v) ? visit(v, parent || k) : v
|
184
193
|
end
|
185
194
|
end
|
186
195
|
|
data/lib/squeel/visitors/base.rb
CHANGED
@@ -27,20 +27,20 @@ module Squeel
|
|
27
27
|
end
|
28
28
|
|
29
29
|
# @param object The object to check
|
30
|
-
# @return [Boolean] Whether or not the visitor can
|
31
|
-
def
|
32
|
-
self.class.
|
30
|
+
# @return [Boolean] Whether or not the visitor can visit the given object
|
31
|
+
def can_visit?(object)
|
32
|
+
self.class.can_visit? object
|
33
33
|
end
|
34
34
|
|
35
35
|
# @param object The object to check
|
36
|
-
# @return [Boolean] Whether or not visitors of this class can
|
37
|
-
def self.
|
38
|
-
@
|
36
|
+
# @return [Boolean] Whether or not visitors of this class can visit the given object
|
37
|
+
def self.can_visit?(object)
|
38
|
+
@can_visit ||= Hash.new do |hash, klass|
|
39
39
|
hash[klass] = klass.ancestors.detect { |ancestor|
|
40
40
|
private_method_defined? DISPATCH[ancestor]
|
41
41
|
} ? true : false
|
42
42
|
end
|
43
|
-
@
|
43
|
+
@can_visit[object.class]
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
@@ -89,8 +89,7 @@ module Squeel
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
-
# Visit the object.
|
93
|
-
# #accept method.
|
92
|
+
# Visit the object.
|
94
93
|
#
|
95
94
|
# @param object The object to visit
|
96
95
|
# @param parent The object's parent within the context
|
@@ -40,7 +40,7 @@ module Squeel
|
|
40
40
|
# @param parent The current parent object in the context
|
41
41
|
# @return [Array] The visited array
|
42
42
|
def visit_Array(o, parent)
|
43
|
-
o.map { |v|
|
43
|
+
o.map { |v| can_visit?(v) ? visit(v, parent) : v }.flatten
|
44
44
|
end
|
45
45
|
|
46
46
|
# Visit ActiveRecord::Base objects. These should be converted to their
|
@@ -61,7 +61,7 @@ module Squeel
|
|
61
61
|
def visit_Squeel_Nodes_KeyPath(o, parent)
|
62
62
|
parent = traverse(o, parent)
|
63
63
|
|
64
|
-
|
64
|
+
visit(o.endpoint, parent)
|
65
65
|
end
|
66
66
|
|
67
67
|
# Visit a Stub by converting it to an ARel attribute
|
@@ -74,6 +74,15 @@ module Squeel
|
|
74
74
|
contextualize(parent)[o.symbol]
|
75
75
|
end
|
76
76
|
|
77
|
+
# Visit a Literal by converting it to an ARel SqlLiteral
|
78
|
+
#
|
79
|
+
# @param [Nodes::Literal] o The Literal to visit
|
80
|
+
# @param parent The parent object in the context (unused)
|
81
|
+
# @return [Arel::Nodes::SqlLiteral] An SqlLiteral
|
82
|
+
def visit_Squeel_Nodes_Literal(o, parent)
|
83
|
+
Arel.sql(o.expr)
|
84
|
+
end
|
85
|
+
|
77
86
|
# Visit a Squeel predicate, converting it into an ARel predicate
|
78
87
|
#
|
79
88
|
# @param [Nodes::Predicate] o The predicate to visit
|
@@ -83,24 +92,25 @@ module Squeel
|
|
83
92
|
def visit_Squeel_Nodes_Predicate(o, parent)
|
84
93
|
value = o.value
|
85
94
|
|
86
|
-
if
|
87
|
-
|
88
|
-
|
95
|
+
if Nodes::KeyPath === value
|
96
|
+
value = can_visit?(value.endpoint) ? visit(value, parent) : contextualize(traverse(value, parent))[value.endpoint.to_sym]
|
97
|
+
else
|
98
|
+
value = visit(value, parent) if can_visit?(value)
|
89
99
|
end
|
90
100
|
|
91
|
-
|
92
|
-
|
101
|
+
value = quote_for_node(o.expr, value)
|
102
|
+
|
103
|
+
attribute = case o.expr
|
104
|
+
when Nodes::Stub, Nodes::Function, Nodes::Literal
|
105
|
+
visit(o.expr, parent)
|
93
106
|
else
|
94
|
-
|
107
|
+
contextualize(parent)[o.expr]
|
95
108
|
end
|
96
109
|
|
97
|
-
|
98
|
-
|
99
|
-
accept(o.expr, parent).send(o.method_name, value)
|
100
|
-
when Nodes::Function
|
101
|
-
accept(o.expr, parent).send(o.method_name, quote(value))
|
110
|
+
if Array === value && [:in, :not_in].include?(o.method_name)
|
111
|
+
o.method_name == :in ? attribute_in_array(attribute, value) : attribute_not_in_array(attribute, value)
|
102
112
|
else
|
103
|
-
|
113
|
+
attribute.send(o.method_name, value)
|
104
114
|
end
|
105
115
|
end
|
106
116
|
|
@@ -113,12 +123,12 @@ module Squeel
|
|
113
123
|
def visit_Squeel_Nodes_Function(o, parent)
|
114
124
|
args = o.args.map do |arg|
|
115
125
|
case arg
|
116
|
-
when Nodes::Function
|
117
|
-
|
126
|
+
when Nodes::Function, Nodes::As, Nodes::Literal
|
127
|
+
visit(arg, parent)
|
118
128
|
when ActiveRecord::Relation
|
119
129
|
arg.arel.ast
|
120
130
|
when Nodes::KeyPath
|
121
|
-
|
131
|
+
can_visit?(arg.endpoint) ? visit(arg, parent) : contextualize(traverse(arg, parent))[arg.endpoint.to_sym]
|
122
132
|
when Symbol, Nodes::Stub
|
123
133
|
Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_sym])
|
124
134
|
else
|
@@ -149,10 +159,10 @@ module Squeel
|
|
149
159
|
def visit_Squeel_Nodes_Operation(o, parent)
|
150
160
|
args = o.args.map do |arg|
|
151
161
|
case arg
|
152
|
-
when Nodes::Function
|
153
|
-
|
162
|
+
when Nodes::Function, Nodes::As, Nodes::Literal
|
163
|
+
visit(arg, parent)
|
154
164
|
when Nodes::KeyPath
|
155
|
-
|
165
|
+
can_visit?(arg.endpoint) ? visit(arg, parent) : contextualize(traverse(arg, parent))[arg.endpoint.to_sym]
|
156
166
|
when Symbol, Nodes::Stub
|
157
167
|
Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_sym])
|
158
168
|
else
|
@@ -184,7 +194,7 @@ module Squeel
|
|
184
194
|
# And node as its expression. All children will be visited before
|
185
195
|
# being passed to the And.
|
186
196
|
def visit_Squeel_Nodes_And(o, parent)
|
187
|
-
Arel::Nodes::Grouping.new(Arel::Nodes::And.new(
|
197
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::And.new(visit(o.children, parent)))
|
188
198
|
end
|
189
199
|
|
190
200
|
# Visit a Squeel Or node, returning an ARel Or node.
|
@@ -193,11 +203,11 @@ module Squeel
|
|
193
203
|
# @param parent The parent object in the context
|
194
204
|
# @return [Arel::Nodes::Or] An ARel Or node, with left and right sides visited
|
195
205
|
def visit_Squeel_Nodes_Or(o, parent)
|
196
|
-
|
206
|
+
visit(o.left, parent).or(visit(o.right, parent))
|
197
207
|
end
|
198
208
|
|
199
209
|
def visit_Squeel_Nodes_Not(o, parent)
|
200
|
-
|
210
|
+
visit(o.expr, parent).not
|
201
211
|
end
|
202
212
|
|
203
213
|
# @return [Boolean] Whether the given value implies a context change
|
@@ -207,7 +217,7 @@ module Squeel
|
|
207
217
|
when Hash, Nodes::Predicate, Nodes::Unary, Nodes::Binary, Nodes::Nary
|
208
218
|
true
|
209
219
|
when Nodes::KeyPath
|
210
|
-
|
220
|
+
can_visit?(v.endpoint) && !(Nodes::Stub === v.endpoint)
|
211
221
|
else
|
212
222
|
false
|
213
223
|
end
|
@@ -230,9 +240,9 @@ module Squeel
|
|
230
240
|
|
231
241
|
case v
|
232
242
|
when Hash, Nodes::KeyPath, Nodes::Predicate, Nodes::Unary, Nodes::Binary, Nodes::Nary
|
233
|
-
|
243
|
+
visit(v, parent || k)
|
234
244
|
when Array
|
235
|
-
v.map {|val|
|
245
|
+
v.map {|val| visit(val, parent || k)}
|
236
246
|
else
|
237
247
|
raise ArgumentError, <<-END
|
238
248
|
Hashes, Predicates, and arrays of visitables as values imply that their
|
@@ -254,17 +264,17 @@ module Squeel
|
|
254
264
|
case v
|
255
265
|
when Nodes::Stub, Symbol
|
256
266
|
v = contextualize(parent)[v.to_sym]
|
257
|
-
when Nodes::KeyPath # If we could
|
267
|
+
when Nodes::KeyPath # If we could visit the endpoint, we wouldn't be here
|
258
268
|
v = contextualize(traverse(v, parent))[v.endpoint.to_sym]
|
259
269
|
end
|
260
270
|
|
261
271
|
case k
|
262
272
|
when Nodes::Predicate
|
263
|
-
|
264
|
-
when Nodes::Function
|
265
|
-
arel_predicate_for(
|
273
|
+
visit(k % quote_for_node(k.expr, v), parent)
|
274
|
+
when Nodes::Function, Nodes::Literal
|
275
|
+
arel_predicate_for(visit(k, parent), quote(v), parent)
|
266
276
|
when Nodes::KeyPath
|
267
|
-
|
277
|
+
visit(k % quote_for_node(k.endpoint, v), parent)
|
268
278
|
else
|
269
279
|
attr_name = k.to_s
|
270
280
|
attribute = if attr_name.include?('.')
|
@@ -285,19 +295,40 @@ module Squeel
|
|
285
295
|
# @param value The value to be compared against
|
286
296
|
# @return [Arel::Nodes::Node] An ARel predicate node
|
287
297
|
def arel_predicate_for(attribute, value, parent)
|
288
|
-
value =
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
end
|
298
|
+
value = can_visit?(value) ? visit(value, parent) : value
|
299
|
+
case value
|
300
|
+
when Array
|
301
|
+
attribute_in_array(attribute, value)
|
302
|
+
when Range, Arel::SelectManager
|
303
|
+
attribute.in(value)
|
295
304
|
else
|
296
305
|
attribute.eq(value)
|
297
306
|
end
|
298
307
|
end
|
299
308
|
|
300
|
-
|
309
|
+
def attribute_in_array(attribute, array)
|
310
|
+
if array.empty?
|
311
|
+
FALSE_SQL
|
312
|
+
elsif array.include? nil
|
313
|
+
array = array.compact
|
314
|
+
array.empty? ? attribute.eq(nil) : attribute.in(array).or(attribute.eq nil)
|
315
|
+
else
|
316
|
+
attribute.in array
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def attribute_not_in_array(attribute, array)
|
321
|
+
if array.empty?
|
322
|
+
TRUE_SQL
|
323
|
+
elsif array.include? nil
|
324
|
+
array = array.compact
|
325
|
+
array.empty? ? attribute.not_eq(nil) : attribute.not_in(array).and(attribute.not_eq nil)
|
326
|
+
else
|
327
|
+
attribute.not_in array
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
# Certain nodes require us to do the quoting before the ARel
|
301
332
|
# visitor gets a chance to try, because we want to avoid having our
|
302
333
|
# values quoted as a type of the last visited column. Otherwise, we
|
303
334
|
# can end up with annoyances like having "joe" quoted to 0, if the
|
@@ -307,10 +338,10 @@ module Squeel
|
|
307
338
|
# @param v The value to (possibly) quote
|
308
339
|
def quote_for_node(node, v)
|
309
340
|
case node
|
310
|
-
when Nodes::Function
|
341
|
+
when Nodes::Function, Nodes::Literal
|
311
342
|
quote(v)
|
312
343
|
when Nodes::Predicate
|
313
|
-
|
344
|
+
quote_for_node(node.expr, v)
|
314
345
|
else
|
315
346
|
v
|
316
347
|
end
|
@@ -14,13 +14,13 @@ module Squeel
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def visit_Array(o, parent)
|
17
|
-
o.map {|e|
|
17
|
+
o.map {|e| visit(e, parent)}.flatten
|
18
18
|
end
|
19
19
|
|
20
20
|
def visit_Hash(o, parent)
|
21
21
|
{}.tap do |hash|
|
22
22
|
o.each do |key, value|
|
23
|
-
hash[
|
23
|
+
hash[visit(key, parent)] = visit(value, parent)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
1
3
|
module Squeel
|
2
4
|
module Adapters
|
3
5
|
module ActiveRecord
|
@@ -335,9 +337,9 @@ module Squeel
|
|
335
337
|
end
|
336
338
|
|
337
339
|
it 'falls back to Array#select behavior with a block that has an arity' do
|
338
|
-
people = Person.select{|p| p.
|
340
|
+
people = Person.select{|p| p.id == 1}
|
339
341
|
people.should have(1).person
|
340
|
-
people.first.
|
342
|
+
people.first.id.should eq 1
|
341
343
|
end
|
342
344
|
|
343
345
|
it 'behaves as normal with standard parameters' do
|
@@ -363,7 +365,7 @@ module Squeel
|
|
363
365
|
|
364
366
|
it 'allows custom operators in the select values via block' do
|
365
367
|
relation = Person.select{name.op('||', '-diddly').as(flanderized_name)}
|
366
|
-
relation.first.flanderized_name.should eq '
|
368
|
+
relation.first.flanderized_name.should eq Person.first.name + '-diddly'
|
367
369
|
end
|
368
370
|
|
369
371
|
it 'allows a subquery in the select values' do
|
@@ -429,8 +431,9 @@ module Squeel
|
|
429
431
|
end
|
430
432
|
|
431
433
|
it 'allows a subquery on the value side of a predicate' do
|
432
|
-
|
433
|
-
|
434
|
+
names = [Person.first.name, Person.last.name]
|
435
|
+
old_and_busted = Person.where(:name => names)
|
436
|
+
new_hotness = Person.where{name.in(Person.select{name}.where{name.in(names)})}
|
434
437
|
new_hotness.should have(2).items
|
435
438
|
old_and_busted.to_a.should eq new_hotness.to_a
|
436
439
|
end
|
@@ -489,7 +492,7 @@ module Squeel
|
|
489
492
|
|
490
493
|
it 'allows complex conditions on aggregate columns' do
|
491
494
|
relation = Person.group(:parent_id).having{salary == max(salary)}
|
492
|
-
relation.first.name.should eq
|
495
|
+
relation.first.name.should eq Person.last.name
|
493
496
|
end
|
494
497
|
|
495
498
|
it 'allows a condition on a function via block' do
|
@@ -613,7 +616,7 @@ module Squeel
|
|
613
616
|
end
|
614
617
|
|
615
618
|
it 'merges relations with a different base' do
|
616
|
-
relation = Person.where{name == 'bob'}.joins(:articles).merge(Article.where{title == 'Hello world!'})
|
619
|
+
relation = Person.where{name == 'bob'}.joins(:articles).merge(Article.where{title == 'Hello world!'}, :articles)
|
617
620
|
sql = relation.to_sql
|
618
621
|
sql.should match /INNER JOIN "articles" ON "articles"."person_id" = "people"."id"/
|
619
622
|
sql.should match /"people"."name" = 'bob'/
|
@@ -635,7 +638,7 @@ module Squeel
|
|
635
638
|
where{{comments => {body => 'First post!'}}}
|
636
639
|
relation.size.should be 1
|
637
640
|
person = relation.first
|
638
|
-
person.
|
641
|
+
person.should eq Person.last
|
639
642
|
person.comments.loaded?.should be true
|
640
643
|
end
|
641
644
|
|
data/spec/squeel/dsl_spec.rb
CHANGED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Squeel
|
4
|
+
module Nodes
|
5
|
+
describe Literal do
|
6
|
+
before do
|
7
|
+
@l = Literal.new 'string'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'hashes like its expr' do
|
11
|
+
@l.hash.should eq 'string'.hash
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns nil when sent to_sym' do
|
15
|
+
@l.to_sym.should be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns a string matching its expr when sent to_s' do
|
19
|
+
@l.to_s.should eq 'string'
|
20
|
+
end
|
21
|
+
|
22
|
+
Squeel::Constants::PREDICATES.each do |method_name|
|
23
|
+
it "creates #{method_name} predicates with no value" do
|
24
|
+
predicate = @l.send(method_name)
|
25
|
+
predicate.expr.should eq @l
|
26
|
+
predicate.method_name.should eq method_name
|
27
|
+
predicate.value?.should be_false
|
28
|
+
end
|
29
|
+
|
30
|
+
it "creates #{method_name} predicates with a value" do
|
31
|
+
predicate = @l.send(method_name, 'value')
|
32
|
+
predicate.expr.should eq @l
|
33
|
+
predicate.method_name.should eq method_name
|
34
|
+
predicate.value.should eq 'value'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Squeel::Constants::PREDICATE_ALIASES.each do |method_name, aliases|
|
39
|
+
aliases.each do |aliaz|
|
40
|
+
['', '_any', '_all'].each do |suffix|
|
41
|
+
it "creates #{method_name.to_s + suffix} predicates with no value using the alias #{aliaz.to_s + suffix}" do
|
42
|
+
predicate = @l.send(aliaz.to_s + suffix)
|
43
|
+
predicate.expr.should eq @l
|
44
|
+
predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
|
45
|
+
predicate.value?.should be_false
|
46
|
+
end
|
47
|
+
|
48
|
+
it "creates #{method_name.to_s + suffix} predicates with a value using the alias #{aliaz.to_s + suffix}" do
|
49
|
+
predicate = @l.send((aliaz.to_s + suffix), 'value')
|
50
|
+
predicate.expr.should eq @l
|
51
|
+
predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
|
52
|
+
predicate.value.should eq 'value'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'creates eq predicates with ==' do
|
59
|
+
predicate = @l == 1
|
60
|
+
predicate.expr.should eq @l
|
61
|
+
predicate.method_name.should eq :eq
|
62
|
+
predicate.value.should eq 1
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'creates not_eq predicates with ^' do
|
66
|
+
predicate = @l ^ 1
|
67
|
+
predicate.expr.should eq @l
|
68
|
+
predicate.method_name.should eq :not_eq
|
69
|
+
predicate.value.should eq 1
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'creates not_eq predicates with !=' do
|
73
|
+
predicate = @l != 1
|
74
|
+
predicate.expr.should eq @l
|
75
|
+
predicate.method_name.should eq :not_eq
|
76
|
+
predicate.value.should eq 1
|
77
|
+
end if respond_to?('!=')
|
78
|
+
|
79
|
+
it 'creates in predicates with >>' do
|
80
|
+
predicate = @l >> [1,2,3]
|
81
|
+
predicate.expr.should eq @l
|
82
|
+
predicate.method_name.should eq :in
|
83
|
+
predicate.value.should eq [1,2,3]
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'creates not_in predicates with <<' do
|
87
|
+
predicate = @l << [1,2,3]
|
88
|
+
predicate.expr.should eq @l
|
89
|
+
predicate.method_name.should eq :not_in
|
90
|
+
predicate.value.should eq [1,2,3]
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'creates matches predicates with =~' do
|
94
|
+
predicate = @l =~ '%bob%'
|
95
|
+
predicate.expr.should eq @l
|
96
|
+
predicate.method_name.should eq :matches
|
97
|
+
predicate.value.should eq '%bob%'
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'creates does_not_match predicates with !~' do
|
101
|
+
predicate = @l !~ '%bob%'
|
102
|
+
predicate.expr.should eq @l
|
103
|
+
predicate.method_name.should eq :does_not_match
|
104
|
+
predicate.value.should eq '%bob%'
|
105
|
+
end if respond_to?('!~')
|
106
|
+
|
107
|
+
it 'creates gt predicates with >' do
|
108
|
+
predicate = @l > 1
|
109
|
+
predicate.expr.should eq @l
|
110
|
+
predicate.method_name.should eq :gt
|
111
|
+
predicate.value.should eq 1
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'creates gteq predicates with >=' do
|
115
|
+
predicate = @l >= 1
|
116
|
+
predicate.expr.should eq @l
|
117
|
+
predicate.method_name.should eq :gteq
|
118
|
+
predicate.value.should eq 1
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'creates lt predicates with <' do
|
122
|
+
predicate = @l < 1
|
123
|
+
predicate.expr.should eq @l
|
124
|
+
predicate.method_name.should eq :lt
|
125
|
+
predicate.value.should eq 1
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'creates lteq predicates with <=' do
|
129
|
+
predicate = @l <= 1
|
130
|
+
predicate.expr.should eq @l
|
131
|
+
predicate.method_name.should eq :lteq
|
132
|
+
predicate.value.should eq 1
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'creates ascending orders' do
|
136
|
+
order = @l.asc
|
137
|
+
order.should be_ascending
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'creates descending orders' do
|
141
|
+
order = @l.desc
|
142
|
+
order.should be_descending
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'creates as nodes with #as' do
|
146
|
+
as = @l.as('other_name')
|
147
|
+
as.should be_a Squeel::Nodes::As
|
148
|
+
as.left.should eq @l
|
149
|
+
as.right.should be_a Arel::Nodes::SqlLiteral
|
150
|
+
as.right.should eq 'other_name'
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -55,6 +55,36 @@ module Squeel
|
|
55
55
|
predicate.should eq '1=1'
|
56
56
|
end
|
57
57
|
|
58
|
+
it 'generates IS NULL for hash keys with a value of [nil]' do
|
59
|
+
predicate = @v.accept(:id => [nil])
|
60
|
+
predicate.to_sql.should be_like '"people"."id" IS NULL'
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'generates IS NULL for in predicates with a value of [nil]' do
|
64
|
+
predicate = @v.accept(:id.in => [nil])
|
65
|
+
predicate.to_sql.should be_like '"people"."id" IS NULL'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'generates IS NOT NULL for not_in predicates with a value of [nil]' do
|
69
|
+
predicate = @v.accept(:id.not_in => [nil])
|
70
|
+
predicate.to_sql.should be_like '"people"."id" IS NOT NULL'
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'generates IN OR IS NULL for hash keys with a value of [1, 2, 3, nil]' do
|
74
|
+
predicate = @v.accept(:id => [1, 2, 3, nil])
|
75
|
+
predicate.to_sql.should be_like '("people"."id" IN (1, 2, 3) OR "people"."id" IS NULL)'
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'generates IN OR IS NULL for in predicates with a value of [1, 2, 3, nil]' do
|
79
|
+
predicate = @v.accept(:id.in => [1, 2, 3, nil])
|
80
|
+
predicate.to_sql.should be_like '("people"."id" IN (1, 2, 3) OR "people"."id" IS NULL)'
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'generates IN AND IS NOT NULL for not_in predicates with a value of [1, 2, 3, nil]' do
|
84
|
+
predicate = @v.accept(:id.not_in => [1, 2, 3, nil])
|
85
|
+
predicate.to_sql.should be_like '"people"."id" NOT IN (1, 2, 3) AND "people"."id" IS NOT NULL'
|
86
|
+
end
|
87
|
+
|
58
88
|
it 'allows a subquery on the value side of an explicit predicate' do
|
59
89
|
predicate = @v.accept dsl{name.in(Person.select{name}.where{name.in(['Aric Smith', 'Gladyce Kulas'])})}
|
60
90
|
predicate.should be_a Arel::Nodes::In
|
data/squeel.gemspec
CHANGED
@@ -29,7 +29,7 @@ you're feeling especially appreciative. It'd help me justify this
|
|
29
29
|
|
30
30
|
s.add_dependency 'activerecord', '~> 3.0'
|
31
31
|
s.add_dependency 'activesupport', '~> 3.0'
|
32
|
-
s.add_development_dependency 'rspec', '~> 2.
|
32
|
+
s.add_development_dependency 'rspec', '~> 2.6.0'
|
33
33
|
s.add_development_dependency 'machinist', '~> 1.0.6'
|
34
34
|
s.add_development_dependency 'faker', '~> 0.9.5'
|
35
35
|
s.add_development_dependency 'sqlite3', '~> 1.3.3'
|
metadata
CHANGED
@@ -1,93 +1,129 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: squeel
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 53
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 8
|
9
|
+
- 5
|
10
|
+
version: 0.8.5
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Ernie Miller
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2011-07-02 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
15
22
|
name: activerecord
|
16
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
25
|
none: false
|
18
|
-
requirements:
|
26
|
+
requirements:
|
19
27
|
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
version: "3.0"
|
22
34
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
26
37
|
name: activesupport
|
27
|
-
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
40
|
none: false
|
29
|
-
requirements:
|
41
|
+
requirements:
|
30
42
|
- - ~>
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 7
|
45
|
+
segments:
|
46
|
+
- 3
|
47
|
+
- 0
|
48
|
+
version: "3.0"
|
33
49
|
type: :runtime
|
34
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
37
52
|
name: rspec
|
38
|
-
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
55
|
none: false
|
40
|
-
requirements:
|
56
|
+
requirements:
|
41
57
|
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 23
|
60
|
+
segments:
|
61
|
+
- 2
|
62
|
+
- 6
|
63
|
+
- 0
|
64
|
+
version: 2.6.0
|
44
65
|
type: :development
|
45
|
-
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
48
68
|
name: machinist
|
49
|
-
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
71
|
none: false
|
51
|
-
requirements:
|
72
|
+
requirements:
|
52
73
|
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 27
|
76
|
+
segments:
|
77
|
+
- 1
|
78
|
+
- 0
|
79
|
+
- 6
|
54
80
|
version: 1.0.6
|
55
81
|
type: :development
|
56
|
-
|
57
|
-
|
58
|
-
- !ruby/object:Gem::Dependency
|
82
|
+
version_requirements: *id004
|
83
|
+
- !ruby/object:Gem::Dependency
|
59
84
|
name: faker
|
60
|
-
|
85
|
+
prerelease: false
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
61
87
|
none: false
|
62
|
-
requirements:
|
88
|
+
requirements:
|
63
89
|
- - ~>
|
64
|
-
- !ruby/object:Gem::Version
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 49
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
- 9
|
95
|
+
- 5
|
65
96
|
version: 0.9.5
|
66
97
|
type: :development
|
67
|
-
|
68
|
-
|
69
|
-
- !ruby/object:Gem::Dependency
|
98
|
+
version_requirements: *id005
|
99
|
+
- !ruby/object:Gem::Dependency
|
70
100
|
name: sqlite3
|
71
|
-
|
101
|
+
prerelease: false
|
102
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
72
103
|
none: false
|
73
|
-
requirements:
|
104
|
+
requirements:
|
74
105
|
- - ~>
|
75
|
-
- !ruby/object:Gem::Version
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
hash: 29
|
108
|
+
segments:
|
109
|
+
- 1
|
110
|
+
- 3
|
111
|
+
- 3
|
76
112
|
version: 1.3.3
|
77
113
|
type: :development
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
with\n a handy block-based syntax. You can write subqueries, access named\n
|
82
|
-
\ functions provided by your RDBMS, and more, all without writing\n SQL
|
83
|
-
strings.\n "
|
84
|
-
email:
|
114
|
+
version_requirements: *id006
|
115
|
+
description: "\n Squeel unlocks the power of ARel in your Rails 3 application with\n a handy block-based syntax. You can write subqueries, access named\n functions provided by your RDBMS, and more, all without writing\n SQL strings.\n "
|
116
|
+
email:
|
85
117
|
- ernie@metautonomo.us
|
86
118
|
executables: []
|
119
|
+
|
87
120
|
extensions: []
|
121
|
+
|
88
122
|
extra_rdoc_files: []
|
89
|
-
|
123
|
+
|
124
|
+
files:
|
90
125
|
- .gitignore
|
126
|
+
- .travis.yml
|
91
127
|
- .yardopts
|
92
128
|
- Gemfile
|
93
129
|
- LICENSE
|
@@ -120,6 +156,7 @@ files:
|
|
120
156
|
- lib/squeel/nodes/function.rb
|
121
157
|
- lib/squeel/nodes/join.rb
|
122
158
|
- lib/squeel/nodes/key_path.rb
|
159
|
+
- lib/squeel/nodes/literal.rb
|
123
160
|
- lib/squeel/nodes/nary.rb
|
124
161
|
- lib/squeel/nodes/not.rb
|
125
162
|
- lib/squeel/nodes/operation.rb
|
@@ -155,6 +192,7 @@ files:
|
|
155
192
|
- spec/squeel/nodes/function_spec.rb
|
156
193
|
- spec/squeel/nodes/join_spec.rb
|
157
194
|
- spec/squeel/nodes/key_path_spec.rb
|
195
|
+
- spec/squeel/nodes/literal_spec.rb
|
158
196
|
- spec/squeel/nodes/operation_spec.rb
|
159
197
|
- spec/squeel/nodes/operators_spec.rb
|
160
198
|
- spec/squeel/nodes/order_spec.rb
|
@@ -166,44 +204,48 @@ files:
|
|
166
204
|
- spec/squeel/visitors/symbol_visitor_spec.rb
|
167
205
|
- spec/support/schema.rb
|
168
206
|
- squeel.gemspec
|
207
|
+
has_rdoc: true
|
169
208
|
homepage: http://metautonomo.us/projects/squeel
|
170
209
|
licenses: []
|
171
|
-
post_install_message: ! '
|
172
210
|
|
211
|
+
post_install_message: |+
|
212
|
+
|
173
213
|
*** Thanks for installing Squeel! ***
|
174
|
-
|
175
214
|
Be sure to check out http://metautonomo.us/projects/squeel/ for a
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
you''re feeling especially appreciative. It''d help me justify this
|
180
|
-
|
215
|
+
walkthrough of Squeel's features, and click the donate link if
|
216
|
+
you're feeling especially appreciative. It'd help me justify this
|
181
217
|
"open source" stuff to my lovely wife. :)
|
182
|
-
|
183
|
-
|
184
|
-
'
|
218
|
+
|
185
219
|
rdoc_options: []
|
186
|
-
|
220
|
+
|
221
|
+
require_paths:
|
187
222
|
- lib
|
188
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
223
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
189
224
|
none: false
|
190
|
-
requirements:
|
191
|
-
- -
|
192
|
-
- !ruby/object:Gem::Version
|
193
|
-
|
194
|
-
|
225
|
+
requirements:
|
226
|
+
- - ">="
|
227
|
+
- !ruby/object:Gem::Version
|
228
|
+
hash: 3
|
229
|
+
segments:
|
230
|
+
- 0
|
231
|
+
version: "0"
|
232
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
195
233
|
none: false
|
196
|
-
requirements:
|
197
|
-
- -
|
198
|
-
- !ruby/object:Gem::Version
|
199
|
-
|
234
|
+
requirements:
|
235
|
+
- - ">="
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
hash: 3
|
238
|
+
segments:
|
239
|
+
- 0
|
240
|
+
version: "0"
|
200
241
|
requirements: []
|
242
|
+
|
201
243
|
rubyforge_project: squeel
|
202
|
-
rubygems_version: 1.
|
244
|
+
rubygems_version: 1.5.2
|
203
245
|
signing_key:
|
204
246
|
specification_version: 3
|
205
247
|
summary: ActiveRecord 3, improved.
|
206
|
-
test_files:
|
248
|
+
test_files:
|
207
249
|
- spec/blueprints/articles.rb
|
208
250
|
- spec/blueprints/comments.rb
|
209
251
|
- spec/blueprints/notes.rb
|
@@ -222,6 +264,7 @@ test_files:
|
|
222
264
|
- spec/squeel/nodes/function_spec.rb
|
223
265
|
- spec/squeel/nodes/join_spec.rb
|
224
266
|
- spec/squeel/nodes/key_path_spec.rb
|
267
|
+
- spec/squeel/nodes/literal_spec.rb
|
225
268
|
- spec/squeel/nodes/operation_spec.rb
|
226
269
|
- spec/squeel/nodes/operators_spec.rb
|
227
270
|
- spec/squeel/nodes/order_spec.rb
|