简体   繁体   English

如何在Ruby on Rails中处理这种类型的模型验证

[英]How to handle this type of model validation in Ruby on Rails

I have a controller/model hypothetically named Pets. 我有一个假设命名为Pets的控制器/模型。 Pets has the following declarations: 宠物具有以下声明:

belongs_to :owner
has_many :dogs
has_many :cats

Not the best example, but again, it demonstrates what I'm trying to solve. 不是最好的例子,但是它再次说明了我要解决的问题。 Now when a request comes in as an HTTP POST to http://127.0.0.1/pets , I want to create an instance of Pets. 现在,当请求以HTTP POST形式发送到http://127.0.0.1/pets ,我想创建一个Pets实例。 The restriction here is, if the user doesn't submit at least one dog or one cat, it should fail validation. 这里的限制是,如果用户不提交至少一只狗或一只猫,则它应该无法通过验证。 It can have both, but it can't be missing both. 它可以同时具有,但是不能同时缺少两者。

How does one handle this in Ruby on Rails? 如何在Ruby on Rails中处理此问题? Dogs don't care if cats exists and the inverse is also true. 狗不在乎猫是否存在,反之亦然。 Can anyone show some example code of what the Pets model would look like to ensure that one or the other exists, or fail otherwise? 任何人都可以显示一些有关Pets模型的示例代码,以确保其中一个或另一个是否存在吗? Remember that dogs and cats are not attributes of the Pets model. 请记住,猫狗不是Pets模型的属性。 I'm not sure how to avoid Pets from being created if its children resources are not available though. 我不确定如果子资源不可用时如何避免创建Pets。

errors.add also takes an attribute, in this case, there is no particular attribute that's failing. errors.add还带有一个属性,在这种情况下,没有任何失败的特定属性。 It's almost a 'virtual' combination that's missing. 这几乎是缺失的“虚拟”组合。 Parameters could come in the form of cat_name="bob" and dog_name="stew", based on the attribute, I should be able to create a new cat or dog, but I need to know at least one of them exists. 参数可以采用cat_name =“ bob”和dog_name =“ stew”的形式,基于该属性,我应该能够创建新的猫或狗,但是我需要知道其中至少有一个。

You're looking for errors.add_to_base . 您正在寻找errors.add_to_base This should do the trick: 这应该可以解决问题:

class Pet < ActiveRecord::Base
  belongs_to :owner
  has_many :dogs
  has_many :cats

  validate :has_cats_or_dogs

  def has_cats_or_dogs
    if dogs.empty? and cats.empty?
      errors.add_to_base("At least one dog or cat required")
    end
  end
end

If you want to pass cat_name or dog_name to the controller action, it may look like this: 如果要将cat_namedog_name传递给控制器​​操作,则可能如下所示:

class PetsController < ApplicationController
  # ...

  def create
    @pet = Pet.new(params[:pet])
    @pet.cats.build(:name => params[:cat_name]) if params[:cat_name]
    @pet.dogs.build(:name => params[:dog_name]) if params[:dog_name]
    if @pet.save
      # success
    else
      # (validation) failure
    end
  end
end

Alternatively, for some more flexibility you can use nested attributes to create new cats and dogs in your controller. 另外,为了获得更大的灵活性,您可以使用嵌套属性在控制器中创建新的猫和狗。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM