rquery 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +87 -0
- data/lib/rquery/active_record/base.rb +35 -0
- data/lib/rquery/active_record.rb +1 -0
- data/lib/rquery/adapters/sql.rb +47 -0
- data/lib/rquery/adapters/sqlite.rb +13 -0
- data/lib/rquery/adapters.rb +2 -0
- data/lib/rquery/declarations.rb +39 -0
- data/lib/rquery/serializers.rb +118 -0
- data/lib/rquery.rb +25 -0
- data/rakefile.rb +7 -0
- data/spec/active_record_base_spec.rb +220 -0
- data/spec/declarations_spec.rb +47 -0
- data/spec/serializers_spec.rb +30 -0
- data/spec/sqlite_adapter_spec.rb +31 -0
- metadata +66 -0
data/README.markdown
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
RQuery
|
2
|
+
======
|
3
|
+
|
4
|
+
RQuery is a small DSL inspired by RSpec for building text queries in languages like SQL. It is meant to be concise, easy to read, and expressive about what the query will be asking for.
|
5
|
+
|
6
|
+
Currently only the ActiveRecord extension is implemented with a Sqlite adapter. Mysql should follow shortly, and then support for Grove + JSON queries to Mnesia.
|
7
|
+
|
8
|
+
ActiveRecord
|
9
|
+
------------
|
10
|
+
|
11
|
+
RQuery extend ActiveRecord to provide the `where` method. `where` accepts a single optional argument and a block that represents the query statements
|
12
|
+
|
13
|
+
###Example compared with `find`
|
14
|
+
|
15
|
+
In a given UsersController your `show` action might find the User like so:
|
16
|
+
|
17
|
+
@user = User.find(params[:id])
|
18
|
+
|
19
|
+
Using RQuery:
|
20
|
+
|
21
|
+
@user = User.where { :id.is == params[:id] }
|
22
|
+
|
23
|
+
|
24
|
+
In the above case, RQuery doesn't provide much of an improvement over the traditional `find` method, but as the query becomes more complex its expressiveness begins to shine through:
|
25
|
+
|
26
|
+
@users = User.find(:all, conditions => ["age between ? and ?", 10 , 20])
|
27
|
+
|
28
|
+
RQuery:
|
29
|
+
|
30
|
+
@users = User.where do
|
31
|
+
:age.from 10..20
|
32
|
+
end
|
33
|
+
|
34
|
+
Or:
|
35
|
+
|
36
|
+
@users = User.where do
|
37
|
+
:age.between 10..20
|
38
|
+
end
|
39
|
+
|
40
|
+
Both the `from` and `between` methods accept argument lists `10,20` or an array `[10,20]`.
|
41
|
+
|
42
|
+
|
43
|
+
###Other Examples
|
44
|
+
|
45
|
+
RQuery supports most of the common SQL operations: =, <>, >, <, >=, <= as well as in, like (see below for specifics), and between. `:column.is_not` works for `.in`, `.between`, `.contains`, and `==`. All operations are anded as of the current version.
|
46
|
+
|
47
|
+
Operators:
|
48
|
+
|
49
|
+
@obj = ActiveRecordObject.where do
|
50
|
+
:foo.is > 2
|
51
|
+
:foo.is_not == 4
|
52
|
+
end
|
53
|
+
#=> conditions array: ["foo > ? and foo <> ?", 2, 4]
|
54
|
+
|
55
|
+
Contains:
|
56
|
+
|
57
|
+
@obj = ActiveRecordObject.where do
|
58
|
+
:foo.contains "bar"
|
59
|
+
end
|
60
|
+
#=> conditions array: ["foo like '%' || ? || '%'", "bar"]
|
61
|
+
#using the default sqlite adapter
|
62
|
+
|
63
|
+
In:
|
64
|
+
|
65
|
+
@obj = ActiveRecordObject.where do
|
66
|
+
:foo.in "bar", "baz", "bak"
|
67
|
+
end
|
68
|
+
#=> conditions array: ["foo in (?)", ["bar", "baz", "bak"]]
|
69
|
+
#using the default sqlite adapter
|
70
|
+
|
71
|
+
|
72
|
+
You can also limit the results returned in a similar manner to the `find` method by passing a symbol argument to the where method. The default is `:all`, when no option is specified.
|
73
|
+
|
74
|
+
First:
|
75
|
+
|
76
|
+
@obj = ActiveRecordObject.where(:first) do
|
77
|
+
:foo.is == "bar"
|
78
|
+
end
|
79
|
+
|
80
|
+
is equivalent to the find call:
|
81
|
+
|
82
|
+
@obj = ActiveRecordObject.find(:first, conditions => ["foo = ?", "bar"])
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RQuery
|
2
|
+
module ActiveRecord
|
3
|
+
@@where_mutex = Mutex.new
|
4
|
+
def where(*args, &block)
|
5
|
+
|
6
|
+
#establish scope for conditions
|
7
|
+
conditions = nil
|
8
|
+
|
9
|
+
#make sure only one thread at a time is altering the class
|
10
|
+
#variables inside RQuery::Serializers::Operations
|
11
|
+
@@where_mutex.synchronize do
|
12
|
+
|
13
|
+
#yielding the block will alter the Operations class
|
14
|
+
yield
|
15
|
+
|
16
|
+
#record altered conditions and values
|
17
|
+
conditions = ::RQuery::Serializers::Operations.conditions
|
18
|
+
|
19
|
+
#clear the alterations
|
20
|
+
::RQuery::Serializers::Operations.clear
|
21
|
+
end
|
22
|
+
|
23
|
+
#limit the records returned (:first, :all, :last)
|
24
|
+
limit = args.first ? args.first : :all
|
25
|
+
|
26
|
+
#call find with the conditions and values provided by the block
|
27
|
+
find(limit, :conditions => conditions)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#extend ActiveRecord::Base with the where method
|
33
|
+
if Object.const_defined?(:ActiveRecord)
|
34
|
+
ActiveRecord::Base.send :extend, RQuery::ActiveRecord
|
35
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "rquery/active_record/base.rb"
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module RQuery
|
2
|
+
module Adapters
|
3
|
+
class Sql
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def in
|
7
|
+
"in (?)"
|
8
|
+
end
|
9
|
+
|
10
|
+
def not_in
|
11
|
+
#using send because 'in' is a keyword
|
12
|
+
"not #{send(:in)}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def between
|
16
|
+
"between ? and ?"
|
17
|
+
end
|
18
|
+
|
19
|
+
def not_between
|
20
|
+
"not #{between}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def neq
|
24
|
+
"<> ?"
|
25
|
+
end
|
26
|
+
|
27
|
+
def ==
|
28
|
+
"= ?"
|
29
|
+
end
|
30
|
+
|
31
|
+
def contains
|
32
|
+
"like '%' + ? + '%'"
|
33
|
+
end
|
34
|
+
|
35
|
+
def join(ops)
|
36
|
+
ops.join(" and ")
|
37
|
+
end
|
38
|
+
|
39
|
+
[:>, :>=, :<, :<=].each do |operator|
|
40
|
+
define_method(operator) do
|
41
|
+
"#{operator} ?"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
module RQuery
|
3
|
+
module Declarations
|
4
|
+
def is
|
5
|
+
::RQuery::Serializers::IsOperations.add_operation(self)
|
6
|
+
::RQuery::Serializers::IsOperations.prefix = nil
|
7
|
+
::RQuery::Serializers::IsOperations
|
8
|
+
end
|
9
|
+
|
10
|
+
def is_not
|
11
|
+
::RQuery::Serializers::IsNotOperations.add_operation(self)
|
12
|
+
::RQuery::Serializers::IsNotOperations.prefix = "not_"
|
13
|
+
::RQuery::Serializers::IsNotOperations
|
14
|
+
end
|
15
|
+
|
16
|
+
def in(*args)
|
17
|
+
::RQuery::Serializers::IsOperations.add_operation(self)
|
18
|
+
::RQuery::Serializers::IsOperations.prefix = nil
|
19
|
+
::RQuery::Serializers::IsOperations.in(*args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def between(*args)
|
23
|
+
::RQuery::Serializers::IsOperations.add_operation(self)
|
24
|
+
::RQuery::Serializers::IsOperations.prefix = nil
|
25
|
+
::RQuery::Serializers::IsOperations.between(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def contains(val)
|
29
|
+
::RQuery::Serializers::IsOperations.add_operation(self)
|
30
|
+
::RQuery::Serializers::IsOperations.prefix = nil
|
31
|
+
::RQuery::Serializers::IsOperations.contains(val)
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :from :between
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Symbol.send :include, RQuery::Declarations
|
39
|
+
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module RQuery
|
2
|
+
module Serializers
|
3
|
+
#The Operations serializer, handles the limiting factors imposed
|
4
|
+
#by a given query. The methods in this class apply to both is and is_not
|
5
|
+
#operations. An example in sql would look like:
|
6
|
+
#
|
7
|
+
#where foo = bar and foo > 2
|
8
|
+
#
|
9
|
+
#This class is a gateway to the selected RQuery.adapter methods.
|
10
|
+
#Calls to methods here, will be passed on to the selected adapter
|
11
|
+
class Operations
|
12
|
+
|
13
|
+
@@prefix = nil
|
14
|
+
@@ops = []
|
15
|
+
@@values = []
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def prefix=(val)
|
19
|
+
@@prefix = val
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
RQuery.adapter.join(@@ops)
|
24
|
+
end
|
25
|
+
|
26
|
+
def conditions
|
27
|
+
[to_s] + @@values
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_operation(val)
|
31
|
+
@@ops << val.to_s
|
32
|
+
end
|
33
|
+
|
34
|
+
def clear
|
35
|
+
@@ops.clear
|
36
|
+
@@values.clear
|
37
|
+
end
|
38
|
+
|
39
|
+
def in(*args)
|
40
|
+
#flatten our args to prevent having to check for an array first arg
|
41
|
+
args.flatten!
|
42
|
+
|
43
|
+
#if a range is passed as the first argument
|
44
|
+
#use it alone, otherwise use the args array
|
45
|
+
#examples:
|
46
|
+
#ruby => args.flatten! => stored values
|
47
|
+
#:id.between 1..100 => [1..100] => 1..100
|
48
|
+
#:id.between [1, 2, 3] => [1, 2, 3] => [1, 2, 3]
|
49
|
+
#:id.between 1, 2 => [1, 2] => [1, 2]
|
50
|
+
#
|
51
|
+
@@values << (args.first.class == Range ? args.first : args)
|
52
|
+
@@ops[@@ops.length-1] += " #{RQuery.adapter.send("#{@@prefix}in")}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def between(*args)
|
56
|
+
#flatten our args to prevent having to check for an array first arg
|
57
|
+
args.flatten!
|
58
|
+
|
59
|
+
#if a range is passed use its first/last element
|
60
|
+
#otherwise use the first and last element of the flattened args array
|
61
|
+
#examples:
|
62
|
+
#ruby => args.flatten! => stored values
|
63
|
+
#:id.between 1..100 => [1..100] => 1 100
|
64
|
+
#:id.between [1, 2, 3] => [1, 2, 3] => 1 3
|
65
|
+
#:id.between 1, 2 => [1, 2] => 1 2
|
66
|
+
#
|
67
|
+
@@values += (args.first.class == Range ? [args.first.first, args.first.last] : [args.first, args.last])
|
68
|
+
@@ops[@@ops.length-1] += " #{RQuery.adapter.send("#{@@prefix}between")}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def contains(str)
|
72
|
+
@@values << str
|
73
|
+
@@ops[@@ops.length-1] += " #{RQuery.adapter.send("#{@@prefix}contains")}"
|
74
|
+
end
|
75
|
+
|
76
|
+
#allows for is.from
|
77
|
+
#examples:
|
78
|
+
#
|
79
|
+
#:id.is.from 1,2
|
80
|
+
#:is.is.from 2..10
|
81
|
+
alias :from :between
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
#The IsOpertaions serializer defines only methods that apply to the .is operator
|
88
|
+
#that is added to the Symbol class in the Declarations module.
|
89
|
+
class IsOperations < Operations
|
90
|
+
|
91
|
+
#define the normal operators for is to call the adapter for the equivelant sql
|
92
|
+
class << self
|
93
|
+
[:==, :>, :>=, :<, :<=].each do |operator|
|
94
|
+
define_method(operator) do |val|
|
95
|
+
@@values << val
|
96
|
+
@@ops[@@ops.length-1] += " #{RQuery.adapter.send(operator)}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
#The IsNotOperations serializer defines only methods that apply to the .is_not operator
|
103
|
+
#that is added to the symbol class in the declarations module. Specifically, == as
|
104
|
+
#ruby does not allow for the overloading of !=
|
105
|
+
class IsNotOperations < Operations
|
106
|
+
|
107
|
+
#define the == value for is_not to call the adapter for the equivelant sql
|
108
|
+
class << self
|
109
|
+
define_method(:==) do |val|
|
110
|
+
@@values << val
|
111
|
+
@@ops[@@ops.length-1] += " #{RQuery.adapter.send(:neq)}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
data/lib/rquery.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
$: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
2
|
+
|
3
|
+
#RQuery is a small DSL for building queries in query languages like SQL. It is meant to be concise, easy to read
|
4
|
+
#and expressive.
|
5
|
+
#
|
6
|
+
|
7
|
+
|
8
|
+
require "rquery/serializers.rb"
|
9
|
+
require "rquery/declarations.rb"
|
10
|
+
require "rquery/adapters.rb"
|
11
|
+
require "rquery/active_record.rb"
|
12
|
+
|
13
|
+
module RQuery
|
14
|
+
@@adapter = RQuery::Adapters::Sqlite
|
15
|
+
|
16
|
+
#Allows for the runtime alteration of the adapter being used
|
17
|
+
#to convert the "rqueries" into the adapters query language
|
18
|
+
def RQuery.adapter=(val)
|
19
|
+
@@adapter = val
|
20
|
+
end
|
21
|
+
def RQuery.adapter
|
22
|
+
@@adapter
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
data/rakefile.rb
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
def Base.find(limit, conditions)
|
4
|
+
return [limit, conditions]
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/rquery.rb")
|
10
|
+
|
11
|
+
describe ActiveRecord do
|
12
|
+
|
13
|
+
before(:all) do
|
14
|
+
RQuery.adapter = RQuery::Adapters::Sqlite
|
15
|
+
end
|
16
|
+
|
17
|
+
#should really set up the find method defined above to use the ruby db libraries and
|
18
|
+
#create the final sql string
|
19
|
+
#all run with default adapter
|
20
|
+
|
21
|
+
it "should set up a where method" do
|
22
|
+
ActiveRecord::Base.respond_to?(:where).should == true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return sql with foo, the operations, and the values for :foo.is <operation> <value>" do
|
26
|
+
|
27
|
+
ActiveRecord::Base.where{
|
28
|
+
:foo.is == "bar"
|
29
|
+
}.should == [:all, {:conditions => ["foo = ?", "bar"]}]
|
30
|
+
|
31
|
+
ActiveRecord::Base.where{
|
32
|
+
:foo.is > 1
|
33
|
+
}.should == [:all, {:conditions => ["foo > ?", 1]}]
|
34
|
+
|
35
|
+
ActiveRecord::Base.where{
|
36
|
+
:foo.is < 2
|
37
|
+
}.should == [:all, {:conditions => ["foo < ?", 2]}]
|
38
|
+
|
39
|
+
ActiveRecord::Base.where{
|
40
|
+
:foo.is >= 3
|
41
|
+
}.should == [:all, {:conditions => ["foo >= ?", 3]}]
|
42
|
+
|
43
|
+
ActiveRecord::Base.where{
|
44
|
+
:foo.is <= 4
|
45
|
+
}.should == [:all, {:conditions => ["foo <= ?", 4]}]
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return sql with foo, the operations, and the values for :foo.is_not <operation> <value>" do
|
50
|
+
ActiveRecord::Base.where{
|
51
|
+
:foo.is_not == "bar"
|
52
|
+
}.should == [:all, {:conditions => ["foo <> ?", "bar"]}]
|
53
|
+
|
54
|
+
ActiveRecord::Base.where{
|
55
|
+
:foo.is_not.in 1,2
|
56
|
+
}.should == [:all, {:conditions => ["foo not in (?)", [1,2]]}]
|
57
|
+
|
58
|
+
ActiveRecord::Base.where{
|
59
|
+
:foo.is_not.between 1..3
|
60
|
+
}.should == [:all, {:conditions => ["foo not between ? and ?", 1, 3]}]
|
61
|
+
|
62
|
+
ActiveRecord::Base.where{
|
63
|
+
:foo.is_not.from 1..3
|
64
|
+
}.should == [:all, {:conditions => ["foo not between ? and ?", 1, 3]}]
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should return sql with foo, the operations, and values for :foo.is.in and :foo.in when used with a list of args, array, and range" do
|
69
|
+
|
70
|
+
resulting_conditions = [:all, {:conditions => ["foo in (?)", [1,2,3,4]]}]
|
71
|
+
|
72
|
+
ActiveRecord::Base.where{
|
73
|
+
:foo.is.in 1,2,3,4
|
74
|
+
}.should == resulting_conditions
|
75
|
+
|
76
|
+
ActiveRecord::Base.where{
|
77
|
+
:foo.is.in [1,2,3,4]
|
78
|
+
}.should == resulting_conditions
|
79
|
+
|
80
|
+
ActiveRecord::Base.where{
|
81
|
+
:foo.is.in 1..4
|
82
|
+
}.should == [:all, {:conditions => ["foo in (?)", 1..4]}]
|
83
|
+
|
84
|
+
ActiveRecord::Base.where{
|
85
|
+
:foo.in 1,2,3,4
|
86
|
+
}.should == resulting_conditions
|
87
|
+
|
88
|
+
ActiveRecord::Base.where{
|
89
|
+
:foo.in [1,2,3,4]
|
90
|
+
}.should == resulting_conditions
|
91
|
+
|
92
|
+
ActiveRecord::Base.where{
|
93
|
+
:foo.in 1..4
|
94
|
+
}.should == [:all, {:conditions => ["foo in (?)", 1..4]}]
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should return sql with foo, operations, and values for :foo.is.between and :foo.between when used with a list of args, array, and range" do
|
99
|
+
|
100
|
+
resulting_conditions = [:all, {:conditions => ["foo between ? and ?", 1, 2]}]
|
101
|
+
|
102
|
+
ActiveRecord::Base.where{
|
103
|
+
:foo.is.between 1,2
|
104
|
+
}.should == resulting_conditions
|
105
|
+
|
106
|
+
ActiveRecord::Base.where{
|
107
|
+
:foo.is.between [1,2]
|
108
|
+
}.should == resulting_conditions
|
109
|
+
|
110
|
+
ActiveRecord::Base.where{
|
111
|
+
:foo.is.between 1..2
|
112
|
+
}.should == resulting_conditions
|
113
|
+
|
114
|
+
ActiveRecord::Base.where{
|
115
|
+
:foo.between 1,2
|
116
|
+
}.should == resulting_conditions
|
117
|
+
|
118
|
+
ActiveRecord::Base.where{
|
119
|
+
:foo.between [1,2]
|
120
|
+
}.should == resulting_conditions
|
121
|
+
|
122
|
+
ActiveRecord::Base.where{
|
123
|
+
:foo.between 1..2
|
124
|
+
}.should == resulting_conditions
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should return sql with foo, operations, and values for :foo.is.from when used with a list of args, array, and range" do
|
129
|
+
|
130
|
+
resulting_conditions = [:all, {:conditions => ["foo between ? and ?", 1, 2]}]
|
131
|
+
|
132
|
+
ActiveRecord::Base.where{
|
133
|
+
:foo.is.from 1,2
|
134
|
+
}.should == resulting_conditions
|
135
|
+
|
136
|
+
ActiveRecord::Base.where{
|
137
|
+
:foo.is.from [1,2]
|
138
|
+
}.should == resulting_conditions
|
139
|
+
|
140
|
+
ActiveRecord::Base.where{
|
141
|
+
:foo.is.from 1..2
|
142
|
+
}.should == resulting_conditions
|
143
|
+
|
144
|
+
ActiveRecord::Base.where{
|
145
|
+
:foo.from 1,2
|
146
|
+
}.should == resulting_conditions
|
147
|
+
|
148
|
+
ActiveRecord::Base.where{
|
149
|
+
:foo.from [1,2]
|
150
|
+
}.should == resulting_conditions
|
151
|
+
|
152
|
+
ActiveRecord::Base.where{
|
153
|
+
:foo.from 1..2
|
154
|
+
}.should == resulting_conditions
|
155
|
+
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should return sql with foo, operations, and values for :foo.contains when used with a range, array, and list" do
|
160
|
+
|
161
|
+
resulting_conditions = [:all, {:conditions => ["foo like '%' || ? || '%'", "bar"]}]
|
162
|
+
|
163
|
+
ActiveRecord::Base.where{
|
164
|
+
:foo.contains "bar"
|
165
|
+
}.should == resulting_conditions
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
it "should return return the correct group of joined sql after multiple operations" do
|
171
|
+
|
172
|
+
ActiveRecord::Base.where{
|
173
|
+
:foo.is == "bar"
|
174
|
+
:foo.is_not.in 1,2,3,4,5
|
175
|
+
}.should == [:all, {:conditions => ["foo = ? and foo not in (?)", "bar", [1,2,3,4,5]]}]
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should return return the correct limit value passed" do
|
180
|
+
|
181
|
+
ActiveRecord::Base.where(:first){
|
182
|
+
:foo.is == "bar"
|
183
|
+
:foo.is_not.in 1,2,3,4,5
|
184
|
+
}.should == [:first, {:conditions => ["foo = ? and foo not in (?)", "bar", [1,2,3,4,5]]}]
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should have the correct 'not' keywords in alternating operations" do
|
189
|
+
|
190
|
+
ActiveRecord::Base.where(:first){
|
191
|
+
:foo.is == "bar"
|
192
|
+
:foo.is_not.in 1,2,3,4,5
|
193
|
+
:foo.is > 3
|
194
|
+
}.should == [:first, {:conditions => ["foo = ? and foo not in (?) and foo > ?", "bar", [1,2,3,4,5], 3]}]
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should return return strings as arguments when passed to between, in, and from (used for date strings)" do
|
199
|
+
|
200
|
+
ActiveRecord::Base.where{
|
201
|
+
:foo.is.between "some string", "2007-01-01"
|
202
|
+
}.should == [:all, {:conditions => ["foo between ? and ?", "some string", "2007-01-01"]}]
|
203
|
+
|
204
|
+
ActiveRecord::Base.where{
|
205
|
+
:foo.is_not.between "some string", "2007-01-01"
|
206
|
+
}.should == [:all, {:conditions => ["foo not between ? and ?", "some string", "2007-01-01"]}]
|
207
|
+
|
208
|
+
ActiveRecord::Base.where{
|
209
|
+
:foo.is.from "some string", "2007-01-01"
|
210
|
+
}.should == [:all, {:conditions => ["foo between ? and ?", "some string", "2007-01-01"]}]
|
211
|
+
|
212
|
+
ActiveRecord::Base.where{
|
213
|
+
:foo.in "some string", "2007-01-01"
|
214
|
+
}.should == [:all, {:conditions => ["foo in (?)", ["some string", "2007-01-01"]]}]
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/rquery.rb")
|
3
|
+
|
4
|
+
describe RQuery::Declarations do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
RQuery.adapter = RQuery::Adapters::Sqlite
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:each) do
|
11
|
+
RQuery::Serializers::Operations.clear
|
12
|
+
end
|
13
|
+
|
14
|
+
it "any Object should respond to is, is_not, in, between, from, and contains methods" do
|
15
|
+
:foo.respond_to?(:is).should == true
|
16
|
+
:foo.respond_to?(:is_not).should == true
|
17
|
+
:foo.respond_to?(:in).should == true
|
18
|
+
:foo.respond_to?(:from).should == true
|
19
|
+
:foo.respond_to?(:between).should == true
|
20
|
+
:foo.respond_to?(:from).should == true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return an Serializer Class when is, is_not are called" do
|
24
|
+
:foo.is.class.should == Class
|
25
|
+
:foo.is_not.class.should == Class
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should add an Operation for each call to is, is_not, and in" do
|
29
|
+
:foo.is
|
30
|
+
:bar.is
|
31
|
+
RQuery::Serializers::Operations.conditions.should == ["foo and bar"]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should add an Operation and the arguments for each call to from, contain, and between" do
|
35
|
+
:foo.between 1,2
|
36
|
+
RQuery::Serializers::Operations.conditions.should == ["foo between ? and ?", 1 , 2]
|
37
|
+
RQuery::Serializers::Operations.clear
|
38
|
+
:bar.from 1,2
|
39
|
+
RQuery::Serializers::Operations.conditions.should == ["bar between ? and ?", 1 , 2]
|
40
|
+
RQuery::Serializers::Operations.clear
|
41
|
+
:baz.contains "something"
|
42
|
+
RQuery::Serializers::Operations.conditions.should == ["baz like '%' || ? || '%'", "something"]
|
43
|
+
RQuery::Serializers::Operations.clear
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/rquery.rb")
|
3
|
+
|
4
|
+
describe RQuery::Serializers do
|
5
|
+
|
6
|
+
it "Object.is should define ==, <, <=, >, >=, in, and between" do
|
7
|
+
:foo.is.respond_to?(:==).should == true
|
8
|
+
:foo.is.respond_to?(:<).should == true
|
9
|
+
:foo.is.respond_to?(:<=).should == true
|
10
|
+
:foo.is.respond_to?(:>).should == true
|
11
|
+
:foo.is.respond_to?(:>=).should == true
|
12
|
+
:foo.is.respond_to?(:in).should == true
|
13
|
+
:foo.is.respond_to?(:between).should == true
|
14
|
+
end
|
15
|
+
|
16
|
+
it "Object.is_not should define == and in" do
|
17
|
+
:foo.is_not.respond_to?(:==).should == true
|
18
|
+
:foo.is_not.respond_to?(:in).should == true
|
19
|
+
:foo.is_not.respond_to?(:between).should == true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "Object.is_not should not redefine <, <=, >, >= in the same way that .is did" do
|
23
|
+
lambda {:foo.is_not.send(:<)}.should raise_error(ArgumentError)
|
24
|
+
lambda {:foo.is_not.send(:<=)}.should raise_error(ArgumentError)
|
25
|
+
lambda {:foo.is_not.send(:>)}.should raise_error(ArgumentError)
|
26
|
+
lambda {:foo.is_not.send(:>=)}.should raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/rquery.rb")
|
3
|
+
|
4
|
+
describe RQuery::Adapters::Sqlite do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
#define the adapter with the new left operand
|
8
|
+
@adapter = RQuery::Adapters::Sqlite
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return the correct sql for comparing :foo with non operator methods" do
|
12
|
+
@adapter.in.should == "in (?)"
|
13
|
+
@adapter.not_in.should == "not in (?)"
|
14
|
+
@adapter.between.should == "between ? and ?"
|
15
|
+
@adapter.not_between.should == "not " + @adapter.between
|
16
|
+
@adapter.neq.should == "<> ?"
|
17
|
+
@adapter.contains.should == "like '%' || ? || '%'"
|
18
|
+
@adapter.not_contains.should == "not " + @adapter.contains
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
it "should return the correct sql for comparing :foo with operators" do
|
23
|
+
@adapter.send(:==).should == "= ?"
|
24
|
+
@adapter.send(:>).should == "> ?"
|
25
|
+
@adapter.send(:>=).should == ">= ?"
|
26
|
+
@adapter.send(:<).should == "< ?"
|
27
|
+
@adapter.send(:<=).should == "<= ?"
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rquery
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John bender
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2000-03-16 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: ""
|
17
|
+
email: john.m.bender@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README.markdown
|
26
|
+
- rakefile.rb
|
27
|
+
- lib/rquery.rb
|
28
|
+
- lib/rquery/declarations.rb
|
29
|
+
- lib/rquery/serializers.rb
|
30
|
+
- lib/rquery/active_record.rb
|
31
|
+
- lib/rquery/active_record/base.rb
|
32
|
+
- lib/rquery/adapters.rb
|
33
|
+
- lib/rquery/adapters/sql.rb
|
34
|
+
- lib/rquery/adapters/sqlite.rb
|
35
|
+
- spec/active_record_base_spec.rb
|
36
|
+
- spec/serializers_spec.rb
|
37
|
+
- spec/declarations_spec.rb
|
38
|
+
- spec/sqlite_adapter_spec.rb
|
39
|
+
has_rdoc: true
|
40
|
+
homepage: http://nickelcode.com/rquery/
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.3.1
|
62
|
+
signing_key:
|
63
|
+
specification_version: 2
|
64
|
+
summary: A ruby DSL for building data queries in SQL and other query languages.
|
65
|
+
test_files: []
|
66
|
+
|