promiscuous 0.53.1 → 0.90.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/lib/promiscuous.rb +25 -28
  2. data/lib/promiscuous/amqp.rb +27 -8
  3. data/lib/promiscuous/amqp/bunny.rb +131 -16
  4. data/lib/promiscuous/amqp/fake.rb +52 -0
  5. data/lib/promiscuous/amqp/hot_bunnies.rb +56 -0
  6. data/lib/promiscuous/amqp/null.rb +6 -6
  7. data/lib/promiscuous/cli.rb +108 -24
  8. data/lib/promiscuous/config.rb +73 -12
  9. data/lib/promiscuous/convenience.rb +18 -0
  10. data/lib/promiscuous/dependency.rb +59 -0
  11. data/lib/promiscuous/dsl.rb +36 -0
  12. data/lib/promiscuous/error.rb +3 -1
  13. data/lib/promiscuous/error/already_processed.rb +5 -0
  14. data/lib/promiscuous/error/base.rb +1 -0
  15. data/lib/promiscuous/error/connection.rb +7 -5
  16. data/lib/promiscuous/error/dependency.rb +111 -0
  17. data/lib/promiscuous/error/lock_unavailable.rb +12 -0
  18. data/lib/promiscuous/error/lost_lock.rb +12 -0
  19. data/lib/promiscuous/error/missing_context.rb +29 -0
  20. data/lib/promiscuous/error/publisher.rb +5 -15
  21. data/lib/promiscuous/error/recovery.rb +7 -0
  22. data/lib/promiscuous/error/subscriber.rb +2 -4
  23. data/lib/promiscuous/key.rb +36 -0
  24. data/lib/promiscuous/loader.rb +12 -16
  25. data/lib/promiscuous/middleware.rb +112 -0
  26. data/lib/promiscuous/publisher.rb +7 -4
  27. data/lib/promiscuous/publisher/context.rb +92 -0
  28. data/lib/promiscuous/publisher/mock_generator.rb +72 -0
  29. data/lib/promiscuous/publisher/model.rb +3 -86
  30. data/lib/promiscuous/publisher/model/active_record.rb +8 -15
  31. data/lib/promiscuous/publisher/model/base.rb +136 -0
  32. data/lib/promiscuous/publisher/model/ephemeral.rb +69 -0
  33. data/lib/promiscuous/publisher/model/mock.rb +61 -0
  34. data/lib/promiscuous/publisher/model/mongoid.rb +57 -100
  35. data/lib/promiscuous/{common/lint.rb → publisher/operation.rb} +1 -1
  36. data/lib/promiscuous/publisher/operation/base.rb +707 -0
  37. data/lib/promiscuous/publisher/operation/mongoid.rb +370 -0
  38. data/lib/promiscuous/publisher/worker.rb +22 -0
  39. data/lib/promiscuous/railtie.rb +21 -3
  40. data/lib/promiscuous/redis.rb +132 -40
  41. data/lib/promiscuous/resque.rb +12 -0
  42. data/lib/promiscuous/sidekiq.rb +15 -0
  43. data/lib/promiscuous/subscriber.rb +9 -20
  44. data/lib/promiscuous/subscriber/model.rb +4 -104
  45. data/lib/promiscuous/subscriber/model/active_record.rb +10 -0
  46. data/lib/promiscuous/subscriber/model/base.rb +96 -0
  47. data/lib/promiscuous/subscriber/model/mongoid.rb +86 -0
  48. data/lib/promiscuous/subscriber/model/observer.rb +37 -0
  49. data/lib/promiscuous/subscriber/operation.rb +167 -0
  50. data/lib/promiscuous/subscriber/payload.rb +34 -0
  51. data/lib/promiscuous/subscriber/worker.rb +22 -18
  52. data/lib/promiscuous/subscriber/worker/message.rb +48 -25
  53. data/lib/promiscuous/subscriber/worker/message_synchronizer.rb +273 -181
  54. data/lib/promiscuous/subscriber/worker/pump.rb +17 -43
  55. data/lib/promiscuous/subscriber/worker/recorder.rb +24 -0
  56. data/lib/promiscuous/subscriber/worker/runner.rb +24 -3
  57. data/lib/promiscuous/subscriber/worker/stats.rb +62 -0
  58. data/lib/promiscuous/timer.rb +38 -0
  59. data/lib/promiscuous/version.rb +1 -1
  60. metadata +98 -143
  61. data/README.md +0 -33
  62. data/lib/promiscuous/amqp/ruby_amqp.rb +0 -140
  63. data/lib/promiscuous/common.rb +0 -4
  64. data/lib/promiscuous/common/class_helpers.rb +0 -12
  65. data/lib/promiscuous/common/lint/base.rb +0 -24
  66. data/lib/promiscuous/common/options.rb +0 -51
  67. data/lib/promiscuous/ephemeral.rb +0 -14
  68. data/lib/promiscuous/error/recover.rb +0 -1
  69. data/lib/promiscuous/observer.rb +0 -5
  70. data/lib/promiscuous/publisher/active_record.rb +0 -7
  71. data/lib/promiscuous/publisher/amqp.rb +0 -18
  72. data/lib/promiscuous/publisher/attributes.rb +0 -32
  73. data/lib/promiscuous/publisher/base.rb +0 -23
  74. data/lib/promiscuous/publisher/class.rb +0 -36
  75. data/lib/promiscuous/publisher/envelope.rb +0 -7
  76. data/lib/promiscuous/publisher/ephemeral.rb +0 -9
  77. data/lib/promiscuous/publisher/lint.rb +0 -35
  78. data/lib/promiscuous/publisher/lint/amqp.rb +0 -14
  79. data/lib/promiscuous/publisher/lint/attributes.rb +0 -12
  80. data/lib/promiscuous/publisher/lint/base.rb +0 -5
  81. data/lib/promiscuous/publisher/lint/class.rb +0 -15
  82. data/lib/promiscuous/publisher/lint/polymorphic.rb +0 -22
  83. data/lib/promiscuous/publisher/mock.rb +0 -79
  84. data/lib/promiscuous/publisher/mongoid.rb +0 -33
  85. data/lib/promiscuous/publisher/mongoid/embedded.rb +0 -27
  86. data/lib/promiscuous/publisher/mongoid/embedded_many.rb +0 -12
  87. data/lib/promiscuous/publisher/polymorphic.rb +0 -8
  88. data/lib/promiscuous/subscriber/active_record.rb +0 -11
  89. data/lib/promiscuous/subscriber/amqp.rb +0 -25
  90. data/lib/promiscuous/subscriber/attributes.rb +0 -35
  91. data/lib/promiscuous/subscriber/base.rb +0 -29
  92. data/lib/promiscuous/subscriber/class.rb +0 -29
  93. data/lib/promiscuous/subscriber/dummy.rb +0 -19
  94. data/lib/promiscuous/subscriber/envelope.rb +0 -18
  95. data/lib/promiscuous/subscriber/lint.rb +0 -30
  96. data/lib/promiscuous/subscriber/lint/amqp.rb +0 -21
  97. data/lib/promiscuous/subscriber/lint/attributes.rb +0 -21
  98. data/lib/promiscuous/subscriber/lint/base.rb +0 -14
  99. data/lib/promiscuous/subscriber/lint/class.rb +0 -13
  100. data/lib/promiscuous/subscriber/lint/polymorphic.rb +0 -39
  101. data/lib/promiscuous/subscriber/mongoid.rb +0 -27
  102. data/lib/promiscuous/subscriber/mongoid/embedded.rb +0 -17
  103. data/lib/promiscuous/subscriber/mongoid/embedded_many.rb +0 -44
  104. data/lib/promiscuous/subscriber/observer.rb +0 -26
  105. data/lib/promiscuous/subscriber/polymorphic.rb +0 -36
  106. data/lib/promiscuous/subscriber/upsert.rb +0 -12
