I have an Entry
model which has many Tag
s. Tag
s are added to an entry by typing them into a textbox on my form, via a tag_names
virtual attribute. Before validation on the Entry
model, the tag_names string is converted into actual Tag
objects using find_or_create_by_name
. The Tag
model also has validation to make sure the tag name matches a regex, which is run via the association.
My Entry model looks like this:
class Entry < ActiveRecord::Base
has_many :entry_tags
has_many :tags, :through => :entry_tags
before_validation :update_tags
attr_writer :tag_names
private
def update_tags
if @tag_names
self.tags = @tag_names.split(",").uniq.map do |name|
Tag.find_or_create_by_name(name.strip)
end
end
end
end
When I create a new Entry
object and assign it tags, everything works correctly -- the tags are not saved if there is a validation error on one of the Tag
s, and an error message is passed back. However, if I try to update an existing Entry object with an invalid tag, instead of passing back a message, my self.tags=
call (in update_tags
above) is throwing an exception with the validation error message. Even if I overwrite find_or_create_by_name
to actually just return a new object instead of calling create
, I get the same outcome.
It seems to me (and the docs seem to corroborate) that the tags=
call is actually saving my Tag
objects before the main record gets saved when the Entry
object already exists. Is there anything I can do to make this save not happen, or to stop it from raising an exception and just causing my save to return false?