wherewolf 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -13,5 +13,5 @@ group :development do
13
13
  gem "simplecov", :require => false
14
14
  gem "sqlite3"
15
15
  gem "rails"
16
- gem "wherewolf", :path => "./"
16
+ gem "mocha"
17
17
  end
@@ -1,10 +1,3 @@
1
- PATH
2
- remote: ./
3
- specs:
4
- wherewolf (0.3.0)
5
- arel
6
- parslet
7
-
8
1
  GEM
9
2
  remote: http://rubygems.org/
10
3
  specs:
@@ -64,7 +57,10 @@ GEM
64
57
  i18n (>= 0.4.0)
65
58
  mime-types (~> 1.16)
66
59
  treetop (~> 1.4.8)
60
+ metaclass (0.0.1)
67
61
  mime-types (1.19)
62
+ mocha (0.12.4)
63
+ metaclass (~> 0.0.1)
68
64
  multi_json (1.3.6)
69
65
  parslet (1.4.0)
70
66
  blankslate (~> 2.0)
@@ -131,10 +127,10 @@ DEPENDENCIES
131
127
  guard
132
128
  guard-test
133
129
  jeweler
130
+ mocha
134
131
  parslet
135
132
  rails
136
133
  rdoc
137
134
  shoulda
138
135
  simplecov
139
136
  sqlite3
140
- wherewolf!
@@ -40,28 +40,44 @@ Then for every model that you want to by queryable, do this:
40
40
  has_query_parsing
41
41
  end
42
42
 
43
- This will add the "from_query" method, which you pass your query string in to.
43
+ This will add the "where_query" method, which you pass your query string in to.
44
44
 
45
45
  == Example
46
46
 
47
47
  For a real-life, running example, check out: http://wherewolf.herokuapp.com/
48
48
 
49
- player = Player.from_query("(position = wing || position = lock) && first_cap < 1905-01-01").order('first_cap')
49
+ player = Player.where_query("(position = wing || position = lock) && first_cap < 1905-01-01").order('first_cap')
50
50
  # Returns all players that play 'wing' or 'lock', and played before 1905-01-01
51
51
 
52
- player = Player.from_query('name = "John Eales"')
52
+ player = Player.where_query('name = "John Eales"')
53
53
  # Returns all players names 'John Eales'
54
54
 
55
- player = Player.from_query("first_cap >= 1905-01-01 && active = false")
55
+ player = Player.where_query("first_cap >= 1905-01-01 && active = false")
56
56
  # Returns all inactitve players that played after 1905-01-01.
57
57
 
58
- player = Player.from_query("first_cap != null")
58
+ player = Player.where_query("first_cap != null")
59
59
  # Returns all players who have received their first cap (ie first_cap is NOT nil)
60
60
 
61
- player = Player.from_query('name ~= "Peter%"')
61
+ player = Player.where_query('name ~= "Peter%"')
62
62
  # Returns all players who's name starts with Peter
63
63
 
64
- As you can see, from_query returns an ARel object, so you chain other statements to it. Please note, though: at the moment from_query needs to be the first in the chain.
64
+ As you can see, where_query returns an ARel object, so you chain other statements to it. Please note, though: at the moment where_query needs to be the first in the chain.
65
+
66
+ == Order
67
+
68
+ You can also supply an order_query to handle ordering
69
+
70
+ player = Player.order_query("name asc")
71
+ # Order by name asc
72
+
73
+ player = Player.order_query("name desc")
74
+ # Order by name desc
75
+
76
+ player = Player.order_query("name")
77
+ # By default ordering is ascending
78
+
79
+ player = Player.order_query("name desc, position desc")
80
+ # You can also have multiple order columns
65
81
 
66
82
  == Errors
67
83
 
@@ -72,7 +88,7 @@ At the moment, error handling is very primitive. Just capture
72
88
  You can print out a simple error message like so
73
89
 
74
90
  begin
75
- Player.from_query('name ~= "Patrick%" || (position = "fail)')
91
+ Player.where_query('name ~= "Patrick%" || (position = "fail)')
76
92
  rescue Wherewolf::ParseError => e
77
93
  puts e.error_message
78
94
  end
@@ -84,7 +100,7 @@ Will print out
84
100
  You can get the character number by:
85
101
 
86
102
  begin
87
- Player.from_query('name ~= "Patrick%" || (position = "fail)')
103
+ Player.where_query('name ~= "Patrick%" || (position = "fail)')
88
104
  rescue Wherewolf::ParseError => e
89
105
  e.position # This value will be 28
90
106
  end
@@ -94,7 +110,7 @@ You can get the character number by:
94
110
  * Better error messages (Give a clue as to why parsing failed)
95
111
  * Aliases such for operators, such as 'and', 'or' etc
96
112
  * Allow single quotes around strings
