How do I validate a virtual attribute in an ActiveRecord model?

activerecord, ruby-on-rails, validation, virtual-attribute

Solution

If you haven't ruled it out already, I'd take a look at using `validates_associated`.

Problem

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 a `Tag` object for each name and check `t.valid?`? Would I somehow collect validation error messages from `Tag` or generate them? - I'm not sure if this is even the right way to do this sort of validation. Any suggestions?

Original source