Forum: Ruby on Rails Dead horse: validates_associated

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
8493b7fca6ae697dfc7fe7d1aa4a3125?d=identicon&s=25 Jake J. (janovetz)
on 2006-06-13 21:04
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
Nick Stuart (Guest)
on 2006-06-13 22:03
(Received via mailing list)
Go here, and look at the if option
http://api.rubyonrails.com/classes/ActiveRecord/Va...

-Nick
8493b7fca6ae697dfc7fe7d1aa4a3125?d=identicon&s=25 Jake J. (janovetz)
on 2006-06-13 22:07
Nick Stuart wrote:
> Go here, and look at the if option
> http://api.rubyonrails.com/classes/ActiveRecord/Va...
>
> -Nick

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

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


Jake
Kevin Olbrich (Guest)
on 2006-06-13 22:23
(Received via mailing list)
On Tuesday, June 13, 2006, at 9:04 PM, Jake Janovetz 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
>Rails@lists.rubyonrails.org
>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
8493b7fca6ae697dfc7fe7d1aa4a3125?d=identicon&s=25 Jake J. (janovetz)
on 2006-06-13 22:28
Kevin Olbrich 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
Kevin Olbrich (Guest)
on 2006-06-13 22:48
(Received via mailing list)
On Tuesday, June 13, 2006, at 10:28 PM, Jake Janovetz wrote:
>has_many and belongs_to setups.  And other things are wrong if it gets
>Rails mailing list
>Rails@lists.rubyonrails.org
>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
8493b7fca6ae697dfc7fe7d1aa4a3125?d=identicon&s=25 Jake J. (janovetz)
on 2006-06-13 23:00
Kevin Olbrich 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.
This topic is locked and can not be replied to.