mongo-search 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ # Vim
21
+ *.swo
22
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in mongo-search.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,33 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mongo-search (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.3)
10
+ ffi (1.0.11)
11
+ guard (1.0.3)
12
+ ffi (>= 0.5.0)
13
+ thor (>= 0.14.6)
14
+ guard-rspec (0.7.0)
15
+ guard (>= 0.10.0)
16
+ rspec (2.10.0)
17
+ rspec-core (~> 2.10.0)
18
+ rspec-expectations (~> 2.10.0)
19
+ rspec-mocks (~> 2.10.0)
20
+ rspec-core (2.10.1)
21
+ rspec-expectations (2.10.0)
22
+ diff-lcs (~> 1.1.3)
23
+ rspec-mocks (2.10.1)
24
+ thor (0.14.6)
25
+
26
+ PLATFORMS
27
+ ruby
28
+
29
+ DEPENDENCIES
30
+ guard
31
+ guard-rspec
32
+ mongo-search!
33
+ rspec
data/Guardfile ADDED
@@ -0,0 +1,19 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+ # Capybara request specs
17
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
18
+ end
19
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ task :default => :spec
5
+
6
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,31 @@
1
+ module MongoSearch
2
+ class Builder
3
+ def initialize(search)
4
+ @search = search
5
+ end
6
+
7
+ def match(attr)
8
+ @search << Matchers::PartialMatcher.new(attr)
9
+ end
10
+
11
+ def exact(attr)
12
+ @search << Matchers::ExactMatcher.new(attr)
13
+ end
14
+
15
+ def intersect(attr)
16
+ @search << Matchers::IntersectMatcher.new(attr)
17
+ end
18
+
19
+ def greater_than(attr, opts = nil)
20
+ @search << Matchers::GreaterThanMatcher.new(attr, opts)
21
+ end
22
+
23
+ def less_than(attr, opts = nil)
24
+ @search << Matchers::LessThanMatcher.new(attr, opts)
25
+ end
26
+
27
+ def sort_with(attr, opts = nil)
28
+ @search.sorter = Sorter.new(attr, opts)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ module MongoSearch
2
+ # Hash of proc converter objects, defaults to identity func
3
+ Converters = Hash.new { |h,k| lambda { |i| i } }
4
+
5
+ Converters[:time] = lambda do |v|
6
+ if v.is_a?(Time)
7
+ v
8
+ else
9
+ Time.parse(v.to_s)
10
+ end
11
+ end
12
+
13
+ Converters[:array] = lambda do |v|
14
+ if v.is_a?(String)
15
+ v.split(/\s*,\s*/)
16
+ else
17
+ Array(v)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ module MongoSearch
2
+ class Definition
3
+ def initialize
4
+ @filters = []
5
+ @sorter = nil
6
+ yield Builder.new(self) if block_given?
7
+ end
8
+
9
+ def <<(filter)
10
+ @filters << filter
11
+ end
12
+
13
+ def sorter=(sorter)
14
+ @sorter = sorter
15
+ end
16
+
17
+ def criteria_for(params)
18
+ conditions = {}
19
+
20
+ @filters.each do |filter|
21
+ conditions.merge! filter.call(params)
22
+ end
23
+
24
+ sort = @sorter ? @sorter.call(params) : []
25
+
26
+ [conditions, sort]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ module MongoSearch
2
+ module Matchers
3
+ class ExactMatcher
4
+ def initialize(attr)
5
+ @attr = attr
6
+ end
7
+
8
+ def call(params)
9
+ filters = {}
10
+ filters[@attr] = params[@attr] if params[@attr]
11
+ filters
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module MongoSearch
2
+ module Matchers
3
+ class GreaterThanMatcher
4
+ def initialize(attr, opts = nil)
5
+ opts ||= {}
6
+ @attr = attr
7
+ @field = opts[:field] || attr
8
+ @operator = opts[:equal] ? :$gte : :$gt
9
+ @conv = Converters[opts[:type]]
10
+ end
11
+
12
+ def call(params)
13
+ filters = {}
14
+ filters[@field] = {@operator => @conv.call(params[@attr])} if params[@attr]
15
+ filters
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module MongoSearch
2
+ module Matchers
3
+ class IntersectMatcher
4
+ def initialize(attr)
5
+ @attr = attr
6
+ end
7
+
8
+ def call(params)
9
+ filters = {}
10
+
11
+ if params[@attr]
12
+ value = params[@attr]
13
+ filters[@attr] = {:$all => Converters[:array].call(value)}
14
+ end
15
+
16
+ filters
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module MongoSearch
2
+ module Matchers
3
+ class LessThanMatcher
4
+ def initialize(attr, opts = nil)
5
+ opts ||= {}
6
+ @attr = attr
7
+ @field = opts[:field] || attr
8
+ @operator = opts[:equal] ? :$lte : :$lt
9
+ @conv = Converters[opts[:type]]
10
+ end
11
+
12
+ def call(params)
13
+ filters = {}
14
+ filters[@field] = {@operator => @conv.call(params[@attr])} if params[@attr]
15
+ filters
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ module MongoSearch
2
+ module Matchers
3
+ class PartialMatcher
4
+ def initialize(attr)
5
+ @attr = attr
6
+ end
7
+
8
+ def call(params)
9
+ filters = {}
10
+ filters[@attr] = /#{Regexp.escape(params[@attr])}/i if params[@attr]
11
+ filters
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ module MongoSearch
2
+ class Sorter
3
+ def initialize(attr, opts = nil)
4
+ @attr, @opts = attr, opts || {}
5
+ end
6
+
7
+ def call(params)
8
+ sort = []
9
+
10
+ if order_by = params[@attr] || @opts[:default]
11
+ order_by.split(/\s*,\s*/).each do |attr_order|
12
+ if attr_order =~ /([^\s]+)(?:\s*(asc|desc)?)$/
13
+ attr_name, dir = $1, ($2 || :asc)
14
+ sort << [:"#{attr_name}_ordenacao", :"#{dir}"]
15
+ sort << [:"#{attr_name}", :"#{dir}"]
16
+ else
17
+ raise ArgumentError, "invalid sorting parameters: #{order_by}"
18
+ end
19
+ end
20
+ end
21
+
22
+ sort
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module Mongo
2
+ module Search
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ require "time"
2
+ require "mongo-search/sorter"
3
+ require "mongo-search/converters"
4
+ require "mongo-search/matchers/exact_matcher"
5
+ require "mongo-search/matchers/partial_matcher"
6
+ require "mongo-search/matchers/intersect_matcher"
7
+ require "mongo-search/matchers/greater_than_matcher"
8
+ require "mongo-search/matchers/less_than_matcher"
9
+ require "mongo-search/definition"
10
+ require "mongo-search/builder"
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "mongo-search/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "mongo-search"
7
+ s.version = Mongo::Search::VERSION
8
+ s.authors = ["Rodrigo Kochenburger <divoxx@gmail.com>", "Tomas Mattia <tomas.mattia@gmail.com>"]
9
+ s.email = ["abril_vejasp_dev@thoughtworks.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Easy search for mongodb}
12
+
13
+ s.rubyforge_project = "mongo-search"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ # specify any dependencies here; for example:
21
+ s.add_development_dependency "rspec"
22
+ s.add_development_dependency "guard"
23
+ s.add_development_dependency "guard-rspec"
24
+ # s.add_runtime_dependency "rest-client"
25
+ end
@@ -0,0 +1,70 @@
1
+ require "spec_helper"
2
+
3
+ describe "Search integration" do
4
+ let :klass do
5
+ mock(:collection => collection)
6
+ end
7
+
8
+ let :collection do
9
+ mock(:collection)
10
+ end
11
+
12
+ subject do
13
+ MongoSearch::Definition.new do |c|
14
+ c.match :name
15
+ c.exact :status
16
+ c.intersect :tags
17
+ c.less_than :updated_before, :field => :updated_at, :type => :time, :equal => true
18
+ c.greater_than :updated_since, :field => :updated_at, :type => :time, :equal => true
19
+ c.sort_with :order, :default => "name asc"
20
+ end
21
+ end
22
+
23
+ it "matches partial string with case-insensitive regexp" do
24
+ c, _ = subject.criteria_for :name => "foo"
25
+ c.should == {:name => /foo/i}
26
+ end
27
+
28
+ it "matches exact string" do
29
+ c, _ = subject.criteria_for :status => 'published'
30
+ c.should == {:status => 'published'}
31
+ end
32
+
33
+ it "matches intersection of list items" do
34
+ c, _ = subject.criteria_for :tags => ['foo', 'bar']
35
+ c.should == {:tags => {:$all => ['foo', 'bar']}}
36
+ end
37
+
38
+ it "matches intersection of comma separate string" do
39
+ c, _ = subject.criteria_for :tags => "foo,bar"
40
+ c.should == {:tags => {:$all => ['foo', 'bar']}}
41
+ end
42
+
43
+ it "matches a parameter against a field using greater than op" do
44
+ time = Time.parse("2012-01-10T22:10:01Z")
45
+ c, _ = subject.criteria_for :updated_since => time.strftime("%Y-%m-%dT%H:%M:%SZ")
46
+ c.should == {:updated_at => {:$gte => time}}
47
+ end
48
+
49
+ it "matches a parameter against a field using less than op" do
50
+ time = Time.parse("2012-01-10T22:10:01Z")
51
+ c, _ = subject.criteria_for :updated_before => time.strftime("%Y-%m-%dT%H:%M:%SZ")
52
+ c.should == {:updated_at => {:$lte => time}}
53
+ end
54
+
55
+ it "uses specified sorting and includes a _ordenacao prefix also" do
56
+ _, s = subject.criteria_for :order => "titulo desc"
57
+ s.should == [[:titulo_ordenacao, :desc], [:titulo, :desc]]
58
+ end
59
+
60
+ it "defaults sorting direction to asc if not specified" do
61
+ _, s = subject.criteria_for :order => "titulo, categoria"
62
+ s.should include([:titulo, :asc])
63
+ s.should include([:categoria, :asc])
64
+ end
65
+
66
+ it "uses default sorting if no specified" do
67
+ _, s = subject.criteria_for({})
68
+ s.should == [[:name_ordenacao, :asc], [:name, :asc]]
69
+ end
70
+ end
@@ -0,0 +1,4 @@
1
+ require "mongo-search"
2
+
3
+ RSpec.configure do |c|
4
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongo-search
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Rodrigo Kochenburger <divoxx@gmail.com>
9
+ - Tomas Mattia <tomas.mattia@gmail.com>
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-05-22 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: &70097252840100 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *70097252840100
26
+ - !ruby/object:Gem::Dependency
27
+ name: guard
28
+ requirement: &70097252839420 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *70097252839420
37
+ - !ruby/object:Gem::Dependency
38
+ name: guard-rspec
39
+ requirement: &70097252838860 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *70097252838860
48
+ description:
49
+ email:
50
+ - abril_vejasp_dev@thoughtworks.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - .gitignore
56
+ - Gemfile
57
+ - Gemfile.lock
58
+ - Guardfile
59
+ - Rakefile
60
+ - lib/mongo-search.rb
61
+ - lib/mongo-search/builder.rb
62
+ - lib/mongo-search/converters.rb
63
+ - lib/mongo-search/definition.rb
64
+ - lib/mongo-search/matchers/exact_matcher.rb
65
+ - lib/mongo-search/matchers/greater_than_matcher.rb
66
+ - lib/mongo-search/matchers/intersect_matcher.rb
67
+ - lib/mongo-search/matchers/less_than_matcher.rb
68
+ - lib/mongo-search/matchers/partial_matcher.rb
69
+ - lib/mongo-search/sorter.rb
70
+ - lib/mongo-search/version.rb
71
+ - mongo-search.gemspec
72
+ - spec/search_spec.rb
73
+ - spec/spec_helper.rb
74
+ homepage: ''
75
+ licenses: []
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project: mongo-search
94
+ rubygems_version: 1.8.10
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: Easy search for mongodb
98
+ test_files:
99
+ - spec/search_spec.rb
100
+ - spec/spec_helper.rb
101
+ has_rdoc: