Forum: Ruby on Rails Validation performed on has_many associations before updatin

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.
3ddf2897026370c1b869159ba19124ec?d=identicon&s=25 Ian Leitch (Guest)
on 2007-07-13 11:36
(Received via mailing list)
Hi,

I have a Campaign model which has_many :condition_sets. The ConditionSet
belongs_to :campaign and also validates_presence_of :campaign_id

Now, If I...

>> c = Campaign.new
>> s = c.condition_sets.build
>> c.save!
ActiveRecord::RecordInvalid: Validation failed: Condition sets is
invalid
>> s.errors.full_messages
=> ["Campaign can't be blank"]

I'd expect Rails to set the campaign_id foreign key _before_ performing
validation on the ConditionSet, right?

Removing the validates_presence_of :campaign_id lets the campaign save..

>> c = Campaign.new
>> s = c.condition_sets.build
>> c.save!
>> s.campaign
=> #<Campaign id: 1, created_at: "2007-07-13 09:20:08", updated_at:
"2007-07-13 09:20:08">

Am I just being dumb???

=========

Ruby version                 1.8.6 (i686-darwin8.10.1)
RubyGems version             0.9.4
Rails version                1.2.3
Active Record version        1.15.3
Action Pack version          1.13.3
Action Web Service version   1.2.3
Action Mailer version        1.3.3
Active Support version       1.4.2
Edge Rails revision          436
Application root             /Users/ian/Projects/systino/trunk
Environment                  development
Database adapter             mysql
Database schema version      64
C64e63b70be7dfed8b0742540b8b27e5?d=identicon&s=25 Mark Reginald James (Guest)
on 2007-07-13 12:15
(Received via mailing list)
Ian Leitch wrote:

> => ["Campaign can't be blank"]
>
> I'd expect Rails to set the campaign_id foreign key _before_ performing
> validation on the ConditionSet, right?

campaign_id can't be set before it's validated because it is unknown
until the campaign is saved, and validation is designed to prevent
anything being saved unless the whole object hierarchy is valid.

The usual solution is:

    class ConditionSet
      validates_presence_of :campaign # Checks for valid object or fk
    end
    c = Campaign.new
    s = c.condition_sets.build
    s.campaign = c # Currently not set automatically by Rails
    c.save!

--
We develop, watch us RoR, in numbers too big to ignore.
3ddf2897026370c1b869159ba19124ec?d=identicon&s=25 Ian Leitch (Guest)
on 2007-07-13 16:51
(Received via mailing list)
Thanks Mark, it seems pretty obvious now you've pointed it out.

I'm having a similar problem with a has_one association this time but
applying what I've learned here doesn't seem to work. To confuse me even
more, the parent has_one association works fine.

Here is some debug of what my app is doing..

BUILD Incentive::ConditionSet#build_promoter
ASSIGN Incentive::ConditionSet#promoter <= Incentive::PromoterCondition
ASSIGN FOREIGN Incentive::PromoterCondition#condition_set <=
Incentive::ConditionSet
================================================================================
BUILD Incentive::PromoterCondition#build_order
ASSIGN Incentive::PromoterCondition#order <= Incentive::OrderCondition
ASSIGN CONDITIONABLE FOREIGN
Incentive::OrderCondition#order_conditionable
<= Incentive::PromoterCondition
================================================================================
BUILD Incentive::OrderCondition#build_order_value
ASSIGN Incentive::OrderCondition#order_value <=
Incentive::OrderValueCondition
ASSIGN FOREIGN Incentive::OrderValueCondition#order <=
Incentive::OrderCondition

ConditionSet, PromoterCondition and OrderCondition all save correctly,
however OrderValueCondition fails due to order_id being NULL. The
situation
is the same if I rely on the build_* methods.

So to recap.. Campaign has_many ConditionSets has_one PromoterCondition
has_one OrderCondition has_one OrderValueCondition. The only difference
between the PromoterCondition / OrderCondition and OrderCondition /
OrderValueCondition associations is that the PromoterCondition /
OrderCondition is infact a polymorphic one via a OrderConditionable
interface, but surely that shouldn't be causing the problem?

Today really is a has_many :headaches day!

Cheers
Ian
3ddf2897026370c1b869159ba19124ec?d=identicon&s=25 Ian Leitch (Guest)
on 2007-07-13 18:32
(Received via mailing list)
OK this is odd.. or just not what I'm expecting.

class OrderValueCondition
    belongs_to :order, :class_name => 'Incentive::OrderCondition'
end

Rails should infer order_id as the foreign key, right? I'm not sure what
Rail thinks it is, because when I explicitly specify :foreign_key =>
:order_id it saves.

...the penny drops..

Just noticed:

DEPRECATION WARNING: The inferred foreign_key name will change in
Rails 2.0to use the association name instead of its class name when
they differ.
When using :class_name in belongs_to, use the :foreign_key option to
explicitly set the key name to avoid problems in the transition.  See
http://www.rubyonrails.org/deprecation for details.

Doh!
This topic is locked and can not be replied to.