mongo_mapper 0.15.3 → 0.15.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -6
  3. data/lib/mongo_mapper/connection.rb +1 -1
  4. data/lib/mongo_mapper/document.rb +1 -0
  5. data/lib/mongo_mapper/extensions/array.rb +1 -1
  6. data/lib/mongo_mapper/extensions/binary.rb +1 -1
  7. data/lib/mongo_mapper/extensions/date.rb +1 -1
  8. data/lib/mongo_mapper/extensions/float.rb +1 -1
  9. data/lib/mongo_mapper/extensions/hash.rb +1 -1
  10. data/lib/mongo_mapper/extensions/nil_class.rb +2 -2
  11. data/lib/mongo_mapper/extensions/object.rb +1 -1
  12. data/lib/mongo_mapper/extensions/object_id.rb +1 -1
  13. data/lib/mongo_mapper/extensions/set.rb +1 -1
  14. data/lib/mongo_mapper/extensions/string.rb +1 -1
  15. data/lib/mongo_mapper/plugins/associations/many_association.rb +2 -3
  16. data/lib/mongo_mapper/plugins/associations/{belongs_to_polymorphic_proxy.rb → proxy/belongs_to_polymorphic_proxy.rb} +0 -0
  17. data/lib/mongo_mapper/plugins/associations/{belongs_to_proxy.rb → proxy/belongs_to_proxy.rb} +0 -0
  18. data/lib/mongo_mapper/plugins/associations/proxy/collection.rb +55 -0
  19. data/lib/mongo_mapper/plugins/associations/{embedded_collection.rb → proxy/embedded_collection.rb} +0 -0
  20. data/lib/mongo_mapper/plugins/associations/{in_array_proxy.rb → proxy/in_array_proxy.rb} +0 -0
  21. data/lib/mongo_mapper/plugins/associations/{in_foreign_array_proxy.rb → proxy/in_foreign_array_proxy.rb} +0 -0
  22. data/lib/mongo_mapper/plugins/associations/{many_documents_as_proxy.rb → proxy/many_documents_as_proxy.rb} +0 -0
  23. data/lib/mongo_mapper/plugins/associations/{many_documents_proxy.rb → proxy/many_documents_proxy.rb} +0 -4
  24. data/lib/mongo_mapper/plugins/associations/{many_embedded_polymorphic_proxy.rb → proxy/many_embedded_polymorphic_proxy.rb} +0 -0
  25. data/lib/mongo_mapper/plugins/associations/{many_embedded_proxy.rb → proxy/many_embedded_proxy.rb} +0 -0
  26. data/lib/mongo_mapper/plugins/associations/{many_polymorphic_proxy.rb → proxy/many_polymorphic_proxy.rb} +0 -0
  27. data/lib/mongo_mapper/plugins/associations/{one_as_proxy.rb → proxy/one_as_proxy.rb} +0 -0
  28. data/lib/mongo_mapper/plugins/associations/{one_embedded_polymorphic_proxy.rb → proxy/one_embedded_polymorphic_proxy.rb} +0 -0
  29. data/lib/mongo_mapper/plugins/associations/{one_embedded_proxy.rb → proxy/one_embedded_proxy.rb} +0 -0
  30. data/lib/mongo_mapper/plugins/associations/{one_proxy.rb → proxy/one_proxy.rb} +0 -0
  31. data/lib/mongo_mapper/plugins/associations/{proxy.rb → proxy/proxy.rb} +64 -48
  32. data/lib/mongo_mapper/plugins/associations/single_association.rb +2 -11
  33. data/lib/mongo_mapper/plugins/caching.rb +2 -2
  34. data/lib/mongo_mapper/plugins/dirty.rb +1 -1
  35. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +2 -2
  36. data/lib/mongo_mapper/plugins/keys/key.rb +9 -6
  37. data/lib/mongo_mapper/plugins/keys.rb +14 -2
  38. data/lib/mongo_mapper/plugins/querying.rb +2 -2
  39. data/lib/mongo_mapper/plugins/shardable.rb +30 -0
  40. data/lib/mongo_mapper/plugins/validations.rb +1 -1
  41. data/lib/mongo_mapper/plugins.rb +18 -1
  42. data/lib/mongo_mapper/version.rb +1 -1
  43. data/lib/mongo_mapper.rb +18 -18
  44. data/spec/examples.txt +1711 -1701
  45. data/spec/functional/callbacks_spec.rb +5 -1
  46. data/spec/functional/keys_spec.rb +13 -0
  47. data/spec/functional/shardable_spec.rb +59 -0
  48. data/spec/support/sharded_model.rb +24 -0
  49. data/spec/unit/associations/proxy_spec.rb +18 -5
  50. data/spec/unit/document_spec.rb +1 -1
  51. data/spec/unit/embedded_document_spec.rb +3 -3
  52. data/spec/unit/extensions_spec.rb +9 -3
  53. data/spec/unit/inspect_spec.rb +1 -1
  54. data/spec/unit/key_spec.rb +7 -1
  55. data/spec/unit/mongo_mapper_spec.rb +10 -5
  56. metadata +36 -19
  57. data/lib/mongo_mapper/plugins/associations/collection.rb +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d5192b00f4bce2f16b7ac329a9bdb059c888ebea3c62ba91e9017a42a43371c
