I am using virtual attributes to save tags in an Entry model from a comma-separated textbox in my form (based on Railscasts #167):
class Entry < ActiveRecord::Base
has_many :entry_tags
has_many :tags, :through => :entry_tags
after_save :update_tags
attr_writer :tag_names
def tag_names
tags.map(&:name).join(", ")
end
def update_tags
if @tag_names
self.tags = @tag_names.split(",").map do |name|
Tag.find_or_create_by_name(name.strip)
end
end
end
private :update_tags
end
I want to add validation on my Tag names, but I'm not sure what the best way to do that would be. I have an existing validation method defined in the Tag model:
class Tag < ActiveRecord::Base
has_many :entry_tags
has_many :entries, :through => :entry_tags
validates_uniqueness_of :name
validates_format_of :name, :with => /\A[a-z0-9_ -]*\Z/, :on => :create
end
However, because the update_tags
method is being called after save, any validation errors from the create would be after the Entry is already saved.
I'm thinking about creating a validation method within the Entry model and calling that on entry save, but:
- If I do that, I'm not sure what the best way to do the validation would be. Do I create my own validation within
Entry
or create aTag
object for each name and checkt.valid?
? Would I somehow collect validation error messages fromTag
or generate them? - I'm not sure if this is even the right way to do this sort of validation.
Any suggestions?