mongo_mapper 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/{README.rdoc → README.md} +28 -20
  4. data/examples/keys.rb +1 -1
  5. data/examples/modifiers/set.rb +1 -1
  6. data/examples/querying.rb +1 -1
  7. data/examples/safe.rb +2 -2
  8. data/examples/scopes.rb +1 -1
  9. data/lib/mongo_mapper.rb +1 -0
  10. data/lib/mongo_mapper/connection.rb +16 -38
  11. data/lib/mongo_mapper/extensions/object_id.rb +5 -1
  12. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +1 -1
  13. data/lib/mongo_mapper/plugins/dirty.rb +29 -37
  14. data/lib/mongo_mapper/plugins/document.rb +1 -1
  15. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +1 -1
  16. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +1 -0
  17. data/lib/mongo_mapper/plugins/embedded_document.rb +1 -1
  18. data/lib/mongo_mapper/plugins/indexes.rb +13 -6
  19. data/lib/mongo_mapper/plugins/keys.rb +1 -2
  20. data/lib/mongo_mapper/plugins/modifiers.rb +27 -10
  21. data/lib/mongo_mapper/plugins/persistence.rb +6 -2
  22. data/lib/mongo_mapper/plugins/querying.rb +9 -3
  23. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +3 -4
  24. data/lib/mongo_mapper/plugins/safe.rb +10 -4
  25. data/lib/mongo_mapper/plugins/stats.rb +1 -3
  26. data/lib/mongo_mapper/utils.rb +2 -2
  27. data/lib/mongo_mapper/version.rb +1 -1
  28. data/spec/examples.txt +1643 -0
  29. data/spec/functional/accessible_spec.rb +1 -1
  30. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +2 -2
  31. data/spec/functional/associations/belongs_to_proxy_spec.rb +4 -4
  32. data/spec/functional/associations/in_array_proxy_spec.rb +14 -14
  33. data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
  34. data/spec/functional/associations/many_documents_proxy_spec.rb +22 -22
  35. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +2 -2
  36. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
  37. data/spec/functional/associations/one_as_proxy_spec.rb +8 -8
  38. data/spec/functional/associations/one_proxy_spec.rb +8 -8
  39. data/spec/functional/associations_spec.rb +3 -3
  40. data/spec/functional/binary_spec.rb +2 -2
  41. data/spec/functional/caching_spec.rb +15 -22
  42. data/spec/functional/callbacks_spec.rb +2 -2
  43. data/spec/functional/counter_cache_spec.rb +10 -10
  44. data/spec/functional/dirty_spec.rb +27 -10
  45. data/spec/functional/document_spec.rb +5 -5
  46. data/spec/functional/dumpable_spec.rb +1 -1
  47. data/spec/functional/embedded_document_spec.rb +5 -5
  48. data/spec/functional/identity_map_spec.rb +6 -6
  49. data/spec/functional/indexes_spec.rb +19 -18
  50. data/spec/functional/keys_spec.rb +22 -22
  51. data/spec/functional/logger_spec.rb +2 -2
  52. data/spec/functional/modifiers_spec.rb +67 -19
  53. data/spec/functional/partial_updates_spec.rb +8 -8
  54. data/spec/functional/protected_spec.rb +1 -1
  55. data/spec/functional/querying_spec.rb +48 -22
  56. data/spec/functional/safe_spec.rb +23 -27
  57. data/spec/functional/sci_spec.rb +7 -7
  58. data/spec/functional/scopes_spec.rb +1 -1
  59. data/spec/functional/static_keys_spec.rb +2 -2
  60. data/spec/functional/stats_spec.rb +28 -12
  61. data/spec/functional/validations_spec.rb +8 -16
  62. data/spec/quality_spec.rb +1 -1
  63. data/spec/spec_helper.rb +32 -8
  64. data/spec/support/matchers.rb +1 -1
  65. data/spec/unit/associations/proxy_spec.rb +1 -1
  66. data/spec/unit/clone_spec.rb +1 -1
  67. data/spec/unit/document_spec.rb +3 -3
  68. data/spec/unit/embedded_document_spec.rb +4 -5
  69. data/spec/unit/extensions_spec.rb +3 -4
  70. data/spec/unit/identity_map_middleware_spec.rb +65 -96
  71. data/spec/unit/key_spec.rb +16 -17
  72. data/spec/unit/keys_spec.rb +7 -7
  73. data/spec/unit/mongo_mapper_spec.rb +41 -88
  74. data/spec/unit/rails_spec.rb +2 -2
  75. metadata +37 -24
  76. data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b6880875b0db1bcf8f52f472551b859be5d399a9
