nql 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,54 +1,54 @@
1
- # NQL
2
-
3
- Natural Query Language built on top of ActiveRecord and Ransack
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'nql'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install nql
18
-
19
- ## Supported comparators
20
-
21
- ----------------------------------
22
- | Symbol | Description |
23
- ----------------------------------
24
- | % | Contains |
25
- | = | Equals |
26
- | != | Not equals |
27
- | > | Grater than |
28
- | >= | Grater or equals than |
29
- | < | Less than |
30
- | <= | Less or equals than |
31
- ----------------------------------
32
-
33
-
34
- ## Usage
35
-
36
- Converts from natural language to query expression
37
-
38
- q = '(name % arg | name % br) & region = south'
39
- Country.search(NQL.to_ransack(q)).result.to_sql
40
- => "SELECT coutries.* FROM countries WHERE (countries.name LIKE '%arg%' OR countries.name LIKE '%br%') AND region = 'south'"
41
-
42
- ### Joins support
43
-
44
- q = 'cities.name % buenos'
45
- Country.search(NQL.to_ransack(q)).result.to_sql
46
- => "SELECT countries.* FROM countries LEFT OUTER JOIN cities ON countries.id = cities.country_id WHERE cities.name LIKE '%buenos%'"
47
-
48
- ## Contributing
49
-
50
- 1. Fork it
51
- 2. Create your feature branch (`git checkout -b my-new-feature`)
52
- 3. Commit your changes (`git commit -am 'Added some feature'`)
53
- 4. Push to the branch (`git push origin my-new-feature`)
54
- 5. Create new Pull Request
1
+ # NQL
2
+
3
+ Natural Query Language built on top of ActiveRecord and Ransack
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'nql'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install nql
18
+
19
+ ## Supported comparators
20
+
21
+ ----------------------------------
22
+ | Symbol | Description |
23
+ ----------------------------------
24
+ | : | Contains |
25
+ | = | Equals |
26
+ | != | Not equals |
27
+ | > | Grater than |
28
+ | >= | Grater or equals than |
29
+ | < | Less than |
30
+ | <= | Less or equals than |
31
+ ----------------------------------
32
+
33
+
34
+ ## Usage
35
+
36
+ Converts from natural language to query expression
37
+
38
+ q = '(name: arg | name: br) & region = south'
39
+ Country.search(NQL.to_ransack(q)).result.to_sql
40
+ => "SELECT coutries.* FROM countries WHERE (countries.name LIKE '%arg%' OR countries.name LIKE '%br%') AND region = 'south'"
41
+
42
+ ### Joins support
43
+
44
+ q = 'cities.name: buenos'
45
+ Country.search(NQL.to_ransack(q)).result.to_sql
46
+ => "SELECT countries.* FROM countries LEFT OUTER JOIN cities ON countries.id = cities.country_id WHERE cities.name LIKE '%buenos%'"
47
+
48
+ ## Contributing
49
+
50
+ 1. Fork it
51
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
52
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
53
+ 4. Push to the branch (`git push origin my-new-feature`)
54
+ 5. Create new Pull Request
data/lib/nql.rb CHANGED
@@ -5,20 +5,21 @@ require 'ransack'
5
5
 
6
6
  require 'nql/version'
7
7
  require 'nql/grammar'
8
+ require 'nql/invalid_expression_error'
8
9
 
9
10
  module NQL
10
11
 
11
12
  def self.to_ransack(query)
12
13
  return nil if query.nil? || query.strip.empty?
13
- expression = SyntaxParser.new.parse(query)
14
- return invalid_condition unless expression
14
+ expression = parser.parse(query)
15
+ raise InvalidExpressionError.new(parser.failure_reason) unless expression
15
16
  expression.to_ransack
16
17
  end
17
18
 
18
19
  private
19
20
 
20
- def self.invalid_condition
21
- {c: [{a: {'0' => {name: 'id'}}, p: 'eq', v: {'0' => {value: '0'}}}]}
21
+ def self.parser
22
+ @@parser ||= SyntaxParser.new
22
23
  end
23
24
 
24
25
  end
@@ -393,7 +393,7 @@ module NQL
393
393
  '>=' => 'gteq',
394
394
  '<' => 'lt',
395
395
  '<=' => 'lteq',
396
- '%' => 'cont'
396
+ ':' => 'cont'
397
397
  }
398
398
  comparators[text_value]
399
399
  end
@@ -473,11 +473,11 @@ module NQL
473
473
  if r7
474
474
  r1 = r7
475
475
  else
