squeel 0.5.5 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +3 -0
- data/Gemfile +8 -3
- data/README.md +368 -0
- data/lib/core_ext/hash.rb +8 -8
- data/lib/core_ext/symbol.rb +7 -6
- data/lib/squeel.rb +2 -0
- data/lib/squeel/adapters/active_record.rb +25 -20
- data/lib/squeel/adapters/active_record/3.0/compat.rb +1 -2
- data/lib/squeel/adapters/active_record/3.0/context.rb +6 -7
- data/lib/squeel/adapters/active_record/3.0/join_dependency.rb +5 -5
- data/lib/squeel/adapters/active_record/context.rb +6 -7
- data/lib/squeel/adapters/active_record/join_dependency.rb +5 -5
- data/lib/squeel/configuration.rb +29 -0
- data/lib/squeel/constants.rb +1 -0
- data/lib/squeel/context.rb +36 -7
- data/lib/squeel/dsl.rb +57 -2
- data/lib/squeel/nodes.rb +6 -0
- data/lib/squeel/nodes/and.rb +1 -0
- data/lib/squeel/nodes/binary.rb +11 -2
- data/lib/squeel/nodes/function.rb +30 -48
- data/lib/squeel/nodes/join.rb +56 -12
- data/lib/squeel/nodes/key_path.rb +68 -2
- data/lib/squeel/nodes/nary.rb +12 -2
- data/lib/squeel/nodes/not.rb +1 -0
- data/lib/squeel/nodes/operation.rb +9 -0
- data/lib/squeel/nodes/operators.rb +16 -0
- data/lib/squeel/nodes/or.rb +1 -0
- data/lib/squeel/nodes/order.rb +19 -1
- data/lib/squeel/nodes/predicate.rb +25 -3
- data/lib/squeel/nodes/predicate_operators.rb +12 -0
- data/lib/squeel/nodes/stub.rb +55 -48
- data/lib/squeel/nodes/unary.rb +7 -1
- data/lib/squeel/predicate_methods.rb +2 -10
- data/lib/squeel/version.rb +1 -1
- data/lib/squeel/visitors/attribute_visitor.rb +80 -4
- data/lib/squeel/visitors/base.rb +70 -4
- data/lib/squeel/visitors/predicate_visitor.rb +28 -9
- data/lib/squeel/visitors/symbol_visitor.rb +1 -1
- data/spec/core_ext/symbol_spec.rb +2 -2
- data/spec/spec_helper.rb +6 -1
- data/spec/squeel/adapters/active_record/context_spec.rb +0 -7
- data/spec/squeel/adapters/active_record/relation_spec.rb +27 -0
- data/spec/squeel/dsl_spec.rb +20 -1
- data/spec/squeel/nodes/join_spec.rb +11 -4
- data/spec/squeel/nodes/key_path_spec.rb +1 -1
- data/spec/squeel/nodes/predicate_spec.rb +0 -42
- data/spec/squeel/nodes/stub_spec.rb +9 -8
- data/spec/squeel/visitors/predicate_visitor_spec.rb +34 -9
- data/squeel.gemspec +6 -9
- metadata +8 -10
- data/README.rdoc +0 -117
- data/lib/squeel/predicate_methods/function.rb +0 -9
- data/lib/squeel/predicate_methods/predicate.rb +0 -11
- data/lib/squeel/predicate_methods/stub.rb +0 -9
- data/lib/squeel/predicate_methods/symbol.rb +0 -9
@@ -93,10 +93,9 @@ module Arel
|
|
93
93
|
column_cache[table][name]
|
94
94
|
end
|
95
95
|
|
96
|
-
# This isn't really very cachey at all. Good enough for now.
|
97
96
|
def column_cache
|
98
97
|
@column_cache ||= Hash.new do |hash, key|
|
99
|
-
Hash[
|
98
|
+
hash[key] = Hash[
|
100
99
|
@engine.connection.columns(key, "#{key} Columns").map do |c|
|
101
100
|
[c.name, c]
|
102
101
|
end
|
@@ -8,8 +8,11 @@ module Squeel
|
|
8
8
|
JoinBase = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinBase
|
9
9
|
|
10
10
|
def initialize(object)
|
11
|
-
@base = object.join_base
|
12
11
|
super
|
12
|
+
@base = object.join_base
|
13
|
+
@engine = @base.arel_engine
|
14
|
+
@arel_visitor = Arel::Visitors.visitor_for @engine
|
15
|
+
@default_table = Arel::Table.new(@base.table_name, :as => @base.aliased_table_name, :engine => @engine)
|
13
16
|
end
|
14
17
|
|
15
18
|
def find(object, parent = @base)
|
@@ -23,7 +26,7 @@ module Squeel
|
|
23
26
|
when Nodes::Join
|
24
27
|
@object.join_associations.detect { |j|
|
25
28
|
j.reflection.name == object.name && j.parent == parent &&
|
26
|
-
(object.polymorphic? ? j.reflection.klass == object.
|
29
|
+
(object.polymorphic? ? j.reflection.klass == object._klass : true)
|
27
30
|
}
|
28
31
|
else
|
29
32
|
@object.join_associations.detect { |j|
|
@@ -43,17 +46,13 @@ module Squeel
|
|
43
46
|
parent
|
44
47
|
end
|
45
48
|
|
46
|
-
def sanitize_sql(conditions, parent)
|
47
|
-
parent.active_record.send(:sanitize_sql, conditions, parent.aliased_table_name)
|
48
|
-
end
|
49
|
-
|
50
49
|
private
|
51
50
|
|
52
51
|
def get_table(object)
|
53
52
|
if [Symbol, Nodes::Stub].include?(object.class)
|
54
53
|
Arel::Table.new(object.to_sym, :engine => @engine)
|
55
54
|
elsif Nodes::Join === object
|
56
|
-
object.
|
55
|
+
object._klass ? object._klass.arel_table : Arel::Table.new(object._name, :engine => @engine)
|
57
56
|
elsif object.respond_to?(:aliased_table_name)
|
58
57
|
Arel::Table.new(object.table_name, :as => object.aliased_table_name, :engine => @engine)
|
59
58
|
else
|
@@ -37,13 +37,13 @@ module Squeel
|
|
37
37
|
case associations
|
38
38
|
when Nodes::Join
|
39
39
|
parent ||= @joins.last
|
40
|
-
reflection = parent.reflections[associations.
|
41
|
-
raise ::ActiveRecord::ConfigurationError, "Association named '#{ associations.
|
40
|
+
reflection = parent.reflections[associations._name] or
|
41
|
+
raise ::ActiveRecord::ConfigurationError, "Association named '#{ associations._name }' was not found; perhaps you misspelled it?"
|
42
42
|
|
43
|
-
unless join_association = find_join_association_respecting_polymorphism(reflection, parent, associations.
|
43
|
+
unless join_association = find_join_association_respecting_polymorphism(reflection, parent, associations._klass)
|
44
44
|
@reflections << reflection
|
45
|
-
join_association = build_join_association_respecting_polymorphism(reflection, parent, associations.
|
46
|
-
join_association.join_type = associations.
|
45
|
+
join_association = build_join_association_respecting_polymorphism(reflection, parent, associations._klass)
|
46
|
+
join_association.join_type = associations._type
|
47
47
|
@joins << join_association
|
48
48
|
cache_joined_association(join_association)
|
49
49
|
end
|
@@ -8,8 +8,11 @@ module Squeel
|
|
8
8
|
JoinPart = ::ActiveRecord::Associations::JoinDependency::JoinPart
|
9
9
|
|
10
10
|
def initialize(object)
|
11
|
-
@base = object.join_base
|
12
11
|
super
|
12
|
+
@base = object.join_base
|
13
|
+
@engine = @base.arel_engine
|
14
|
+
@arel_visitor = Arel::Visitors.visitor_for @engine
|
15
|
+
@default_table = Arel::Table.new(@base.table_name, :as => @base.aliased_table_name, :engine => @engine)
|
13
16
|
end
|
14
17
|
|
15
18
|
def find(object, parent = @base)
|
@@ -23,7 +26,7 @@ module Squeel
|
|
23
26
|
when Nodes::Join
|
24
27
|
@object.join_associations.detect { |j|
|
25
28
|
j.reflection.name == object.name && j.parent == parent &&
|
26
|
-
(object.polymorphic? ? j.reflection.klass == object.
|
29
|
+
(object.polymorphic? ? j.reflection.klass == object._klass : true)
|
27
30
|
}
|
28
31
|
else
|
29
32
|
@object.join_associations.detect { |j|
|
@@ -43,17 +46,13 @@ module Squeel
|
|
43
46
|
parent
|
44
47
|
end
|
45
48
|
|
46
|
-
def sanitize_sql(conditions, parent)
|
47
|
-
parent.active_record.send(:sanitize_sql, conditions, parent.aliased_table_name)
|
48
|
-
end
|
49
|
-
|
50
49
|
private
|
51
50
|
|
52
51
|
def get_table(object)
|
53
52
|
if [Symbol, Nodes::Stub].include?(object.class)
|
54
53
|
Arel::Table.new(object.to_sym, :engine => @engine)
|
55
54
|
elsif Nodes::Join === object
|
56
|
-
object.
|
55
|
+
object._klass ? object._klass.arel_table : Arel::Table.new(object._name, :engine => @engine)
|
57
56
|
elsif object.respond_to?(:aliased_table_name)
|
58
57
|
Arel::Table.new(object.table_name, :as => object.aliased_table_name, :engine => @engine)
|
59
58
|
else
|
@@ -36,13 +36,13 @@ module Squeel
|
|
36
36
|
case associations
|
37
37
|
when Nodes::Join
|
38
38
|
parent ||= join_parts.last
|
39
|
-
reflection = parent.reflections[associations.
|
40
|
-
raise ::ActiveRecord::ConfigurationError, "Association named '#{ associations.
|
39
|
+
reflection = parent.reflections[associations._name] or
|
40
|
+
raise ::ActiveRecord::ConfigurationError, "Association named '#{ associations._name }' was not found; perhaps you misspelled it?"
|
41
41
|
|
42
|
-
unless join_association = find_join_association_respecting_polymorphism(reflection, parent, associations.
|
42
|
+
unless join_association = find_join_association_respecting_polymorphism(reflection, parent, associations._klass)
|
43
43
|
@reflections << reflection
|
44
|
-
join_association = build_join_association_respecting_polymorphism(reflection, parent, associations.
|
45
|
-
join_association.join_type = associations.
|
44
|
+
join_association = build_join_association_respecting_polymorphism(reflection, parent, associations._klass)
|
45
|
+
join_association.join_type = associations._type
|
46
46
|
@join_parts << join_association
|
47
47
|
cache_joined_association(join_association)
|
48
48
|
end
|
data/lib/squeel/configuration.rb
CHANGED
@@ -2,18 +2,47 @@ require 'squeel/constants'
|
|
2
2
|
require 'squeel/predicate_methods'
|
3
3
|
|
4
4
|
module Squeel
|
5
|
+
# The Squeel configuration module. The Squeel module extends this to provide its
|
6
|
+
# configuration capability.
|
5
7
|
module Configuration
|
6
8
|
|
9
|
+
# Start a Squeel configuration block in an initializer.
|
10
|
+
#
|
11
|
+
# @yield [config] A configuration block
|
12
|
+
#
|
13
|
+
# @example Load hash and symbol extensions
|
14
|
+
# Squeel.configure do |config|
|
15
|
+
# config.load_core_extensions :hash, :symbol
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# @example Alias a predicate
|
19
|
+
# Squeel.configure do |config|
|
20
|
+
# config.alias_ptedicate :is_less_than, :lt
|
21
|
+
# end
|
7
22
|
def configure
|
8
23
|
yield self
|
9
24
|
end
|
10
25
|
|
26
|
+
# Load core extensions for Hash, Symbol, or both
|
27
|
+
#
|
28
|
+
# @overload load_core_extensions(sym)
|
29
|
+
# Load a single extension
|
30
|
+
# @param [Symbol] sym :hash or :symbol
|
31
|
+
# @overload load_core_extensions(sym1, sym2)
|
32
|
+
# Load both extensions
|
33
|
+
# @param [Symbol] sym1 :hash or :symbol
|
34
|
+
# @param [Symbol] sym2 :hash or :symbol
|
11
35
|
def load_core_extensions(*exts)
|
12
36
|
exts.each do |ext|
|
13
37
|
require "core_ext/#{ext}"
|
14
38
|
end
|
15
39
|
end
|
16
40
|
|
41
|
+
# Create an alias to an existing predication method. The _any/_all variations will
|
42
|
+
# be created automatically.
|
43
|
+
# @param [Symbol] new_name The alias name
|
44
|
+
# @param [Symbol] existing_name The existing predicate name
|
45
|
+
# @raise [ArgumentError] The existing name is an _any/_all variation, and not the original predicate name
|
17
46
|
def alias_predicate(new_name, existing_name)
|
18
47
|
raise ArgumentError, 'the existing name should be the base name, not an _any/_all variation' if existing_name.to_s =~ /(_any|_all)$/
|
19
48
|
['', '_any', '_all'].each do |suffix|
|
data/lib/squeel/constants.rb
CHANGED
data/lib/squeel/context.rb
CHANGED
@@ -1,35 +1,64 @@
|
|
1
1
|
require 'arel'
|
2
2
|
|
3
3
|
module Squeel
|
4
|
+
# @abstract Subclass and implement {#traverse}, #{find} and {#get_table}
|
5
|
+
# to create a Context that supports a given ORM.
|
4
6
|
class Context
|
5
7
|
attr_reader :base, :engine, :arel_visitor
|
6
8
|
|
9
|
+
# The Squeel context expects some kind of context object that is
|
10
|
+
# representative of the current joins in a query in order to return
|
11
|
+
# appropriate tables. Again, in the case of an ActiveRecord context,
|
12
|
+
# this will be a JoinDependency. Subclasses are expected to set the
|
13
|
+
# <tt>@base</tt>, <tt>@engine</tt>, and <tt>@arel_visitor</tt>
|
14
|
+
# instance variables to appropriate values for use in their implementations
|
15
|
+
# of other required methods.
|
16
|
+
#
|
17
|
+
# @param object The object the context will use for contextualization
|
7
18
|
def initialize(object)
|
8
19
|
@object = object
|
9
|
-
@engine = @base.arel_engine
|
10
|
-
@arel_visitor = Arel::Visitors.visitor_for @engine
|
11
|
-
@default_table = Arel::Table.new(@base.table_name, :as => @base.aliased_table_name, :engine => @engine)
|
12
20
|
@tables = Hash.new {|hash, key| hash[key] = get_table(key)}
|
13
21
|
end
|
14
22
|
|
23
|
+
# This method should find a given object inside the context.
|
24
|
+
#
|
25
|
+
# @param object The object to find
|
26
|
+
# @param parent The parent object, if applicable
|
27
|
+
# @return a valid "parent" or contextualizable object
|
15
28
|
def find(object, parent = @base)
|
16
29
|
raise NotImplementedError, "Subclasses must implement public method find"
|
17
30
|
end
|
18
31
|
|
32
|
+
# This method should traverse a keypath and return an object for use
|
33
|
+
# in future calls to #traverse, #find, or #contextualize.
|
34
|
+
#
|
35
|
+
# @param [Nodes::KeyPath] keypath The keypath to traverse
|
36
|
+
# @param parent The parent object from which traversal should start.
|
37
|
+
# @param [Boolean] include_endpoint Whether or not the KeyPath's
|
38
|
+
# endpoint should be treated as a traversable key
|
39
|
+
# @return a valid "parent" or contextualizable object
|
19
40
|
def traverse(keypath, parent = @base, include_endpoint = false)
|
20
41
|
raise NotImplementedError, "Subclasses must implement public method traverse"
|
21
42
|
end
|
22
43
|
|
44
|
+
# This method, as implemented, just makes use of the table cache, which will
|
45
|
+
# call get_table, where the real work of getting the ARel Table occurs.
|
46
|
+
#
|
47
|
+
# @param object A contextualizable object (this will depend on the subclass's implementation)
|
48
|
+
# @return [Arel::Table] A table corresponding to the object param
|
23
49
|
def contextualize(object)
|
24
50
|
@tables[object]
|
25
51
|
end
|
26
52
|
|
27
|
-
def sanitize_sql(conditions, parent)
|
28
|
-
raise NotImplementedError, "Subclasses must implement public method sanitize_sql"
|
29
|
-
end
|
30
|
-
|
31
53
|
private
|
32
54
|
|
55
|
+
# Returns an Arel::Table that's appropriate for the object it's been sent.
|
56
|
+
# What's "appropriate"? Well, that's up to the implementation to decide, but
|
57
|
+
# it should probably generate a table that is least likely to result in invalid
|
58
|
+
# SQL.
|
59
|
+
#
|
60
|
+
# @param object A contextualizable object (this will depend on the subclass's implementation)
|
61
|
+
# @return [Arel::Table] A table corresponding to the object param.
|
33
62
|
def get_table(object)
|
34
63
|
raise NotImplementedError, "Subclasses must implement private method get_table"
|
35
64
|
end
|
data/lib/squeel/dsl.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module Squeel
|
2
|
+
# Interprets DSL blocks, generating various Squeel nodes as appropriate.
|
2
3
|
class DSL
|
3
4
|
|
5
|
+
# We're creating a BlankSlate-type class here, since we want most
|
6
|
+
# method calls to fall through to method_missing.
|
4
7
|
Squeel.evil_things do
|
5
8
|
(instance_methods + private_instance_methods).each do |method|
|
6
9
|
unless method.to_s =~ /^(__|instance_eval)/
|
@@ -9,15 +12,67 @@ module Squeel
|
|
9
12
|
end
|
10
13
|
end
|
11
14
|
|
15
|
+
# Called from an adapter, not directly.
|
16
|
+
# Evaluates a block of Squeel DSL code.
|
17
|
+
#
|
18
|
+
# @example A DSL block that uses instance_eval
|
19
|
+
# Post.where{title == 'Hello world!'}
|
20
|
+
#
|
21
|
+
# @example A DSL block with access to methods from the closure
|
22
|
+
# Post.where{|dsl| dsl.title == local_method(local_var)}
|
23
|
+
#
|
24
|
+
# @yield [dsl] A block of Squeel DSL code, with an optional argument if
|
25
|
+
# access to closure methods is desired.
|
26
|
+
# @return The results of the interpreted DSL code.
|
12
27
|
def self.eval(&block)
|
13
28
|
if block.arity > 0
|
14
|
-
yield self.new
|
29
|
+
yield self.new(block.binding)
|
15
30
|
else
|
16
|
-
self.new.instance_eval(&block)
|
31
|
+
self.new(block.binding).instance_eval(&block)
|
17
32
|
end
|
18
33
|
end
|
19
34
|
|
35
|
+
private
|
36
|
+
|
37
|
+
# This isn't normally called directly, but via DSL.eval, which will
|
38
|
+
# pass the block's binding to the new instance, for use with #my.
|
39
|
+
#
|
40
|
+
# @param [Binding] The block's binding.
|
41
|
+
def initialize(caller_binding)
|
42
|
+
@caller = caller_binding.eval 'self'
|
43
|
+
end
|
44
|
+
|
45
|
+
# If you really need to get at an instance variable or method inside
|
46
|
+
# a DSL block, this method will let you do it. It passes a block back
|
47
|
+
# to the DSL's caller for instance_eval.
|
48
|
+
#
|
49
|
+
# It's also pretty evil, so I hope you enjoy using it while I'm burning in
|
50
|
+
# programmer hell.
|
51
|
+
#
|
52
|
+
# @param &block A block to instance_eval against the DSL's caller.
|
53
|
+
# @return
|
54
|
+
def my(&block)
|
55
|
+
@caller.instance_eval &block
|
56
|
+
end
|
57
|
+
|
58
|
+
# Node generation inside DSL blocks.
|
59
|
+
#
|
60
|
+
# @overload node_name
|
61
|
+
# Creates a Stub. Method calls chained from this Stub will determine
|
62
|
+
# what type of node we eventually end up with.
|
63
|
+
# @return [Nodes::Stub] A stub with the name of the method
|
64
|
+
# @overload node_name(klass)
|
65
|
+
# Creates a Join with a polymorphic class matching the given parameter
|
66
|
+
# @param [Class] klass The polymorphic class of the join node
|
67
|
+
# @return [Nodes::Join] A join node with the name of the method and the given class
|
68
|
+
# @overload node_name(first_arg, *other_args)
|
69
|
+
# Creates a Function with the given arguments becoming the function's arguments
|
70
|
+
# @param first_arg The first argument
|
71
|
+
# @param *other_args Optional additional arguments
|
72
|
+
# @return [Nodes::Function] A function node for the given method name with the given arguments
|
20
73
|
def method_missing(method_id, *args)
|
74
|
+
super if method_id == :to_ary
|
75
|
+
|
21
76
|
if args.empty?
|
22
77
|
Nodes::Stub.new method_id
|
23
78
|
elsif (args.size == 1) && (Class === args[0])
|
data/lib/squeel/nodes.rb
CHANGED
data/lib/squeel/nodes/and.rb
CHANGED
data/lib/squeel/nodes/binary.rb
CHANGED
@@ -2,22 +2,31 @@ require 'squeel/nodes/predicate_operators'
|
|
2
2
|
|
3
3
|
module Squeel
|
4
4
|
module Nodes
|
5
|
+
# A node that represents an operation with two operands.
|
5
6
|
class Binary
|
7
|
+
|
6
8
|
include PredicateOperators
|
7
9
|
|
8
|
-
|
10
|
+
# The left operand
|
11
|
+
attr_reader :left
|
12
|
+
|
13
|
+
# The right operand
|
14
|
+
attr_reader :right
|
9
15
|
|
16
|
+
# @param left The left operand
|
17
|
+
# @param right The right operand
|
10
18
|
def initialize(left, right)
|
11
19
|
@left, @right = left, right
|
12
20
|
end
|
13
21
|
|
22
|
+
# Comparison with other nodes
|
14
23
|
def eql?(other)
|
15
24
|
self.class == other.class &&
|
16
25
|
self.left == other.left &&
|
17
26
|
self.right == other.right
|
18
27
|
end
|
19
|
-
|
20
28
|
alias :== :eql?
|
29
|
+
|
21
30
|
end
|
22
31
|
end
|
23
32
|
end
|
@@ -2,26 +2,49 @@ require 'squeel/predicate_methods'
|
|
2
2
|
|
3
3
|
module Squeel
|
4
4
|
module Nodes
|
5
|
+
# A node that represents an SQL function call
|
5
6
|
class Function
|
6
7
|
|
7
8
|
include PredicateMethods
|
8
9
|
include Operators
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
alias :== :eq
|
12
|
+
alias :'^' :not_eq
|
13
|
+
alias :'!=' :not_eq if respond_to?(:'!=')
|
14
|
+
alias :>> :in
|
15
|
+
alias :<< :not_in
|
16
|
+
alias :=~ :matches
|
17
|
+
alias :'!~' :does_not_match if respond_to?(:'!~')
|
18
|
+
alias :> :gt
|
19
|
+
alias :>= :gteq
|
20
|
+
alias :< :lt
|
21
|
+
alias :<= :lteq
|
22
|
+
|
23
|
+
# @return [Symbol] The name of the SQL function to be called
|
24
|
+
attr_reader :name
|
25
|
+
|
26
|
+
# @return [Array] The arguments to be passed to the SQL function
|
27
|
+
attr_reader :args
|
28
|
+
|
29
|
+
# @return [String] The SQL function's alias
|
30
|
+
# @return [NilClass] If no alias
|
31
|
+
attr_reader :alias
|
32
|
+
|
33
|
+
# Create a node representing an SQL Function with the given name and arguments
|
34
|
+
# @param [Symbol] name The function name
|
35
|
+
# @param [Array] args The array of arguments to pass to the function.
|
12
36
|
def initialize(name, args)
|
13
37
|
@name, @args = name, args
|
14
38
|
end
|
15
39
|
|
40
|
+
# Set an alias for the function
|
41
|
+
# @param [String, Symbol] The alias name
|
42
|
+
# @return [Function] This function with the new alias value.
|
16
43
|
def as(alias_name)
|
17
44
|
@alias = alias_name.to_s
|
18
45
|
self
|
19
46
|
end
|
20
47
|
|
21
|
-
def ==(value)
|
22
|
-
Predicate.new self, :eq, value
|
23
|
-
end
|
24
|
-
|
25
48
|
def asc
|
26
49
|
Order.new self, 1
|
27
50
|
end
|
@@ -30,51 +53,10 @@ module Squeel
|
|
30
53
|
Order.new self, -1
|
31
54
|
end
|
32
55
|
|
33
|
-
# Won't work on Ruby 1.8.x so need to do this conditionally
|
34
|
-
define_method('!=') do |value|
|
35
|
-
Predicate.new(self, :not_eq, value)
|
36
|
-
end if respond_to?('!=')
|
37
|
-
|
38
|
-
def ^(value)
|
39
|
-
Predicate.new self, :not_eq, value
|
40
|
-
end
|
41
|
-
|
42
|
-
def >>(value)
|
43
|
-
Predicate.new self, :in, value
|
44
|
-
end
|
45
|
-
|
46
|
-
def <<(value)
|
47
|
-
Predicate.new self, :not_in, value
|
48
|
-
end
|
49
|
-
|
50
|
-
def =~(value)
|
51
|
-
Predicate.new self, :matches, value
|
52
|
-
end
|
53
|
-
|
54
|
-
# Won't work on Ruby 1.8.x so need to do this conditionally
|
55
|
-
define_method('!~') do |value|
|
56
|
-
Predicate.new(self, :does_not_match, value)
|
57
|
-
end if respond_to?('!~')
|
58
|
-
|
59
|
-
def >(value)
|
60
|
-
Predicate.new self, :gt, value
|
61
|
-
end
|
62
|
-
|
63
|
-
def >=(value)
|
64
|
-
Predicate.new self, :gteq, value
|
65
|
-
end
|
66
|
-
|
67
|
-
def <(value)
|
68
|
-
Predicate.new self, :lt, value
|
69
|
-
end
|
70
|
-
|
71
|
-
def <=(value)
|
72
|
-
Predicate.new self, :lteq, value
|
73
|
-
end
|
74
|
-
|
75
56
|
# expand_hash_conditions_for_aggregates assumes our hash keys can be
|
76
57
|
# converted to symbols, so this has to be implemented, but it doesn't
|
77
58
|
# really have to do anything useful.
|
59
|
+
# @return [NilClass] Just to avoid bombing out on expand_hash_conditions_for_aggregates
|
78
60
|
def to_sym
|
79
61
|
nil
|
80
62
|
end
|