mongo_db 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,6 +11,9 @@ module Mongo::Ext::Collection
11
11
  end
12
12
 
13
13
  def update_with_ext selector, document, opts = {}
14
+ selector = convert_underscore_to_dollar_in_selector selector
15
+ document = convert_underscore_to_dollar_in_update document
16
+
14
17
  # because :multi works only with $ operators, we need to check it
15
18
  opts = if document.keys.any?{|k| k =~ /^\$/}
16
19
  reverse_merge_defaults(opts, :safe, :multi)
@@ -22,6 +25,7 @@ module Mongo::Ext::Collection
22
25
  end
23
26
 
24
27
  def remove_with_ext selector = {}, opts = {}
28
+ selector = convert_underscore_to_dollar_in_selector selector
25
29
  remove_without_ext selector, reverse_merge_defaults(opts, :safe, :multi)
26
30
  end
27
31
 
@@ -32,9 +36,12 @@ module Mongo::Ext::Collection
32
36
  #
33
37
  # Querying
34
38
  #
35
- def first *args
36
- o = find_one *args
37
- ::Mongo::Ext::HashHelper.unmarshal o
39
+ def first spec_or_object_id = nil, opts = {}
40
+ spec_or_object_id = convert_underscore_to_dollar_in_selector spec_or_object_id if spec_or_object_id.is_a? Hash
41
+
42
+ o = find_one spec_or_object_id, opts
43
+ o = ::Mongo::Ext::HashHelper.symbolize o if Mongo.defaults[:symbolize]
44
+ o
38
45
  end
39
46
 
40
47
  def all *args, &block
@@ -48,11 +55,13 @@ module Mongo::Ext::Collection
48
55
  end
49
56
 
50
57
  def each selector = {}, opts = {}, &block
58
+ selector = convert_underscore_to_dollar_in_selector selector
59
+
51
60
  cursor = nil
52
61
  begin
53
62
  cursor = find selector, reverse_merge_defaults(opts, :batch_size)
54
63
  cursor.each do |o|
55
- o = ::Mongo::Ext::HashHelper.unmarshal o
64
+ o = ::Mongo::Ext::HashHelper.symbolize o if Mongo.defaults[:symbolize]
56
65
  block.call o
57
66
  end
58
67
  nil
@@ -62,6 +71,20 @@ module Mongo::Ext::Collection
62
71
  end
63
72
 
64
73
  protected
74
+ def convert_underscore_to_dollar_in_selector selector
75
+ if Mongo.defaults[:convert_underscore_to_dollar]
76
+ selector = ::Mongo::Ext::HashHelper.convert_underscore_to_dollar_in_selector selector
77
+ end
78
+ selector
79
+ end
80
+
81
+ def convert_underscore_to_dollar_in_update update
82
+ if Mongo.defaults[:convert_underscore_to_dollar]
83
+ update = ::Mongo::Ext::HashHelper.convert_underscore_to_dollar_in_selector update
84
+ end
85
+ update
86
+ end
87
+
65
88
  def reverse_merge_defaults opts, *keys
66
89
  h = opts.clone
67
90
  keys.each do |k|
@@ -11,21 +11,54 @@ class Mongo::Ext::HashHelper
11
11
  # Date, DateTime,
12
12
  # BSON::ObjectId
13
13
  # ].to_set
14
+
15
+ QUERY_KEYWORDS = [
16
+ :_lt, :_lte, :_gt, :_gte,
17
+ :_all, :_exists, :_mod, :_ne, :_in, :_nin,
18
+ :_nor, :_or, :_and,
19
+ :_size, :_type
20
+ ].to_set
21
+
22
+ UPDATE_KEYWORDS = [
23
+ :_inc, :_set, :_unset, :_push, :_pushAll, :_addToSet, :_pop, :_pull, :_pullAll, :_rename, :_bit
24
+ ].to_set
14
25
 
15
26
  class << self
16
27
  # symbolizing hashes
17
- def unmarshal o
18
- return o unless Mongo.defaults[:symbolize]
19
-
28
+ def symbolize o
29
+ convert o do |k, v, result|
30
+ k = k.to_sym if k.is_a? String
31
+ result[k] = v
32
+ end
33
+ end
34
+
35
+ # replaces :_lt to :$lt in query
36
+ def convert_underscore_to_dollar_in_selector selector
37
+ convert selector do |k, v, result|
38
+ k = "$#{k.to_s[1..-1]}".to_sym if QUERY_KEYWORDS.include?(k)
39
+ result[k] = v
40
+ end
41
+ end
42
+
43
+ # replaces :_set to :$set in query
44
+ def convert_underscore_to_dollar_in_update update
45
+ convert update do |k, v, result|
46
+ k = "$#{k.to_s[1..-1]}".to_sym if UPDATE_KEYWORDS.include?(k)
47
+ result[k] = v
48
+ end
49
+ end
50
+
51
+ # converts hashes (also works with nested & arrays)
52
+ def convert o, &block
20
53
  if o.is_a? Hash
21
- h = {}
54
+ result = {}
22
55
  o.each do |k, v|
23
- k = k.to_sym if k.is_a?(String)
24
- h[k] = unmarshal v
56
+ v = convert v, &block
57
+ block.call k, v, result
25
58
  end
26
- h
59
+ result
27
60
  elsif o.is_a? Array
28
- o.collect{|v| unmarshal v}
61
+ o.collect{|v| convert v, &block}
29
62
  else
30
63
  o
31
64
  end
@@ -12,6 +12,10 @@ module Mongo::Ext::Collection
12
12
  end
13
13
  alias_method :by_id!, :first_by_id!
14
14
 
15
+ def where &block
16
+ Mongo::Ext::Query.new self, &block
17
+ end
18
+
15
19
  protected
16
20
  #
17
21
  # first_by_field, all_by_field
@@ -4,10 +4,4 @@ class Mongo::NotFound < StandardError; end
4
4
 
