restful_query 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|