simply_stored 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
1
  Changelog
2
2
  =============
3
3
 
4
+ 0.6.2
5
+
6
+ - Decorate conflict exceptions with information about the conflict
7
+
4
8
  0.6.1
5
9
 
6
10
  - Fix warning of dynamically created views to point to the correct called
@@ -77,34 +77,57 @@ module SimplyStored
77
77
  def retry_on_conflict(max_retries = 2, &blk)
78
78
  retry_count = 0
79
79
  begin
80
+ _reset_conflict_information
80
81
  blk.call
81
82
  rescue RestClient::Exception, RestClient::Conflict => e
82
83
  if (e.http_code == 409 || e.is_a?(RestClient::Conflict)) && self.class.auto_conflict_resolution_on_save && retry_count < max_retries && try_to_merge_conflict
83
84
  retry_count += 1
84
85
  retry
85
86
  else
87
+ _decorate_with_conflict_details(e) if e.is_a?(RestClient::Conflict)
86
88
  raise e
87
89
  end
88
90
  end
89
91
  end
90
-
92
+
93
+ def _decorate_with_conflict_details(exception)
94
+ if @_conflict_information.present?
95
+ def exception.metaclass
96
+ class << self
97
+ self
98
+ end
99
+ end
100
+ local_conflict_information = @_conflict_information
101
+ exception.metaclass.send(:define_method, :message){ "409 Conflict - conflict on attributes: #{local_conflict_information.inspect}" }
102
+ end
103
+ end
104
+
91
105
  def try_to_merge_conflict
92
106
  original = self.class.find(id)
93
107
  our_attributes = self.attributes.dup
94
108
  their_attributes = original.attributes.dup
95
- [:updated_at, :created_at, :id, :rev, :_id, :_rev].each do |skipped_attribute|
96
- our_attributes.delete(skipped_attribute)
97
- their_attributes.delete(skipped_attribute)
98
- end
109
+ _clear_non_relevant_attributes(our_attributes)
110
+ _clear_non_relevant_attributes(their_attributes)
99
111
  if _merge_possible?(our_attributes, their_attributes)
100
112
  _copy_non_conflicting_attributes(our_attributes, their_attributes)
101
113
  self._rev = original._rev
102
114
  true
103
115
  else
116
+ @_conflict_information = _conflicting_attributes(our_attributes, their_attributes)
104
117
  false
105
118
  end
106
119
  end
107
-
120
+
121
+ def _reset_conflict_information
122
+ @_conflict_information = nil
123
+ end
124
+
125
+ def _clear_non_relevant_attributes(attr_list)
126
+ [:updated_at, :created_at, :id, :rev, :_id, :_rev].each do |skipped_attribute|
127
+ attr_list.delete(skipped_attribute)
128
+ end
129
+ end
130
+
108
131
  def _copy_non_conflicting_attributes(our_attributes, their_attributes)
109
132
  their_attributes.each do |attr_name, their_value|
110
133
  if !self.send("#{attr_name}_changed?") && our_attributes[attr_name] != their_value
@@ -114,13 +137,21 @@ module SimplyStored
114
137
  end
115
138
 
116
139
  def _merge_possible?(our_attributes, their_attributes)
117
- their_attributes.all? do |attr_name, their_value|
118
- our_attributes[attr_name] == their_value || # same
119
- !self.send("#{attr_name}_changed?") || # we didn't change
120
- self.send("#{attr_name}_changed?") && their_value == self.send("#{attr_name}_was") # we changed and they kept the original
140
+ _conflicting_attributes(our_attributes, their_attributes).empty?
141
+ end
142
+
143
+ def _conflicting_attributes(our_attributes, their_attributes)
144
+ their_attributes.keys.delete_if do |attr_name|
145
+ _attribute_not_in_conflict?(attr_name, our_attributes[attr_name], their_attributes[attr_name])
121
146
  end
122
147
  end
123
-
148
+
149
+ def _attribute_not_in_conflict?(attr_name, our_value, their_value)
150
+ our_value == their_value || # same
151
+ !self.send("#{attr_name}_changed?") || # we didn't change
152
+ self.send("#{attr_name}_changed?") && their_value == self.send("#{attr_name}_was") # we changed and they kept the original
153
+ end
154
+
124
155
  def reset_association_caches
125
156
  self.class.properties.each do |property|
126
157
  if property.respond_to?(:association?) && property.association?
data/lib/simply_stored.rb CHANGED
@@ -5,7 +5,7 @@ unless defined?(SimplyStored)
5
5
  require File.expand_path(File.dirname(__FILE__) + '/simply_stored/class_methods_base')
6
6
 
7
7
  module SimplyStored
8
- VERSION = '0.6.1'
8
+ VERSION = '0.6.2'
9
9
  class Error < RuntimeError; end
10
10
  class RecordNotFound < RuntimeError; end
11
11
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simply_stored
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
4
+ hash: 3
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 1
10
- version: 0.6.1
9
+ - 2
10
+ version: 0.6.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Mathias Meyer, Jonathan Weiss
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-06 00:00:00 Z
18
+ date: 2011-08-07 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  version_requirements: &id001 !ruby/object:Gem::Requirement