@@ -1,25 +1,18 @@
1
1
  module Promiscuous::Publisher::Model::ActiveRecord
2
2
  extend ActiveSupport::Concern
3
+ include Promiscuous::Publisher::Model::Base
3
4
 
4
- module ModelInstanceMethods
5
- extend ActiveSupport::Concern
5
+ # TODO FIXME This needs some serious work. We need to hook deeper.
6
6
 
7
- def with_promiscuous(options={}, &block)
8
- fetch_proc = proc { self.class.find(self.id) }
9
- self.class.promiscuous_publisher.new(options.merge(:instance => self, :fetch_proc => fetch_proc)).commit(&block)
10
- end
11
-
12
- included do
13
- around_create { |&block| with_promiscuous(:operation => :create, &block) }
14
- around_update { |&block| with_promiscuous(:operation => :update, &block) }
15
- around_destroy { |&block| with_promiscuous(:operation => :destroy, &block) }
16
- end
7
+ included do
8
+ around_create { |&block| promiscuous.sync(:operation => :create, &block) }
9
+ around_update { |&block| promiscuous.sync(:operation => :update, &block) }
10
+ around_destroy { |&block| promiscuous.sync(:operation => :destroy, &block) }
17
11
  end
18
12
 
19
13
  module ClassMethods
