Nested Models and Parent Validation

Nested models and parent validation

This will probably work for you, but I have a feeling there's a much better answer out there. It sounds like a bug to me.

class Parent < ActiveRecord::Base
validate :must_have_children

def must_have_children
if children.empty? || children.all?(&:marked_for_destruction?)
errors.add(:base, 'Must have at least one child')
end
end
end

How to validate a nested model object based on the state of the parent object?

Add a virtual attribute on your Address model:

class Address < ActiveRecord::Base
belongs_to :participant
attr_accessor :skip_validation
validates_presence_of :address1, :state, :suburb, :postcode,
:unless => :skip_validation
end

Set the virtual attribute on the address object when current_step is set.

class Participant < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
attr_accessor :current_step
validates_presence_of :first_name, :last_name,
:if => lambda {|r| r.current_step == "name"}


def current_step=(value)
unless (value == "address")
address.skip_validation = true
end
@current_step = value
end
end

Validations Across Models and Nested Model/Object Form in Rails

edit: hum, I read your post a bit too fast, I thought that with where the child references a value in the parent, you meant the foreign key parent_id... My answer might still help, not sure.

I think you're looking for the inverse_of option. Try that:

class Parent < ActiveRecord::Base
has_one :child, inverse_of :parent
end

class Child < ActiveRecord::Base
belongs_to :parent, inverse_of :child
end

From the doc:

Validating the presence of a parent model

If you want to validate that a child record is associated with a parent record, you can use validates_presence_of and inverse_of as this example illustrates:

class Member < ActiveRecord::Base
has_many :posts, :inverse_of => :member
accepts_nested_attributes_for :posts
end

class Post < ActiveRecord::Base
belongs_to :member, :inverse_of => :posts
validates_presence_of :member
end

Django Nested Admin validation of nested inlines from parent forms

It appears you can still use the model.clean() method for form validation:

from django.core.exceptions import ValidationError


class Child(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='children')
starts_at = models.DateTimeField(null=True, blank=True)

def clean(self):
parent_start = self.parent.starts_at
child_start = self.starts_at
if parent_start and child_start < parent_start:
raise ValidationError(f'This group cannot start before the season starts')

Which will make ValidationError appear on the Child form. Using the clean method on the Parent form is also possible, and would give the errors at that level.

Custom validation errors on nested models

You should keep them in the child model since that's the one validated, however, you can set conditionals with if: and unless:

class Order < ActiveRecord::Base
validates :card_number, presence: true, if: :paid_with_card?

def paid_with_card?
payment_type == "card"
end
end

You can do several variations on this, read more in the rails documentation http://edgeguides.rubyonrails.org/active_record_validations.html#conditional-validation

I guess you could add an attribute, created_by to child, and make Child select which validations to use depending on that one. You can do that like they do in this answer: Rails how to set a temporary variable that's not a database field

How to validate existence of parent id in child model in Rails for nested attributes

If I get it right you have trouble saving associated records with your setup:

params = {number: 'order-123', order_items_attributes:{product_id:1, quantity: 2, price: 3}}
Order.create params # => this should not work

To fix it, you need to tell Rails explicitly about associations, using inverse_of option:

class Order
# without inverse_of option validation on OrderItem
# is run before this association is created
has_many :order_items, inverse_of: :order
accepts_nested_attributes_for :order_items
end

It's not required in your case but your can add inverse_of in OrderItem as well:

class OrderItem
belongs_to :order, inverse_of: :order_items
# ... the rest
end

More about using inverse_of option with associations can be read here.



Related Topics



Leave a reply



Submit