4
- data.tar.gz: 9e3f0dca756cb0e260266fa147800c07d02133dfad74376f3aaa169f56d67f36
3
+ metadata.gz: ab17d58378959cb58a5f2168fe0f9c7740628b4fa470547c708cf9d9740ef668
4
+ data.tar.gz: fcba32755feb7d0a439f8d2f0217a2a99092b8cf48317ef6b1f13265874595de
5
5
  SHA512:
6
- metadata.gz: 052506c11e7921c9412fdbbdaeedbc05a199700867502e87c73bb00d4bb649007ed4f5c8f3f57020f96084d26128aaf5ba9973504018a76a1ecf4cd93b014186
7
- data.tar.gz: fb775b4103f3eaa22ae76c5e4875d6c3117e44db8c2e6cd39189800d0fcafb63a8d8368a91a195ea8380cf9ce0744431e41e303bec0c478d61c5606d4ca8bd14
6
+ metadata.gz: 2b0fa4d463705845f6b445c0e4e5d367b931822bb20992704bec606ad133ba4342a426a15785faf237ab91a98b9ff3835c17ee53a520eabe995e129a9c0f3ec6
7
+ data.tar.gz: cb57c4f3128a2f3dcb2a80dfd61b3ed473931b600876cf1ab5b00c0a51fe14cf0ba7f503e1779470ef9027957252738aa7e0e7bd9136fe20fbbd31d3c6177eda
data/README.md CHANGED
@@ -6,7 +6,7 @@ A Ruby Object Mapper for Mongo.
6
6
 
