首页 > 解决方案 > 如何在 Rails 中手动导致 ActiveRecord RecordInvalid

问题描述

条目:我有从其中一种类型派生的属性类,ActiveRecord并实现方法 cast(value) 将提供的值转换为派生的 Active Record 类型。在我们的例子中,我们仅在提供的值是 String 时执行转换,否则执行默认的整数转换。私有方法to_minutes将格式化时间转换为表示花费分钟数的整数。我以为1d = 8h = 480m。例如to_minutes('1d 1h 1m') = 541 的结果。(我在 Ruby on Rails 5 ActiveRecord 中使用了这个资源自定义属性

如果string来的没有数字,我需要返回一个验证错误,并将这个错误设置为@card.errors. 我该怎么做?我尝试:

if time.scan(/\d/).empty?
  raise ActiveRecord::RecordInvalid.new(InvalidRecord.new)
end

但它不起作用,我得到一个错误

NameError in CardsController#update
uninitialized constant CardDuration::Type::InvalidRecord
Extracted source (around line #15):

我为整数类型创建了自己的属性:

class CardDuration
  class Type < ActiveRecord::Type::Value
    def cast(value)
      if value.is_a?(String)
        to_seconds(value)
      else
        super
      end
    end

    private

    def to_seconds(time)
      if time.scan(/\d/).empty?
           return raise ActiveRecord::RecordInvalid.new, { errors: {message: 'Duration is too short (minimum is 1 number)'} }
      end
      time_sum = 0
      time.split(' ').each do |time_part|
        value = time_part.to_i
        type = time_part[-1,1]
        case type
        when 'm'
          value
        when 'h'
          value *= 60
        when 'd'
          value *= 8*60
        else
          value
        end
        time_sum += value
      end
      time_sum
    end
  end
end

和内部模型:

class Card < ApplicationRecord
  validates :duration,  length: { within: 0..14880 }
  attribute :duration, CardDuration::Type.new
end

验证也不起作用,我不明白为什么。谢谢)在控制器内部,这个字段只能更新,所以我需要将错误设置为@card.errors:

class CardsController < ApplicationController
  def update
    if @card.update(card_params)
      flash[:success] = "Card was successfully updated."
    else
      flash[:error] = @card.errors.full_messages.join("\n")
      render status: 422
    end
    rescue ActiveRecord::RecordInvalid => e
      return e.record
  end
end

标签: ruby-on-railsrubyactiverecord

解决方案


在 ActiveRecord::RecordInvalid.new(...) 中,您需要传递具有方法“错误”文档的结构。尝试raise ActiveRecord::RecordInvalid.new(self.new) 使用方法编写或拥有类,errors这将处理您的异常


推荐阅读