20
- def setup_class_binding
21
- super
22
- klass.__send__(:include, ModelInstanceMethods) if klass
14
+ def __promiscuous_missing_record_exception
15
+ ActiveRecord::RecordNotFound
23
16
  end
24
17
  end
25
18
  end
@@ -0,0 +1,136 @@
1
+ module Promiscuous::Publisher::Model::Base
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ class_attribute :publish_to, :published_attrs, :tracked_attrs
6
+ cattr_accessor :published_db_fields # There is one on each root class, none on the subclasses
7
+ self.published_attrs = []
8
+ self.tracked_attrs = []
9
+ self.published_db_fields = []
10
+ track_dependencies_of :id
11
+ Promiscuous::Publisher::Model.publishers[self.promiscuous_collection_name] = self
12
+ end
13
+
14
+ module PromiscuousMethodsBase
15
+ def initialize(instance)
16
+ @instance = instance
17
+ end
18
+
19
+ def sync(options={}, &block)
20
+ options = {:instance => @instance, :operation => :update}.merge(options)
21
+ Promiscuous::Publisher::Operation::Base.new(options).execute(&block)
22
+ end
23
+
24
+ def payload(options={})
25
+ # It's nice to see the entire payload in one piece, not merged 36 times
26
+ # TODO migrate this format to something that makes more sense once the store is out
27
+ msg = {}
28
+ msg[:__amqp__] = @instance.class.publish_to
29
+ msg[:type] = @instance.class.publish_as # for backward compatibility
30
+ msg[:ancestors] = @instance.class.ancestors.select { |a| a < Promiscuous::Publisher::Model::Base }.map(&:publish_as)
31
+ msg[:id] = @instance.id.to_s
32
+ if @instance.respond_to?(:promiscuous_payload)
33
+ msg[:payload] = @instance.promiscuous_payload
34
+ else
35
+ msg[:payload] = self.attributes unless options[:with_attributes] == false
36
+ end
37
+ msg
38
+ end
39
+
40
+ def attributes
41
+ Hash[@instance.class.published_attrs.map { |attr| [attr, self.attribute(attr)] }]
42
+ end
43
+
44
+ def attribute(attr)
45
+ value = @instance.__send__(attr)
46
+ value = value.promiscuous.payload if value.respond_to?(:promiscuous)
47
+ value
48
+ end
49
+
50
+ def get_dependency(attr, value)
51
+ return nil unless value
52
+ @collection ||= @instance.class.promiscuous_collection_name
53
+ Promiscuous::Dependency.new(@collection, attr, value)
54
+ end
55
+
56
+ def tracked_dependencies(options={})
57
+ # FIXME This is not sufficient, we need to consider the previous and next
58
+ # values in case of an update.
59
+ # Note that the caller expect the id dependency to come first
60
+ @instance.class.tracked_attrs
61
+ .map { |attr| [attr, @instance.__send__(attr)] }
62
+ .map { |attr, value| get_dependency(attr, value) }
63
+ .compact
64
+ end
65
+ end
66
+
67
+ class PromiscuousMethods
68
+ include Promiscuous::Publisher::Model::Base::PromiscuousMethodsBase
69
+ end
70
+
71
+ def promiscuous
72
+ # XXX Not thread safe
73
+ @promiscuous ||= self.class.const_get(:PromiscuousMethods).new(self)
74
+ end
75
+
76
+ def valid?(*args)
77
+ # Validations are not dependencies
78
+ # TODO we should yell if the user is trying to write
79
+ without_promiscuous { super }
80
+ end
81
+
82
+ module ClassMethods
83
+ # all methods are virtual
84
+
85
+ def publish(*args, &block)
86
+ options = args.extract_options!
87
+ attributes = args.map(&:to_sym)
88
+
89
+ # TODO reject invalid options
90
+
91
+ if attributes.present? && self.publish_to && options[:to] && self.publish_to != options[:to]
92
+ raise 'versionned publishing is not supported yet'
93
+ end
94
+ self.publish_to ||= options[:to] || "#{Promiscuous::Config.app}/#{self.name.underscore}"
95
+ @publish_as = options[:as].to_s if options[:as]
96
+
97
+ ([self] + descendants).each do |klass|
98
+ # When the user passes :use => [:f1, :f2] for example, operation/mongoid.rb
99
+ # can track f1 and f2 as fields important for the publishing.
100
+ # It's important for virtual attributes. The published_db_fields is global
101
+ # for the entire subclass tree.
102
+ klass.published_db_fields |= [options[:use]].flatten.map(&:to_sym) if options[:use]
103
+ klass.published_db_fields |= attributes # aliased fields are resolved later
104
+ klass.published_attrs |= attributes
105
+ end
106
+ end
107
+
108
+ def track_dependencies_of(*attributes)
109
+ ([self] + descendants).each { |klass| klass.tracked_attrs |= attributes.map(&:to_sym) }
110
+ end
111
+
112
+ def promiscuous_collection_name
113
+ self.name.pluralize.underscore
114
+ end
115
+
116
+ def get_operation_class_for(operation)
117
+ Promiscuous::Publisher::Operation::Base
118
+ end
119
+
120
+ def publish_as
121
+ @publish_as || name
122
+ end
123
+
124
+ def inherited(subclass)
125
+ super
126
+ subclass.published_attrs = self.published_attrs.dup
127
+ subclass.tracked_attrs = self.tracked_attrs.dup
128
+ # no copy for published_db_fields
129
+ end
130
+
131
+ class None; end
132
+ def promiscuous_missing_record_exception
133
+ None
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,69 @@
1
+ module Promiscuous::Publisher::Model::Ephemeral
2
+ extend ActiveSupport::Concern
3
+ include Promiscuous::Publisher::Model::Base
4
+
5
+ attr_accessor :id, :new_record, :destroyed
6
+
7
+ module PromiscuousMethodsEphemeral
8
+ def attribute(attr)
9
+ value = super
10
+ if value.is_a?(Array) &&
11
+ value.first.is_a?(Promiscuous::Publisher::Model::Ephemeral)
12
+ value = {:__amqp__ => '__promiscuous__/embedded_many',
13
+ :payload => value.map(&:promiscuous).map(&:payload)}
14
+ end
15
+ value
16
+ end
17
+ end
18
+
19
+ class PromiscuousMethods
20
+ include Promiscuous::Publisher::Model::Base::PromiscuousMethodsBase
21
+ include Promiscuous::Publisher::Model::Ephemeral::PromiscuousMethodsEphemeral
22
+ end
23
+
24
+ def initialize(attrs={})
25
+ self.id ||= 'none'
26
+ self.new_record = true
27
+ self.destroyed = false
28
+ attrs.each { |attr, value| __send__("#{attr}=", value) }
29
+ end
30
+
31
+ def save
32
+ operation = :create
33
+ operation = :update unless self.new_record
34
+ operation = :destroy if self.destroyed
35
+ promiscuous.sync(:operation => operation)
36
+ self.new_record = false
37
+ true
38
+ end
39
+ alias :save! :save
40
+
41
+ def update_attributes(attrs)
42
+ attrs.each { |attr, value| __send__("#{attr}=", value) }
43
+ save
44
+ end
45
+ alias :update_attributes! :update_attributes
46
+
47
+ def destroy
48
+ self.destroyed = true
49
+ save
50
+ end
51
+
52
+ def attributes
53
+ Hash[self.class.published_attrs.map { |attr| [attr, __send__(attr)] }]
54
+ end
55
+
56
+ module ClassMethods
57
+ def publish(*args)
58
+ super
59
+ published_attrs.each do |attr|
60
+ # TODO do not overwrite existing methods
61
+ attr_accessor attr
62
+ end
63
+ end
64
+
65
+ def create(attributes)
66
+ new(attributes).tap { |m| m.save }
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,61 @@
1
+ module Promiscuous::Publisher::Model::Mock
2
+ extend ActiveSupport::Concern
3
+ include Promiscuous::Publisher::Model::Ephemeral
4
+
5
+ included { class_attribute :mock_options }
6
+
7
+ def initialize(attrs={})
8
+ self.id = __get_new_id
9
+ super
10
+ end
11
+
12
+ def __get_new_id
13
+ if self.class.mock_options.try(:[], :id) == :bson
14
+ BSON::ObjectId.new
15
+ else
16
+ # XXX Not thread safe
17
+ @@next_id ||= 1
18
+ @@next_id += 1
19
+ end
20
+ end
21
+
22
+ class PromiscuousMethods
23
+ include Promiscuous::Publisher::Model::Base::PromiscuousMethodsBase
24
+ include Promiscuous::Publisher::Model::Ephemeral::PromiscuousMethodsEphemeral
25
+
26
+ def sync(options={}, &block)
27
+ payload = self.payload
28
+ payload[:operation] = options[:operation] || :update
29
+ Promiscuous::Subscriber::Worker::Message.new(MultiJson.dump(payload)).process
30
+ end
31
+ end
32
+
33
+ module ClassMethods
34
+ def publish_as
35
+ # The mocks are in the publisher's namespace, so we need to remove that.
36
+ @publish_as ||= ($2 if self.name =~ /^(.+)::Publishers::(.+)$/)
37
+ end
38
+
39
+ def mock(options={})
40
+ self.mock_options = options
41
+ end
42
+
43
+ def publish(*args, &block)
44
+ super
45
+
46
+ args.extract_options!
47
+ attributes = args
48
+ attr_accessor(*attributes)
49
+
50
+ # Hacks for associations on the factory
51
+ associations = attributes.map { |attr| $1 if attr =~ /^(.*)_id$/ }.compact
52
+ associations.each do |attr|
53
+ attr_accessor(attr)
54
+ define_method("#{attr}=") do |value|
55
+ instance_variable_set("@#{attr}", value)
56
+ instance_variable_set("@#{attr}_id", value.nil? ? value : value.id)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,129 +1,86 @@
1
1
  module Promiscuous::Publisher::Model::Mongoid
