Phone is defined as a string in db schema, but integers are stored as valid in Ruby

It seems to me that I am missing something very simple here ...

My db schema:

create_table "plans", force: true do |t|
  t.string   "phone1"
  ...
end

      

Here is a snippet from my console:

@plan = Plan.create(a bunch of params)
@plan.phone1 = "123"
@plan.valid?
# => true

# above is great, here where the problem comes in:
@plan.update_attribute("phone1", 123)
@plan.phone1
# => 123
@plan.valid?
# => true

      

This doesn't make my model tests very happy. And I'm not in this. From my model, here are all the relevant checks:

validates :phone1, presence: true
validates :phone1, length: { is: 3 }

      

+3


source to share


2 answers


ActiveRecord looks at yours schema.rb

and creates setters that are of type based on the column value.

class Plan < ActiveRecord::Base
  # "Automagically" creating by Active Record.
  # def phone1= val
  #   @phone1 = val.to_s
  # end
end

      

So when you call .valid

in @plan

, the 'phone1' attribute is a string. I'm not sure what your test looks like, but if you do:

plan = Plan.new(123)
expect(plan.valid?).to be_falsy

      

Expecting the plan to be invalid just because it passed a number different from yours just misunderstood how the rails work.



Given:

$ rails g model plan phone1:string ends:datetime
$ rails g migrate

      


irb(main):004:0>@plan = Plan.create(ends: Date.tomorrow, phone1: 123)
   (0.3ms)  begin transaction
  SQL (1.2ms)  INSERT INTO "plans" ("ends", "phone1", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["ends", "2015-06-24 00:00:00.000000"], ["phone1", "123"], ["created_at", "2015-06-23 02:21:39.236332"], ["updated_at", "2015-06-23 02:21:39.236332"]]
   (1.2ms)  commit transaction
=> #<Plan id: 2, phone1: "123", ends: "2015-06-24 00:00:00", created_at: "2015-06-23 02:21:39", updated_at: "2015-06-23 02:21:39">
irb(main):005:0> @plan.phone1 = 123456
=> 123456
irb(main):006:0> @plan.phone1.class
=> String
irb(main):007:0> @plan.update_attribute("phone1", 123)
   (0.8ms)  begin transaction
   (0.3ms)  commit transaction
=> true
irb(main):008:0> @plan.phone1.class
=> String
irb(main):013:0> @plan.ends = "2015-06-23"
=> "2015-06-23"
irb(main):014:0> @plan.ends
=> Tue, 23 Jun 2015 00:00:00 UTC +00:00
irb(main):015:0> 

      

+1


source


You can write your own check method to check that phone1

a String

*:

class Plan
   validates :phone1, presence: true
   validates :phone1, length: { is: 3 }
   validates :special_validations

   def special_validations
      errors.add(:phone1, "Must be String") unless phone1.is_a? String
      # add whatever you feel like
      true
   def
end

      

On the other hand, if you get a numeric field when loading data from a database, then the database field type is not a string. Maybe the older setting is kept?




* I'm not too smart as Rails functions have functions, so there might be a shortcut for that ...

0


source







All Articles