Dead horse: validates_associated


#1

Regarding validates_associated…

Let’s say I have:
article belongs_to author
But for whatever reason, I want an article to also be written
anonymously and therefore not require an author. Then I have:

Article:
belongs_to :author
validates_associated :author

But I DON’T have validates_presence_of. What I want to do is validate
that an author is valid --if it is specified–.

  • I want to allow for the case where article.author_id = nil.
  • I DO NOT want to allow for the case where article.author_id =
    SOME_INVALID_ID

During testing, I tried this:
article = Article.new
article.author_id = nil
assert c.valid? (True – working so far)
article.author_id = 5
assert c.valid? (True – because author 5 is valid)
article.author_id = 999
assert c.valid? (True!?! – shouldn’t be!)

So, how can one protect for the case where the associated link doesn’t
refer to an existing database row at all?

Can someone give me an example of a successful use of
validates_associated that is NOT coupled to validates_presence_of?
Afterall, it seems quite pointless to have validates_associated if it
returns true for an object that isn’t even in the database.

Jake


#2

Go here, and look at the if option
http://api.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html#M000820

-Nick


#3

Nick S. wrote:

Go here, and look at the if option
http://api.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html#M000820

-Nick

Yes, I considered that. Are you suggesting something like:

validates_presence_of :article, :if => Proc.new { |c|
!c.article_id.nil? }

Jake


#4

On Tuesday, June 13, 2006, at 9:04 PM, Jake J. wrote:

assert c.valid? (True – working so far)
Afterall, it seems quite pointless to have validates_associated if it
returns true for an object that isn’t even in the database.

Jake


Posted via http://www.ruby-forum.com/.


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

Oddly enough, I just encounted that problem myself. I am in the process
of testing a plugin that fixes the behavior of validates_associated so
that it detects invalid entries…

Here it is… should work in most cases, but I haven’t completely tested
it. YMMV.

from the console,
script/generate plugin validates_associated
put this in the lib folder and then add
require ‘validates_associated’ in the init.rb file.
Restart your server and you’re off.

module ActiveRecord
module Validations
module ClassMethods

  # Checks associated object to ensure validity according to

ActiveRecord standards
# Will not fail if the association is not defined, use
validates_presence_of to ensure
# a foreign key exists, if necessary. This validation will fail
if an associated object is invalid
# or if a foreign key points to a non-existent record.
def validates_associated(*attr_names)
configuration = { :message =>
ActiveRecord::Errors.default_error_messages[:invalid], :on => :save }
configuration.update(attr_names.pop) if
attr_names.last.is_a?(Hash)

     validates_each(attr_names, configuration) do |record,

attr_name, value|
reflection = self.reflect_on_association(attr_name)
if reflection.macro == :belongs_to
class_to_check = reflection.options[:polymorphic] ?
record.send(reflection.options[:foreign_type]).constantize :
reflection.active_record
unless record.send(reflection.primary_key_name).blank? &&
class_to_check.exists?(record.send(reflection.primary_key_name))
record.errors.add(attr_name,configuration[:message])
end
end
record.errors.add(attr_name, configuration[:message]) unless
(value.is_a?(Array) ? value : [value]).all? { |r| r.nil? or
r.valid? }
end
end
end
end
end

_Kevin


#5

Kevin O. wrote:

Oddly enough, I just encounted that problem myself. I am in the process
of testing a plugin that fixes the behavior of validates_associated so
that it detects invalid entries…

Here it is… should work in most cases, but I haven’t completely tested
it. YMMV.

Thanks Kevin. I may use the plugin. Really, it was a safety measure –
afterall, my “invalid entries” should have been deleted with proper
has_many and belongs_to setups. And other things are wrong if it gets
to this point.

I’m still curious – was the original behavior to be expected? Was this
how Rails was designed? If so, is there a reason for it?

Jake


#6

Kevin O. wrote:

My personal spin on this is that the association should be invalid IF
the associated record is invalid AND if the association link is invalid.

In most cases, it won’t be an issue because active record is pretty good
at cleaning up after itself, but you never know. This is kind of a
belt-and-suspenders type of patch. It’s more likely to show up as a
problem during development than in live code.

_Kevin

Yes. I completely agree.


#7

On Tuesday, June 13, 2006, at 10:28 PM, Jake J. wrote:

has_many and belongs_to setups. And other things are wrong if it gets
Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

Incidentally, here’s the ticket I opened on this recently.
http://dev.rubyonrails.org/ticket/5369

The original behavior is to flag an association as invalid IF and ONLY
IF the associated object is invalid (via activerecord). If there is no
associated record, it is not flagged as invalid. If the foreign key is
invalid, it won’t trigger either.

My personal spin on this is that the association should be invalid IF
the associated record is invalid AND if the association link is invalid.

In most cases, it won’t be an issue because active record is pretty good
at cleaning up after itself, but you never know. This is kind of a
belt-and-suspenders type of patch. It’s more likely to show up as a
problem during development than in live code.

_Kevin