2
2
  extend ActiveSupport::Concern
3
+ include Promiscuous::Publisher::Model::Base
3
4
 
4
- class Commit
5
- attr_accessor :collection, :selector, :document, :operation
6
- def initialize(options={})
7
- self.collection = options[:collection]
8
- self.selector = options[:selector]
9
- self.document = options[:document]
10
- self.operation = options[:operation]
11
- end
5
+ mattr_accessor :collection_mapping
6
+ self.collection_mapping = {}
12
7
 
13
- def klass
14
- @klass ||= document.try(:[], '_type').try(:constantize) ||
15
- collection.singularize.camelize.constantize
16
- rescue NameError
17
- end
8
+ # We hook at the database driver level
9
+ require 'promiscuous/publisher/operation/mongoid'
10
+ included do
11
+ # Important for the query hooks (see ../operation/mongoid.rb)
12
+ # We want the root class when we do a collection name lookup
18
13
 
19
- def fetch
20
- case operation
21
- when :create then klass.new(document, :without_protection => true)
22
- when :update then klass.with(:consistency => :strong).where(selector).first
23
- when :destroy then klass.with(:consistency => :strong).where(selector).first
24
- end
14
+ root_class = self.collection.name.singularize.camelize.constantize
15
+ unless self == root_class
16
+ raise "Please include Promiscuous::Publisher in #{root_class} first (the root class)"
25
17
  end
