切换到Ruby 2.3.0(从2.0.0开始)会在Active Record验证上产生问题

时间:2016-10-10 10:38:08

标签: ruby-on-rails ruby ruby-on-rails-4 activerecord

我最近将我的Rails 4.2应用程序从ruby 2.0.0切换到2.3.0,当我启动我的rails服务器($ rails s)时,出现了一个新的通知

/home/app/models/user.rb:127: warning: key :numericality is duplicated and overwritten on line 128
/homeapp/models/user.rb:127: warning: key :on is duplicated and overwritten on line 128
/home/app/admin/user.rb:142: warning: key :collection is duplicated and overwritten on line 147
/home/app/models/deal.rb:223: warning: key :numericality is duplicated and overwritten on line 226
/home/app/models/deal.rb:234: warning: key :numericality is duplicated and overwritten on line 237

以下是导致问题的行的示例,它们是在创建帐户时我将属性nb设置为3(on :: create),并且用户在其帐户的生命周期中可以增加他的权限数量但永远不能超过7(on :: update)。

validates :nb_of_permissions,
            presence:true,
            numericality: { equal_to: 3 }, on: :create,               
            numericality: { less_than_or_equal_to: 7 }, on: :update   

我应该改变什么?

由于

3 个答案:

答案 0 :(得分:3)

你应该试试这个

validates :nb_of_permissions, presence:true, numericality: { equal_to: 3 }, on: :create
validates :nb_of_permissions, presence:true, numericality: { less_than_or_equal_to: 7 }, on: :update

答案 1 :(得分:3)

你的旧代码是错误的,并没有做你认为的那样。这里的行为没有变化;你只是被告知一个有用的警告,以突出可能的错误!

考虑以下简单示例:

hash = {a: 1, a: 2}

在ruby版本2.0 2.3中,这相当于仅定义:

hash = {a: 2}

...因为哈希键被覆盖了。同样,您的代码:

validates :nb_of_permissions,
            presence:true,
            numericality: { equal_to: 3 }, on: :create,
            numericality: { less_than_or_equal_to: 7 }, on: :update

......过去,而且永远等同于写作:

validates :nb_of_permissions,
            presence:true,
            numericality: { less_than_or_equal_to: 7 },
            on: :update

There is more than one way to do it,但是您可以通过定义两个验证来修复此错误,例如:

validates :nb_of_permissions,
            presence:true,
            numericality: { less_than_or_equal_to: 7 },
            on: :update

validates :nb_of_permissions,
            presence:true,
            numericality: { equal_to: 3 },
            on: :create

答案 2 :(得分:3)

这里的主要区别是Ruby升级告诉你一个 您之前未经注意的应用中的错误。只有第二个numericality: { less_than_or_equal_to: 7 }, on: :update才真正使用过。

irb(main):001:0> { foo: 1, foo: 2 }
(irb):1: warning: key :foo is duplicated and overwritten on line 1
=> {:foo=>2}

条件相对简单时使用validates :att, {}。 由于您的验证适用于不同的生命周期事件,因此您应将每个验证声明为单独的验证。

validates :nb_of_permissions, { presence: true }
validates_numericality_of :nb_of_permissions equal_to: 3, on: :create 
validates_numericality_of :nb_of_permissions less_than_or_equal_to: 7, on: :update 

测试模型验证基础骨骼实际上非常简单(虽然不如与Shoulda-Matchers一样灵活):

RSpec.describe Thing do
  describe "validations"
    describe "#nb_of_permissions" do
      context "when updating" do
        let(:thing) { Thing.create(nb_of_permissions: 3) } 
        let(:errors) { thing.valid?.errors[:nb_of_permissions] }
        it 'is must be present' do
          thing.nb_of_permissions = nil
          expect(errors).to include 'must be present.'
        end
        it 'is must be at least 7' do
          thing.nb_of_permissions = 10000
          expect(errors).to include "must be less than or equal to 7"
        end
      end 
    end
  end
end