【问题标题】:Rails: Getting rid of generic "X is invalid" validation errorsRails:摆脱通用的“X 无效”验证错误
【发布时间】:2011-02-26 04:52:49
【问题描述】:

我有一个注册表单,其中包含您想要调用的任何嵌套关联/属性。

我的层次结构是这样的:

class User < ActiveRecord::Base
  acts_as_authentic
  belongs_to :user_role, :polymorphic => true
end

class Customer < ActiveRecord::Base
  has_one :user, :as => :user_role, :dependent => :destroy
  accepts_nested_attributes_for :user, :allow_destroy => true
  validates_associated :user
end

class Employee < ActiveRecord::Base
  has_one :user, :as => :user_role, :dependent => :destroy
  accepts_nested_attributes_for :user, :allow_destroy => true
  validates_associated :user
end

我在这些课程中也有一些验证内容。我的问题是,如果我尝试使用空白表单创建客户(或员工等),我会得到所有我应该得到的验证错误以及一些通用错误,如“用户无效”和“客户无效”如果我迭代我得到的错误如下:

user.login can't be blank
User is invalid
customer.whatever is blah blah blah...etc
customer.some_other_error etc etc

由于嵌套 User 模型中至少有一个无效字段,因此会在错误列表中添加一条额外的“X 无效”消息。这让我的客户感到困惑,所以我想知道是否有一种快速的方法可以做到这一点,而不必自己填写错误。

【问题讨论】:

    标签: ruby-on-rails validation nested-attributes


    【解决方案1】:

    使用after_validation方法

      def after_validation
        # Skip errors that won't be useful to the end user
        filtered_errors = self.errors.reject{ |err| %w{ user User  }.include?(err.first) }
        self.errors.clear
        filtered_errors.each { |err| self.errors.add(*err) }
      end
    

    已编辑

    注意:-

    在您的情况下添加以下列表中的用户或用户。如果您有多个由空格分隔的关联,则可以添加多个。

    %w{ User user }.include?(err.first) #### This piece of code from the above method has logic which reject the errors which won't be useful to the end user
    

    【讨论】:

    • 好吧,这看起来很有希望! :) 我认为您在“注意:-”下有语法错误,这让我感到困惑..“添加 ... ???”另外,我应该把这个功能放在哪里?在每个这样做的模型中?这是 ARB 的函数覆盖吗?
    • 语法抱歉:)。将此方法放在您编写 validates_associated 的每个模型中
    • 好的,我现在就给你投票,因为这主要是有效的。但是有一个问题:而不是这样:登录 太短(最少 3 个字符)密码 太短(最少 4 个字符)密码确认 太短(最少 4 个字符)我得到这个:User.login 太短(最少 3 个字符)User.password 太短(最少4 个字符)User.password 确认 太短(最少 4 个字符)如果你能弄清楚如何解决这个问题,我会接受你的回答。
    【解决方案2】:

    Salil 的回答几乎是正确的,但他从未做到 100%。以下是正确的做法:

    def after_validation
        # Skip errors that won't be useful to the end user
        filtered_errors = self.errors.reject{ |err| %{ person }.include?(err.first) }
    
        # recollect the field names and retitlize them
        # this was I won't be getting 'user.person.first_name' and instead I'll get
        # 'First name'
        filtered_errors.collect{ |err|
          if err[0] =~ /(.+\.)?(.+)$/
            err[0] = $2.titleize
          end
          err
        }
    
        # reset the errors collection and repopulate it with the filtered errors.
        self.errors.clear
        filtered_errors.each { |err| self.errors.add(*err) }
      end
    

    【讨论】:

    • 另外,我提出了一个功能请求作为比这个解决方法更好的解决方案:rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/…
    • 我收到错误“没有将符号隐式转换为字符串”
    • @Chemist 这适用于旧版本的导轨。尝试编辑提供的代码,使其与您现在使用的版本正常工作。
    • @Chemist - 修复“将符号隐式转换为字符串”将 %{} 更改为 %w{}
    • 尽管在 Rails 4.1 中,我注意到您需要使用符号数组 (%i{})
    猜你喜欢
    • 2012-11-04
    • 2011-05-31
    • 1970-01-01
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 2013-09-04
    • 2019-04-30
    • 1970-01-01
    相关资源
    最近更新 更多