uniqueness validation raises error for persisted record without pk.

Closes #21304.

While we can validate uniqueness for record without primary key on
creation, there is no way to exclude the current record when
updating. (The update itself will need a primary key to work correctly).
This commit is contained in:
Yves Senn 2015-08-20 12:07:02 +02:00
parent 013dd756e1
commit 50e4afff20
4 changed files with 39 additions and 4 deletions

@ -1,3 +1,10 @@
* Uniqueness validator raises descriptive error when running on a persisted
record without primary key.
Closes #21304.
*Yves Senn*
* Add a native JSON data type support in MySQL.
Example:

@ -218,11 +218,12 @@ def initialize(errors)
class UnknownPrimaryKey < ActiveRecordError
attr_reader :model
def initialize(model)
super("Unknown primary key for table #{model.table_name} in model #{model}.")
def initialize(model, description = nil)
message = "Unknown primary key for table #{model.table_name} in model #{model}."
message += "\n#{description}" if description
super(message)
@model = model
end
end
# Raised when a relation cannot be mutated because it's already loaded.

@ -18,7 +18,11 @@ def validate_each(record, attribute, value)
relation = build_relation(finder_class, table, attribute, value)
if record.persisted? && finder_class.primary_key.to_s != attribute.to_s
relation = relation.where.not(finder_class.primary_key => record.id)
if finder_class.primary_key
relation = relation.where.not(finder_class.primary_key => record.id)
else
raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
end
end
relation = scope_relation(record, table, relation)
relation = relation.merge(options[:conditions]) if options[:conditions]

@ -4,6 +4,7 @@
require 'models/warehouse_thing'
require 'models/guid'
require 'models/event'
require 'models/dashboard'
class Wizard < ActiveRecord::Base
self.abstract_class = true
@ -446,4 +447,26 @@ def self.name
key2.key_number = 10
assert_not key2.valid?
end
def test_validate_uniqueness_without_primary_key
klass = Class.new(ActiveRecord::Base) do
self.table_name = "dashboards"
validates_uniqueness_of :dashboard_id
def self.name; "Dashboard" end
end
abc = klass.create!(dashboard_id: "abc")
assert klass.new(dashboard_id: "xyz").valid?
assert_not klass.new(dashboard_id: "abc").valid?
abc.dashboard_id = "def"
e = assert_raises ActiveRecord::UnknownPrimaryKey do
abc.save!
end
assert_match(/\AUnknown primary key for table dashboards in model/, e.message)
assert_match(/Can not validate uniqueness for persisted record without primary key.\z/, e.message)
end
end