lib/unique_attributes.rb in unique_attributes-0.1.0 vs lib/unique_attributes.rb in unique_attributes-0.1.2
- old
+ new
@@ -62,10 +62,12 @@
blank_attrs = blank_unique_attributes
# If we have blank unique attributes.
if blank_attrs.size > 0
attempts = 0
+ attr_group = "(?<attr>#{blank_attrs.keys.join('|')})"
+ other_fields = "(, [\\w`'\".]+)*"
# Keep retrying until the save works.
while !self.persisted?
attempts += 1 # Keep track of the number of times we've tried to save.
@@ -75,28 +77,32 @@
begin
ActiveRecord::Base.transaction(requires_new: true) do
yield # Perform the save, and see if it works.
end
rescue ActiveRecord::RecordNotUnique => error
- attr_group = "(?<attr>#{blank_attrs.keys.join('|')})"
- other_fields = "(, [\\w`'\"]+)*"
- sqlite3_regex = /column(s)? #{attr_group}#{other_fields} (is|are) not unique/
- postgresql_regex = /Key \(#{attr_group}#{other_fields}\)=\([\w\s,]*\) already exists/
+ if attempts <= SAVE_ATTEMPTS_LIMIT
+ match = [
+ # Postgres
+ /Key \(#{attr_group}#{other_fields}\)=\([\w\s,]*\) already exists/,
+ # SQLite
+ /column(s)? #{attr_group}#{other_fields} (is|are) not unique/,
+ /UNIQUE constraint failed: #{self.class.table_name}\.#{attr_group}#{other_fields}:/
+ ].inject(nil) { |m, regex| m || regex.match(error.message) }
- match = sqlite3_regex.match(error.message) ||
- postgresql_regex.match(error.message)
-
- # If we've managed to hit the same unique attribute of a record
- # already in the database, then we should wipe the attribute and try
- # again, unless we've already done this many times in which case we
- # should let the error bubble up.
- if match && attempts <= SAVE_ATTEMPTS_LIMIT
- attr = match[:attr].to_sym
- blank_attrs = { attr => blank_attrs[attr] }
- write_attribute(attr, nil)
- else
- raise error # If something else went wrong, let it propagate.
+ # If we've managed to hit the same unique attribute of a record
+ # already in the database, then we should wipe the attribute and
+ # try again
+ if match
+ attr = match[:attr].to_sym
+ blank_attrs = { attr => self.class.unique_attributes[attr] }
+ write_attribute(attr, nil)
+ next
+ end
end
+
+ # If we're already at the attempts limit, or some other attribute
+ # was the problem, let the error propagate.
+ raise error
end
end
else # If the unique values are already set, perform a regular save.
yield
end