476
- if has_terminal?('%', false, index)
476
+ if has_terminal?(':', false, index)
477
477
  r8 = instantiate_node(SyntaxNode,input, index...(index + 1))
478
478
  @index += 1
479
479
  else
480
- terminal_parse_failure('%')
480
+ terminal_parse_failure(':')
481
481
  r8 = nil
482
482
  end
483
483
  if r8
@@ -68,7 +68,7 @@ module NQL
68
68
  end
69
69
 
70
70
  rule comparator
71
- ('=' / '!=' / '>' / '>=' / '<' / '<=' / '%')+ {
71
+ ('=' / '!=' / '>' / '>=' / '<' / '<=' / ':')+ {
72
72
  def to_ransack
73
73
  comparators = {
74
74
  '=' => 'eq',
@@ -77,7 +77,7 @@ module NQL
77
77
  '>=' => 'gteq',
78
78
  '<' => 'lt',
79
79
  '<=' => 'lteq',
80
- '%' => 'cont'
80
+ ':' => 'cont'
81
81
  }
82
82
  comparators[text_value]
83
83
  end
@@ -0,0 +1,7 @@
1
+ module NQL
2
+ class InvalidExpressionError < StandardError
3
+ def initialize(message)
4
+ super
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module NQL
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -55,10 +55,10 @@ describe NQL::SyntaxParser, '-> Comparison' do
55
55
  end
56
56
 
57
57
  it 'Contains' do
58
- tree = parser.parse('var % value')
58
+ tree = parser.parse('var : value')
59
59
 
60
60
  tree.comparison.variable.text_value.should eq 'var'
61
- tree.comparison.comparator.text_value.should eq '%'
61
+ tree.comparison.comparator.text_value.should eq ':'
62
62
  tree.comparison.value.text_value.should eq 'value'
63
63
  end
64
64
 
@@ -55,7 +55,7 @@ describe 'Ransack Query' do
55
55
  end
56
56
 
57
57
  it 'Contains' do
58
- q = parser.parse('id % 1234').to_ransack
58
+ q = parser.parse('id : 1234').to_ransack
59
59
 
60
60
  q[:c][0].should have_attribute 'id'
61
61
  q[:c][0].should have_predicate 'cont'
@@ -87,7 +87,7 @@ describe 'Ransack Query' do
87
87
  end
88
88
 
89
89
  it 'Or' do
90
- q = parser.parse('id < 1234 | name % abcd').to_ransack
90
+ q = parser.parse('id < 1234 | name : abcd').to_ransack
91
91
 
92
92
  q[:g][0][:m].should eq 'or'
93
93
  q[:g][0][:c][0].should have_attribute 'id'
@@ -99,7 +99,7 @@ describe 'Ransack Query' do
99
99
  end
100
100
 
101
101
  it 'And then Or' do
102
- q = parser.parse('id > 1234 & name = abcd | name % efgh').to_ransack
102
+ q = parser.parse('id > 1234 & name = abcd | name : efgh').to_ransack
103
103
 
104
104
  q[:g][0][:m].should eq 'and'
105
105
  q[:g][0][:c][0].should have_attribute 'id'
@@ -115,7 +115,7 @@ describe 'Ransack Query' do
115
115
  end
116
116
 
117
117
  it 'With parentheses' do
118
- q = parser.parse('(id > 1234 & name = abcd) | name % efgh').to_ransack
118
+ q = parser.parse('(id > 1234 & name = abcd) | name : efgh').to_ransack
119
119
 
120
120
  q[:g][0][:g][0][:m].should eq 'and'
121
121
  q[:g][0][:g][0][:c][0].should have_attribute 'id'
@@ -41,7 +41,7 @@ describe 'SQL generation' do
41
41
  end
42
42
 
43
43
  it 'Contains' do
44
- q = 'name % abcd'
44
+ q = 'name : abcd'
45
45
  Country.search(NQL.to_ransack(q)).result.should produce_sql "SELECT \"countries\".* FROM \"countries\" WHERE (\"countries\".\"name\" LIKE '%abcd%')"
46
46
  end
47
47
 
@@ -55,17 +55,17 @@ describe 'SQL generation' do
55
55
  end
56
56
 
57
57
  it 'Or' do
58
- q = 'id < 1234 | name % abcd'
58
+ q = 'id < 1234 | name : abcd'
59
59
  Country.search(NQL.to_ransack(q)).result.should produce_sql "SELECT \"countries\".* FROM \"countries\" WHERE ((\"countries\".\"id\" < 1234 OR \"countries\".\"name\" LIKE '%abcd%'))"
60
60
  end
61
61
 
62
62
  it 'And then Or' do
63
- q = 'id > 1234 & name = abcd | name % efgh'
63
+ q = 'id > 1234 & name = abcd | name : efgh'
64
64
  Country.search(NQL.to_ransack(q)).result.should produce_sql "SELECT \"countries\".* FROM \"countries\" WHERE ((\"countries\".\"id\" > 1234 AND (\"countries\".\"name\" = 'abcd' OR \"countries\".\"name\" LIKE '%efgh%')))"
65
65
  end
66
66
 
67
67
  it 'With parentheses' do
68
- q = '(id > 1234 & name = abcd) | name % efgh'
68
+ q = '(id > 1234 & name = abcd) | name : efgh'
69
69
  Country.search(NQL.to_ransack(q)).result.should produce_sql "SELECT \"countries\".* FROM \"countries\" WHERE ((\"countries\".\"name\" LIKE '%efgh%' OR (\"countries\".\"id\" > 1234 AND \"countries\".\"name\" = 'abcd')))"
70
70
  end
71
71
 
@@ -74,17 +74,17 @@ describe 'SQL generation' do
74
74
  context 'Model joins' do
75
75
 
76
76
  it 'Parent join' do
77
- q = 'country.name % abcd'
77
+ q = 'country.name : abcd'
78
78
  City.search(NQL.to_ransack(q)).result.should produce_sql "SELECT \"cities\".* FROM \"cities\" LEFT OUTER JOIN \"countries\" ON \"countries\".\"id\" = \"cities\".\"country_id\" WHERE (\"countries\".\"name\" LIKE '%abcd%')"
79
79
  end
80
80
 
81
81
  it 'Children join' do
82
- q = 'cities.name % abcd'
82
+ q = 'cities.name : abcd'
83
83
  Country.search(NQL.to_ransack(q)).result.should produce_sql "SELECT \"countries\".* FROM \"countries\" LEFT OUTER JOIN \"cities\" ON \"cities\".\"country_id\" = \"countries\".\"id\" WHERE (\"cities\".\"name\" LIKE '%abcd%')"
84
84
  end
85
85
 
86
86
  it 'Children join distinct' do
87
- q = 'cities.name % abcd'
87
+ q = 'cities.name : abcd'
88
88
  Country.search(NQL.to_ransack(q)).result(distinct: true).should produce_sql "SELECT DISTINCT \"countries\".* FROM \"countries\" LEFT OUTER JOIN \"cities\" ON \"cities\".\"country_id\" = \"countries\".\"id\" WHERE (\"cities\".\"name\" LIKE '%abcd%')"
89
89
  end
90
90
 
@@ -109,7 +109,7 @@ describe 'SQL generation' do
109
109
 
110
110
  it 'Partial expression' do
111
111
  q = 'id ='
112
- Country.search(NQL.to_ransack(q)).result.should produce_sql "SELECT \"countries\".* FROM \"countries\" WHERE \"countries\".\"id\" = 0"
112
+ expect{Country.search(NQL.to_ransack(q)).result}.should raise_exception NQL::InvalidExpressionError
113
113
  end
114
114
 
115
115
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-11-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: treetop
16
- requirement: &28497180 !ruby/object:Gem::Requirement
16
+ requirement: &28678476 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *28497180
24
+ version_requirements: *28678476
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activerecord
27
- requirement: &28496880 !ruby/object:Gem::Requirement
27
+ requirement: &28678152 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.2.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *28496880
35
+ version_requirements: *28678152
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: activesupport
38
- requirement: &28496568 !ruby/object:Gem::Requirement
38
+ requirement: &28677828 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 3.2.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *28496568
46
+ version_requirements: *28677828
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: ransack
49
- requirement: &28496340 !ruby/object:Gem::Requirement
49
+ requirement: &28677600 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *28496340
57
+ version_requirements: *28677600
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: sqlite3
60
- requirement: &28496064 !ruby/object:Gem::Requirement
60
+ requirement: &28677324 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *28496064
68
+ version_requirements: *28677324
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &28495812 !ruby/object:Gem::Requirement
71
+ requirement: &28677060 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *28495812
79
+ version_requirements: *28677060
80
80
  description: Natural Query Language built on top of ActiveRecord and Ransack
81
81
  email:
82
82
  - gabynaiman@gmail.com
@@ -92,6 +92,7 @@ files:
92
92
  - lib/nql.rb
93
93
  - lib/nql/grammar.rb
94
94
  - lib/nql/grammar.treetop
95
+ - lib/nql/invalid_expression_error.rb
95
96
  - lib/nql/version.rb
96
97
  - nql.gemspec
97
98
  - spec/comparison_parser_spec.rb