5
5
  %w(
6
6
  collection
7
- ).each{|f| require "mongo_db/driver/more/#{f}"}
8
-
9
- Mongo.defaults.merge! \
10
- symbolize: true,
11
- batch_size: 50,
12
- multi: true,
13
- safe: true
7
+ ).each{|f| require "mongo_db/driver/more/#{f}"}
File without changes
data/lib/old/query.rb ADDED
@@ -0,0 +1,91 @@
1
+ class Mongo::Ext::Query
2
+ class Dsl < BasicObject
3
+ class Statement < ::Array
4
+ def add_to hash
5
+ operator, value = self[-2, -1]
6
+ path = self[0..-3]
7
+
8
+ current = hash
9
+ path.each_with_index do |key, index|
10
+ if index == path.size - 1
11
+ raise "dupliate key :#{key}!" if current.include? key
12
+ current[key] = value
13
+ else
14
+ raise "dupliate key :#{key}!" if current.include?(key) and !current[key].is_a?(Hash)
15
+ current[key] ||= {}
16
+ current = current[key]
17
+ end
18
+ end
19
+ nil
20
+ end
21
+ end
22
+
23
+ def initialize &block
24
+ @statements = [Statement.new]
25
+ block.call self
26
+ statements.pop if statements.last.empty?
27
+ end
28
+
29
+ {
30
+ :== => :==,
31
+ :!= => :$ne,
32
+ :< => :$lt,
33
+ :<= => :$lte,
34
+ :> => :$gt,
35
+ :>= => :$gte,
36
+ }.each do |ruby, mongo|
37
+ define_method ruby do |arg|
38
+ emit mongo
39
+ emit arg, true
40
+ end
41
+ end
42
+
43
+ def to_hash
44
+ h = {}
45
+ statements.each{|s| h.add_to h}
46
+ h
47
+ end
48
+
49
+ protected
50
+ attr_reader :statements
51
+
52
+ def emit statement = nil, terminate = false
53
+ statements.last << statement if statement
54
+ statements << Statement.new if terminate
55
+ nil
56
+ end
57
+
58
+ def method_missing m, *args, &block
59
+ raise "invalid usage, there can be only one argument (#{args})!" if args.size > 1
60
+
61
+ if args.empty?
62
+ emit m
63
+ self
64
+ else
65
+ emit m
66
+ emit args.first, true
67
+ end
68
+ end
69
+
70
+ def p *args
71
+ ::Kernel.p *args
72
+ end
73
+ end
74
+
75
+ def initialize collection, &block
76
+ @collection = collection
77
+ @hash_query = Dsl.new(&block).to_hash
78
+ end
79
+
80
+ def first
81
+ collection.first to_hash
82
+ end
83
+
84
+ def all &block
85
+ collection.first to_hash, &block
86
+ end
87
+ alias_method :each, :all
88
+
89
+ protected
90
+ attr_reader :collection, :hash_query
91
+ end
@@ -0,0 +1,77 @@
1
+ require 'driver/spec_helper'
2
+
3
+ describe "Query" do
4
+ dsl_class = Mongo::Ext::Query::Dsl
5
+ dsl_class.class_eval do
6
+ public :statements
7
+ end
8
+
9
+ it "operators" do
10
+ value = :value
11
+ dsl_class.new do |o|
12
+ o.key == value
13
+ o.key != value
14
+ o.key < value
15
+ o.key <= value
16
+ o.key > value
17
+ o.key >= value
18
+ o.key.all value
19
+ o.key.exists true
20
+ o.key.mod value
21
+ o.key.in value
22
+ o.key.nin value
23
+ o.key.size value
24
+ o.key.type value
25
+ end.statements.should == [
26
+ [:key, :==, :value],
27
+ [:key, :$ne, :value],
28
+ [:key, :$lt, :value],
29
+ [:key, :$lte, :value],
30
+ [:key, :$gt, :value],
31
+ [:key, :$gte, :value],
32
+ [:key, :all, :value],
33
+ [:key, :exists, true],
34
+ [:key, :mod, :value],
35
+ [:key, :in, :value],
36
+ [:key, :nin, :value],
37
+ [:key, :size, :value],
38
+ [:key, :type, :value]
39
+ ]
40
+ end
41
+
42
+ it ":nor, :or, :and"
43
+
44
+ describe "statement" do
45
+ def process_statement *args
46
+ s = Mongo::Ext::Query::Dsl::Statement.new
47
+ s.push *args
48
+ result = {}
49
+ s.add_to result
50
+ result
51
+ end
52
+
53
+ it "basics", focus: true do
54
+ p process_statement(:age, :$gt, 34)
55
+ end
56
+ end
57
+
58
+ # it "to_hash" do
59
+ # dsl.new do |o|
60
+ # # o.name == 'Jim'
61
+ # o.age > 34
62
+ # end.to_hash.should == {
63
+ # # name: 'Jim',
64
+ # :$gt => {age: 34}
65
+ # }
66
+ # end
67
+ #
68
+ # it do
69
+ # dsl.new do |unit|
70
+ # unit.name == 'Zeratul'
71
+ # unit.stats.life > 100
72
+ # unit.stats.attack != 0
73
+ # end.statement.should == {
74
+ # name: 1
75
+ # }
76
+ # end
77
+ end
data/readme.md CHANGED
@@ -14,6 +14,9 @@ Note: By default it also adds a little magic and alters some default values of s
14
14
  ``` ruby
15
15
  require 'mongo_db/driver'
16
16
 
17
+ # changing some defaults
18
+ Mongo.defaults.merge! symbolize: true, multi: true, safe: true
19
+
17
20
  # connection & db
18
21
  connection = Mongo::Connection.new
19
22
  db = connection.db 'default_test'
@@ -41,9 +44,19 @@ Optionall stuff:
41
44
 
42
45
  ``` ruby
43
46
  # simple finders (bang versions also availiable)