4
- data.tar.gz: ee4023cda04c706b6c56aa7358040b1a3d0c07e8
2
+ SHA256:
3
+ metadata.gz: 143438e47efd4cc910b443067a35aff261a7c32baa12bbe8836b0505edb6c8ad
4
+ data.tar.gz: 0d8d33172da4805fa47544585d2ea5369a82e9154be19dcd9be2789b5c2747cb
5
5
  SHA512:
6
- metadata.gz: acae6e9a273dd77a8c41f06138b910c23c197d0c3e790be33042fc9198fb02398a30bb73360655ca4bc8b1256b140e40ee568530fa75f56caa11f79b36f22ef8
7
- data.tar.gz: dbb174abd832dddcc86e720a296198696401abc28da84e1a96737785c5d68b8197b7b8ce87b726340ba2e3858ae6f59649c6b270b663865a5fe2628871ee1fe1
6
+ metadata.gz: 50b970107ed41cc982e24fe9d171fed471847c593db3c5239b7e60fa88fb67ef799473eb1a088d2eb92d6d2cda49d8ec391b61a24e92bb5b9a9e7eea399ed61b
7
+ data.tar.gz: 1674cc8cdc27d2f3bc7460a8f32017903bde7263feeae62bf3074386d5fa0b080b3fc52c4407c200a7b4df8fb083fd917e6b5611b19f8538ec10033c789667ab
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 John Nunemaker
1
+ Copyright (c) 2009-2020 MongoMapper: John Nunemaker, Chris Heald, Scott Taylor
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -1,39 +1,35 @@
1
- = MongoMapper
2
-
3
- {<img src="https://badge.fury.io/rb/mongo_mapper.png" alt="RubyGem" />}[https://rubygems.org/gems/mongo_mapper]
4
- {<img src="https://travis-ci.org/mongomapper/mongomapper.png?branch=master" alt="Build Status" />}[https://travis-ci.org/mongomapper/mongomapper]
5
- {<img src="https://coveralls.io/repos/mongomapper/mongomapper/badge.png" alt="Coverage Status" />}[https://coveralls.io/r/mongomapper/mongomapper]
1
+ # MongoMapper
6
2
 
7
3
  A Ruby Object Mapper for Mongo.
8
4
 
9
- == Install
5
+ [<img src="https://badge.fury.io/rb/mongo_mapper.png" alt="RubyGems">](https://rubygems.org/gems/mongo_mapper)
6
+
7
+ [<img src="https://travis-ci.org/mongomapper/mongomapper.png?branch=master" alt="Build Status" />](https://travis-ci.org/mongomapper/mongomapper)
8
+
9
+ [<img src="https://coveralls.io/repos/mongomapper/mongomapper/badge.png" alt="Coverage Status" />](https://coveralls.io/r/mongomapper/mongomapper)
10
+
11
+ ## Install
10
12
 
11
13
  $ gem install mongo_mapper
12
14
 
13
- == Documentation
15
+ ## Documentation
14
16
 
15
17
  http://mongomapper.com/documentation/
16
18
 
17
19
  http://rdoc.info/github/mongomapper/mongomapper
18
20
 
19
- == Compatibility
21
+ ## Compatibility
20
22
 
21
23
  MongoMapper is tested against:
22
24
 
23
- * MRI 1.8.7
24
- * MRI 1.9.3
25
- * MRI 2.0.0
26
- * MRI 2.1.1
25
+ * MRI 2.4 - 2.7
27
26
  * JRuby (Versions with 1.9 compatibility)
28
27
 
29
28
  Additionally, MongoMapper is tested against:
30
29
 
31
- * Rails 3.0.x
32
- * Rails 3.1.x
33
- * Rails 3.2.x
34
- * Rails 4.0.x
30
+ * Rails 5.0+ - 6.0
35
31
 
36
- == Contributing & Development
32
+ ## Contributing & Development
37
33
 
38
34
  $ git clone https://github.com/mongomapper/mongomapper && cd mongomapper
39
35
  $ bundle install
@@ -45,12 +41,24 @@ Additionally, MongoMapper is tested against:
45
41
  * Commit, do not mess with Rakefile, version, or history. If you want to have your own version, that is fine but bump version in a commit by itself in another branch so a maintainer ignore it when your pull request is merged.
46
42
  * Send a pull request. Bonus points for topic branches.
47
43
 
48
- == Problems or Questions?
44
+ ## Problems or Questions?
49
45
 
50
46
  Hit up the Google group: http://groups.google.com/group/mongomapper
51
47
 
52
48
  Hop on IRC: irc://chat.freenode.net/#mongomapper
53
49
 
54
- == License & Copyright
50
+ ## Copyright
51
+
52
+ Copyright (c) 2009-2020 MongoMapper. See LICENSE for details.
53
+
54
+ ## Contributors
55
+
56
+ MongoMapper/Plucky is:
57
+
58
+ * John Nunemaker
59
+ * Chris Heald
60
+ * Scott Taylor
61
+
62
+ With contributions from:
55
63
 
56
- See LICENSE for details.
64
+ * Frederick Cheung
@@ -16,7 +16,7 @@ class User
16
16
  key :links, Hash
17
17
  timestamps!
18
18
  end
19
- User.collection.remove # empties collection
19
+ User.collection.drop # empties collection
20
20
 
21
21
  john = User.create({
22
22
  :first_name => 'John',
@@ -10,7 +10,7 @@ class User
10
10
  key :name, String
11
11
  key :tags, Array
12
12
  end
13
- User.collection.remove # empties collection
13
+ User.collection.drop # empties collection
14
14
 
15
15
  john = User.create(:name => 'John', :tags => %w[ruby mongo], :age => 28)
16
16
  bill = User.create(:name => 'Bill', :tags => %w[ruby mongo], :age => 30)
@@ -10,7 +10,7 @@ class User
10
10
  key :name, String
11
11
  key :tags, Array
12
12
  end
13
- User.collection.remove # empties collection
13
+ User.collection.drop # empties collection
14
14
 
15
15
  User.create(:name => 'John', :tags => %w[ruby mongo], :age => 28)
16
16
  User.create(:name => 'Bill', :tags => %w[ruby mongo], :age => 30)
@@ -22,7 +22,7 @@ puts
22
22
  begin
23
23
  user = User.new(:email => 'nunemaker@gmail.com')
24
24
  user.save(:safe => true)
25
- rescue Mongo::OperationFailure => e
25
+ rescue Mongo::Error::OperationFailure => e
26
26
  puts 'Mongo Operation failure raised because duplicate email was entered'
27
27
  puts e.inspect
28
28
  puts
@@ -37,7 +37,7 @@ User.safe
37
37
 
38
38
  begin
39
39
  User.create(:email => 'nunemaker@gmail.com')
40
- rescue Mongo::OperationFailure => e
40
+ rescue Mongo::Error::OperationFailure => e
41
41
  puts 'Mongo Operation failure raised because duplicate email was entered'
42
42
  puts e.inspect
43
43
  end
@@ -28,7 +28,7 @@ class User
28
28
  key :name, String
29
29
  key :tags, Array
30
30
  end
31
- User.collection.remove # empties collection
31
+ User.collection.drop # empties collection
32
32
 
33
33
  User.create(:name => 'John', :tags => %w[ruby mongo], :age => 28)
34
34
  User.create(:name => 'Bill', :tags => %w[ruby mongo], :age => 30)
@@ -3,6 +3,7 @@ require 'plucky'
3
3
  require 'active_support'
4
4
  require 'active_support/core_ext'
5
5
  require 'active_model'
6
+ require 'activemodel-serializers-xml'
6
7
  require "mongo_mapper/railtie" if defined?(Rails)
7
8
 
8
9
  I18n.load_path << File.expand_path('../mongo_mapper/locale/en.yml', __FILE__)
@@ -4,13 +4,12 @@ require 'uri'
4
4
  module MongoMapper
5
5
  module Connection
6
6
  @@connection = nil
7
- @@database = nil
8
- @@database_name = nil
9
7
  @@config = nil
8
+ @@database = nil
10
9
 
11
10
  # @api public
12
11
  def connection
13
- @@connection ||= Mongo::MongoClient.new
12
+ @@connection ||= Mongo::Client.new ['127.0.0.1:27017']
14
13
  end
15
14
 
16
15
  def connection?
@@ -29,15 +28,12 @@ module MongoMapper
29
28
 
30
29
  # @api public
31
30
  def database=(name)
32
- @@database = nil
33
- @@database_name = name
31
+ @@database = connection.use(name).database
34
32
  end
35
33
 
36
34
  # @api public
37
35
  def database
38
- return nil if @@database_name.blank?
39
-
40
- @@database ||= MongoMapper.connection.db(@@database_name)
36
+ @@database ||= connection.database
41
37
  end
42
38
 
43
39
  def config=(hash)
@@ -51,46 +47,28 @@ module MongoMapper
51
47
 
52
48
  # @api private
53
49
  def config_for_environment(environment)
54
- env = config[environment.to_s] || {}
55
- return env if env['uri'].blank?
56
-
57
- uri = URI.parse(env['uri'])
58
- raise InvalidScheme.new('must be mongodb') unless uri.scheme == 'mongodb'
59
- {
60
- 'host' => uri.host,
61
- 'port' => uri.port,
62
- 'database' => uri.path.gsub(/^\//, ''),
63
- 'username' => uri.user,
64
- 'password' => uri.password,
65
- }
50
+ config[environment.to_s]
66
51
  end
67
52
 
68
53
  def connect(environment, options={})
69
54
  raise 'Set config before connecting. MongoMapper.config = {...}' if config.blank?
70
- env = config_for_environment(environment)
55
+ env = config_for_environment(environment).dup
56
+ addresses_or_uri = env.delete('hosts') ||
57
+ env.delete('uri') ||
58
+ [env.delete('host')].compact
71
59
 
72
60
  if env['options'].is_a?(Hash)
73
- options = env['options'].symbolize_keys.merge(options)
74
- end
75
- options[:read] = options[:read].to_sym if options[:read].is_a? String
76
-
77
- if env.key?('ssl')
78
- options[:ssl] = env['ssl']
61
+ options = env.delete('options').symbolize_keys.merge(options)
79
62
  end
63
+ #database etc are all options to Mongo::Client.new now
64
+ options = env.symbolize_keys.merge(options)
80
65
 
81
- MongoMapper.connection = if env.key?('hosts')
82
- klass = (env.key?("mongos") || env.key?("sharded")) ? Mongo::MongoShardedClient : Mongo::MongoReplicaSetClient
83
- if env['hosts'].first.is_a?(String)
84
- klass.new( env['hosts'], options )
85
- else
86
- klass.new( *env['hosts'].push(options) )
87
- end
88
- else
89
- Mongo::MongoClient.new(env['host'], env['port'], options)
66
+ if options[:port]
67
+ raise "port should be specified as part of the host or uri"
90
68
  end
91
69
 
92
- MongoMapper.database = env['database']
93
- MongoMapper.database.authenticate(env['username'], env['password']) if env['username'] && env['password']
70
+ options[:read] = options[:read].to_sym if options[:read].is_a? String
71
+ MongoMapper.connection = Mongo::Client.new(addresses_or_uri, options)
94
72
  end
95
73
 
96
74
  def setup(config, environment, options={})
@@ -18,7 +18,7 @@ class ObjectId
18
18
  end
19
19
 
20
20
  class BSON::ObjectId
21
- alias_method :original_to_json, :to_json
21
+ alias_method :original_as_json, :as_json
22
22
 
23
23
  def as_json(options=nil)
24
24
  to_s
@@ -29,4 +29,8 @@ class BSON::ObjectId
29
29
  end
30
30
 
31
31
  alias to_str to_s
32
+
33
+ def original_to_json(*args)
34
+ original_as_json.to_json(*args)
35
+ end
32
36
  end
@@ -29,7 +29,7 @@ module MongoMapper
29
29
 
30
30
  def add_touch_callbacks
31
31
  name = self.name
32
- method_name = "belongs_to_touch_after_save_or_destroy_for_#{name}"
32
+ method_name = :"belongs_to_touch_after_save_or_destroy_for_#{name}"
33
33
  touch = options.fetch(:touch)
34
34
 
35
35
  @model.send(:define_method, method_name) do
@@ -3,58 +3,50 @@ module MongoMapper
3
3
  module Plugins
4
4
  module Dirty
5
5
  extend ActiveSupport::Concern
6
-
7
6
  include ::ActiveModel::Dirty
8
7
 
9
- def initialize(*)
10
- # never register initial id assignment as a change
11
- # Chaining super into tap breaks implicit block passing in Ruby 1.8
12
- doc = super
13
- doc.tap { changed_attributes.delete('_id') }
14
- end
15
-
16
- def save(*)
17
- clear_changes { super }
18
- end
19
-
20
- def reload(*)
21
- doc = super
22
- doc.tap { clear_changes }
23
- end
24
-
25
- def clear_changes
26
- previous = changes
27
- (block_given? ? yield : true).tap do |result|
28
- unless result == false #failed validation; nil is OK.
29
- @previously_changed = previous
30
- changed_attributes.clear
8
+ module ClassMethods
9
+ def create_accessors_for(key)
10
+ super.tap do
11
+ define_attribute_methods([key.name])
31
12
  end
32
13
  end
33
14
  end
34
15
 
35
- protected
16
+ def create_or_update(*)
17
+ super.tap do
18
+ changes_applied
19
+ end
20
+ end
36
21
 
37
- # We don't call super here to avoid invoking #attributes, which builds a whole new hash per call.
38
- def attribute_method?(attr_name)
39
- keys.key?(attr_name) || !embedded_associations.detect {|a| a.name == attr_name }.nil?
22
+ def reload!
23
+ super.tap do
24
+ clear_changes_information
25
+ end
40
26
  end
41
27
 
42
28
  private
43
29
 
44
- def write_key(key, value)
45
- key = unalias_key(key)
46
- if !keys.key?(key)
30
+ def write_key(key_name, value)
31
+ key_name = unalias_key(key_name)
32
+
33
+ if !keys.key?(key_name)
47
34
  super
48
35
  else
49
- attribute_will_change!(key) unless attribute_changed?(key)
50
- super.tap do
51
- changed_attributes.delete(key) unless attribute_value_changed?(key)
36
+ # find the MongoMapper::Plugins::Keys::Key
37
+ _, key = keys.detect { |n, v| n == key_name }
38
+
39
+ # typecast to the new value
40
+ old_value = read_key(key_name)
41
+ new_value = key.type.to_mongo(value)
42
+
43
+ # only mark changed if really changed value (after typecasting)
44
+ unless old_value == new_value
45
+ attribute_will_change!(key_name)
52
46
  end
53
- end
54
- end
55
47
 
56
- def attribute_value_changed?(key_name)
57
- changed_attributes[key_name] != read_key(key_name)
48
+ super
49
+ end
58
50
  end
59
51
  end
60
52
  end
@@ -19,7 +19,7 @@ module MongoMapper
19
19
  end
20
20
 
21
21
  def reload
22
- if doc = collection.find_one(:_id => id)
22
+ if doc = collection.find({:_id => id},{limit: -1}).first
23
23
  self.class.associations.each_value do |association|
24
24
  get_proxy(association).reset
25
25
  end
@@ -42,4 +42,4 @@ module MongoMapper
42
42
  end
43
43
  end
44
44
  end
45
- end
45
+ end
@@ -44,6 +44,7 @@ module MongoMapper
44
44
  definition.each do |prefix, suffixes|
45
45
  suffixes.each do |suffix|
46
46
  callback = "%s_%s" % [prefix, suffix]
47
+
47
48
  class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
48
49
  class << self
49
50
  alias_method :__original_#{callback}, :#{callback}
@@ -41,7 +41,7 @@ module MongoMapper
41
41
 
42
42
  def persist(options={})
43
43
  @_new = false
44
- clear_changes if respond_to?(:clear_changes)
44
+ changes_applied if respond_to?(:changes_applied)
45
45
  save_to_collection(options)
46
46
  end
47
47
 
@@ -6,19 +6,20 @@ module MongoMapper
6
6
 
7
7
  module ClassMethods
8
8
  def ensure_index(spec, options = {})
9
- collection.ensure_index dealias_options(spec), options
9
+ #TODO: should we emulate the mongo 1.x behaviour of caching attempts to create indexes?
10
+ collection.indexes.create_one dealias_options(spec), options
10
11
  end
11
12
 
12
13
  def create_index(spec, options = {})
13
- collection.create_index dealias_options(spec), options
14
+ collection.indexes.create_one dealias_options(spec), options
14
15
  end
15
16
 
16
17
  def drop_index(name)
17
- collection.drop_index name
18
+ collection.indexes.drop_one name
18
19
  end
19
20
 
20
21
  def drop_indexes
21
- collection.drop_indexes
22
+ collection.indexes.drop_all
22
23
  end
23
24
 
24
25
  private
@@ -26,11 +27,17 @@ module MongoMapper
26
27
  def dealias_options(options)
27
28
  case options
28
29
  when Symbol, String
29
- abbr(options)
30
+ {abbr(options) => 1}
30
31
  when Hash
31
32
  dealias_keys(options)
32
33
  when Array
33
- options.map {|o| dealias_options(o) }
34
+ if options.first.is_a?(Hash)
35
+ options.map {|o| dealias_options(o) }
36
+ elsif options.first.is_a?(Array) # [[:foo, 1], [:bar, 1]]
37
+ options.inject({}) {|acc, tuple| acc.merge(dealias_options(tuple))}
38
+ else
39
+ dealias_keys(Hash[*options])
40
+ end
34
41
  else
35
42
  options
36
43
  end