97
- * Allow from_query to nested (ie Player.where('first_cap < 2000-01-01').from_query('active = true')
113
+ * Allow where_query to nested (ie Player.where('first_cap < 2000-01-01').where_query('active = true')
98
114
  * More edge case testing
99
115
  * Abillity to filter columns that are searchable
100
116
  * Ability to call named scopes
data/Rakefile CHANGED
@@ -22,7 +22,7 @@ Jeweler::Tasks.new do |gem|
22
22
  gem.description = %Q{Wherewolf allows you to consume search terms as strings without worrying about database injections. It parses the query and converts it into ARel. It's great for creating filterable REST APIs.}
23
23
  gem.email = "myles@madpilot.com.au"
24
24
  gem.authors = ["Myles Eftos"]
25
- gem.version = "0.3.0"
25
+ gem.version = "0.4.0"
26
26
  # dependencies defined in Gemfile
27
27
  end
28
28
  Jeweler::RubygemsDotOrgTasks.new
@@ -30,7 +30,7 @@ Jeweler::RubygemsDotOrgTasks.new
30
30
  require 'rake/testtask'
31
31
  Rake::TestTask.new(:test) do |test|
32
32
  test.libs << 'lib' << 'test'
33
- test.pattern = 'test/*_test.rb'
33
+ test.pattern = 'test/**/*_test.rb'
34
34
  test.verbose = true
35
35
  end
36
36
 
@@ -1,5 +1,8 @@
1
- require File.join(File.dirname(__FILE__), 'wherewolf', 'parser.rb')
2
1
  require File.join(File.dirname(__FILE__), 'wherewolf', 'processor.rb')
2
+ require File.join(File.dirname(__FILE__), 'wherewolf', 'where', 'parser.rb')
3
+ require File.join(File.dirname(__FILE__), 'wherewolf', 'where', 'processor.rb')
4
+ require File.join(File.dirname(__FILE__), 'wherewolf', 'order', 'parser.rb')
5
+ require File.join(File.dirname(__FILE__), 'wherewolf', 'order', 'processor.rb')
3
6
  require File.join(File.dirname(__FILE__), 'wherewolf', 'parse_error.rb')
4
7
 
5
8
  module Wherewolf
@@ -14,8 +17,12 @@ module Wherewolf
14
17
  end
15
18
 
16
19
  module QueryMethods
17
- def from_query(query)
18
- Wherewolf::Processor.parse(self, query)
20
+ def where_query(query)
21
+ Wherewolf::Where::Processor.parse(self, query)
22
+ end
23
+
24
+ def order_query(query)
25
+ Wherewolf::Order::Processor.parse(self, query)
19
26
  end
20
27
  end
21
28
  end
@@ -0,0 +1,20 @@
1
+ require 'parslet'
2
+
3
+ module Wherewolf
4
+ module Order
5
+ class Parser < Parslet::Parser
6
+ rule(:space) { match('\s').repeat(1) }
7
+ rule(:space?) { space.maybe }
8
+ rule(:comma) { str(',') >> space? }
9
+
10
+ rule(:literal) { match('[a-zA-Z0-9\-_]').repeat(1).as(:column) >> space? }
11
+ rule(:direction) { str('asc') | str('desc') }
12
+
13
+ rule(:order) { literal >> direction.maybe.as(:direction) }
14
+ rule(:multiple) { order >> (comma >> order).repeat }
15
+ rule(:expression) { multiple | order }
16
+
17
+ root :expression
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ require 'arel'
2
+
3
+ module Wherewolf
4
+ module Order
5
+ class Processor < Wherewolf::Processor
6
+ def self.parse(model, query)
7
+ instance = self.new
8
+ instance.parse(model, query)
9
+ end
10
+
11
+ def parse(model, query)
12
+ begin
13
+ ast = Wherewolf::Order::Parser.new.parse(query)
14
+ process(ast, model)
15
+ rescue Parslet::ParseFailed => error
16
+ raise Wherewolf::ParseError, error
17
+ end
18
+ end
19
+
20
+ def process(ast, model)
21
+ ast = [ast] unless ast.is_a?(Array)
22
+ table = model.arel_table
23
+ ast.each do |order|
24
+ check_column!(order[:column], table)
25
+ direction = (order[:direction] || 'asc').to_sym
26
+ model = model.order(table[order[:column].to_sym].send(direction))
27
+ end
28
+ model
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,71 +1,6 @@
1
- require 'arel'
2
-
3
1
  module Wherewolf
4
2
  class Processor
5
- def self.parse(model, query)
6
- instance = self.new
7
- instance.parse(model, query)
8
- end
9
-
10
- def parse(model, query)
11
- begin
12
- ast = Wherewolf::Parser.new.parse(query)
13
- table = model.arel_table
14
- model.where(process(ast, table))
15
- rescue Parslet::ParseFailed => error
16
- raise Wherewolf::ParseError, error
17
- end
18
- end
19
-
20
- def process(ast, table)
21
- operation = ast.keys.first
22
- self.send("process_#{operation}".to_sym, ast[operation], table) if self.respond_to?("process_#{operation}".to_sym)
23
- end
24
-
25
- protected
26
- def process_and(ast, table)
27
- process(ast[:left], table).and(process(ast[:right], table))
28
- end
29
-
30
- def process_or(ast, table)
31
- process(ast[:left], table).or(process(ast[:right], table))
32
- end
33
-
34
- def process_eq(ast, table)
35
- check_column!(ast[:left], table)
36
- table[ast[:left].to_sym].eq(parse_value(ast[:right]))
37
- end
38
-
39
- def process_not_eq(ast, table)
40
- check_column!(ast[:left], table)
41
- table[ast[:left].to_sym].not_eq(parse_value(ast[:right]))
42
- end
43
-
44
- def process_matches(ast, table)
45
- check_column!(ast[:left], table)
46
- table[ast[:left].to_sym].matches(parse_value(ast[:right]))
47
- end
48
-
49
- def process_lt(ast, table)
50
- check_column!(ast[:left], table)
51
- table[ast[:left].to_sym].lt(parse_value(ast[:right]))
52
- end
53
-
54
- def process_lteq(ast, table)
55
- check_column!(ast[:left], table)
56
- table[ast[:left].to_sym].lteq(parse_value(ast[:right]))
57
- end
58
-
59
- def process_gt(ast, table)
60
- check_column!(ast[:left], table)
61
- table[ast[:left].to_sym].gt(parse_value(ast[:right]))
62
- end
63
-
64
- def process_gteq(ast, table)
65
- check_column!(ast[:left], table)
66
- table[ast[:left].to_sym].gteq(parse_value(ast[:right]))
67
- end
68
-
3
+ protected
69
4
  def check_column!(value, table)
70
5
  unless table.columns.map(&:name).include?(value.to_sym)
71
6
  source = Parslet::Source.new(value.to_s)
@@ -73,17 +8,5 @@ protected
73
8
  raise Parslet::ParseFailed.new('Column not found', cause)
74
9
  end
75
10
  end
76
-
77
- def parse_value(value)
78
- type = value.keys.first
79
- case type
80
- when :nil
81
- return nil
82
- when :boolean
83
- return value[:boolean] == "true"
84
- else
85
- return value[type].to_s
86
- end
87
- end
88
11
  end
89
12
  end
@@ -0,0 +1,57 @@
1
+ require 'parslet'
2
+
3
+ module Wherewolf
4
+ module Where
5
+ class Parser < Parslet::Parser
6
+ rule(:space) { match('\s').repeat(1) }
7
+ rule(:space?) { space.maybe }
8
+ rule(:left_parenthesis) { str('(') }
9
+ rule(:right_parenthesis) { str(')') }
10
+
11
+ # Comparisons
12
+ rule(:eq) { str('=') }
13
+ rule(:not_eq) { str('!=') }
14
+ rule(:matches) { str('~=') }
15
+ rule(:lt) { str('<') }
16
+ rule(:lteq) { str('<=') }
17
+ rule(:gt) { str('>') }
18
+ rule(:gteq) { str('>=') }
19
+
20
+ # Operators
21
+ rule(:and_operator) { str('&&') }
22
+ rule(:or_operator) { str('||') }
23
+
24
+ # Operand
25
+ rule(:null) { str("null").as(:nil) }
26
+ rule(:boolean) { str("true").as(:boolean) | str("false").as(:boolean) }
27
+ rule(:number) { match('[-+]?([0-9]*\.)?[0-9]').repeat(1).as(:number) }
28
+ rule(:double_quote_string) do
29
+ str('"') >>
30
+ (
31
+ (str('\\') >> any) |
32
+ (str('"').absent? >> any)
33
+ ).repeat.as(:string) >>
34
+ str('"')
35
+ end
36
+ rule(:literal) { match('[a-zA-Z0-9\-_]').repeat(1) }
37
+ rule(:identifier) { null | boolean | number | double_quote_string | literal.as(:string) }
38
+
39
+ # Grammar
40
+ rule(:compare_eq) { (literal.as(:left) >> space? >> eq >> space? >> identifier.as(:right)).as(:eq) }
41
+ rule(:compare_not_eq) { (literal.as(:left) >> space? >> not_eq >> space? >> identifier.as(:right)).as(:not_eq) }
42
+ rule(:compare_matches) { (literal.as(:left) >> space? >> matches >> space? >> identifier.as(:right)).as(:matches) }
43
+ rule(:compare_lt) { (literal.as(:left) >> space? >> lt >> space? >> identifier.as(:right)).as(:lt) }
44
+ rule(:compare_lteq) { (literal.as(:left) >> space? >> lteq >> space? >> identifier.as(:right)).as(:lteq) }
45
+ rule(:compare_gt) { (literal.as(:left) >> space? >> gt >> space? >> identifier.as(:right)).as(:gt) }
46
+ rule(:compare_gteq) { (literal.as(:left) >> space? >> gteq >> space? >> identifier.as(:right)).as(:gteq) }
47
+
48
+ rule(:compare) { compare_eq | compare_not_eq | compare_matches | compare_lteq | compare_lt | compare_gteq | compare_gt }
49
+
50
+ rule(:primary) { left_parenthesis >> space? >> or_operation >> space? >> right_parenthesis | compare }
51
+ rule(:and_operation) { (primary.as(:left) >> space? >> and_operator >> space? >> and_operation.as(:right)).as(:and) | primary }
52
+ rule(:or_operation) { (and_operation.as(:left) >> space? >> or_operator >> space? >> or_operation.as(:right)).as(:or) | and_operation }
53
+
54
+ root :or_operation
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,83 @@
1
+ require 'arel'
2
+
3
+ module Wherewolf
4
+ module Where
5
+ class Processor < Wherewolf::Processor
6
+ def self.parse(model, query)
7
+ instance = self.new
8
+ instance.parse(model, query)
9
+ end
10
+
11
+ def parse(model, query)
12
+ begin
13
+ ast = Wherewolf::Where::Parser.new.parse(query)
14
+ table = model.arel_table
15
+ model.where(process(ast, table))
16
+ rescue Parslet::ParseFailed => error
17
+ raise Wherewolf::ParseError, error
18
+ end
19
+ end
20
+
21
+ def process(ast, table)
22
+ operation = ast.keys.first
23
+ self.send("process_#{operation}".to_sym, ast[operation], table) if self.respond_to?("process_#{operation}".to_sym)
24
+ end
25
+
26
+ protected
27
+ def process_and(ast, table)
28
+ process(ast[:left], table).and(process(ast[:right], table))
29
+ end
30
+
31
+ def process_or(ast, table)
32
+ process(ast[:left], table).or(process(ast[:right], table))
33
+ end
34
+
35
+ def process_eq(ast, table)
36
+ check_column!(ast[:left], table)
37
+ table[ast[:left].to_sym].eq(parse_value(ast[:right]))
38
+ end
39
+
40
+ def process_not_eq(ast, table)
41
+ check_column!(ast[:left], table)
42
+ table[ast[:left].to_sym].not_eq(parse_value(ast[:right]))
43
+ end
44
+
45
+ def process_matches(ast, table)
46
+ check_column!(ast[:left], table)
47
+ table[ast[:left].to_sym].matches(parse_value(ast[:right]))
48
+ end
49
+
50
+ def process_lt(ast, table)
51
+ check_column!(ast[:left], table)
52
+ table[ast[:left].to_sym].lt(parse_value(ast[:right]))
53
+ end
54
+
55
+ def process_lteq(ast, table)
56
+ check_column!(ast[:left], table)
57
+ table[ast[:left].to_sym].lteq(parse_value(ast[:right]))
58
+ end
59
+
60
+ def process_gt(ast, table)
61
+ check_column!(ast[:left], table)
62
+ table[ast[:left].to_sym].gt(parse_value(ast[:right]))
63
+ end
64
+
65
+ def process_gteq(ast, table)
66
+ check_column!(ast[:left], table)
67
+ table[ast[:left].to_sym].gteq(parse_value(ast[:right]))
68
+ end
69
+
70
+ def parse_value(value)
71
+ type = value.keys.first
72
+ case type
73
+ when :nil
74
+ return nil
75
+ when :boolean
76
+ return value[:boolean] == "true"
77
+ else
78
+ return value[type].to_s
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -15,6 +15,7 @@ end
15
15
 
16
16
  require 'test/unit'
17
17
  require 'shoulda'
18
+ require 'mocha'
18
19
 
19
20
  require 'thread'
20
21
  require 'rails/all'
@@ -59,4 +60,26 @@ class Team < ActiveRecord::Base
59
60
  end
60
61
 
61
62
  class Test::Unit::TestCase
63
+ def setup_fixtures
64
+ Player.create!(:name => "Patrick 'Paddy' Carew", :position => 'lock', :first_cap => '1899-06-24', :active => false)
65
+ Player.create!(:name => "Charlie Ellis", :position => 'flanker', :first_cap => '1899-06-24', :active => false)
66
+ Player.create!(:name => "Arthur Corfe", :position => 'flanker', :first_cap => '1899-07-22', :active => false)
67
+ Player.create!(:name => "Syd Miller", :position => 'wing', :first_cap => '1899-08-05', :active => false)
68
+ Player.create!(:name => "Charlie Redwood", :position => 'wing', :first_cap => '1903-08-15', :active => false)
69
+ Player.create!(:name => "Patrick 'Pat' Walsh", :position => 'no. 8', :first_cap => '1904-07-02', :active => false)
70
+ Player.create!(:name => "John Manning", :position => 'fly-half', :first_cap => '1904-07-23', :active => false)
71
+ Player.create!(:name => "Dally Messenger", :position => 'wing', :first_cap => '1907-08-03', :active => false)
72
+ Player.create!(:name => "Salesi Ma'afu", :position => 'prop', :first_cap => '2010-06-05', :active => true)
73
+ Player.create!(:name => "James Slipper", :position => 'prop', :first_cap => nil, :active => true)
74
+ end
75
+
76
+ def setup_database
77
+ ActiveRecord::Base.establish_connection({
78
+ :adapter => 'sqlite3',
79
+ :database => ':memory:',
80
+ :verbosity => 'quiet'
81
+ })
82
+ Arel::Table.engine = Arel::Sql::Engine.new(ActiveRecord::Base)
83
+ AddUsers.migrate(:up)
84
+ end
62
85
  end
@@ -0,0 +1,31 @@
1
+ require 'helper'
2
+
3
+ class OrderParserTest < Test::Unit::TestCase
4
+ context 'OrderParser' do
5
+ setup do
6
+ @parser = Wherewolf::Order::Parser.new
7
+ end
8
+
9
+ context "operands" do
10
+ should 'parse column name' do
11
+ result = @parser.parse('name')
12
+ assert_equal({ :column => "name", :direction => nil }, result)
13
+ end
14
+
15
+ should 'parse column with desc' do
16
+ result = @parser.parse('name desc')
17
+ assert_equal({ :column => "name", :direction => "desc" }, result)
18
+ end
19
+
20
+ should 'parse column with asc' do
21
+ result = @parser.parse('name asc')
22
+ assert_equal({ :column => "name", :direction => "asc" }, result)
23
+ end
24
+
25
+ should 'parse multiple comma seperated order expressions' do
26
+ result = @parser.parse('name asc, age desc')
27
+ assert_equal([ { :column => "name", :direction => "asc" }, { :column => "age", :direction => "desc" } ], result)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,62 @@
1
+ require 'helper'
2
+
3
+ class OrderProcessorTest < Test::Unit::TestCase
4
+ def setup_fixtures
5
+ Player.create!(:name => "Patrick 'Paddy' Carew", :position => 'lock', :first_cap => '1899-06-24', :active => false)
6
+ Player.create!(:name => "Charlie Ellis", :position => 'flanker', :first_cap => '1899-06-24', :active => false)
7
+ Player.create!(:name => "Arthur Corfe", :position => 'flanker', :first_cap => '1899-07-22', :active => false)
8
+ Player.create!(:name => "Syd Miller", :position => 'wing', :first_cap => '1899-08-05', :active => false)
9
+ Player.create!(:name => "Charlie Redwood", :position => 'wing', :first_cap => '1903-08-15', :active => false)
10
+ Player.create!(:name => "Patrick 'Pat' Walsh", :position => 'no. 8', :first_cap => '1904-07-02', :active => false)
11
+ Player.create!(:name => "John Manning", :position => 'fly-half', :first_cap => '1904-07-23', :active => false)
12
+ Player.create!(:name => "Dally Messenger", :position => 'wing', :first_cap => '1907-08-03', :active => false)
13
+ Player.create!(:name => "Salesi Ma'afu", :position => 'prop', :first_cap => '2010-06-05', :active => true)
14
+ Player.create!(:name => "James Slipper", :position => 'prop', :first_cap => nil, :active => true)
15
+ end
16
+
17
+ context 'OrderProcessor' do
18
+ setup do
19
+ setup_database
20
+ setup_fixtures
21
+ end
22
+
23
+ should 'be a Wherewolf::Processor' do
24
+ Wherewolf::Order::Processor.is_a?(Wherewolf::Processor)
25
+ end
26
+
27
+ context 'Parsing' do
28
+ context 'Error' do
29
+ should 'be raised is there is a parser error' do
30
+ assert_raise Wherewolf::ParseError do
31
+ Player.order_query('name up')
32
+ end
33
+ end
34
+
35
+ should 'check that the column is in the list' do
36
+ Wherewolf::Order::Processor.any_instance.expects(:check_column!).once
37
+ Player.order_query('name asc')
38
+ end
39
+ end
40
+
41
+ should 'construct an asc sort' do
42
+ players = Player.order_query('name asc')
43
+ assert_equal Player.order('name asc').all.map(&:name), players.all.map(&:name)
44
+ end
45
+
46
+ should 'construct an desc sort' do
47
+ players = Player.order_query('name desc')
48
+ assert_equal Player.order('name desc').all.map(&:name), players.all.map(&:name)
49
+ end
50
+
51
+ should 'default to asc' do
52
+ players = Player.order_query('name')
53
+ assert_equal Player.order('name asc').all.map(&:name), players.all.map(&:name)
54
+ end
55
+
56
+ should 'handle multiple sorts' do
57
+ players = Player.order_query('name asc, position asc')
58
+ assert_equal Player.order('name asc, position asc').all.map(&:name), players.all.map(&:name)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,153 +1,21 @@
1
1
  require 'helper'
2
2
 
3
3
  class ProcessorTest < Test::Unit::TestCase
4
- def setup_fixtures
5
- Player.create!(:name => "Patrick 'Paddy' Carew", :position => 'lock', :first_cap => '1899-06-24', :active => false)
6
- Player.create!(:name => "Charlie Ellis", :position => 'flanker', :first_cap => '1899-06-24', :active => false)
7
- Player.create!(:name => "Arthur Corfe", :position => 'flanker', :first_cap => '1899-07-22', :active => false)
8
- Player.create!(:name => "Syd Miller", :position => 'wing', :first_cap => '1899-08-05', :active => false)
9
- Player.create!(:name => "Charlie Redwood", :position => 'wing', :first_cap => '1903-08-15', :active => false)
10
- Player.create!(:name => "Patrick 'Pat' Walsh", :position => 'no. 8', :first_cap => '1904-07-02', :active => false)
11
- Player.create!(:name => "John Manning", :position => 'fly-half', :first_cap => '1904-07-23', :active => false)
12
- Player.create!(:name => "Dally Messenger", :position => 'wing', :first_cap => '1907-08-03', :active => false)
13
- Player.create!(:name => "Salesi Ma'afu", :position => 'prop', :first_cap => '2010-06-05', :active => true)
14
- Player.create!(:name => "James Slipper", :position => 'prop', :first_cap => nil, :active => true)
15
- end
16
-
17
- context 'Processor' do
4
+ context 'WhereProcessor' do
18
5
  setup do
19
- ActiveRecord::Base.establish_connection({
20
- :adapter => 'sqlite3',
21
- :database => ':memory:',
22
- :verbosity => 'quiet'
23
- })
24
- Arel::Table.engine = Arel::Sql::Engine.new(ActiveRecord::Base)
25
- AddUsers.migrate(:up)
6
+ setup_database
26
7
  setup_fixtures
27
8
  end
28
9
 
29
- context 'Parsing' do
30
- context 'Error' do
31
- should 'be raised is there is a parser error' do
32
- assert_raise Wherewolf::ParseError do
33
- Player.from_query('name ~= "Patrick%" || (position = "fail)')
34
- end
35
- end
36
-
37
- should 'allow retrieval of the error position' do
38
- begin
39
- Player.from_query('name ~= "Patrick%" || (position = "fail)')
40
- rescue Wherewolf::ParseError => e
41
- assert_equal 28, e.position
42
- end
43
- end
44
-
45
- should 'show a nice debug error' do
46
- begin
47
- Player.from_query('name ~= "Patrick%" || (position = "fail)')
48
- rescue Wherewolf::ParseError => e
49
- assert_equal "Parsing error occured at character 28", e.error_message
50
- end
51
- end
52
-
53
- should 'to_s should print out nice error' do
54
- begin
55
- Player.from_query('name ~= "Patrick%" || (position = "fail)')
56
- rescue Wherewolf::ParseError => e
57
- assert_equal "Parsing error occured at character 28", e.to_s
58
- end
59
- end
60
-
61
- should 'be raised if the requested column is not in the list' do
62
- assert_raise Wherewolf::ParseError do
63
- Player.from_query('shoe_size > 10')
64
- end
10
+ context 'check_column!' do
11
+ should 'raise a ParseError if column is not in the mode' do
12
+ value = mock
13
+ value.stubs(:to_sym).returns(:show_size)
14
+ value.stubs(:to_s).returns('show_size')
15
+ value.stubs(:offset).returns(0)
16
+ assert_raise Parslet::ParseFailed do
17
+ Wherewolf::Processor.new.send(:check_column!, value, Player.arel_table)
65
18
  end
66
-
67
- should 'show a nice debug error if the requested column is not in the list' do
68
- begin
69
- Player.from_query('shoe_size > 10')
70
- rescue Wherewolf::ParseError => e
71
- assert_equal "Parsing error occured at character 0", e.to_s
72
- end
73
- end
74
- end
75
-
76
- should 'construct simple boolean statements' do
77
- player = Player.from_query('name = "Charlie Ellis"')
78
- assert_equal 1, player.count
79
- assert_equal 'Charlie Ellis', player.first.name
80
- end
81
-
82
- should 'construct two boolean statments' do
83
- player = Player.from_query('position=lock && first_cap < 2010-01-01')
84
- assert_equal 1, player.count
85
- assert_equal "Patrick 'Paddy' Carew", player.first.name
86
- end
87
-
88
- should 'contruct nested brackets' do
89
- player = Player.from_query("(position = wing || position = lock) && first_cap <= 1905-01-01").order('first_cap')
90
- assert_equal 3, player.count
91
- assert_equal "Patrick 'Paddy' Carew", player[0].name
92
- assert_equal "Syd Miller", player[1].name
93
- assert_equal "Charlie Redwood", player[2].name
94
- end
95
-
96
- should 'handle matches' do
97
- player = Player.from_query('name ~= "James%"')
98
- assert_equal 1, player.count
99
- assert_equal "James Slipper", player.first.name
100
- end
101
-
102
- should 'handle nulls' do
103
- player = Player.from_query("first_cap = null")
104
- assert_equal 1, player.count
105
- assert_equal "James Slipper", player.first.name
106
- end
107
-
108
- should 'handle booleans' do
109
- player = Player.from_query("active = true")
110
- assert_equal 2, player.count
111
- player = Player.from_query("active = false")
112
- assert_equal 8, player.count
113
- end
114
-
115
- should 'handle dates' do
116
- player = Player.from_query("first_cap > 2000-01-01")
117
- assert_equal 1, player.count
118
- assert_equal "Salesi Ma'afu", player.first.name
119
- end
120
-
121
- should 'process =' do
122
- player = Player.from_query('name = "Charlie Ellis"')
123
- assert_equal 1, player.count
124
- assert_equal 'Charlie Ellis', player.first.name
125
- end
126
-
127
- should 'process !=' do
128
- player = Player.from_query('name != "Charlie Ellis"')
129
- assert_equal 9, player.count
130
- assert_equal false, player.map(&:name).include?('Charlie Ellis')
131
- end
132
-
133
- should 'process >' do
134
- player = Player.from_query('first_cap > 1907-08-03')
135
- assert_equal 1, player.count
136
- end
137
-
138
- should 'process >=' do
139
- player = Player.from_query('first_cap >= 1907-08-03')
140
- assert_equal 2, player.count
141
- end
142
-
143
- should 'process <' do
144
- player = Player.from_query('first_cap < 1907-08-03')
145
- assert_equal 7, player.count
146
- end
147
-
148
- should 'process <=' do
149
- player = Player.from_query('first_cap <= 1907-08-03')
150
- assert_equal 8, player.count
151
19
  end
152
20
  end
153
21
  end
@@ -2,12 +2,12 @@ require 'helper'
2
2
 
3
3
  class RailtieTest < Test::Unit::TestCase
4
4
  context 'Railtie' do
5
- should 'not enable from_query if has_query_parsing is not called' do
6
- assert_equal false, Team.respond_to?(:from_query)
5
+ should 'not enable where_query if has_query_parsing is not called' do
6
+ assert_equal false, Team.respond_to?(:where_query)
7
7
  end
8
8
 
9
- should 'enable from_query if has_query_parsing is called' do
10
- assert_equal true, Player.respond_to?(:from_query)
9
+ should 'enable where_query if has_query_parsing is called' do
10
+ assert_equal true, Player.respond_to?(:where_query)
11
11
  end
12
12
  end
13
13
  end
@@ -1,9 +1,9 @@
1
1
  require 'helper'
2
2
 
3
- class ParserTest < Test::Unit::TestCase
4
- context 'Parser' do
3
+ class WhereParserTest < Test::Unit::TestCase
4
+ context 'WhereParser' do
5
5
  setup do
6
- @parser = Wherewolf::Parser.new
6
+ @parser = Wherewolf::Where::Parser.new
7
7
  end
8
8
 
9
9
  context "operands" do
@@ -0,0 +1,140 @@
1
+ require 'helper'
2
+
3
+ class WhereProcessorTest < Test::Unit::TestCase
4
+ context 'WhereProcessor' do
5
+ setup do
6
+ setup_database
7
+ setup_fixtures
8
+ end
9
+
10
+ should 'be a Wherewolf::Processor' do
11
+ Wherewolf::Where::Processor.is_a?(Wherewolf::Processor)
12
+ end
13
+
14
+ context 'Parsing' do
15
+ context 'Error' do
16
+ should 'be raised is there is a parser error' do
17
+ assert_raise Wherewolf::ParseError do
18
+ Player.where_query('name ~= "Patrick%" || (position = "fail)')
19
+ end
20
+ end
21
+
22
+ should 'allow retrieval of the error position' do
23
+ begin
24
+ Player.where_query('name ~= "Patrick%" || (position = "fail)')
25
+ rescue Wherewolf::ParseError => e
26
+ assert_equal 28, e.position
27
+ end
28
+ end
29
+
30
+ should 'show a nice debug error' do
31
+ begin
32
+ Player.where_query('name ~= "Patrick%" || (position = "fail)')
33
+ rescue Wherewolf::ParseError => e
34
+ assert_equal "Parsing error occured at character 28", e.error_message
35
+ end
36
+ end
37
+
38
+ should 'to_s should print out nice error' do
39
+ begin
40
+ Player.where_query('name ~= "Patrick%" || (position = "fail)')
41
+ rescue Wherewolf::ParseError => e
42
+ assert_equal "Parsing error occured at character 28", e.to_s
43
+ end
44
+ end
45
+
46
+ should 'be raised if the requested column is not in the list' do
47
+ assert_raise Wherewolf::ParseError do
48
+ Player.where_query('shoe_size > 10')
49
+ end
50
+ end
51
+
52
+ should 'check to see if the column is allowed' do
53
+ Wherewolf::Where::Processor.any_instance.expects(:check_column!).once
54
+ begin
55
+ Player.where_query('shoe_size > 10')
56
+ rescue Wherewolf::ParseError => e
57
+ assert_equal "Parsing error occured at character 0", e.to_s
58
+ end
59
+ end
60
+ end
61
+
62
+ should 'construct simple boolean statements' do
63
+ player = Player.where_query('name = "Charlie Ellis"')
64
+ assert_equal 1, player.count
65
+ assert_equal 'Charlie Ellis', player.first.name
66
+ end
67
+
68
+ should 'construct two boolean statments' do
69
+ player = Player.where_query('position=lock && first_cap < 2010-01-01')
70
+ assert_equal 1, player.count
71
+ assert_equal "Patrick 'Paddy' Carew", player.first.name
72
+ end
73
+
74
+ should 'contruct nested brackets' do
75
+ player = Player.where_query("(position = wing || position = lock) && first_cap <= 1905-01-01").order('first_cap')
76
+ assert_equal 3, player.count
77
+ assert_equal "Patrick 'Paddy' Carew", player[0].name
78
+ assert_equal "Syd Miller", player[1].name
79
+ assert_equal "Charlie Redwood", player[2].name
80
+ end
81
+
82
+ should 'handle matches' do
83
+ player = Player.where_query('name ~= "James%"')
84
+ assert_equal 1, player.count
85
+ assert_equal "James Slipper", player.first.name
86
+ end
87
+
88
+ should 'handle nulls' do
89
+ player = Player.where_query("first_cap = null")
90
+ assert_equal 1, player.count
91
+ assert_equal "James Slipper", player.first.name
92
+ end
93
+
94
+ should 'handle booleans' do
95
+ player = Player.where_query("active = true")
96
+ assert_equal 2, player.count
97
+ player = Player.where_query("active = false")
98
+ assert_equal 8, player.count
99
+ end
100
+
101
+ should 'handle dates' do
102
+ player = Player.where_query("first_cap > 2000-01-01")
103
+ assert_equal 1, player.count
104
+ assert_equal "Salesi Ma'afu", player.first.name
105
+ end
106
+
107
+ should 'process =' do
108
+ player = Player.where_query('name = "Charlie Ellis"')
109
+ assert_equal 1, player.count
110
+ assert_equal 'Charlie Ellis', player.first.name
111
+ end
112
+
113
+ should 'process !=' do
114
+ player = Player.where_query('name != "Charlie Ellis"')
115
+ assert_equal 9, player.count
116
+ assert_equal false, player.map(&:name).include?('Charlie Ellis')
117
+ end
118
+
119
+ should 'process >' do
120
+ player = Player.where_query('first_cap > 1907-08-03')
121
+ assert_equal 1, player.count
122
+ end
123
+
124
+ should 'process >=' do
125
+ player = Player.where_query('first_cap >= 1907-08-03')
126
+ assert_equal 2, player.count
127
+ end
128
+
129
+ should 'process <' do
130
+ player = Player.where_query('first_cap < 1907-08-03')
131
+ assert_equal 7, player.count
132
+ end
133
+
134
+ should 'process <=' do
135
+ player = Player.where_query('first_cap <= 1907-08-03')
136
+ assert_equal 8, player.count
137
+ end
138
+ end
139
+ end
140
+ end
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "wherewolf"
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Myles Eftos"]
@@ -25,21 +25,27 @@ Gem::Specification.new do |s|
25
25
  "README.rdoc",
26
26
  "Rakefile",
27
27
  "lib/wherewolf.rb",
28
+ "lib/wherewolf/order/parser.rb",
29
+ "lib/wherewolf/order/processor.rb",
28
30
  "lib/wherewolf/parse_error.rb",
29
- "lib/wherewolf/parser.rb",
30
31
  "lib/wherewolf/processor.rb",
31
32
  "lib/wherewolf/railtie.rb",
33
+ "lib/wherewolf/where/parser.rb",
34
+ "lib/wherewolf/where/processor.rb",
32
35
  "test/helper.rb",
36
+ "test/order/parser_test.rb",
37
+ "test/order/processor_test.rb",
33
38
  "test/parse_error_test.rb",
34
- "test/parser_test.rb",
35
39
  "test/processor_test.rb",
36
40
  "test/railtie_test.rb",
41
+ "test/where/parser_test.rb",
42
+ "test/where/processor_test.rb",
37
43
  "wherewolf.gemspec"
38
44
  ]
39
45
  s.homepage = "http://github.com/madpilot/wherewolf"
40
46
  s.licenses = ["MIT"]
41
47
  s.require_paths = ["lib"]
42
- s.rubygems_version = "1.8.15"
48
+ s.rubygems_version = "1.8.24"
43
49
  s.summary = "Makes filtering and searching to your REST API crazy easy."
44
50
 
45
51
  if s.respond_to? :specification_version then
@@ -57,7 +63,7 @@ Gem::Specification.new do |s|
57
63
  s.add_development_dependency(%q<simplecov>, [">= 0"])
58
64
  s.add_development_dependency(%q<sqlite3>, [">= 0"])
59
65
  s.add_development_dependency(%q<rails>, [">= 0"])
60
- s.add_development_dependency(%q<wherewolf>, [">= 0"])
66
+ s.add_development_dependency(%q<mocha>, [">= 0"])
61
67
  else
62
68
  s.add_dependency(%q<arel>, [">= 0"])
63
69
  s.add_dependency(%q<parslet>, [">= 0"])
@@ -70,7 +76,7 @@ Gem::Specification.new do |s|
70
76
  s.add_dependency(%q<simplecov>, [">= 0"])
71
77
  s.add_dependency(%q<sqlite3>, [">= 0"])
72
78
  s.add_dependency(%q<rails>, [">= 0"])
73
- s.add_dependency(%q<wherewolf>, [">= 0"])
79
+ s.add_dependency(%q<mocha>, [">= 0"])
74
80
  end
75
81
  else
76
82
  s.add_dependency(%q<arel>, [">= 0"])
@@ -84,7 +90,7 @@ Gem::Specification.new do |s|
84
90
  s.add_dependency(%q<simplecov>, [">= 0"])
85
91
  s.add_dependency(%q<sqlite3>, [">= 0"])
86
92
  s.add_dependency(%q<rails>, [">= 0"])
87
- s.add_dependency(%q<wherewolf>, [">= 0"])
93
+ s.add_dependency(%q<mocha>, [">= 0"])
88
94
  end
89
95
  end
90
96
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wherewolf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-10-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: arel
16
- requirement: &70231215234580 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70231215234580
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: parslet
27
- requirement: &70231215233400 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70231215233400
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: shoulda
38
- requirement: &70231215232100 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70231215232100
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rdoc
49
- requirement: &70231215230020 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70231215230020
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: bundler
60
- requirement: &70231215244520 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: '0'
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *70231215244520
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: jeweler
71
- requirement: &70231215243640 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ! '>='
@@ -76,10 +101,15 @@ dependencies:
76
101
  version: '0'
77
102
  type: :development
78
103
  prerelease: false
79
- version_requirements: *70231215243640
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
80
110
  - !ruby/object:Gem::Dependency
81
111
  name: guard
82
- requirement: &70231215242880 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
83
113
  none: false
84
114
  requirements:
85
115
  - - ! '>='
@@ -87,10 +117,15 @@ dependencies:
87
117
  version: '0'
88
118
  type: :development
89
119
  prerelease: false
90
- version_requirements: *70231215242880
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
91
126
  - !ruby/object:Gem::Dependency
92
127
  name: guard-test
93
- requirement: &70231215242000 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
94
129
  none: false
95
130
  requirements:
96
131
  - - ! '>='
@@ -98,10 +133,15 @@ dependencies:
98
133
  version: '0'
99
134
  type: :development
100
135
  prerelease: false
101
- version_requirements: *70231215242000
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
102
142
  - !ruby/object:Gem::Dependency
103
143
  name: simplecov
104
- requirement: &70231215240760 !ruby/object:Gem::Requirement
144
+ requirement: !ruby/object:Gem::Requirement
105
145
  none: false
106
146
  requirements:
107
147
  - - ! '>='
@@ -109,10 +149,15 @@ dependencies:
109
149
  version: '0'
110
150
  type: :development
111
151
  prerelease: false
112
- version_requirements: *70231215240760
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
113
158
  - !ruby/object:Gem::Dependency
114
159
  name: sqlite3
115
- requirement: &70231215239680 !ruby/object:Gem::Requirement
160
+ requirement: !ruby/object:Gem::Requirement
116
161
  none: false
117
162
  requirements:
118
163
  - - ! '>='
@@ -120,10 +165,15 @@ dependencies:
120
165
  version: '0'
121
166
  type: :development
122
167
  prerelease: false
123
- version_requirements: *70231215239680
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
124
174
  - !ruby/object:Gem::Dependency
125
175
  name: rails
126
- requirement: &70231215238260 !ruby/object:Gem::Requirement
176
+ requirement: !ruby/object:Gem::Requirement
127
177
  none: false
128
178
  requirements:
129
179
  - - ! '>='
@@ -131,10 +181,15 @@ dependencies:
131
181
  version: '0'
132
182
  type: :development
133
183
  prerelease: false
134
- version_requirements: *70231215238260
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
135
190
  - !ruby/object:Gem::Dependency
136
- name: wherewolf
137
- requirement: &70231215253700 !ruby/object:Gem::Requirement
191
+ name: mocha
192
+ requirement: !ruby/object:Gem::Requirement
138
193
  none: false
139
194
  requirements:
140
195
  - - ! '>='
@@ -142,7 +197,12 @@ dependencies:
142
197
  version: '0'
143
198
  type: :development
144
199
  prerelease: false
145
- version_requirements: *70231215253700
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ! '>='
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
146
206
  description: Wherewolf allows you to consume search terms as strings without worrying
147
207
  about database injections. It parses the query and converts it into ARel. It's great
148
208
  for creating filterable REST APIs.
@@ -161,15 +221,21 @@ files:
161
221
  - README.rdoc
162
222
  - Rakefile
163
223
  - lib/wherewolf.rb
224
+ - lib/wherewolf/order/parser.rb
225
+ - lib/wherewolf/order/processor.rb
164
226
  - lib/wherewolf/parse_error.rb
165
- - lib/wherewolf/parser.rb
166
227
  - lib/wherewolf/processor.rb
167
228
  - lib/wherewolf/railtie.rb
229
+ - lib/wherewolf/where/parser.rb
230
+ - lib/wherewolf/where/processor.rb
168
231
  - test/helper.rb
232
+ - test/order/parser_test.rb
233
+ - test/order/processor_test.rb
169
234
  - test/parse_error_test.rb
170
- - test/parser_test.rb
171
235
  - test/processor_test.rb
172
236
  - test/railtie_test.rb
237
+ - test/where/parser_test.rb
238
+ - test/where/processor_test.rb
173
239
  - wherewolf.gemspec
174
240
  homepage: http://github.com/madpilot/wherewolf
175
241
  licenses:
@@ -186,7 +252,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
186
252
  version: '0'
187
253
  segments:
188
254
  - 0
189
- hash: 730622563305472605
255
+ hash: 3659032346363356481
190
256
  required_rubygems_version: !ruby/object:Gem::Requirement
191
257
  none: false
192
258
  requirements:
@@ -195,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
261
  version: '0'
196
262
  requirements: []
197
263
  rubyforge_project:
198
- rubygems_version: 1.8.15
264
+ rubygems_version: 1.8.24
199
265
  signing_key:
200
266
  specification_version: 3
201
267
  summary: Makes filtering and searching to your REST API crazy easy.
@@ -1,55 +0,0 @@
1
- require 'parslet'
2
-
3
- module Wherewolf
4
- class Parser < Parslet::Parser
5
- rule(:space) { match('\s').repeat(1) }
6
- rule(:space?) { space.maybe }
7
- rule(:left_parenthesis) { str('(') }
8
- rule(:right_parenthesis) { str(')') }
9
-
10
- # Comparisons
11
- rule(:eq) { str('=') }
12
- rule(:not_eq) { str('!=') }
13
- rule(:matches) { str('~=') }
14
- rule(:lt) { str('<') }
15
- rule(:lteq) { str('<=') }
16
- rule(:gt) { str('>') }
17
- rule(:gteq) { str('>=') }
18
-
19
- # Operators
20
- rule(:and_operator) { str('&&') }
21
- rule(:or_operator) { str('||') }
22
-
23
- # Operand
24
- rule(:null) { str("null").as(:nil) }
25
- rule(:boolean) { str("true").as(:boolean) | str("false").as(:boolean) }
26
- rule(:number) { match('[-+]?([0-9]*\.)?[0-9]').repeat(1).as(:number) }
27
- rule(:double_quote_string) do
28
- str('"') >>
29
- (
30
- (str('\\') >> any) |
31
- (str('"').absent? >> any)
32
- ).repeat.as(:string) >>
33
- str('"')
34
- end
35
- rule(:literal) { match('[a-zA-Z0-9\-_]').repeat(1) }
36
- rule(:identifier) { null | boolean | number | double_quote_string | literal.as(:string) }
37
-
38
- # Grammar
39
- rule(:compare_eq) { (literal.as(:left) >> space? >> eq >> space? >> identifier.as(:right)).as(:eq) }
40
- rule(:compare_not_eq) { (literal.as(:left) >> space? >> not_eq >> space? >> identifier.as(:right)).as(:not_eq) }
41
- rule(:compare_matches) { (literal.as(:left) >> space? >> matches >> space? >> identifier.as(:right)).as(:matches) }
42
- rule(:compare_lt) { (literal.as(:left) >> space? >> lt >> space? >> identifier.as(:right)).as(:lt) }
43
- rule(:compare_lteq) { (literal.as(:left) >> space? >> lteq >> space? >> identifier.as(:right)).as(:lteq) }
44
- rule(:compare_gt) { (literal.as(:left) >> space? >> gt >> space? >> identifier.as(:right)).as(:gt) }
45
- rule(:compare_gteq) { (literal.as(:left) >> space? >> gteq >> space? >> identifier.as(:right)).as(:gteq) }
46
-
47
- rule(:compare) { compare_eq | compare_not_eq | compare_matches | compare_lteq | compare_lt | compare_gteq | compare_gt }
48
-
49
- rule(:primary) { left_parenthesis >> space? >> or_operation >> space? >> right_parenthesis | compare }
50
- rule(:and_operation) { (primary.as(:left) >> space? >> and_operator >> space? >> and_operation.as(:right)).as(:and) | primary }
51
- rule(:or_operation) { (and_operation.as(:left) >> space? >> or_operator >> space? >> or_operation.as(:right)).as(:or) | and_operation }
52
-
53
- root :or_operation
54
- end
55
- end