Phone在db模式中定义为字符串,但整数在Ruby中保存为有效

时间:2015-06-20 23:34:33

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

我觉得我在这里错过了一些非常简单的事情......

我的数据库架构:

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

这是我控制台的一个片段:

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

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

这并不是让我的模型测试非常开心。也不是我的事。从我的模型中,以下是所有相关的验证:

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

2 个答案:

答案 0 :(得分:1)

ActiveRecord查看您的schema.rb并创建基于列值进行类型转换的setter。

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

因此,当您在.valid上致电@plan时,'phone1'属性为字符串。我不确定你的测试是什么样的,但如果你正在做的话:

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

期望计划无效只是因为它传递了一个数字,而不是简单地误解了rails的运作方式。

假设:

$ 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 :(得分:0)

您可以编写自定义验证方法来检查phone1String *:

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

另一方面,如果从数据库加载数据时得到数字字段,则数据库的字段类型不是字符串。也许旧的环境仍然存在?

*就Rails专业功能而言,我并不太精明,所以可能有一条捷径......