ransack_mongo 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aa14d28f6e8b1cd4f880003a75f9fbe386065fde
4
- data.tar.gz: db5b0fc818f5624ba66e18d310cecf139a3c7a12
3
+ metadata.gz: 653de3c263786edc9d472e925e4c2802b9d8723e
4
+ data.tar.gz: 6bc873650e072552a2582dca3fdc4f3a6606c5d0
5
5
  SHA512:
6
- metadata.gz: d1990c1854b2d5b6c9ac567b412d0f7ee967496acad4908cf60c372d72f956d729f160a2efd4a8881857be18aa907dab013e9231095abf95957d705236078545
7
- data.tar.gz: b0b08055f284c65882ea7cd9d67d8b0527af1ce091e5ee53120a7504148654b9ccc53c03c4f1d63e0d08528b861fe069127388ddf32757c33224c272dc5d774f
6
+ metadata.gz: add84c5b3298b51116656d07c7d541fa6733a1b0dc568caf6a15297921edc2342042a32408dfb797b526ddb8a80c9b2e246106a5ae9f028109e6d5a404303edf
7
+ data.tar.gz: 23e2806cc27103853ccf12a53d224ac93cc319c47f09e675556493e140947f4f3e91914fabf864c4f49eb4d553dd34328aa8904b759553fa1799088796f4661c
data/.travis.yml ADDED
@@ -0,0 +1,16 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 1.9.2
5
+ - 2.0.0
6
+ # - 2.1.0
7
+ # - ruby-head
8
+ - jruby-19mode
9
+ - jruby-head
10
+
11
+ notifications:
12
+ email:
13
+ on_success: change
14
+ on_failure: always
15
+
16
+ script: bundle exec rspec spec
data/README.md CHANGED
@@ -1,6 +1,14 @@
1
- # RansackMongo
1
+ # Ransack Mongo
2
2
 
