nql 0.0.2 → 0.0.3

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/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