Mathieu Mathieu - 1 month ago 17
Ruby Question

Switch to Ruby 2.3.0 (from 2.0.0) creates issue on Active Record validates

I recently switched my Rails 4.2 app from ruby 2.0.0 to 2.3.0 and when I start my rails server ($ rails s), a new notifcation just appeared

/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


Here is an example of the line causing issues, they are the ones where on creation of the account I set the attribute nb equal to 3 (on: :create), and the user, in the life of his account, can grow his number of permissions but will never be able to have more than 7 (on: :update).

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


What should I change ?

Thanks

max max
Answer

The main difference here is that the Ruby upgrade is telling you about a bug in your app that was previously passing unnoticed. Only the second numericality: { less_than_or_equal_to: 7 }, on: :update was ever really used.

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

Use validates :att, {} when you have relatively simple conditions. Since your validations apply to different lifecycle events you should declare each as a separate validation.

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 

Testing model validations base bones is actually pretty easy (although not as slick as with 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
Comments