There are some small issues with the current nested attributes and
autosave implementation that I would like to address until Rails 3.
1) The first one was already dissused on the mailing list, which is
the use of "_delete" in accepts_nested_attributes_for when both the
DSL (:allow_destroy) and the behavior are destroy. I've created a
patch that just checks for _destroy instead of _delete with backwards
compatibility.
https://rails.lighthouseapp.com/projects/8994/tickets/2889
This is to avoid confusion and open room for more improvements in the
future.
2) How messages are created with nested attributes are hard to
translate and does not work for other languages. For instance:
model_name + " " + attribute_name + " " + message
Is not grammatically correct in portuguese and japanese. There is a
ticket about it on Lighthouse:
https://rails.lighthouseapp.com/projects/8994/tickets/2210
Although the ticket does not solve the whole problem. It only deals
with attributes at the beginning of the message, but not with the
errors messages. For instance, when you have a project which has many
tasks, it will search for messages at:
+
activerecord.errors.messages.project.tasks.name
And it does not fallback to:
+
activerecord.errors.messages.task.name
So if I customize the error message, I will have to do that in two
places.
3) Another problem that has bitten me frequently when using autosave
is that I don't want error messages to be copied to the parent when
I'm giving both parent and child to error_messages_for. For that, I
usually need to create an after_validate callback that delete the
messages in the parent:
def after_validate
self.errors.each do |key, value|
next unless key.to_s =~ /child_/
self.errors.instance_variable_get('@errors').delete(key)
end
end
Right now, we deal with parent-child errors in two ways:
+ We copy the child errors to the parent (default for autosave);
+ We add an error to the parent saying that the child is invalid
(default for validate => true);
I would like to add a third one:
+ Do nothing with the error messages;
The patch would be simple, the tricky is how the DSL is going to be. A
suggestion (which definitely needs improvement):
has_many :tasks, :validate => :copy_errors # copy all messages
to the parent
has_many :account, :validate => true # add one message
that the parent is invalid
has_one :account, :validate => :skip_errors # validate but skip
the error messages
has_one :account, :validate => false # does not
validate
I already have a patch for (1), working on another patch for (2) and
would like to have some discussion on the DSL for (3) before working
on it.
What are your thoughts?