26
18
 
27
- def commit(&block)
28
- return block.call unless klass
29
-
30
- # We bypass the call if instance == nil, the destroy or the update would
31
- # have had no effect
32
- instance = fetch
33
- return if instance.nil?
34
-
35
- return block.call unless instance.class.respond_to?(:promiscuous_publisher)
36
-
37
- self.selector = {:id => instance.id}
38
-
39
- publisher = instance.class.promiscuous_publisher
40
- publisher.new(:operation => operation,
41
- :instance => instance,
42
- :fetch_proc => method(:fetch)).commit(&block)
43
- end
19
+ Promiscuous::Publisher::Model::Mongoid.collection_mapping[self.collection.name] = self
44
20
  end
45
21
 
46
- module ModelInstanceMethods
47
- extend ActiveSupport::Concern
48
-
49
- def promiscuous_sync
50
- publisher = self.class.promiscuous_publisher
22
+ class PromiscuousMethods
23
+ include Promiscuous::Publisher::Model::Base::PromiscuousMethodsBase
51
24
 
52
- fetch_proc = proc { self.class.with(:consistency => :strong).where(atomic_selector).first }
25
+ def sync(options={}, &block)
26
+ raise "Use promiscuous.sync on the parent instance" if @instance.embedded?
27
+ super
28
+ end
53
29
 
54
- publisher.new(:operation => :update,
55
- :instance => self,
56
- :fetch_proc => fetch_proc).commit
30
+ def attribute(attr)
31
+ value = super
32
+ if value.is_a?(Array) &&
33
+ value.respond_to?(:ancestors) &&
34
+ value.ancestors.any? { |a| a == Promiscuous::Publisher::Model::Mongoid }
35
+ value = {:__amqp__ => '__promiscuous__/embedded_many',
36
+ :payload => value.map(&:promiscuous).map(&:payload)}
37
+ end
38
+ value
57
39
  end
58
40
  end
59
41
 
60
42
  module ClassMethods
61
- def setup_class_binding
43
+ # TODO DRY this up with the publisher side
44
+ def publish(*args, &block)
62
45
  super
63
- klass.__send__(:include, ModelInstanceMethods) if klass
64
- end
65
- end
46
+ return unless block
66
47
 
67
- def self.hook_mongoid
68
- Moped::Collection.class_eval do
69
- alias_method :insert_orig, :insert
70
- def insert(documents, flags=nil)
71
- documents = [documents] unless documents.is_a?(Array)
72
- documents.each do |doc|
73
- Promiscuous::Publisher::Model::Mongoid::Commit.new(
74
- :collection => self.name,
75
- :document => doc,
76
- :operation => :create
77
- ).commit do
78
- insert_orig(doc, flags)
79
- end
80
- end
48
+ begin
49
+ @in_publish_block = true
50
+ block.call
51
+ ensure
52
+ @in_publish_block = false
81
53
  end
82
54
  end
83
55
 
84
- Moped::Query.class_eval do
85
- alias_method :update_orig, :update
86
- def update(change, flags=nil)
87
- if flags && flags.include?(:multi)
88
- raise "Promiscuous: Do not use multi updates, update each instance separately"
89
- end
90
-
91
- Promiscuous::Publisher::Model::Mongoid::Commit.new(
92
- :collection => collection.name,
93
- :selector => selector,
94
- :operation => :update
95
- ).commit do
96
- update_orig(change, flags)
56
+ def self.publish_on(method, options={})
57
+ define_method(method) do |name, *args, &block|
58
+ super(name, *args, &block)
59
+ if @in_publish_block
60
+ name = args.last[:as] if args.last.is_a?(Hash) && args.last[:as]
61
+ publish(name)
97
62
  end
98
63
  end
64
+ end
99
65
 
100
- alias_method :modify_orig, :modify
101
- def modify(change, options={})
102
- Promiscuous::Publisher::Model::Mongoid::Commit.new(
103
- :collection => collection.name,
104
- :selector => selector,
105
- :operation => :update
106
- ).commit do
107
- modify_orig(change, options)
108
- end
109
- end
66
+ publish_on :field
67
+ publish_on :embeds_one
68
+ publish_on :embeds_many
110
69
 
111
- alias_method :remove_orig, :remove
112
- def remove
113
- Promiscuous::Publisher::Model::Mongoid::Commit.new(
114
- :collection => collection.name,
115
- :selector => selector,
116
- :operation => :destroy
117
- ).commit do
118
- remove_orig
119
- end
120
- end
70
+ def promiscuous_collection_name
71
+ self.collection.name
72
+ end
121
73
 
122
- alias_method :remove_all_orig, :remove_all
123
- def remove_all
124
- raise "Promiscuous: Do not use delete_all, use destroy_all"
74
+ def get_operation_class_for(operation)
75
+ if operation == :create
76
+ Moped::PromiscuousCollectionWrapper::PromiscuousCollectionOperation
77
+ else
78
+ Moped::PromiscuousQueryWrapper::PromiscuousQueryOperation
125
79
  end
126
80
  end
81
+
82
+ def promiscuous_missing_record_exception
83
+ Mongoid::Errors::DocumentNotFound
84
+ end
127
85
  end
128
- hook_mongoid
129
86
  end