Forum: Ruby on Rails conditional validates_associated

Posted by Rafael C. de Almeida (Guest)
on 2013-02-13 02:31
(Received via mailing list)
Hello,

Have you guys noticed that conditional validation with 
validates_associated
does not work well when you are creating a new record?

Consider this gist: https://gist.github.com/aflag/4780225

The Lawyer class has validates_associated on address conditioned on 
whether
the Lawyer data comes from a known source or not. So, if lawyer.source
equals to some string, then lawyer.address must not be validated. 
However,
if I'm trying to create a new record, it is validated regardless of 
whether
source is nil or not. Is it expected to behave like that? Is that a bug?

Cheers,
Rafael
Posted by Matt Jones (Guest)
on 2013-02-13 16:00
(Received via mailing list)
On Tuesday, 12 February 2013 20:29:49 UTC-5, Rafael C. de Almeida wrote:
> lawyer.source equals to some string, then lawyer.address must not be
> validated. However, if I'm trying to create a new record, it is validated
> regardless of whether source is nil or not. Is it expected to behave like
> that? Is that a bug?
>
>
The behavior is intentional, though perhaps not documented as well as it
should be. It has to do with the autosave behavior for has_many on new
records - the part that enables you to build a new record, add some 
unsaved
child records (phones, etc in your example) and then save the parent 
object
and get all the others saved as well.

You should be able to turn off this validation by passing 'validate: 
false'
to your has_many associations as needed.

--Matt Jones
Posted by Rafael C. de Almeida (Guest)
on 2013-02-13 21:43
(Received via mailing list)
On Wednesday, February 13, 2013 12:59:11 PM UTC-2, Matt Jones wrote:
>> The Lawyer class has validates_associated on address conditioned on
> child records (phones, etc in your example) and then save the parent object
> and get all the others saved as well.
>

I see. Thank you for the clarification. However, isn't that behavior
counter-intuitive? Why should "valid?" return a different thing 
depending
on whether a nested model is saved or not? If you want to skip the
validation of one nested model, but still validate other things, then 
your
only option is doing something like:

    object.save validate:false
    object.reload
    object.valid? || object.delete

That also has the potential problem of leaving some of the nested model
data behind in the database.

Maybe there's some gem that changes that behavior. Anyhow, at least now 
I
know what's going on, I can come up with a workaround.

Cheers,
Rafael
Posted by Matt Jones (Guest)
on 2013-02-14 17:50
(Received via mailing list)
On Wednesday, 13 February 2013 15:41:49 UTC-5, Rafael C. de Almeida 
wrote:
>>> Consider this gist: https://gist.github.com/aflag/4780225
>> should be. It has to do with the autosave behavior for has_many on new
>
Better option: don't save records to the DB that are invalid. That's
typically considered a bad thing, so Rails makes it hard to do.

I'd recommend extending the "extracted?" method into your related 
models:

class Lawyer < ActiveRecord::Base
  has_many :phones, :inverse_of => :lawyer

...
end

class Phone < ActiveRecord::Base

  belongs_to :lawyer, :inverse_of => :phones

  validates_something_of :foo, :if => :extracted?

  def extracted?
    lawyer.extracted?
  end
end

This has the advantage of making the validations you want to skip
*explicit* (they get the :if => :extracted? condition) instead of just
skipping them entirely when needed.

--Matt Jones
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.