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 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
@@ -9,6 +9,7 @@ lib/restful_query/can_query.rb
9
9
  lib/restful_query/condition.rb
10
10
  lib/restful_query/parser.rb
11
11
  lib/restful_query/sort.rb
12
+ lib/sequel/extensions/restful_query.rb
12
13
  rails/init.rb
13
14
  restful_query.gemspec
14
15
  tasks/restful_query_tasks.rake
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
- Please see the project homepage for usage and more info:
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.new('restful_query', RestfulQuery::VERSION) do |p|
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.description = p.summary = 'Simple ActiveRecord queries from a RESTful and safe interface'
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
- 'like' => 'LIKE'
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
- REVERSE_OPERATOR_MAPPING = {
17
- '<' => 'lt',
18
- '>' => 'gt',
19
- '>=' => 'gteq',
20
- '<=' => 'lteq',
21
- '=' => 'eq',
22
- 'LIKE' => 'like'
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
- @options = options if options.is_a?(Hash)
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 ? REVERSE_OPERATOR_MAPPING.dup : OPERATOR_MAPPING.dup
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
- parsed_value = if operator == 'LIKE'
58
- "%#{value}%"
59
- elsif options[:integer]
60
- value.to_i
61
- else
62
- value
63
- end
64
- ["#{column} #{operator} ?", parsed_value]
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 options[:chronic]
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
- else
100
+ elsif value =~ /^\:/ && CONVERTABLE_VALUES.has_key?(value)
101
+ CONVERTABLE_VALUES[value]
102
+ else
72
103
  value
73
104
  end
74
105
  end
@@ -1,16 +1,17 @@
1
1
  module RestfulQuery
2
2
  class Parser
3
- attr_reader :query_hash, :exclude_columns, :integer_columns, :options
3
+ attr_reader :query, :exclude_columns, :integer_columns, :options
4
4
 
5
- def initialize(query_hash, options = {})
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
- @query_hash = (query_hash || {}).dup
11
- @default_join = @query_hash.delete(:join) || :and
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
- map_hash_to_conditions
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 = @query_hash
43
- hash['join'] = @default_join
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(@query_hash.delete('_sort'))
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 map_hash_to_conditions
115
- @query_hash.each do |column, hash_conditions|
116
- unless exclude_columns.include?(column.to_s)
117
- condition_options = {}
118
- condition_options[:chronic] = true if chronic_columns.include?(column.to_s)
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
- add_condition_for(column, Condition.new(column, value, operator, condition_options))
125
+ conditions_array << {'column' => column, 'operator' => operator, 'value' => value}
123
126
  end
124
127
  else
125
- add_condition_for(column, Condition.new(column, hash_conditions, '=', condition_options))
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
@@ -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.2.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 can_query}.each do |lib|
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
@@ -1,3 +1,4 @@
1
1
  require File.join(File.dirname(__FILE__),'..','lib','restful_query.rb')
2
+ require File.join(File.dirname(__FILE__),'..','lib','restful_query', 'can_query.rb')
2
3
 
3
4
  ActiveRecord::Base.send(:include, RestfulQuery::CanQuery)
@@ -2,49 +2,45 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{restful_query}
5
- s.version = "0.2.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-03-21}
10
- s.description = %q{Simple ActiveRecord queries from a RESTful and safe interface}
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", "README.rdoc"]
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.rdoc"]
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.1}
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 = 2
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.3"])
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>, [">= 1.8.0"])
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.3"])
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>, [">= 1.8.0"])
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.3"])
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>, [">= 1.8.0"])
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.query_hash)
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.query_hash.to_hash
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.2.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-03-21 00:00:00 -04:00
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.3
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: 1.8.0
63
+ version: 2.3.3
74
64
  version:
75
- description: Simple ActiveRecord queries from a RESTful and safe interface
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.rdoc
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.1
121
+ rubygems_version: 1.3.5
130
122
  signing_key:
131
- specification_version: 2
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