3
- TODO: Write a gem description
3
+ [![Build Status](https://travis-ci.org/phstc/ransack_mongo.svg)](https://travis-ci.org/phstc/ransack_mongo)
4
+
5
+ Ransack Mongo is based on [Ransack](https://github.com/activerecord-hackery/ransack), but for MongoDB.
6
+
7
+ With Ransack Mongo you can convert query params into Mongo queries.
8
+
9
+ ## Why another gem?
10
+
11
+ > [Given that Ransack is built on top of ARel and that ARel only works with relational databases, I don't see how we could add Mongoid support without dramatically changing everything.](https://github.com/activerecord-hackery/ransack/issues/120#issuecomment-7539851)
4
12
 
5
13
  ## Installation
6
14
 
@@ -18,11 +26,62 @@ Or install it yourself as:
18
26
 
19
27
  ## Usage
20
28
 
21
- TODO: Write usage instructions here
29
+ ```ruby
30
+ # GET /customers?q[name_eq]=Pablo&q[middle_name_or_last_name_cont]=Cantero
31
+ # params[:q]
32
+ # => { name_eq: 'Pablo', middle_name_or_last_name_cont: 'Cantero' }
33
+ # query.to_query(params[:q])
34
+ # => { name: 'Pablo', '$or' => { middle_name: /Cantero/i, last_name: /Cantero/i } }
35
+
36
+ # GET /customers
37
+ def index
38
+ query = RansackMongo::Query.new
39
+ selector = query.to_query(params[:q])
40
+
41
+ # Mongo Ruby Driver
42
+ @customers = db.customers.find(selector)
43
+
44
+ # Mongoid
45
+ @customers = Customer.where(selector)
46
+ end
47
+ ```
48
+
49
+ ### Available predicates
50
+
51
+ * eq
52
+ * not_eq
53
+ * cont
54
+ * in
55
+ * gt
56
+ * lt
57
+ * gteq
58
+ * lteq
59
+
60
+ ### OR operator
61
+
62
+ You can also combine predicates for OR queries.
63
+
64
+ ```ruby
65
+ query_param = { name_eq: 'Pablo', middle_name_or_last_name_cont: 'Cantero' }
66
+ query.to_query(params[:q])
67
+ # => { name: 'Pablo', '$or' => { middle_name: /Cantero/i, last_name: /Cantero/i } }
68
+ ```
69
+
70
+ ### to_query!
71
+
72
+ You can use to_query! for stricter validations. This method will raise an exception if a query cannot be produced.
73
+ ```ruby
74
+ # xpto isn't a valid predicate
75
+
76
+ query.to_query(name_xpto: 'Pablo')
77
+ # => {}
78
+ query.to_query!(name_xpto: 'Pablo')
79
+ # => RansackMongo::MatcherNotFound: No matchers found. To allow empty queries use .to_query instead
80
+ ```
22
81
 
23
82
  ## Contributing
24
83
 
25
- 1. Fork it ( http://github.com/<my-github-username>/ransack_mongo/fork )
84
+ 1. Fork it ( https://github.com/phstc/ransack_mongo/fork )
26
85
  2. Create your feature branch (`git checkout -b my-new-feature`)
27
86
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
87
  4. Push to the branch (`git push origin my-new-feature`)
@@ -27,23 +27,19 @@ module RansackMongo
27
27
  end
28
28
 
29
29
  def gt_matcher(attr, value)
30
- @query[attr] ||= {}
31
- @query[attr]['$gt'] = value.to_f
30
+ append_sizeable_matcher('$gt', attr, value)
32
31
  end
33
32
 
34
33
  def lt_matcher(attr, value)
35
- @query[attr] ||= {}
36
- @query[attr]['$lt'] = value.to_f
34
+ append_sizeable_matcher('$lt', attr, value)
37
35
  end
38
36
 
39
37
  def gteq_matcher(attr, value)
40
- @query[attr] ||= {}
41
- @query[attr]['$gte'] = value.to_f
38
+ append_sizeable_matcher('$gte', attr, value)
42
39
  end
43
40
 
44
41
  def lteq_matcher(attr, value)
45
- @query[attr] ||= {}
46
- @query[attr]['$lte'] = value.to_f
42
+ append_sizeable_matcher('$lte', attr, value)
47
43
  end
48
44
 
49
45
  def or_op # or operation
@@ -60,13 +56,24 @@ module RansackMongo
60
56
  @query = original_query
61
57
  end
62
58
 
63
- def sanitize(unsanitized)
64
- # http://docs.mongodb.org/manual/faq/developers/#how-does-mongodb-address-sql-or-query-injection
65
- unsanitized
66
- end
67
-
68
59
  def self.predicates
69
60
  PREDICATES
70
61
  end
62
+
63
+ private
64
+
65
+ def append_sizeable_matcher(m, attr, value)
66
+ @query[attr] ||= {}
67
+ @query[attr][m] = parse_sizeable_value(value)
68
+ end
69
+
70
+ def parse_sizeable_value(value)
71
+ case value
72
+ when Date, Time
73
+ value
74
+ else
75
+ Float(value) rescue value
76
+ end
77
+ end
71
78
  end
72
79
  end
@@ -14,8 +14,8 @@ module RansackMongo
14
14
 
15
15
  parsed_predicates.keys.each do |p|
16
16
  parsed_predicates[p].each do |parsed_predicate|
17
- attr = db_adapter.sanitize(parsed_predicate['attr'])
18
- value = db_adapter.sanitize(parsed_predicate['value'])
17
+ attr = parsed_predicate['attr']
18
+ value = parsed_predicate['value']
19
19
 
20
20
  begin
21
21
  if attr.include? '_or_'
@@ -34,6 +34,16 @@ module RansackMongo
34
34
  db_adapter.to_query
35
35
  end
36
36
 
37
+ def to_query!(params)
38
+ selector = to_query params
39
+
40
+ if selector.empty?
41
+ raise MatcherNotFound, "No matchers found. To allow empty queries use .to_query instead"
42
+ end
43
+
44
+ selector
45
+ end
46
+
37
47
  def or_query(db_adapter, attr, value, p)
38
48
  db_adapter.or_op do
39
49
  attr.split('_or_').each do |or_attr|
@@ -1,3 +1,3 @@
1
1
  module RansackMongo
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
@@ -9,9 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Pablo Cantero']
10
10
  spec.email = ['pablo@pablocantero.com']
11
11
  spec.homepage = 'https://github.com/phstc/ransack_mongo'
12
- spec.summary = %q{Object-based searching for MongoDB (currently).}
13
- spec.description = %q{Ransack Mongo is inspired/based on Ransack but for MongoDB}
14
- spec.homepage = ''
12
+ spec.summary = %q{Query params based searching for MongoDB}
13
+ spec.description = %q{Ransack Mongo is based on Ransack but for MongoDB}
15
14
  spec.license = 'MIT'
16
15
 
17
16
  spec.files = `git ls-files`.split($/)
@@ -48,35 +48,38 @@ module RansackMongo
48
48
  end
49
49
  end
50
50
 
51
- describe '#gt_matcher' do
52
- it 'returns the matcher' do
53
- subject.gt_matcher('quantity', 1)
51
+ %w[gt lt gteq lteq].each do |m|
52
+ op_name = { 'gteq' => 'gte', 'lteq' => 'lte' }[m] || m
54
53
 
55
- expect(subject.to_query).to eq('quantity' => { '$gt' => 1 })
56
- end
57
- end
54
+ describe "##{m}_matcher" do
55
+ it 'returns the matcher' do
56
+ subject.send "#{m}_matcher", 'quantity', 1
58
57
 
59
- describe '#lt_matcher' do
60
- it 'returns the matcher' do
61
- subject.lt_matcher('quantity', 1)
58
+ expect(subject.to_query).to eq('quantity' => { "$#{op_name}" => 1 })
59
+ end
62
60
 
63
- expect(subject.to_query).to eq('quantity' => { '$lt' => 1 })
64
- end
65
- end
61
+ it 'accepts time' do
62
+ updated_at = Time.now
63
+ subject.send "#{m}_matcher", 'updated_at', updated_at
66
64
 
67
- describe '#gteq_matcher' do
68
- it 'returns the matcher' do
69
- subject.gteq_matcher('quantity', 1)
65
+ expect(subject.to_query).to eq('updated_at' => { "$#{op_name}" => updated_at })
66
+ end
70
67
 
71
- expect(subject.to_query).to eq('quantity' => { '$gte' => 1 })
72
- end
73
- end
68
+ it 'accepts time as a string' do
69
+ updated_at = '2014-10-11 14:48:07 -0300'
74
70
 
75
- describe '#lteq_matcher' do
76
- it 'returns the matcher' do
77
- subject.lteq_matcher('quantity', 1)
71
+ subject.send "#{m}_matcher", 'updated_at', updated_at
72
+
73
+ expect(subject.to_query).to eq('updated_at' => { "$#{op_name}" => updated_at })
74
+ end
75
+
76
+ it 'accepts date' do
77
+ updated_at = Date.new
78
78
 
79
- expect(subject.to_query).to eq('quantity' => { '$lte' => 1 })
79
+ subject.send "#{m}_matcher", 'updated_at', updated_at
80
+
81
+ expect(subject.to_query).to eq('updated_at' => { "$#{op_name}" => updated_at })
82
+ end
80
83
  end
81
84
  end
82
85
 
@@ -14,10 +14,6 @@ module RansackMongo
14
14
  @query
15
15
  end
16
16
 
17
- def sanitize(unsanitized)
18
- unsanitized
19
- end
20
-
21
17
  def self.predicates
22
18
  PREDICATES
23
19
  end
@@ -36,6 +32,19 @@ module RansackMongo
36
32
  end
37
33
 
38
34
  context 'when MongoAdapter' do
35
+ describe '#to_query!' do
36
+ it 'raises exception when query evaluates to an empty hash' do
37
+ params = { 'name' => 'Pablo' }
38
+ expect { described_class.new.to_query!(params) }.to raise_error(MatcherNotFound)
39
+ end
40
+
41
+ it 'returns the query' do
42
+ params = { 'name_eq' => 'Pablo', 'fullname_cont' => 'Cantero' }
43
+
44
+ expect(described_class.new.to_query!(params)).to eq('name' => 'Pablo', 'fullname' => /Cantero/i)
45
+ end
46
+ end
47
+
39
48
  describe '#to_query' do
40
49
  it 'returns the query' do
41
50
  params = { 'name_eq' => 'Pablo', 'fullname_cont' => 'Cantero' }
data/spec/spec_helper.rb CHANGED
@@ -7,7 +7,6 @@ Dir['../lib/**/*.rb'].each &method(:require)
7
7
  require './lib/ransack_mongo'
8
8
 
9
9
  RSpec.configure do |config|
10
- config.color_enabled = true
11
10
  config.formatter = 'progress'
12
11
  end
13
12
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ransack_mongo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Cantero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-23 00:00:00.000000000 Z
11
+ date: 2014-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,7 +52,7 @@ dependencies:
52
52
  - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description: Ransack Mongo is inspired/based on Ransack but for MongoDB
55
+ description: Ransack Mongo is based on Ransack but for MongoDB
56
56
  email:
57
57
  - pablo@pablocantero.com
58
58
  executables: []
@@ -60,6 +60,7 @@ extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
62
  - .gitignore
63
+ - .travis.yml
63
64
  - Gemfile
64
65
  - LICENSE.txt
65
66
  - README.md
@@ -74,7 +75,7 @@ files:
74
75
  - spec/ransack_mongo/predicate_spec.rb
75
76
  - spec/ransack_mongo/query_spec.rb
76
77
  - spec/spec_helper.rb
77
- homepage: ''
78
+ homepage: https://github.com/phstc/ransack_mongo
78
79
  licenses:
79
80
  - MIT
80
81
  metadata: {}
@@ -97,7 +98,7 @@ rubyforge_project:
97
98
  rubygems_version: 2.0.14
98
99
  signing_key:
99
100
  specification_version: 4
100
- summary: Object-based searching for MongoDB (currently).
101
+ summary: Query params based searching for MongoDB
101
102
  test_files:
102
103
  - spec/ransack_mongo/mongo_adapter_spec.rb
103
104
  - spec/ransack_mongo/predicate_spec.rb