Rails: Why does failing validate_uniqeness still allow save?
-- Question rewritten based on further testing --
So, my app has_many Folders which belong_to Collections. Folders are nested, they can also belong_to another Folder.
I want to validate uniqueness of the folder names within each collection. When I create folders at the top level this works, but when I create it in lower levels it does not work. Here are the models:
class Folder < ActiveRecord::Base
# CALLBACKS
before_create :associate_collection
# RELATIONSHIPS
belongs_to :collection
belongs_to :parent, :class_name => 'Folder'
has_many :subfolders, :开发者_Python百科class_name => 'Folder', :foreign_key => :parent_id
# VALIDATIONS
validates_presence_of :name
validates_uniqueness_of :name, :scope => :collection_id
private
def associate_collection
if self.collection.nil?
self.collection = self.parent.collection
end
end
end
class Collection < ActiveRecord::Base
# RELATIONSHIPS
has_one :root_folder, :class_name => 'Folder', :conditions => { :parent_id => nil }
has_many :folders
# CALLBACKS
after_create :setup_root_folder
private
def setup_root_folder
self.create_root_folder(:name=>'Collection Root')
self.save!
end
end
Here's an abridged example of what happens in the console:
c = Collection.new(:name=>'ExampleCollection')
#<Collection id: 1>
root = c.root_folder
#<Folder id: 1, collection_id: 1>
f1 = root.subfolders.create(:name=>'Test')
#<Folder id: 2 collection_id: 1>
f1.valid?
# TRUE
f2 = root.subfolders.create(:name=>'Test')
#<Folder id: 3 collection_id: 1>
f2.valid?
# FALSE
f1.valid?
# FALSE
So, while the collection is being associated with a subfolder correctly, its not triggering the validations correctly until after it's saved.
Suggestions?
The only way I can think to explain it is that the validation is being called before the collection_id is assigned, due to the syntax you are using. Maybe try
Folder.create(:collection => @collection, :name => 'example')
and see if it changes anything.
Doh.
My associate_collection
callback needs to happen before_validation
, not before_create
.
Fixed. Thanks for looking guys!
精彩评论