7
7
  [<img src="https://github.com/mongomapper/mongomapper/workflows/Ruby/badge.svg?branch=master" alt="Build Status" />](https://github.com/mongomapper/mongomapper/actions?query=workflow%3ARuby+branch%3Amaster)
8
8
 
9
- [<img src="https://coveralls.io/repos/mongomapper/mongomapper/badge.svg" alt="Coverage Status" />](https://coveralls.io/r/mongomapper/mongomapper)
9
+ <!-- [<img src="https://coveralls.io/repos/mongomapper/mongomapper/badge.svg" alt="Coverage Status" />](https://coveralls.io/r/mongomapper/mongomapper) -->
10
10
 
11
11
  ## Install
12
12
 
@@ -18,16 +18,27 @@ http://mongomapper.com/documentation/
18
18
 
19
19
  http://rdoc.info/github/mongomapper/mongomapper
20
20
 
21
+ ## Open Commit Policy
22
+
23
+ Like Rubinius, we're trying out an "open commit policy".
24
+
25
+ If you've committed one (code) patch that has been accepted and would like to
26
+ work some more on the project, send an email to Scott Taylor
27
+ <scott@railsnewbie.com> along with your commit sha1.
28
+
21
29
  ## Compatibility
22
30
 
23
31
  MongoMapper is tested against:
24
32
 
25
- * MRI 2.4 - 2.7
33
+ * MRI 2.4 - 3.0.1
26
34
  * JRuby (Versions with 1.9 compatibility)
27
35
 
28
36
  Additionally, MongoMapper is tested against:
29
37
 
30
- * Rails 5.0+ - 6.0
38
+ * Rails 5.0 - 5.2
39
+ * Rails 6.0 - 6.1
40
+
41
+ Note, if you are using Ruby 3.0+, you'll need Rails 6.
31
42
 
32
43
  ## Contributing & Development
33
44
 
@@ -37,17 +48,21 @@ Additionally, MongoMapper is tested against:
37
48
 
38
49
  * Fork the project.
39
50
  * Make your feature addition or bug fix. All specs should pass.
40
- * Add specs for your changes. This is important so I don't break it in a future version unintentionally.
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.
51
+ * Add specs for your changes. This is important so that it doesn't break in a future version.
52
+ * 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 can ignore it when your pull request is merged.
42
53
  * Send a pull request. Bonus points for topic branches.
43
54
 
55
+ ## How to release
56
+
57
+ See `HOW_TO_RELEASE.md`
58
+
44
59
  ## Problems or Questions?
45
60
 
46
61
  Hit up the Google group: http://groups.google.com/group/mongomapper
47
62
 
48
63
  ## Copyright
49
64
 
50
- Copyright (c) 2009-2020 MongoMapper. See LICENSE for details.
65
+ Copyright (c) 2009-2021 MongoMapper. See LICENSE for details.
51
66
 
52
67
  ## Contributors
53
68
 
@@ -81,7 +81,7 @@ module MongoMapper
81
81
  # :nocov:
82
82
  if defined?(PhusionPassenger)
83
83
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
84
- connection.connect if forked
84
+ connection.reconnect if forked
85
85
  end
86
86
  end
87
87
  # :nocov:
@@ -39,6 +39,7 @@ module MongoMapper
39
39
  include Plugins::PartialUpdates
40
40
  include Plugins::IdentityMap
41
41
  include Plugins::CounterCache
42
+ include Plugins::Shardable
42
43
 
43
44
  included do
44
45
  extend Plugins
@@ -24,4 +24,4 @@ end
24
24
 
25
25
  class Array
26
26
  include MongoMapper::Extensions::Array
27
- end
27
+ end
@@ -19,4 +19,4 @@ end
19
19
 
20
20
  class Binary
21
21
  extend MongoMapper::Extensions::Binary
22
- end
22
+ end
@@ -22,4 +22,4 @@ end
22
22
 
23
23
  class Date
24
24
  extend MongoMapper::Extensions::Date
25
- end
25
+ end
@@ -11,4 +11,4 @@ end
11
11
 
12
12
  class Float
13
13
  extend MongoMapper::Extensions::Float
14
- end
14
+ end
@@ -23,4 +23,4 @@ end
23
23
 
24
24
  class Hash
25
25
  include MongoMapper::Extensions::Hash
26
- end
26
+ end
@@ -14,5 +14,5 @@ module MongoMapper
14
14
  end
15
15
 
16
16
  class NilClass
17
- include MongoMapper::Extensions::NilClass
18
- end
17
+ extend MongoMapper::Extensions::NilClass
18
+ end
@@ -27,4 +27,4 @@ end
27
27
 
28
28
  class Object
29
29
  include MongoMapper::Extensions::Object
30
- end
30
+ end
@@ -33,4 +33,4 @@ class BSON::ObjectId
33
33
  def original_to_json(*args)
34
34
  original_as_json.to_json(*args)
35
35
  end
36
- end
36
+ end
@@ -17,4 +17,4 @@ end
17
17
 
18
18
  class Set
19
19
  extend MongoMapper::Extensions::Set
20
- end
20
+ end
@@ -23,4 +23,4 @@ end
23
23
 
24
24
  class String
25
25
  include MongoMapper::Extensions::String
26
- end
26
+ end
@@ -30,12 +30,11 @@ module MongoMapper
30
30
  def setup(model)
31
31
  model.associations_module.module_eval(<<-end_eval, __FILE__, __LINE__ + 1)
32
32
  def #{name}
33
- get_proxy(associations[#{name.inspect}])
33
+ get_proxy(associations[#{name.inspect}]).read
34
34
  end
35
35
 
36
36
  def #{name}=(value)
37
- get_proxy(associations[#{name.inspect}]).replace(value)
38
- value
37
+ get_proxy(associations[#{name.inspect}]).write(value)
39
38
  end
40
39
  end_eval
41
40
 
@@ -0,0 +1,55 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module Associations
5
+ class Collection < Proxy
6
+ include Enumerable
7
+
8
+ def to_a
9
+ load_target
10
+
11
+ target.is_a?(Array) ?
12
+ target :
13
+ Array(target)
14
+ end
15
+
16
+ alias_method :to_ary, :to_a
17
+
18
+ def each(&block)
19
+ to_a.each(&block)
20
+ end
21
+
22
+ def [](val)
23
+ objs = to_a
24
+ objs ? objs[val] : nil
25
+ end
26
+
27
+ def empty?
28
+ to_a.empty?
29
+ end
30
+
31
+ def size
32
+ to_a.size
33
+ end
34
+
35
+ def length
36
+ to_a.length
37
+ end
38
+
39
+ def reset
40
+ super
41
+ target = []
42
+ end
43
+
44
+ def read
45
+ self
46
+ end
47
+
48
+ def write(value)
49
+ replace(value)
50
+ read
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -76,10 +76,6 @@ module MongoMapper
76
76
  @target.each { |doc| doc.save(options) } if @target
77
77
  end
78
78
 
79
- def each(&block)
80
- load_target.each(&block)
81
- end
82
-
83
79
  protected
84
80
 
85
81
  def query(options={})
@@ -1,19 +1,25 @@
1
1
  # encoding: UTF-8
2
2
  require 'forwardable'
3
+
3
4
  module MongoMapper
4
5
  module Plugins
5
6
  module Associations
6
7
  class Proxy
7
8
  extend Forwardable
8
9
 
9
- alias :proxy_respond_to? :respond_to?
10
- alias :proxy_extend :extend
11
-
12
- instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^respond_to_missing\?$|^object_id$)/ }
10
+ class << self
11
+ def define_proxy_method(method)
12
+ define_method(method) do |*args, &block|
13
+ proxy_method(method, *args, &block)
14
+ end
15
+ end
16
+ end
13
17
 
14
18
  attr_reader :proxy_owner, :association, :target
15
19
 
16
- alias :proxy_association :association
20
+ alias_method :proxy_respond_to?, :respond_to?
21
+ alias_method :proxy_extend, :extend
22
+ alias_method :proxy_association, :association
17
23
 
18
24
  def_delegators :proxy_association, :klass, :options
19
25
  def_delegator :klass, :collection
@@ -24,26 +30,31 @@ module MongoMapper
24
30
  reset
25
31
  end
26
32
 
27
- # Active support in rails 3 beta 4 can override to_json after this is loaded,
28
- # at least when run in mongomapper tests. The implementation was changed in master
29
- # some time after this, so not sure whether this is still a problem.
30
- #
31
- # In rails 2, this isn't a problem however it also solves an issue where
32
- # to_json isn't forwarded because it supports to_json itself
33
- def to_json(*options)
34
- load_target
35
- target.to_json(*options)
36
- end
37
-
38
- # see comments to to_json
39
- def as_json(*options)
40
- load_target
41
- target.as_json(*options)
33
+ [
34
+ :is_a?,
35
+ :to_mongo,
36
+ :==,
37
+ :!=,
38
+ :nil?,
39
+ :blank?,
40
+ :present?,
41
+ :hash,
42
+ # Active support in rails 3 beta 4 can override to_json after this is loaded,
43
+ # at least when run in mongomapper tests. The implementation was changed in master
44
+ # some time after this, so not sure whether this is still a problem.
45
+ #
46
+ # In rails 2, this isn't a problem however it also solves an issue where
47
+ # to_json isn't forwarded because it supports to_json itself
48
+ :to_json,
49
+ # see comments to to_json
50
+ :as_json,
51
+ ].each do |m|
52
+ define_proxy_method(m)
42
53
  end
43
54
 
44
55
  def inspect
45
56
  load_target
46
- target.inspect
57
+ "#<#{self.class.inspect}:#{object_id} #{@target.inspect}>"
47
58
  end
48
59
 
49
60
  def loaded?
@@ -54,21 +65,6 @@ module MongoMapper
54
65
  @loaded = true
55
66
  end
56
67
 
57
- def nil?
58
- load_target
59
- target.nil?
60
- end
61
-
62
- def blank?
63
- load_target
64
- target.blank?
65
- end
66
-
67
- def present?
68
- load_target
69
- target.present?
70
- end
71
-
72
68
  def reload
73
69
  reset
74
70
  load_target
@@ -87,16 +83,7 @@ module MongoMapper
87
83
  end
88
84
 
89
85
  def respond_to?(*args)
90
- proxy_respond_to?(*args) || (load_target && target.respond_to?(*args))
91
- end
92
-
93
- def send(method, *args, &block)
94
- if proxy_respond_to?(method, true)
95
- super
96
- else
97
- load_target
98
- target.send(method, *args, &block)
99
- end
86
+ super || (load_target && target.respond_to?(*args))
100
87
  end
101
88
 
102
89
  def read
@@ -104,6 +91,16 @@ module MongoMapper
104
91
  @target
105
92
  end
106
93
 
94
+ def write(value)
95
+ replace(value)
96
+ read
97
+ end
98
+
99
+ def proxy_method(method, *args, &block)
100
+ load_target
101
+ target.public_send(method, *args, &block)
102
+ end
103
+
107
104
  protected
108
105
 
109
106
  def load_target
@@ -138,9 +135,28 @@ module MongoMapper
138
135
  false
139
136
  end
140
137
 
138
+ def define_proxy_method(method)
139
+ metaclass = class << self; self; end
140
+ metaclass.class_eval do
141
+ define_proxy_method(method)
142
+ end
143
+ end
144
+
145
+ def define_and_call_proxy_method(method, *args, &block)
146
+ define_proxy_method(method)
147
+ public_send(method, *args, &block)
148
+ end
149
+
141
150
  def method_missing(method, *args, &block)
142
- if load_target
143
- target.public_send(method, *args, &block)
151
+ # load the target just in case it isn't loaded
152
+ load_target
153
+
154
+ # only define the method if the target has the method
155
+ # NOTE: include private methods!
156
+ if target.respond_to?(method, true)
157
+ define_and_call_proxy_method(method, *args, &block)
158
+ else
159
+ super
144
160
  end
145
161
  end
146
162
  end
@@ -8,20 +8,11 @@ module MongoMapper
8
8
 
9
9
  model.associations_module.module_eval(<<-end_eval, __FILE__, __LINE__ + 1)
10
10
  def #{name}
11
- proxy = get_proxy(associations[#{name.inspect}])
12
- proxy.nil? ? nil : proxy.read
11
+ get_proxy(associations[#{name.inspect}]).read
13
12
  end
14
13
 
15
14
  def #{name}=(value)
16
- association = associations[#{name.inspect}]
17
- proxy = get_proxy(association)
18
-
19
- if proxy.nil? || proxy.target != value
20
- proxy = build_proxy(association)
21
- end
22
-
23
- proxy.replace(value)
24
- proxy.read
15
+ get_proxy(associations[#{name.inspect}]).write(value)
25
16
  end
26
17
 
27
18
  def #{name}?
@@ -9,7 +9,7 @@ module MongoMapper
9
9
  when !persisted?
10
10
  "#{self.class.name}/new"
11
11
  when timestamp = self[:updated_at]
12
- "#{self.class.name}/#{id}-#{timestamp.to_s(:number)}"
12
+ "#{self.class.name}/#{id}-#{timestamp.to_formatted_s(:number)}"
13
13
  else
14
14
  "#{self.class.name}/#{id}"
15
15
  end
@@ -18,4 +18,4 @@ module MongoMapper
18
18
  end
19
19
  end
20
20
  end
21
- end
21
+ end
@@ -38,7 +38,7 @@ module MongoMapper
38
38
 
39
39
  # typecast to the new value
40
40
  old_value = read_key(key_name)
41
- new_value = key.get(key.set(value))
41
+ new_value = key.set(value)
42
42
 
43
43
  # only mark changed if really changed value (after typecasting)
44
44
  unless old_value == new_value
@@ -49,9 +49,9 @@ module MongoMapper
49
49
  class << self
50
50
  alias_method :__original_#{callback}, :#{callback}
51
51
 
52
- def #{callback}(*args, &block)
52
+ def #{callback}(*args, **options, &block)
53
53
  embedded_callbacks_on if @embedded_callbacks_status.nil?
54
- __original_#{callback}(*args, &block)
54
+ __original_#{callback}(*args, **options, &block)
55
55
  end
56
56
  end
57
57
  CALLBACK
@@ -61,7 +61,7 @@ module MongoMapper
61
61
  # Special Case: Generate default _id on access
62
62
  value = default_value if @is_id and !value
63
63
 
64
- value = type.from_mongo(value)
64
+ value = type ? type.from_mongo(value) : value
65
65
 
66
66
  if @typecast
67
67
  klass = typecast_class # Don't make this lookup on every call
@@ -76,22 +76,25 @@ module MongoMapper
76
76
 
77
77
  def set(value)
78
78
  # Avoid tap here so we don't have to create a block binding.
79
- values = type.to_mongo(value)
79
+ value = type ? type.to_mongo(value) : value.to_mongo
80
+
80
81
  if @typecast
81
- values.map { |v| typecast_class.to_mongo(v) }
82
+ klass = typecast_class # Don't make this lookup on every call
83
+ value.map { |v| klass.to_mongo(v) }
82
84
  else
83
- values
85
+ value
84
86
  end
85
87
  end
86
88
 
87
89
  def default_value
88
90
  return unless default?
91
+
89
92
  if default.instance_of? Proc
90
- type.to_mongo default.call
93
+ default.call
91
94
  else
92
95
  # Using Marshal is easiest way to get a copy of mutable objects
93
96
  # without getting an error on immutable objects
94
- type.to_mongo Marshal.load(Marshal.dump(default))
97
+ Marshal.load(Marshal.dump(default))
95
98
  end
96
99
  end
97
100
 
@@ -251,12 +251,24 @@ module MongoMapper
251
251
 
252
252
  def remove_validate_callbacks(a_name)
253
253
  chain = _validate_callbacks.dup.reject do |callback|
254
- f = callback.raw_filter
254
+ f = callback_filter(callback)
255
255
  f.respond_to?(:attributes) && f.attributes == a_name
256
256
  end
257
257
  reset_callbacks(:validate)
258
258
  chain.each do |callback|
259
- set_callback 'validate', callback.raw_filter
259
+ set_callback 'validate', callback_filter(callback)
260
+ end
261
+ end
262
+
263
+ # The interface to obtain @filter from ActiveSupport::Callbacks::Callback has changed since rails 7.0.
264
+ # https://github.com/rails/rails/commit/d5ac941ddc3de7ad1aaff80ed67aa04fb626a263#diff-bf79b7ea0085308139af6de0afad9a9f22f13d4563cc56d784994414d88c5dd1
265
+ if ActiveSupport::VERSION::MAJOR >= 7
266
+ def callback_filter(callback)
267
+ callback.filter
268
+ end
269
+ else
270
+ def callback_filter(callback)
271
+ callback.raw_filter
260
272
  end
261
273
  end
262
274
  end
@@ -148,7 +148,7 @@ module MongoMapper
148
148
  when :insert
149
149
  collection.insert_one(update, query_options)
150
150
  when :save
151
- collection.update_one({:_id => _id}, update, query_options.merge(upsert: true))
151
+ collection.update_one({:_id => _id}.merge(shard_key_filter), update, query_options.merge(upsert: true))
152
152
  when :update
153
153
  update.stringify_keys!
154
154
 
@@ -180,4 +180,4 @@ module MongoMapper
180
180
  end
181
181
  end
182
182
  end
183
- end
183
+ end
@@ -0,0 +1,30 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module Shardable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ class_attribute :shard_key_fields
8
+ self.shard_key_fields = []
9
+ end
10
+
11
+ def shard_key_filter
12
+ filter = {}
13
+ shard_key_fields.each do |field|
14
+ filter[field] = if new_record?
15
+ send(field)
16
+ else
17
+ changed_attributes.key?(field) ? changed_attributes[field] : send(field)
18
+ end
19
+ end
20
+ filter
21
+ end
22
+
23
+ module ClassMethods
24
+ def shard_key(*fields)
25
+ self.shard_key_fields = fields.map(&:to_s).freeze
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -54,7 +54,7 @@ module MongoMapper
54
54
  conditions[:_id.ne] = record._id if record._id
55
55
 
56
56
  if @klass.exists?(conditions)
57
- record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
57
+ record.errors.add(attribute, :taken, **options.except(:case_sensitive, :scope).merge(:value => value))
58
58
  end
59
59
  end
60
60