ActiveRecord验证

时间:2014-06-30 18:05:29

标签: ruby-on-rails ruby validation


我想知道在短时间内验证记录是否可能有活跃的记录暂缓?例如,在我的webapp中,我有一个名为Sizes的表,其中包含一个名为sort_order的属性,用户可以通过修改sort_order来重新组织显示大小的顺序。当他们这样做时,我有这个函数,它将遍历大小列表并重新计算排序顺序,相应地更新列。

  def update_size_order
    @size_ids = params[:categories]
    n = 0
    ActiveRecord::Base.transaction do
      @size_ids.each do |temp|
        temp = temp.split('_')
        id = temp[1]
        size = Size.find(id)
        size.sort_order = n
        n += 1
        size.save!
      end
    end
    render :json => {}
  end

问题出现了,因为在我的模型中我有

validates :sort_order, presence: true, uniqueness: true

但是当模型试图保存size时,我收到错误,因为尺寸不一定是唯一的。有没有办法让ActiveRecord在此函数完成之前不执行验证?我的谷歌搜索技能似乎已经达到了他们的匹配,但我觉得这个问题有一个简单的解决方法。谢谢你的帮助!

2 个答案:

答案 0 :(得分:1)

使用size.update_attribute :sort_order, n代替save!。它只是更新数据库而不运行任何形式的验证。由于您在事务中运行它,您应该没问题,但通常您应该避免使用update_attribute,因为它绕过了验证和回调。

此外,each_with_index是您的朋友:

def update_size_order
  @size_ids = params[:categories]

  ActiveRecord::Base.transaction do
    @size_ids.each_with_index do |temp,n|
      temp = temp.split('_')
      id = temp[1]
      Size.find(id).update_attribute :sort_order, n
    end
  end
  render :json => {}
end

由于您只对更新属性感兴趣,因此您也可以跳过实例化AR对象的整个过程,并放弃Size.find(id)调用,转而使用update_all。这将默默地忽略任何未找到的ID,但是当您减半正在运行的查询数时,它将显着提高循环的性能。而不是select查询,然后完全实例化AR模型,并为每条记录update,它将只生成update查询:

  @size_ids.each_with_index do |temp,n|
    temp = temp.split('_')
    id = temp[1]
    Size.where(id: tmp[1]).update_all(sort_order: n)
  end

答案 1 :(得分:1)

让我们说出这个:

validates: :sort_order,
           presence: true,
           uniqueness: true,
           on: :create

这就是你想要的吗? 这样,您的验证仅在创建新对象时执行。