【问题标题】:Validation fails, field must exist with allow_nil验证失败,字段必须与 allow_nil 存在
【发布时间】:2016-12-09 22:19:58
【问题描述】:

我正在创建一个博客,其中的文章可以是对其他文章的回应。文章也可以是组的一部分。但是,文章不必在一个组中,也不必是对另一篇文章的回应。

我正在尝试按照 Rails 文档以 self-joined records 创建文章。

我创建了用户、组和文章脚手架:

bin/rails g scaffold user username:string email:string birthday:date

bin/rails g scaffold group name:string user:references

bin/rails g scaffold article user:references parent:references title:string subheading:string body:text pub_date:datetime group:references hidden:boolean prompt:boolean

我正在尝试在模型验证中使用allow_nil

class Article < ApplicationRecord
  belongs_to :user
  belongs_to :parent, class_name: "Article"
  has_many :replies, class_name: "Article", foreign_key: "parent_id"
  belongs_to :group

  validates :parent, length: {minimum: 1}, allow_nil: true
  validates :group, length: {minimum: 1}, allow_nil: true
end

但是当我运行 db:seed:

user1 = User.create(username: "pete01",email: "pete01@gmail.com",
    birthday:"1980-01-30")

article1 = Article.create!(user:user1, parent:nil, title:"My First Article",
        subheading:"This is important", body:"The body of my first article",
        pub_date:"2015-12-26", group:nil, hidden:false, prompt:false)

我收到此错误:

ActiveRecord::RecordInvalid: Validation failed: Parent must exist, Group must exist

还有什么地方我应该告诉 Rails 它不需要验证 Group 和 Parent 吗?

【问题讨论】:

  • 你的验证应该验证什么?
  • 理想情况下什么都没有。我想关闭对父级和组的验证。
  • 然后删除您对验证的调用
  • 我得到了同样的错误,没有任何验证调用。我以为我必须通过 allow_nil 才能关闭验证。
  • ApplicationRecord 是否添加任何验证?请在 Rails 控制台上运行 Article.validators 并将结果添加到您的问题中。

标签: ruby-on-rails validation


【解决方案1】:

解决办法是找到文件new_framework_defaults.rb,把这个改成false

Rails.application.config.active_record.belongs_to_required_by_default = false

【讨论】:

    【解决方案2】:
    #app/models/article.rb
    class Article < ActiveRecord::Base
       belongs_to :parent, class_name: "Article"
       belongs_to :group
    
       validates :parent, presence: true, allow_nil: true
       validates :group, presence: true, allow_nil: true
    end
    

    给你的几个问题:

    您正在验证 parentgroup -- 这些是关联的对象

    你的错误是"[Object] must exist",这意味着你的验证有效——Rails 找不到“nil”关联(它需要对象)。

    应该拥有的是验证parent_idgroup_id,或者使用presence之类的东西来验证关联对象的存在。

    我已包含以下我将使用的验证:

    validates :parent, presence: true, allow_nil: true
    validates :group, presence: true, allow_nil: true
    

    你也可以试试:

    validates :parent_id, length: { minimum: 1 }, allow_nil: true
    validates :group_id, length: { minimum: 1 }, allow_nil: true
    

    文章也可以是组的一部分

    那么您可能想要使用has_and_belongs_to_many 关联:

    #app/models/article.rb
    class Article < ActiveRecord::Base
       has_and_belongs_to_many :groups
    end
    
    #app/models/group.rb
    class Group < ActiveRecord::Base
       has_and_belongs_to_many :articles
    end
    

    您需要一个名为 articles_groups 的连接表,其中包含 article_idgroup_id 列:

    您可以按如下方式创建迁移:

    $ rails g migration CreateArticlesGroups
    
    # db/migrate/create_articles_groups__________.rb
    class CreateArticlesGroups < ActiveRecord::Migration
      def change
        create_table :articles_groups, id: false do |t|
          t.belongs_to :article, index: true
          t.belongs_to :group, index: true
        end
      end
    end
    
    $ rake db:migrate
    

    这将允许您像这样填充关联对象:

    @article = Article.find params[:article_id]
    @group = Group.find params[:id]
    
    @article.groups << group
    

    【讨论】:

    • 感谢您解释 object 和 id 之间的区别,这是关键。
    【解决方案3】:

    这很可能是迁移到 Rails 5 的结果,其中 belongs_to 关系的默认值发生了变化。详情见this answer

    【讨论】:

      【解决方案4】:

      allow_nil: true 是验证器的选项,而不是 validates 方法的选项。您正在使用 length: 键,它将以 {minimum: 1} 哈希作为参数调用 LengthValidator(类似于使用 validates_length_of)。

      例如,使用

      validates :parent, length: {minimum: 1, allow_nil: true}

      而不是

      validates :parent, length: {minimum: 1}, allow_nil: true


      注意:如果使用多个验证器,您需要为每个验证器指定 allow_nil

      【讨论】:

      • validates 的两个版本都给出相同的错误消息。
      • 这很奇怪。我已经使用 Rails 有一段时间了,我对此非常确定。您是否将重构应用于两个验证行?你用的是宙斯吗? (重启!)
      【解决方案5】:

      尝试删除您的验证。还要检查您的 Article 迁移。也许你有null: false 那里有group_idparent_id

      class Article < ApplicationRecord
        belongs_to :user
        belongs_to :parent, class_name: "Article"
        has_many :replies, class_name: "Article", foreign_key: "parent_id"
        belongs_to :group
      end
      

      【讨论】:

      • 删除验证会得到相同的结果。我检查了迁移和架构,父级和组没有null: true
      猜你喜欢
      • 2016-12-23
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 2020-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多