Exception: Promiscuous::Error::Dependency
- Defined in:
- lib/promiscuous/error/dependency.rb
Instance Attribute Summary collapse
-
#dependency_solutions ⇒ Object
Returns the value of attribute dependency_solutions.
-
#operation ⇒ Object
Returns the value of attribute operation.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ Dependency
constructor
A new instance of Dependency.
-
#message ⇒ Object
(also: #to_s)
TODO Convert all that with Erb.
Constructor Details
#initialize(options = {}) ⇒ Dependency
Returns a new instance of Dependency.
4 5 6 |
# File 'lib/promiscuous/error/dependency.rb', line 4 def initialize(={}) self.operation = [:operation] end |
Instance Attribute Details
#dependency_solutions ⇒ Object
Returns the value of attribute dependency_solutions.
2 3 4 |
# File 'lib/promiscuous/error/dependency.rb', line 2 def dependency_solutions @dependency_solutions end |
#operation ⇒ Object
Returns the value of attribute operation.
2 3 4 |
# File 'lib/promiscuous/error/dependency.rb', line 2 def operation @operation end |
Class Method Details
.explain_operation(operation, limit = 100) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/promiscuous/error/dependency.rb', line 78 def self.explain_operation(operation, limit=100) instance = operation.instance selector = instance ? get_selector(instance.attributes, limit) : "" class_name = instance ? instance.class : "Unknown" if operation.operation == :create "#{instance.class}.create(#{selector})" else case operation.operation_ext || operation.operation when :count then verb = 'count' when :mapreduce then verb = 'mapreduce(...)' when :read then verb = operation.multi? ? 'each { ... }' : 'first' when :update then verb = operation.multi? ? 'update_all' : 'update' when :destroy then verb = operation.multi? ? 'delete_all' : 'delete' end msg = "#{class_name}#{selector.present? ? ".where(#{selector})" : ""}.#{verb}" if operation.operation == :update && operation.respond_to?(:change) && operation.change msg += "(#{get_selector(operation.change, limit)})" end if operation.operation == :commit msg = "Transaction commit" end msg end end |
.get_selector(attributes, limit = 100) ⇒ Object
106 107 108 109 110 111 112 113 |
# File 'lib/promiscuous/error/dependency.rb', line 106 def self.get_selector(attributes, limit=100) # TODO ActiveRecord? attributes = attributes['$set'] if attributes.count == 1 && attributes['$set'] attributes.reject! { |k,v| v.nil? } selector = attributes.map { |k,v| ":#{k} => #{v}" }.join(", ") selector = "#{selector[0...(limit-3)]}..." if selector.size > limit selector end |
Instance Method Details
#message ⇒ Object Also known as: to_s
TODO Convert all that with Erb
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/promiscuous/error/dependency.rb', line 10 def msg = nil case operation.operation when :read msg = "Promiscuous doesn't have any tracked dependencies to perform this multi read operation.\n" + "This is what you can do:\n\n" + " 1. Bypass Promiscuous\n\n" + " If you don't use the result of this operation in your following writes,\n" + " you can wrap your read query in a 'without_promiscuous { }' block.\n" + " This is the preferred solution when you are sure that the read doesn't\n" + " influence the value of a published attribute.\n\n" + " Rule of thumb: Predicates (methods ending with ?) are often suitable for this use case.\n\n" cnt = 2 if operation.operation_ext != :count msg += " #{cnt}. Synchronize on individual instances\n\n" + " If the collection you are iterating through is small (<10), it becomes intersting\n" + " to track instances through their ids instead of the query selector. Example:\n\n" + " criteria.without_promiscuous.each do |doc|\n" + " next if doc.should_do_something?\n" + " doc.reload # tell promiscuous to track the instance\n" + " doc.do_something!\n" + " end\n\n" cnt += 1 end if operation.selector_keys.present? msg += " #{cnt}. Track New Dependencies\n\n" + " Add #{operation.selector_keys.count == 1 ? "the following line" : "one of the following lines"} " + "in the #{operation.instance.class} model:\n\n" + " class #{operation.instance.class}\n" + operation.selector_keys.map { |field| " track_dependencies_of :#{field}" }.join("\n") + "\n" + " end\n\n" + (operation.selector_keys.count > 1 ? " The more specific field, the better. Promiscuous works better when working with small subsets\n" + " For example, tracking something like 'member_id' is a fairly safe choice.\n\n" : "") + " Note that dependency tracking slows down your writes. It can be seen as the analogous\n" + " of an index on a regular database.\n" + " You may find more information about the implications in the Promiscuous wiki (TODO:link).\n\n" end when :update msg = "Promiscuous cannot track dependencies of a multi update operation.\n" + "This is what you can do:\n\n" + " 1. Instead of doing a multi updates, update each instance separately\n\n" + " 2. Do not assign has_many associations directly, but use the << operator instead.\n\n" when :destroy msg = "Promiscuous cannot track dependencies of a multi delete operation.\n" + "This is what you can do:\n\n" + " 1. Instead of doing a multi delete, delete each instance separatly.\n\n" + " 2. Use destroy_all instead of destroy_all.\n\n" + " 3. Declare your has_many relationships with :dependent => :destroy instead of :delete.\n\n" end msg += "#{"-" * 100}\n\n" msg += "Promiscuous cannot allow the following " case operation.operation_ext || operation.operation when :count then msg += 'count' when :mapreduce then msg += 'mapreduce' when :read then msg += 'each loop' when :update then msg += 'multi update' when :destroy then msg += 'multi destroy' end msg += " #{self.class.explain_operation(self.operation)}" msg += "\n\nProTip: Try again with TRACE=2 in the shell or ENV['TRACE']='2' in the console.\n" unless ENV['TRACE'] msg rescue Exception => e "#{e}\n#{e.backtrace.join("\n")}" end |