44
- db.units.by_name 'Zeratul' # => zeratul
45
- db.units.first_by_name 'Zeratul' # => zeratul
46
- db.units.all_by_name 'Zeratul' # => [zeratul]
47
+ db.units.by_name 'Zeratul' # => zeratul
48
+ db.units.first_by_name 'Zeratul' # => zeratul
49
+ db.units.all_by_name 'Zeratul' # => [zeratul]
50
+
51
+ # query sugar, use {life: {_lt: 100}} instead of {life: {:$lt => 100}}
52
+ # it will affect olny small set of keywords (:_lt, :_inc),
53
+ # other underscored keys will be intact.
54
+ Mongo.defaults.merge! convert_underscore_to_dollar: true
55
+ db.units.all life: {_lt: 100} # => [tassadar]
56
+
57
+ # it's also trivial to add support for {:life.lt => 100} notion, but
58
+ # it uses ugly '=>' hash notation instead of ':' and it differs from
59
+ # how it looks in native MongoDB JSON query.
47
60
  ```
48
61
 
49
62
  More docs - there's no need for more docs, the whole point of this extension is to be small, intuitive, 100% compatible with official driver (at least should be), and require no extra knowledge.
@@ -0,0 +1,19 @@
1
+ require 'driver/spec_helper'
2
+
3
+ describe "HashHelper" do
4
+ it "symbolize" do
5
+ Mongo::Ext::HashHelper.symbolize({
6
+ 'a' => 1,
7
+ 'b' => {
8
+ 'c' => 2,
9
+ 'd' => [{'e' => 3}]
10
+ }
11
+ }).should == {
12
+ a: 1,
13
+ b: {
14
+ c: 2,
15
+ d: [{e: 3}]
16
+ }
17
+ }
18
+ end
19
+ end
@@ -0,0 +1,59 @@
1
+ require 'driver/spec_helper'
2
+
3
+ describe "Querying" do
4
+ with_mongo
5
+
6
+ before do
7
+ @jim = {name: 'Jim', age: 34}
8
+ @units = db.units
9
+ end
10
+
11
+ describe "dynamic finders" do
12
+ it "find, first, by" do
13
+ @units.first_by_name('Jim').should be_nil
14
+ -> {@units.first_by_name!('Jim')}.should raise_error(Mongo::NotFound)
15
+ @units.by_name('Jim').should be_nil
16
+ -> {@units.by_name!('Jim')}.should raise_error(Mongo::NotFound)
17
+ @units.first_by_name('Jim').should be_nil
18
+ -> {@units.first_by_name!('Jim')}.should raise_error(Mongo::NotFound)
19
+
20
+ @units.save @jim
21
+
22
+ @units.first_by_name('Jim').should == @jim
23
+ @units.first_by_name!('Jim').should == @jim
24
+ @units.by_name('Jim').should == @jim
25
+ @units.by_name!('Jim').should == @jim
26
+ @units.first_by_name('Jim').should == @jim
27
+ @units.first_by_name!('Jim').should == @jim
28
+ end
29
+
30
+ it "all" do
31
+ @units.all_by_name('Jim').should == []
32
+ @units.save @jim
33
+ @units.all_by_name('Jim').should == [@jim]
34
+ end
35
+
36
+ it "should allow to use bang version only with :first" do
37
+ -> {@units.all_by_name!('Jim')}.should raise_error(/can't use bang/)
38
+ end
39
+
40
+ it "by_id (special case)" do
41
+ @units.method(:by_id).should == @units.method(:first_by_id)
42
+ @units.method(:by_id!).should == @units.method(:first_by_id!)
43
+
44
+ @units.by_id('4de81858cf26bde569000009').should be_nil
45
+ -> {@units.by_id!('4de81858cf26bde569000009')}.should raise_error(Mongo::NotFound)
46
+
47
+ @units.save @jim
48
+
49
+ @units.by_id(@jim[:_id]).should == @jim
50
+ @units.by_id!(@jim[:_id]).should == @jim
51
+ end
52
+ end
53
+
54
+ it "underscore to dollar" do
55
+ @units.save @jim
56
+ @units.save name: 'Zeratul', age: 600
57
+ @units.all(age: {_lt: 100}).should == [@jim]
58
+ end
59
+ end
@@ -1,5 +1,12 @@
1
1
  require 'mongo_db/driver'
2
2
 
3
+ Mongo.defaults.merge! \
4
+ symbolize: true,
5
+ convert_underscore_to_dollar: true,
6
+ batch_size: 50,
7
+ multi: true,
8
+ safe: true
9
+
3
10
  require 'ruby_ext'
4
11
  require 'rspec_ext'
5
12
  require 'mongo_db/driver/spec'
@@ -10,6 +10,9 @@ describe "Example" do
10
10
  it "core" do
11
11
  require 'mongo_db/driver'
12
12
 
13
+ # changing some defaults
14
+ Mongo.defaults.merge! symbolize: true, multi: true, safe: true
15
+
13
16
  # connection & db
14
17
  connection = Mongo::Connection.new
15
18
  db = connection.db 'default_test'
@@ -36,10 +39,20 @@ describe "Example" do
36
39
  end
37
40
  end
38
41
 
39
- it "optional" do
42
+ it "optional" do
40
43
  # simple finders (bang versions also availiable)
41
44
  db.units.by_name 'Zeratul' # => zeratul
42
45
  db.units.first_by_name 'Zeratul' # => zeratul
43
46
  db.units.all_by_name 'Zeratul' # => [zeratul]
47
+
48
+ # query sugar, use {life: {_lt: 100}} instead of {life: {:$lt => 100}}
49
+ # it will affect olny small set of keywords (:_lt, :_inc),
50
+ # other underscored keys will be intact.
51
+ Mongo.defaults.merge! convert_underscore_to_dollar: true
52
+ db.units.all life: {_lt: 100} # => [tassadar]
53
+
54
+ # it's also trivial to add support for {:life.lt => 100} notion, but
55
+ # it uses ugly '=>' hash notation instead of ':' and it differs from
56
+ # how it looks in native MongoDB JSON query.
44
57
  end
45
58
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo_db
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-08-13 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongo
16
- requirement: &2844700 !ruby/object:Gem::Requirement
16
+ requirement: &366240 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '1.3'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2844700
24
+ version_requirements: *366240
25
25
  description:
26
26
  email:
27
27
  executables: []
@@ -41,11 +41,14 @@ files:
41
41
  - lib/mongo_db/gems.rb
42
42
  - lib/mongo_db/model.rb
43
43
  - lib/mongo_db/support.rb
44
+ - lib/old/advanced_finders.rb
45
+ - lib/old/query.rb
46
+ - lib/old/query_spec.rb
44
47
  - spec/driver/core/collection_spec.rb
45
48
  - spec/driver/core/crud_spec.rb
46
49
  - spec/driver/core/database_spec.rb
47
- - spec/driver/more/advanced_finders.rb
48
- - spec/driver/more/simple_finders_spec.rb
50
+ - spec/driver/core/hash_helper_spec.rb
51
+ - spec/driver/more/querying_spec.rb
49
52
  - spec/driver/spec_helper.rb
50
53
  - spec/driver_example_spec.rb
51
54
  - spec/migration/migration_spec.rb
@@ -1,51 +0,0 @@
1
- require 'driver/spec_helper'
2
-
3
- describe "Querying" do
4
- with_mongo
5
-
6
- before do
7
- @jim = {name: 'Jim'}
8
- @units = db.units
9
- end
10
-
11
- it "find, first, by" do
12
- @units.first_by_name('Jim').should be_nil
13
- -> {@units.first_by_name!('Jim')}.should raise_error(Mongo::NotFound)
14
- @units.by_name('Jim').should be_nil
15
- -> {@units.by_name!('Jim')}.should raise_error(Mongo::NotFound)
16
- @units.first_by_name('Jim').should be_nil
17
- -> {@units.first_by_name!('Jim')}.should raise_error(Mongo::NotFound)
18
-
19
- @units.save @jim
20
-
21
- @units.first_by_name('Jim').should == @jim
22
- @units.first_by_name!('Jim').should == @jim
23
- @units.by_name('Jim').should == @jim
24
- @units.by_name!('Jim').should == @jim
25
- @units.first_by_name('Jim').should == @jim
26
- @units.first_by_name!('Jim').should == @jim
27
- end
28
-
29
- it "all" do
30
- @units.all_by_name('Jim').should == []
31
- @units.save @jim
32
- @units.all_by_name('Jim').should == [@jim]
33
- end
34
-
35
- it "should allow to use bang version only with :first" do
36
- -> {@units.all_by_name!('Jim')}.should raise_error(/can't use bang/)
37
- end
38
-
39
- it "by_id (special case)" do
40
- @units.method(:by_id).should == @units.method(:first_by_id)
41
- @units.method(:by_id!).should == @units.method(:first_by_id!)
42
-
43
- @units.by_id('4de81858cf26bde569000009').should be_nil
44
- -> {@units.by_id!('4de81858cf26bde569000009')}.should raise_error(Mongo::NotFound)
45
-
46
- @units.save @jim
47
-
48
- @units.by_id(@jim[:_id]).should == @jim
49
- @units.by_id!(@jim[:_id]).should == @jim
50
- end
51
- end