restful_query 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +13 -0
- data/Manifest.txt +1 -0
- data/README.rdoc +40 -1
- data/Rakefile +5 -4
- data/lib/restful_query/condition.rb +58 -27
- data/lib/restful_query/parser.rb +33 -18
- data/lib/restful_query/sort.rb +8 -1
- data/lib/restful_query.rb +2 -2
- data/lib/sequel/extensions/restful_query.rb +25 -0
- data/rails/init.rb +1 -0
- data/restful_query.gemspec +16 -20
- data/test/test_restful_query_condition.rb +62 -0
- data/test/test_restful_query_parser.rb +33 -2
- metadata +12 -20
data/History.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
== 0.3.0 2009-08-10
|
2
|
+
|
3
|
+
* Vast improvements/enhancements
|
4
|
+
* Added Sequel::Dataset extension: restful_query - works like the can_query named_scope
|
5
|
+
* Added IN and NOT IN to Condition operators - value can be split on delimiter option
|
6
|
+
* Changed the default behavior to storing conditions as an array of condition hashes
|
7
|
+
* Added ability to pass an array of :conditions to the parser, see tests for format.
|
8
|
+
* Added English/Human names to condition operators
|
9
|
+
* Added list of CONVERTABLE_VALUES which are prefixed w/ : and are converted to their true ruby counterparts (nil, null, true, etc)
|
10
|
+
* Added operators for IS and IS NOT
|
11
|
+
* Added neq/!= operator to conditions
|
12
|
+
* Added a clear_default_sort! action that deletes the default before switching
|
13
|
+
|
1
14
|
== 0.2.0 2009-03-20
|
2
15
|
|
3
16
|
* 1 major enhancement:
|
data/Manifest.txt
CHANGED
data/README.rdoc
CHANGED
@@ -8,7 +8,44 @@ RestfulQuery provides a RESTful interface for easily and safely querying ActiveR
|
|
8
8
|
|
9
9
|
== USAGE:
|
10
10
|
|
11
|
-
|
11
|
+
=== Rails/ActiveRecord:
|
12
|
+
|
13
|
+
# as a gem, in environment.rb
|
14
|
+
config.gem 'restful_query'
|
15
|
+
|
16
|
+
or install the plugin.
|
17
|
+
In your model:
|
18
|
+
|
19
|
+
class Post < ActiveRecord::Base
|
20
|
+
can_query
|
21
|
+
end
|
22
|
+
|
23
|
+
In your controller:
|
24
|
+
|
25
|
+
class PostsController < ApplicationController
|
26
|
+
# ...
|
27
|
+
def index
|
28
|
+
@posts = Post.restful_query(params[:query])
|
29
|
+
end
|
30
|
+
# ...
|
31
|
+
end
|
32
|
+
|
33
|
+
Now you can query your model via the URL:
|
34
|
+
|
35
|
+
/posts?query[name][like]=jon&query[_sort]=created_at-desc
|
36
|
+
|
37
|
+
=== Sequel
|
38
|
+
|
39
|
+
Theres also a Sequel extension that works very similar to ActiveRecord::Base.can_query:
|
40
|
+
|
41
|
+
require 'sequel/extensions/restful_query'
|
42
|
+
|
43
|
+
DB[:posts].restful_query({'name' => {'like' => 'jon'}, '_sort' => 'created_at-desc'})
|
44
|
+
<Sequel::SQLite::Dataset: "SELECT * FROM `posts` WHERE (name LIKE %jon%) ORDER BY `created_at` DESC">
|
45
|
+
|
46
|
+
=== More!
|
47
|
+
|
48
|
+
Please see the project homepage for detailed usage and info:
|
12
49
|
|
13
50
|
http://code.quirkey.com/restful_query
|
14
51
|
|
@@ -24,6 +61,8 @@ or from github:
|
|
24
61
|
|
25
62
|
To install as a rails plugin
|
26
63
|
|
64
|
+
./script/plugin install git://github.com/quirkey/restful_query.git
|
65
|
+
|
27
66
|
== LICENSE:
|
28
67
|
|
29
68
|
Free for use under the terms of the MIT License - see LICENSE for details
|
data/Rakefile
CHANGED
@@ -1,17 +1,18 @@
|
|
1
|
-
%w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
1
|
+
%w[rubygems rake rake/clean hoe fileutils newgem rubigen].each { |f| require f }
|
2
2
|
require File.dirname(__FILE__) + '/lib/restful_query'
|
3
3
|
|
4
4
|
# Generate all the Rake tasks
|
5
5
|
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
6
|
-
$hoe = Hoe.
|
6
|
+
$hoe = Hoe.spec('restful_query') do |p|
|
7
|
+
p.version = RestfulQuery::VERSION
|
7
8
|
p.developer('Aaron Quint', 'aaron@quirkey.com')
|
8
9
|
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
9
10
|
p.rubyforge_name = 'quirkey'
|
10
|
-
p.
|
11
|
+
p.summary = 'Simple ActiveRecord and Sequel queries from a RESTful and safe interface'
|
12
|
+
p.description = %q{RestfulQuery provides a simple interface in front of a complex parser to parse specially formatted query hashes into complex SQL queries. It includes ActiveRecord and Sequel extensions.}
|
11
13
|
p.url = 'http://code.quirkey.com/restful_query'
|
12
14
|
p.extra_deps = [
|
13
15
|
['activesupport','>= 2.2.0'],
|
14
|
-
['activerecord','>= 2.2.0'],
|
15
16
|
['chronic','>= 0.2.3']
|
16
17
|
]
|
17
18
|
p.extra_dev_deps = [
|
@@ -5,33 +5,51 @@ module RestfulQuery
|
|
5
5
|
attr_reader :column, :value, :operator, :options
|
6
6
|
|
7
7
|
OPERATOR_MAPPING = {
|
8
|
-
'lt'
|
9
|
-
'gt'
|
10
|
-
'gteq'
|
11
|
-
'lteq'
|
12
|
-
'eq'
|
13
|
-
'
|
8
|
+
'lt' => '<',
|
9
|
+
'gt' => '>',
|
10
|
+
'gteq' => '>=',
|
11
|
+
'lteq' => '<=',
|
12
|
+
'eq' => '=',
|
13
|
+
'neq' => '!=',
|
14
|
+
'is' => 'IS',
|
15
|
+
'not' => 'IS NOT',
|
16
|
+
'like' => 'LIKE',
|
17
|
+
'in' => 'IN',
|
18
|
+
'notin' => 'NOT IN'
|
14
19
|
}.freeze
|
15
|
-
|
16
|
-
|
17
|
-
'
|
18
|
-
'
|
19
|
-
'
|
20
|
-
'
|
21
|
-
|
22
|
-
|
20
|
+
|
21
|
+
CONVERTABLE_VALUES = {
|
22
|
+
':true' => true,
|
23
|
+
':false' => false,
|
24
|
+
':nil' => nil,
|
25
|
+
':null' => nil
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
ENGLISH_OPERATOR_MAPPING = {
|
29
|
+
'Less than' => 'lt',
|
30
|
+
'Greater than' => 'gt',
|
31
|
+
'Less than or equal to' => 'lteq',
|
32
|
+
'Greater than or equal to' => 'gteq',
|
33
|
+
'Equal to' => 'eq',
|
34
|
+
'Not equal to' => 'neq',
|
35
|
+
'Is' => 'is',
|
36
|
+
'Is not' => 'not',
|
37
|
+
'Like' => 'like',
|
38
|
+
'In' => 'in',
|
39
|
+
'Not in' => 'notin'
|
23
40
|
}.freeze
|
24
41
|
|
42
|
+
|
25
43
|
def initialize(column, value, operator = '=', options = {})
|
26
44
|
@options = {}
|
27
|
-
|
45
|
+
self.options = options if options.is_a?(Hash)
|
28
46
|
self.column = column
|
29
|
-
self.value = value
|
30
47
|
self.operator = operator
|
48
|
+
self.value = value
|
31
49
|
end
|
32
50
|
|
33
51
|
def map_operator(operator_to_look_up, reverse = false)
|
34
|
-
mapping = reverse ?
|
52
|
+
mapping = reverse ? OPERATOR_MAPPING.dup.invert : OPERATOR_MAPPING.dup
|
35
53
|
return operator_to_look_up if mapping.values.include?(operator_to_look_up)
|
36
54
|
found = mapping[operator_to_look_up.to_s]
|
37
55
|
end
|
@@ -49,26 +67,39 @@ module RestfulQuery
|
|
49
67
|
@value = parse_value(value)
|
50
68
|
end
|
51
69
|
|
70
|
+
def options=(options)
|
71
|
+
options.each {|k, v| @options[k.to_sym] = v }
|
72
|
+
end
|
73
|
+
|
52
74
|
def to_hash
|
53
75
|
{column => {map_operator(operator, true) => value}}
|
54
76
|
end
|
55
77
|
|
56
78
|
def to_condition_array
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
79
|
+
["#{column} #{operator} #{placeholder}", value]
|
80
|
+
end
|
81
|
+
|
82
|
+
def placeholder
|
83
|
+
if ['IN', 'NOT IN'].include?(operator)
|
84
|
+
'(?)'
|
85
|
+
else
|
86
|
+
'?'
|
87
|
+
end
|
65
88
|
end
|
66
89
|
|
67
90
|
protected
|
68
91
|
def parse_value(value)
|
69
|
-
if
|
92
|
+
if operator == 'LIKE'
|
93
|
+
"%#{value}%"
|
94
|
+
elsif ['IN', 'NOT IN'].include?(operator) && !value.is_a?(Array)
|
95
|
+
value.split(options[:delimiter] || ',')
|
96
|
+
elsif options[:integer]
|
97
|
+
value.to_i
|
98
|
+
elsif options[:chronic]
|
70
99
|
Chronic.parse(value.to_s)
|
71
|
-
|
100
|
+
elsif value =~ /^\:/ && CONVERTABLE_VALUES.has_key?(value)
|
101
|
+
CONVERTABLE_VALUES[value]
|
102
|
+
else
|
72
103
|
value
|
73
104
|
end
|
74
105
|
end
|
data/lib/restful_query/parser.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
module RestfulQuery
|
2
2
|
class Parser
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :query, :exclude_columns, :integer_columns, :options
|
4
4
|
|
5
|
-
def initialize(
|
5
|
+
def initialize(query, options = {})
|
6
6
|
@options = options || {}
|
7
7
|
@exclude_columns = options[:exclude_columns] ? [options.delete(:exclude_columns)].flatten.collect {|c| c.to_s } : []
|
8
8
|
@integer_columns = options[:integer_columns] ? [options.delete(:integer_columns)].flatten.collect {|c| c.to_s } : []
|
9
9
|
@default_sort = options[:default_sort] ? [Sort.parse(options[:default_sort])] : []
|
10
|
-
@
|
11
|
-
@
|
10
|
+
@single_sort = options[:single_sort] || false
|
11
|
+
@query = (query || {}).dup
|
12
|
+
@default_join = @query.delete(:join) || :and
|
12
13
|
extract_sorts_from_conditions
|
13
|
-
|
14
|
+
map_conditions
|
14
15
|
end
|
15
16
|
|
16
17
|
def conditions
|
@@ -39,9 +40,8 @@ module RestfulQuery
|
|
39
40
|
end
|
40
41
|
|
41
42
|
def to_query_hash
|
42
|
-
hash = @
|
43
|
-
hash['
|
44
|
-
hash['_sort'] = sorts.collect {|s| s.to_s }
|
43
|
+
hash = @query
|
44
|
+
hash['_sort'] = sorts.collect {|s| s.to_s } unless sorts.empty?
|
45
45
|
hash
|
46
46
|
end
|
47
47
|
|
@@ -87,6 +87,10 @@ module RestfulQuery
|
|
87
87
|
end
|
88
88
|
new_sort
|
89
89
|
end
|
90
|
+
|
91
|
+
def clear_default_sort!
|
92
|
+
@sorts.reject! {|s| s == @default_sort.first }
|
93
|
+
end
|
90
94
|
|
91
95
|
protected
|
92
96
|
def add_condition_for(column, condition)
|
@@ -107,26 +111,37 @@ module RestfulQuery
|
|
107
111
|
end
|
108
112
|
|
109
113
|
def extract_sorts_from_conditions
|
110
|
-
@sorts = self.class.sorts_from_hash(@
|
114
|
+
@sorts = self.class.sorts_from_hash(@query.delete('_sort'))
|
111
115
|
@sorts = @default_sort if @sorts.empty?
|
112
116
|
end
|
113
117
|
|
114
|
-
def
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
condition_options[:integer] = true if integer_columns.include?(column.to_s)
|
118
|
+
def map_conditions
|
119
|
+
conditions = query.delete(:conditions) || query
|
120
|
+
if conditions.is_a?(Hash)
|
121
|
+
conditions_array = []
|
122
|
+
conditions.each do |column, hash_conditions|
|
120
123
|
if hash_conditions.is_a?(Hash)
|
121
124
|
hash_conditions.each do |operator, value|
|
122
|
-
|
125
|
+
conditions_array << {'column' => column, 'operator' => operator, 'value' => value}
|
123
126
|
end
|
124
127
|
else
|
125
|
-
|
128
|
+
conditions_array << {'column' => column, 'value' => hash_conditions}
|
126
129
|
end
|
127
130
|
end
|
131
|
+
conditions = conditions_array
|
132
|
+
end
|
133
|
+
# with a normalized array of conditions
|
134
|
+
conditions.each do |condition|
|
135
|
+
column, operator, value = condition['column'], condition['operator'] || 'eq', condition['value']
|
136
|
+
unless exclude_columns.include?(column.to_s)
|
137
|
+
condition_options = {}
|
138
|
+
condition_options[:chronic] = true if chronic_columns.include?(column.to_s)
|
139
|
+
condition_options[:integer] = true if integer_columns.include?(column.to_s)
|
140
|
+
condition_options.merge!(condition['options'] || {})
|
141
|
+
add_condition_for(column, Condition.new(column, value, operator, condition_options))
|
142
|
+
end
|
128
143
|
end
|
129
144
|
end
|
130
|
-
|
145
|
+
|
131
146
|
end
|
132
147
|
end
|
data/lib/restful_query/sort.rb
CHANGED
@@ -2,6 +2,8 @@ module RestfulQuery
|
|
2
2
|
class InvalidDirection < Error; end
|
3
3
|
|
4
4
|
class Sort
|
5
|
+
include Comparable
|
6
|
+
|
5
7
|
attr_reader :column, :direction
|
6
8
|
|
7
9
|
DIRECTIONS = {
|
@@ -19,7 +21,7 @@ module RestfulQuery
|
|
19
21
|
self.direction = direction
|
20
22
|
end
|
21
23
|
|
22
|
-
def self.parse(sort_string, split_on =
|
24
|
+
def self.parse(sort_string, split_on = /\-|\ /)
|
23
25
|
return unless sort_string
|
24
26
|
column, direction = sort_string.split(split_on)
|
25
27
|
new(column, direction)
|
@@ -38,6 +40,11 @@ module RestfulQuery
|
|
38
40
|
direction == 'ASC' ? 'DESC' : 'ASC'
|
39
41
|
end
|
40
42
|
|
43
|
+
def ==(other)
|
44
|
+
return false unless other.is_a?(Sort)
|
45
|
+
column == other.column && direction == other.direction
|
46
|
+
end
|
47
|
+
|
41
48
|
# Makes a roundabout for directions nil -> desc -> asc -> nil
|
42
49
|
def self.next_direction(current_direction)
|
43
50
|
case current_direction.to_s.downcase
|
data/lib/restful_query.rb
CHANGED
@@ -11,12 +11,12 @@ rescue LoadError
|
|
11
11
|
end
|
12
12
|
|
13
13
|
module RestfulQuery
|
14
|
-
VERSION = '0.
|
14
|
+
VERSION = '0.3.0'
|
15
15
|
|
16
16
|
class Error < RuntimeError; end
|
17
17
|
end
|
18
18
|
|
19
19
|
|
20
|
-
%w{condition sort parser
|
20
|
+
%w{condition sort parser}.each do |lib|
|
21
21
|
require File.join("restful_query","#{lib}.rb")
|
22
22
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'restful_query.rb')
|
2
|
+
|
3
|
+
module RestfulQuery
|
4
|
+
class Sort
|
5
|
+
|
6
|
+
def to_sequel
|
7
|
+
column.to_sym.send(direction.downcase)
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Sequel
|
14
|
+
class Dataset
|
15
|
+
|
16
|
+
def restful_query(query_hash, options = {})
|
17
|
+
parser = RestfulQuery::Parser.new(query_hash, options = {})
|
18
|
+
collection = self
|
19
|
+
collection = collection.filter(*parser.to_conditions_array) if parser.has_conditions?
|
20
|
+
collection = collection.order(*parser.sorts.collect {|s| s.to_sequel }) if parser.has_sort?
|
21
|
+
collection
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/rails/init.rb
CHANGED
data/restful_query.gemspec
CHANGED
@@ -2,49 +2,45 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{restful_query}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.3.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Aaron Quint"]
|
9
|
-
s.date = %q{2009-
|
10
|
-
s.description = %q{
|
9
|
+
s.date = %q{2009-08-10}
|
10
|
+
s.description = %q{RestfulQuery provides a simple interface in front of a complex parser to parse specially formatted query hashes into complex SQL queries. It includes ActiveRecord and Sequel extensions.}
|
11
11
|
s.email = ["aaron@quirkey.com"]
|
12
|
-
s.extra_rdoc_files = ["History.txt", "Manifest.txt"
|
13
|
-
s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "init.rb", "lib/restful_query.rb", "lib/restful_query/can_query.rb", "lib/restful_query/condition.rb", "lib/restful_query/parser.rb", "lib/restful_query/sort.rb", "rails/init.rb", "restful_query.gemspec", "tasks/restful_query_tasks.rake", "test/test_helper.rb", "test/test_restful_query_can_query.rb", "test/test_restful_query_condition.rb", "test/test_restful_query_parser.rb", "test/test_restful_query_sort.rb"]
|
14
|
-
s.has_rdoc = true
|
12
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
|
13
|
+
s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "init.rb", "lib/restful_query.rb", "lib/restful_query/can_query.rb", "lib/restful_query/condition.rb", "lib/restful_query/parser.rb", "lib/restful_query/sort.rb", "lib/sequel/extensions/restful_query.rb", "rails/init.rb", "restful_query.gemspec", "tasks/restful_query_tasks.rake", "test/test_helper.rb", "test/test_restful_query_can_query.rb", "test/test_restful_query_condition.rb", "test/test_restful_query_parser.rb", "test/test_restful_query_sort.rb"]
|
15
14
|
s.homepage = %q{http://code.quirkey.com/restful_query}
|
16
|
-
s.rdoc_options = ["--main", "README.
|
15
|
+
s.rdoc_options = ["--main", "README.txt"]
|
17
16
|
s.require_paths = ["lib"]
|
18
17
|
s.rubyforge_project = %q{quirkey}
|
19
|
-
s.rubygems_version = %q{1.3.
|
20
|
-
s.summary = %q{Simple ActiveRecord queries from a RESTful and safe interface}
|
18
|
+
s.rubygems_version = %q{1.3.5}
|
19
|
+
s.summary = %q{Simple ActiveRecord and Sequel queries from a RESTful and safe interface}
|
21
20
|
s.test_files = ["test/test_helper.rb", "test/test_restful_query_can_query.rb", "test/test_restful_query_condition.rb", "test/test_restful_query_parser.rb", "test/test_restful_query_sort.rb"]
|
22
21
|
|
23
22
|
if s.respond_to? :specification_version then
|
24
23
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
-
s.specification_version =
|
24
|
+
s.specification_version = 3
|
26
25
|
|
27
26
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
27
|
s.add_runtime_dependency(%q<activesupport>, [">= 2.2.0"])
|
29
|
-
s.add_runtime_dependency(%q<activerecord>, [">= 2.2.0"])
|
30
28
|
s.add_runtime_dependency(%q<chronic>, [">= 0.2.3"])
|
31
|
-
s.add_development_dependency(%q<newgem>, [">= 1.2
|
29
|
+
s.add_development_dependency(%q<newgem>, [">= 1.5.2"])
|
32
30
|
s.add_development_dependency(%q<Shoulda>, [">= 1.2.0"])
|
33
|
-
s.add_development_dependency(%q<hoe>, [">=
|
31
|
+
s.add_development_dependency(%q<hoe>, [">= 2.3.3"])
|
34
32
|
else
|
35
33
|
s.add_dependency(%q<activesupport>, [">= 2.2.0"])
|
36
|
-
s.add_dependency(%q<activerecord>, [">= 2.2.0"])
|
37
34
|
s.add_dependency(%q<chronic>, [">= 0.2.3"])
|
38
|
-
s.add_dependency(%q<newgem>, [">= 1.2
|
35
|
+
s.add_dependency(%q<newgem>, [">= 1.5.2"])
|
39
36
|
s.add_dependency(%q<Shoulda>, [">= 1.2.0"])
|
40
|
-
s.add_dependency(%q<hoe>, [">=
|
37
|
+
s.add_dependency(%q<hoe>, [">= 2.3.3"])
|
41
38
|
end
|
42
39
|
else
|
43
40
|
s.add_dependency(%q<activesupport>, [">= 2.2.0"])
|
44
|
-
s.add_dependency(%q<activerecord>, [">= 2.2.0"])
|
45
41
|
s.add_dependency(%q<chronic>, [">= 0.2.3"])
|
46
|
-
s.add_dependency(%q<newgem>, [">= 1.2
|
42
|
+
s.add_dependency(%q<newgem>, [">= 1.5.2"])
|
47
43
|
s.add_dependency(%q<Shoulda>, [">= 1.2.0"])
|
48
|
-
s.add_dependency(%q<hoe>, [">=
|
44
|
+
s.add_dependency(%q<hoe>, [">= 2.3.3"])
|
49
45
|
end
|
50
|
-
end
|
46
|
+
end
|
@@ -59,6 +59,68 @@ class RestfulQueryConditionTest < Test::Unit::TestCase
|
|
59
59
|
assert_equal(1.week.ago.to_s, @condition.value.to_s)
|
60
60
|
end
|
61
61
|
end
|
62
|
+
|
63
|
+
context "with a value of ':nil'" do
|
64
|
+
setup do
|
65
|
+
@condition = RestfulQuery::Condition.new('created_at', ':nil')
|
66
|
+
end
|
67
|
+
|
68
|
+
should "convert value to true nil" do
|
69
|
+
assert_equal(nil, @condition.value)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with a value of ':true'" do
|
74
|
+
setup do
|
75
|
+
@condition = RestfulQuery::Condition.new('created_at', ':true')
|
76
|
+
end
|
77
|
+
|
78
|
+
should "convert value to true true" do
|
79
|
+
assert_equal(true, @condition.value)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "with the IN operator" do
|
84
|
+
setup do
|
85
|
+
@condition = RestfulQuery::Condition.new('year', '1995,2005,2006', 'in')
|
86
|
+
end
|
87
|
+
|
88
|
+
should "assign the operator" do
|
89
|
+
assert_equal 'IN', @condition.operator
|
90
|
+
end
|
91
|
+
|
92
|
+
should "split values by the delimiter option" do
|
93
|
+
assert_equal ['1995', '2005', '2006'], @condition.value
|
94
|
+
end
|
95
|
+
|
96
|
+
should "include parens in placeholder" do
|
97
|
+
assert_equal ["year IN (?)", ['1995', '2005', '2006']], @condition.to_condition_array
|
98
|
+
end
|
99
|
+
|
100
|
+
context "when the value is already an array" do
|
101
|
+
setup do
|
102
|
+
@condition = RestfulQuery::Condition.new('year', ['1995', '2005', '2006'], 'in')
|
103
|
+
end
|
104
|
+
|
105
|
+
should "not resplit the value" do
|
106
|
+
assert_equal ['1995', '2005', '2006'], @condition.value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "with the NOT IN operator" do
|
112
|
+
setup do
|
113
|
+
@condition = RestfulQuery::Condition.new('year', '1995|2005|2006', 'notin', :delimiter => '|')
|
114
|
+
end
|
115
|
+
|
116
|
+
should "assign the operator" do
|
117
|
+
assert_equal 'NOT IN', @condition.operator
|
118
|
+
end
|
119
|
+
|
120
|
+
should "split values by delimiter option" do
|
121
|
+
assert_equal ['1995', '2005', '2006'], @condition.value
|
122
|
+
end
|
123
|
+
end
|
62
124
|
end
|
63
125
|
|
64
126
|
|
@@ -19,7 +19,7 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
19
19
|
end
|
20
20
|
|
21
21
|
should "have a blank hash for query hash" do
|
22
|
-
assert_equal({}, @parser.
|
22
|
+
assert_equal({}, @parser.to_query_hash)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -33,7 +33,7 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
33
33
|
end
|
34
34
|
|
35
35
|
should "save hash to query_hash" do
|
36
|
-
assert_equal @base_query_hash, @parser.
|
36
|
+
assert_equal @base_query_hash, @parser.to_query_hash
|
37
37
|
end
|
38
38
|
|
39
39
|
should "save each condition as a condition object" do
|
@@ -177,6 +177,37 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
177
177
|
end
|
178
178
|
end
|
179
179
|
end
|
180
|
+
|
181
|
+
context "from an array of conditions" do
|
182
|
+
setup do
|
183
|
+
@array_of_conditions = [
|
184
|
+
{'column' => 'created_at', 'operator' => 'gt', 'value' => '1 week ago'},
|
185
|
+
{'column' => 'created_at', 'operator' => 'lt', 'value' => '1 hour ago'},
|
186
|
+
{'column' => 'updated_at', 'operator' => 'lt', 'value' => '1 day ago'},
|
187
|
+
{'column' => 'title', 'operator' => 'eq', 'value' => 'Test'},
|
188
|
+
{'column' => 'other_time', 'operator' => 'gt', 'value' => 'oct 1'},
|
189
|
+
{'column' => 'name', 'value' => 'Aaron'}
|
190
|
+
]
|
191
|
+
@parser = RestfulQuery::Parser.new(:conditions => @array_of_conditions)
|
192
|
+
end
|
193
|
+
|
194
|
+
should "return parser object" do
|
195
|
+
assert @parser.is_a?(RestfulQuery::Parser)
|
196
|
+
end
|
197
|
+
|
198
|
+
should "save each condition as a condition object" do
|
199
|
+
assert @parser.conditions.is_a?(Array)
|
200
|
+
assert_equal 6, @parser.conditions.length
|
201
|
+
assert @parser.conditions.first.is_a?(RestfulQuery::Condition)
|
202
|
+
end
|
203
|
+
|
204
|
+
should "save condition without operator with default operator" do
|
205
|
+
assert @parser.conditions_for(:name)
|
206
|
+
assert @parser.conditions_for(:name).first.is_a?(RestfulQuery::Condition)
|
207
|
+
assert_equal '=', @parser.conditions_for(:name).first.operator
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
180
211
|
|
181
212
|
context "a loaded parser" do
|
182
213
|
setup do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restful_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Quint
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-08-10 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -22,16 +22,6 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: 2.2.0
|
24
24
|
version:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: activerecord
|
27
|
-
type: :runtime
|
28
|
-
version_requirement:
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 2.2.0
|
34
|
-
version:
|
35
25
|
- !ruby/object:Gem::Dependency
|
36
26
|
name: chronic
|
37
27
|
type: :runtime
|
@@ -50,7 +40,7 @@ dependencies:
|
|
50
40
|
requirements:
|
51
41
|
- - ">="
|
52
42
|
- !ruby/object:Gem::Version
|
53
|
-
version: 1.2
|
43
|
+
version: 1.5.2
|
54
44
|
version:
|
55
45
|
- !ruby/object:Gem::Dependency
|
56
46
|
name: Shoulda
|
@@ -70,9 +60,9 @@ dependencies:
|
|
70
60
|
requirements:
|
71
61
|
- - ">="
|
72
62
|
- !ruby/object:Gem::Version
|
73
|
-
version:
|
63
|
+
version: 2.3.3
|
74
64
|
version:
|
75
|
-
description:
|
65
|
+
description: RestfulQuery provides a simple interface in front of a complex parser to parse specially formatted query hashes into complex SQL queries. It includes ActiveRecord and Sequel extensions.
|
76
66
|
email:
|
77
67
|
- aaron@quirkey.com
|
78
68
|
executables: []
|
@@ -82,7 +72,6 @@ extensions: []
|
|
82
72
|
extra_rdoc_files:
|
83
73
|
- History.txt
|
84
74
|
- Manifest.txt
|
85
|
-
- README.rdoc
|
86
75
|
files:
|
87
76
|
- History.txt
|
88
77
|
- LICENSE
|
@@ -95,6 +84,7 @@ files:
|
|
95
84
|
- lib/restful_query/condition.rb
|
96
85
|
- lib/restful_query/parser.rb
|
97
86
|
- lib/restful_query/sort.rb
|
87
|
+
- lib/sequel/extensions/restful_query.rb
|
98
88
|
- rails/init.rb
|
99
89
|
- restful_query.gemspec
|
100
90
|
- tasks/restful_query_tasks.rake
|
@@ -105,10 +95,12 @@ files:
|
|
105
95
|
- test/test_restful_query_sort.rb
|
106
96
|
has_rdoc: true
|
107
97
|
homepage: http://code.quirkey.com/restful_query
|
98
|
+
licenses: []
|
99
|
+
|
108
100
|
post_install_message:
|
109
101
|
rdoc_options:
|
110
102
|
- --main
|
111
|
-
- README.
|
103
|
+
- README.txt
|
112
104
|
require_paths:
|
113
105
|
- lib
|
114
106
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -126,10 +118,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
118
|
requirements: []
|
127
119
|
|
128
120
|
rubyforge_project: quirkey
|
129
|
-
rubygems_version: 1.3.
|
121
|
+
rubygems_version: 1.3.5
|
130
122
|
signing_key:
|
131
|
-
specification_version:
|
132
|
-
summary: Simple ActiveRecord queries from a RESTful and safe interface
|
123
|
+
specification_version: 3
|
124
|
+
summary: Simple ActiveRecord and Sequel queries from a RESTful and safe interface
|
133
125
|
test_files:
|
134
126
|
- test/test_helper.rb
|
135
127
|
- test/test_restful_query_can_query.rb
|