rquery 0.3.0 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +14 -0
- data/lib/rquery.rb +1 -3
- data/lib/rquery/active_record/base.rb +26 -16
- data/lib/rquery/attribute_collection.rb +12 -37
- data/lib/rquery/operation_collector.rb +14 -57
- data/lib/rquery/operations_group.rb +32 -0
- data/spec/{active_record_base_spec_attribute_collection.rb → active_record_base_attribute_collection_spec.rb} +46 -40
- data/spec/or_and_operations_spec.rb +6 -8
- data/spec/sniper_scope_spec.rb +21 -0
- data/spec/spec_helper.rb +26 -0
- metadata +7 -5
- data/spec/mock_active_record.rb +0 -13
data/README.markdown
CHANGED
@@ -17,6 +17,20 @@ In you're rails environment file simply require rquery. The default adapter is t
|
|
17
17
|
|
18
18
|
You can view both Sql and Sqlite in the adapters directory if you are interested in writing your own (mysql?). As a side note it would be nice at some point to decide the adapter based on the db chosen for a given environment.
|
19
19
|
|
20
|
+
###Sniper Scopes
|
21
|
+
|
22
|
+
Its now extremely easy to use rquery's dsl as named scopes. For example
|
23
|
+
|
24
|
+
class User < ActiveRecord::Base
|
25
|
+
sniper_scope :with_name do |user, passed_name|
|
26
|
+
user.name == passed_name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
User.with_name('George')
|
31
|
+
|
32
|
+
The first parameter will be an object representing the user and the rest will be the parameters passed when the method is called. Since this functionality makes use of the named_scope method it can be chained with other sniper_scopes and named_scopes. If the name seems a bit odd, I'm open to other suggestions :D
|
33
|
+
|
20
34
|
###Examples
|
21
35
|
|
22
36
|
RQuery extend ActiveRecord to provide the `where` method. `where` accepts a single optional argument and a block that represents the query statements
|
data/lib/rquery.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
$: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
2
2
|
|
3
|
-
|
4
|
-
#and expressive.
|
5
|
-
|
3
|
+
require "rquery/operations_group.rb"
|
6
4
|
require "rquery/operation_collector.rb"
|
7
5
|
require "rquery/attribute_collection.rb"
|
8
6
|
require "rquery/adapters.rb"
|
@@ -1,26 +1,36 @@
|
|
1
1
|
module RQuery
|
2
2
|
module ActiveRecord
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
module ClassMethods
|
4
|
+
def where(*args, &block)
|
5
|
+
collector = AttributeCollection.new(columns.map {|x| x.name })
|
6
|
+
|
7
|
+
#Passes a new AttributeCollection object to the block, which will in turn
|
8
|
+
#instantiate a OperationCollector to be used for each expression
|
9
|
+
yield(collector)
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
#record altered conditions and values
|
12
|
+
conditions = collector.clauses.to_conditions
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
#limit the records returned (:first, :all, :last)
|
15
|
+
limit = args.first ? args.first : :all
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
#call find with the conditions and values provided by the block
|
18
|
+
find(limit, :conditions => conditions)
|
19
|
+
end
|
20
|
+
|
21
|
+
def sniper_scope(name, &block)
|
22
|
+
#rescope self
|
23
|
+
klass = self
|
24
|
+
named_scope name, lambda { |*args|
|
25
|
+
collector = AttributeCollection.new(klass.columns.map {|x| x.name })
|
26
|
+
block.call(collector, *args)
|
27
|
+
{ :conditions => collector.clauses.to_conditions }
|
28
|
+
}
|
29
|
+
end
|
19
30
|
end
|
20
31
|
end
|
21
32
|
end
|
22
33
|
|
23
34
|
#extend ActiveRecord::Base with the where method
|
24
|
-
|
25
|
-
|
26
|
-
end
|
35
|
+
ActiveRecord::Base.send :extend, RQuery::ActiveRecord::ClassMethods
|
36
|
+
|
@@ -3,45 +3,23 @@ module RQuery
|
|
3
3
|
attr_reader :clauses
|
4
4
|
|
5
5
|
def initialize(fields)
|
6
|
-
@fields = fields.map{ |x| x.to_s }
|
7
6
|
@clauses = OperationCollector.new
|
8
|
-
end
|
9
|
-
|
10
|
-
#if the field was added upon initialization its a valid call
|
11
|
-
#otherwise report to the user it is invalid. Reports errors at the ruby level
|
12
|
-
#instead of the data store level with something like "column doesn't exist"
|
13
|
-
#
|
14
|
-
#example
|
15
|
-
#
|
16
|
-
# >> user = RQuery::FieldCollection.new([:age, :name])
|
17
|
-
# => #<RQuery::FieldCollection:0x1a2c21c @fields=[:age, :name]>
|
18
|
-
# >> user.age
|
19
|
-
# => #<RQuery::Field:0x1a2b240 @name=:age>
|
20
|
-
# >> user.name
|
21
|
-
# => #<RQuery::Field:0x1a2a390 @name=:name>
|
22
|
-
# >> user.weight
|
23
|
-
# ArgumentError: The field 'weight' doesn't exist for this object
|
24
|
-
# from /Users/johnbender/Projects/rquery/lib/rquery/where_clause.rb:20:in `method_missing'
|
25
|
-
# from (irb):5
|
26
|
-
def method_missing(symbol, *args)
|
27
|
-
attr_str = symbol.to_s
|
28
|
-
eq_str = attr_str.gsub(/=/, '')
|
29
7
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
8
|
+
# For each field define it and its setter to add the appropriate clause
|
9
|
+
fields.each do |field|
|
10
|
+
self.class.send(:define_method, field) do |*args|
|
11
|
+
add_clause(field)
|
12
|
+
@clauses
|
13
|
+
end
|
14
|
+
|
15
|
+
self.class.send(:define_method, (field + '=')) do |*args|
|
16
|
+
add_clause(field)
|
17
|
+
eq(*args)
|
18
|
+
@clauses
|
19
|
+
end
|
37
20
|
end
|
38
|
-
|
39
|
-
#explicit return of OperationCollector, same instance returned by methods of Operation collector
|
40
|
-
#but included here for clarity
|
41
|
-
@clauses
|
42
21
|
end
|
43
22
|
|
44
|
-
|
45
23
|
private
|
46
24
|
def add_clause(str)
|
47
25
|
@clauses.add_operation(str)
|
@@ -50,8 +28,5 @@ module RQuery
|
|
50
28
|
def eq(*args)
|
51
29
|
@clauses.send(:==, *args)
|
52
30
|
end
|
53
|
-
|
54
31
|
end
|
55
|
-
|
56
|
-
class AttributeNotFoundError < ArgumentError; end
|
57
32
|
end
|
@@ -25,53 +25,21 @@ module RQuery
|
|
25
25
|
self
|
26
26
|
end
|
27
27
|
|
28
|
-
#grouping is done by using the | and & operators between multiple operations
|
29
|
-
#objects on a single line.
|
30
|
-
#
|
31
|
-
#This works because each operation ie (user.age.is == 2) is
|
32
|
-
#evaluated before these two operators thus pushing
|
33
|
-
#the equivelant operation string onto the @operations array (ie 'age = ?').
|
34
|
-
#When an operation is evaluated it returns the Operations class which can be compared
|
35
|
-
#using the aforementioned operators. Those operators call the group method
|
36
|
-
#popping the last two arguments off the stack and dealing with them in one of two ways
|
37
|
-
#
|
38
|
-
#1. if the second object popped is a string both objects should be
|
39
|
-
# added to a new OperationGroup which is then put back onto the stack
|
40
|
-
#
|
41
|
-
#2. if the second object popped is an OperationGroup the firest belongs to this group as
|
42
|
-
# well (it was on the same line). It is added to the OperationGroup and put back on the
|
43
|
-
# stack
|
44
|
-
#
|
45
|
-
#TODO requires refactoring
|
46
|
-
def group(type)
|
47
|
-
second_op, first_op = @operations.pop, @operations.pop
|
48
|
-
|
49
|
-
#if the previous operation on the stack is an Operation Group we need to add to it
|
50
|
-
#and push it back on the @operations stack
|
51
|
-
if first_op.class == OperationsGroup
|
52
|
-
if first_op.type == type
|
53
|
-
first_op.ops << second_op
|
54
|
-
@operations << first_op
|
55
|
-
else
|
56
|
-
@operations << OperationsGroup.new(first_op.to_s, second_op, type)
|
57
|
-
end
|
58
|
-
else
|
59
|
-
@operations << OperationsGroup.new(first_op, second_op, type)
|
60
|
-
end
|
61
|
-
|
62
|
-
self
|
63
|
-
end
|
64
|
-
|
65
28
|
#used to group operations for anding on a single line
|
66
29
|
#example with sqlite adapter
|
67
30
|
#(user.age.in [1,2,3]) | (user.name.contains "foo")
|
68
31
|
#=>(age in (?) and name like '%' || 'foo' || '%')
|
32
|
+
#
|
33
|
+
# note that second is not used in this case because it should
|
34
|
+
# have been collected into the @operations array earlier
|
69
35
|
def &(second)
|
70
|
-
|
36
|
+
@operations << AndOperationsGroup.new(tail_ops!(2))
|
37
|
+
self
|
71
38
|
end
|
72
39
|
|
73
40
|
def |(second)
|
74
|
-
|
41
|
+
@operations << OrOperationsGroup.new(tail_ops!(2))
|
42
|
+
self
|
75
43
|
end
|
76
44
|
|
77
45
|
def in(*args)
|
@@ -120,13 +88,17 @@ module RQuery
|
|
120
88
|
alias :from :between
|
121
89
|
alias :not_from :not_between
|
122
90
|
|
123
|
-
private
|
91
|
+
private
|
92
|
+
def tail_ops!(num)
|
93
|
+
@operations.slice!(@operations.length-2, num)
|
94
|
+
end
|
95
|
+
|
124
96
|
def chain(method)
|
125
97
|
@operations[@operations.length-1] += " #{RQuery::Config.adapter.send(method)}"
|
126
98
|
self
|
127
99
|
end
|
128
100
|
|
129
|
-
def call_in(prefix
|
101
|
+
def call_in(prefix, *args)
|
130
102
|
#flatten our args to prevent having to check for an array first arg
|
131
103
|
args.flatten!
|
132
104
|
|
@@ -141,7 +113,7 @@ module RQuery
|
|
141
113
|
chain :"#{prefix}in"
|
142
114
|
end
|
143
115
|
|
144
|
-
def call_between(prefix
|
116
|
+
def call_between(prefix, *args)
|
145
117
|
#flatten our args to prevent having to check for an array first arg
|
146
118
|
args.flatten!
|
147
119
|
|
@@ -157,19 +129,4 @@ module RQuery
|
|
157
129
|
chain :"#{prefix}between"
|
158
130
|
end
|
159
131
|
end
|
160
|
-
|
161
|
-
class OperationsGroup
|
162
|
-
attr_accessor :ops, :type
|
163
|
-
|
164
|
-
def initialize(left, right, type)
|
165
|
-
@ops = Array.new
|
166
|
-
@ops << left
|
167
|
-
@ops << right
|
168
|
-
@type = type
|
169
|
-
end
|
170
|
-
|
171
|
-
def to_s
|
172
|
-
RQuery::Config.adapter.send("#{type.to_s}_group", @ops)
|
173
|
-
end
|
174
|
-
end
|
175
132
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module RQuery
|
2
|
+
class OperationsGroup
|
3
|
+
attr_accessor :operations
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
@operations = []
|
7
|
+
#if the two args passed are strings make a new group
|
8
|
+
#otherwise add the second arg to the previous operation group
|
9
|
+
#
|
10
|
+
# NOTE coupling by type assumption here
|
11
|
+
@operations = args[0].instance_of?(String) ? args[0,2] : (args[0].operations << args[1])
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
RQuery::Config.adapter.send("#{@type.to_s}_group", @operations)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class OrOperationsGroup < OperationsGroup
|
20
|
+
def initialize(args)
|
21
|
+
super(args)
|
22
|
+
@type = :or
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class AndOperationsGroup < OperationsGroup
|
27
|
+
def initialize(args)
|
28
|
+
super(args)
|
29
|
+
@type = :and
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + "/
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + "/../lib/rquery.rb")
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
|
3
2
|
|
4
3
|
describe ActiveRecord do
|
5
4
|
|
@@ -8,50 +7,57 @@ describe ActiveRecord do
|
|
8
7
|
end
|
9
8
|
|
10
9
|
it "should set up a where method" do
|
11
|
-
|
10
|
+
MockObject.respond_to?(:where).should == true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should behave properly when using the id method" do
|
14
|
+
MockObject.where { |mock|
|
15
|
+
mock.id == 1
|
16
|
+
}.should == [:all, {:conditions => ['(id = ?)', 1]}]
|
12
17
|
end
|
13
18
|
|
14
19
|
it "should return sql with foo, the operations, and the values for mock.foo <operation> <value>" do
|
15
|
-
|
20
|
+
MockObject.where{ |mock|
|
16
21
|
mock.foo == "bar"
|
17
22
|
mock.foo = "bar"
|
18
23
|
}.should == [:all, {:conditions => ["(foo = ? and foo = ?)", "bar", "bar"]}]
|
19
24
|
|
20
|
-
|
25
|
+
MockObject.where{ |mock|
|
21
26
|
mock.foo > 1
|
22
27
|
}.should == [:all, {:conditions => ["(foo > ?)", 1]}]
|
23
28
|
|
24
|
-
|
29
|
+
MockObject.where{ |mock|
|
25
30
|
mock.foo < 2
|
26
31
|
}.should == [:all, {:conditions => ["(foo < ?)", 2]}]
|
27
32
|
|
28
|
-
|
33
|
+
MockObject.where{ |mock|
|
29
34
|
mock.foo >= 3
|
30
35
|
}.should == [:all, {:conditions => ["(foo >= ?)", 3]}]
|
31
36
|
|
32
|
-
|
37
|
+
MockObject.where{ |mock|
|
33
38
|
mock.foo <= 4
|
34
39
|
}.should == [:all, {:conditions => ["(foo <= ?)", 4]}]
|
35
40
|
end
|
36
41
|
|
37
42
|
it "should return sql with foo, the operations, and the values for mock.foo.not_<operation> <value>" do
|
38
|
-
|
43
|
+
MockObject.where{ |mock|
|
39
44
|
mock.foo.not = "bar"
|
40
45
|
}.should == [:all, {:conditions => ["(foo <> ?)", "bar"]}]
|
41
46
|
|
42
|
-
|
47
|
+
MockObject.where{ |mock|
|
43
48
|
mock.foo.not_in 1,2
|
44
49
|
}.should == [:all, {:conditions => ["(foo not in (?))", [1,2]]}]
|
45
50
|
|
46
|
-
|
51
|
+
MockObject.where{ |mock|
|
47
52
|
mock.foo.not_between 1..3
|
48
53
|
}.should == [:all, {:conditions => ["(foo not between ? and ?)", 1, 3]}]
|
49
54
|
|
50
|
-
|
55
|
+
|
56
|
+
MockObject.where{ |mock|
|
51
57
|
mock.foo.not_from 1..3
|
52
58
|
}.should == [:all, {:conditions => ["(foo not between ? and ?)", 1, 3]}]
|
53
59
|
|
54
|
-
|
60
|
+
MockObject.where{ |mock|
|
55
61
|
mock.foo.without "bar"
|
56
62
|
}.should == [:all, {:conditions => ["(foo not like '%' || ? || '%')", "bar"]}]
|
57
63
|
end
|
@@ -59,27 +65,27 @@ describe ActiveRecord do
|
|
59
65
|
it "should return sql with foo, the operations, and values for mock.foo.in and mock.foo.in when used with a list of args, array, and range" do
|
60
66
|
resulting_conditions = [:all, {:conditions => ["(foo in (?))", [1,2,3,4]]}]
|
61
67
|
|
62
|
-
|
68
|
+
MockObject.where{ |mock|
|
63
69
|
mock.foo.in 1,2,3,4
|
64
70
|
}.should == resulting_conditions
|
65
71
|
|
66
|
-
|
72
|
+
MockObject.where{ |mock|
|
67
73
|
mock.foo.in [1,2,3,4]
|
68
74
|
}.should == resulting_conditions
|
69
75
|
|
70
|
-
|
76
|
+
MockObject.where{ |mock|
|
71
77
|
mock.foo.in 1..4
|
72
78
|
}.should == [:all, {:conditions => ["(foo in (?))", 1..4]}]
|
73
79
|
|
74
|
-
|
80
|
+
MockObject.where{ |mock|
|
75
81
|
mock.foo.in 1,2,3,4
|
76
82
|
}.should == resulting_conditions
|
77
83
|
|
78
|
-
|
84
|
+
MockObject.where{ |mock|
|
79
85
|
mock.foo.in [1,2,3,4]
|
80
86
|
}.should == resulting_conditions
|
81
87
|
|
82
|
-
|
88
|
+
MockObject.where{ |mock|
|
83
89
|
mock.foo.in 1..4
|
84
90
|
}.should == [:all, {:conditions => ["(foo in (?))", 1..4]}]
|
85
91
|
end
|
@@ -87,27 +93,27 @@ describe ActiveRecord do
|
|
87
93
|
it "should return sql with foo, operations, and values for mock.foo.between and mock.foo.between when used with a list of args, array, and range" do
|
88
94
|
resulting_conditions = [:all, {:conditions => ["(foo between ? and ?)", 1, 2]}]
|
89
95
|
|
90
|
-
|
96
|
+
MockObject.where{ |mock|
|
91
97
|
mock.foo.between 1,2
|
92
98
|
}.should == resulting_conditions
|
93
99
|
|
94
|
-
|
100
|
+
MockObject.where{ |mock|
|
95
101
|
mock.foo.between [1,2]
|
96
102
|
}.should == resulting_conditions
|
97
103
|
|
98
|
-
|
104
|
+
MockObject.where{ |mock|
|
99
105
|
mock.foo.between 1..2
|
100
106
|
}.should == resulting_conditions
|
101
107
|
|
102
|
-
|
108
|
+
MockObject.where{ |mock|
|
103
109
|
mock.foo.between 1,2
|
104
110
|
}.should == resulting_conditions
|
105
111
|
|
106
|
-
|
112
|
+
MockObject.where{ |mock|
|
107
113
|
mock.foo.between [1,2]
|
108
114
|
}.should == resulting_conditions
|
109
115
|
|
110
|
-
|
116
|
+
MockObject.where{ |mock|
|
111
117
|
mock.foo.between 1..2
|
112
118
|
}.should == resulting_conditions
|
113
119
|
end
|
@@ -115,27 +121,27 @@ describe ActiveRecord do
|
|
115
121
|
it "should return sql with foo, operations, and values for mock.foo.from when used with a list of args, array, and range" do
|
116
122
|
resulting_conditions = [:all, {:conditions => ["(foo between ? and ?)", 1, 2]}]
|
117
123
|
|
118
|
-
|
124
|
+
MockObject.where{ |mock|
|
119
125
|
mock.foo.from 1,2
|
120
126
|
}.should == resulting_conditions
|
121
127
|
|
122
|
-
|
128
|
+
MockObject.where{ |mock|
|
123
129
|
mock.foo.from [1,2]
|
124
130
|
}.should == resulting_conditions
|
125
131
|
|
126
|
-
|
132
|
+
MockObject.where{ |mock|
|
127
133
|
mock.foo.from 1..2
|
128
134
|
}.should == resulting_conditions
|
129
135
|
|
130
|
-
|
136
|
+
MockObject.where{ |mock|
|
131
137
|
mock.foo.from 1,2
|
132
138
|
}.should == resulting_conditions
|
133
139
|
|
134
|
-
|
140
|
+
MockObject.where{ |mock|
|
135
141
|
mock.foo.from [1,2]
|
136
142
|
}.should == resulting_conditions
|
137
143
|
|
138
|
-
|
144
|
+
MockObject.where{ |mock|
|
139
145
|
mock.foo.from 1..2
|
140
146
|
}.should == resulting_conditions
|
141
147
|
end
|
@@ -143,27 +149,27 @@ describe ActiveRecord do
|
|
143
149
|
it "should return sql with foo, operations, and values for mock.foo.contains when used with a range, array, and list" do
|
144
150
|
resulting_conditions = [:all, {:conditions => ["(foo like '%' || ? || '%')", "bar"]}]
|
145
151
|
|
146
|
-
|
152
|
+
MockObject.where{ |mock|
|
147
153
|
mock.foo.contains "bar"
|
148
154
|
}.should == resulting_conditions
|
149
155
|
end
|
150
156
|
|
151
157
|
it "should return return the correct group of joined sql after multiple operations" do
|
152
|
-
|
158
|
+
MockObject.where{ |mock|
|
153
159
|
mock.foo == "bar"
|
154
160
|
mock.foo.not_in 1,2,3,4,5
|
155
161
|
}.should == [:all, {:conditions => ["(foo = ? and foo not in (?))", "bar", [1,2,3,4,5]]}]
|
156
162
|
end
|
157
163
|
|
158
164
|
it "should return return the correct limit value passed" do
|
159
|
-
|
165
|
+
MockObject.where(:first){ |mock|
|
160
166
|
mock.foo == "bar"
|
161
167
|
mock.foo.not_in 1,2,3,4,5
|
162
168
|
}.should == [:first, {:conditions => ["(foo = ? and foo not in (?))", "bar", [1,2,3,4,5]]}]
|
163
169
|
end
|
164
170
|
|
165
171
|
it "should have the correct 'not' keywords in alternating operations" do
|
166
|
-
|
172
|
+
MockObject.where(:first){ |mock|
|
167
173
|
mock.foo == "bar"
|
168
174
|
mock.foo.not_in 1,2,3,4,5
|
169
175
|
mock.foo > 3
|
@@ -171,25 +177,25 @@ describe ActiveRecord do
|
|
171
177
|
end
|
172
178
|
|
173
179
|
it "should return return strings as arguments when passed to between, in, and from (used for date strings)" do
|
174
|
-
|
180
|
+
MockObject.where{ |mock|
|
175
181
|
mock.foo.between "some string", "2007-01-01"
|
176
182
|
}.should == [:all, {:conditions => ["(foo between ? and ?)", "some string", "2007-01-01"]}]
|
177
183
|
|
178
|
-
|
184
|
+
MockObject.where{ |mock|
|
179
185
|
mock.foo.not_between "some string", "2007-01-01"
|
180
186
|
}.should == [:all, {:conditions => ["(foo not between ? and ?)", "some string", "2007-01-01"]}]
|
181
187
|
|
182
|
-
|
188
|
+
MockObject.where{ |mock|
|
183
189
|
mock.foo.from "some string", "2007-01-01"
|
184
190
|
}.should == [:all, {:conditions => ["(foo between ? and ?)", "some string", "2007-01-01"]}]
|
185
191
|
|
186
|
-
|
192
|
+
MockObject.where{ |mock|
|
187
193
|
mock.foo.in "some string", "2007-01-01"
|
188
194
|
}.should == [:all, {:conditions => ["(foo in (?))", ["some string", "2007-01-01"]]}]
|
189
195
|
end
|
190
196
|
|
191
197
|
it "should throw and exception when trying to use a field not in the objects attributes" do
|
192
198
|
attribute = "arbitrary_attribute_name"
|
193
|
-
lambda {
|
199
|
+
lambda { MockObject.where{ |mock| mock.send(attribute) == 2 }}.should raise_error(NoMethodError)
|
194
200
|
end
|
195
201
|
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + "/
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + "/../lib/rquery.rb")
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
|
3
2
|
|
4
3
|
describe RQuery::OperationCollector do
|
5
4
|
|
@@ -9,7 +8,7 @@ describe RQuery::OperationCollector do
|
|
9
8
|
|
10
9
|
it "should group two operations on the same line with parens and the 'or' keyword when the | operator is used" do
|
11
10
|
|
12
|
-
|
11
|
+
MockObject.where{ |mock|
|
13
12
|
(mock.foo == 2) | (mock.foo.in 1,2,3)
|
14
13
|
}.should == [:all, {:conditions => ["((foo = ? or foo in (?)))", 2, [1,2,3]]}]
|
15
14
|
|
@@ -17,7 +16,7 @@ describe RQuery::OperationCollector do
|
|
17
16
|
|
18
17
|
it "should group two operations on the same line with parns and the 'and' keyword when the & operator is used" do
|
19
18
|
|
20
|
-
|
19
|
+
MockObject.where{ |mock|
|
21
20
|
(mock.foo == 2) & (mock.foo.in 1,2,3)
|
22
21
|
}.should == [:all, {:conditions => ["((foo = ? and foo in (?)))", 2, [1,2,3]]}]
|
23
22
|
|
@@ -25,7 +24,7 @@ describe RQuery::OperationCollector do
|
|
25
24
|
|
26
25
|
it "should group two operations on the same line and continue to add subsequent operations" do
|
27
26
|
|
28
|
-
|
27
|
+
MockObject.where{ |mock|
|
29
28
|
(mock.foo == 2) & (mock.foo.in 1,2,3)
|
30
29
|
mock.foo > 3
|
31
30
|
}.should == [:all, {:conditions => ["((foo = ? and foo in (?)) and foo > ?)", 2, [1,2,3], 3]}]
|
@@ -34,7 +33,7 @@ describe RQuery::OperationCollector do
|
|
34
33
|
|
35
34
|
it "should properly group multiple nested groupings on the same line" do
|
36
35
|
|
37
|
-
|
36
|
+
MockObject.where{ |mock|
|
38
37
|
(mock.foo == 2) | (mock.foo.in 1,2,3) | (mock.foo.contains "george")
|
39
38
|
mock.foo > 3
|
40
39
|
(mock.foo == 2) & (mock.foo.in 1,2,3)
|
@@ -44,10 +43,9 @@ describe RQuery::OperationCollector do
|
|
44
43
|
|
45
44
|
it "& should have precedence when evaluating multiple operation group types on a single line" do
|
46
45
|
|
47
|
-
|
46
|
+
MockObject.where{ |mock|
|
48
47
|
(mock.foo == 2) | (mock.foo.in 1,2,3) & (mock.foo.contains "george")
|
49
48
|
}.should == [:all, {:conditions => ["((foo = ? or (foo in (?) and foo like '%' || ? || '%')))", 2, [1,2,3], "george"]}]
|
50
|
-
|
51
49
|
|
52
50
|
end
|
53
51
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/spec_helper.rb")
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/rquery.rb")
|
3
|
+
|
4
|
+
describe ActiveRecord do
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
RQuery::Config.adapter = RQuery::Adapters::Sqlite
|
8
|
+
MockObject.sniper_scope :baz do |object, foo_val|
|
9
|
+
object.foo == foo_val
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should proved a named scope on the active record object when sniper_scope is defined" do
|
14
|
+
MockObject.respond_to?(:baz).should == true
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should set the named scope conditions properly when the sniper_scope is defined" do
|
18
|
+
result = MockObject.baz('bar').proxy_options
|
19
|
+
result.should == {:conditions => ['(foo = ?)', 'bar']}
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'spec/autorun'
|
4
|
+
require 'active_record'
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/rquery.rb")
|
6
|
+
|
7
|
+
class MockObject < ActiveRecord::Base
|
8
|
+
def self.find(limit, conditions)
|
9
|
+
[limit, conditions]
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.columns
|
16
|
+
[Column.new("foo"), Column.new("id")]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Column
|
21
|
+
attr_accessor :name
|
22
|
+
def initialize(n)
|
23
|
+
@name = n
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rquery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John bender
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-14 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -32,10 +32,12 @@ files:
|
|
32
32
|
- lib/rquery/adapters/sql.rb
|
33
33
|
- lib/rquery/adapters/sqlite.rb
|
34
34
|
- lib/rquery/operation_collector.rb
|
35
|
-
-
|
36
|
-
- spec/
|
35
|
+
- lib/rquery/operations_group.rb
|
36
|
+
- spec/active_record_base_attribute_collection_spec.rb
|
37
37
|
- spec/or_and_operations_spec.rb
|
38
38
|
- spec/sqlite_adapter_spec.rb
|
39
|
+
- spec/sniper_scope_spec.rb
|
40
|
+
- spec/spec_helper.rb
|
39
41
|
has_rdoc: true
|
40
42
|
homepage: http://github.com/johnbender/rquery
|
41
43
|
licenses: []
|
@@ -60,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
62
|
requirements: []
|
61
63
|
|
62
64
|
rubyforge_project:
|
63
|
-
rubygems_version: 1.3.
|
65
|
+
rubygems_version: 1.3.5
|
64
66
|
signing_key:
|
65
67
|
specification_version: 3
|
66
68
|
summary: An ActiveRecord extension providing a DSL replacement for complex find queries.
|