ransack_mongo 0.0.1 → 0.0.2

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