Rails [已解决] 升级到 rails4.1 的困惑 同样的代码 4.1 执行两次

moioo · May 06, 2014 · Last by moioo replied at May 06, 2014 · 3059 hits

rails4.1 发布了,手痒升到 4.1 再 rspec 报错,折腾 1 个多小时没找到原因 student.rb

before_create do |t|
  t.rno = t.generate_rno
  t.pinyin_name = Pinyin.t(t.name,:splitter => '')
end

before_update do |t|
  t.pinyin_name = Pinyin.t(t.name,:splitter => '') if t.name_changed?
end

rails 4.0.4

Loading development environment (Rails 4.0.4)
[1] pry(main)> student = User.first.smart_customer.students.new(:name => 'xxx')
  User Load (0.5ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
  SmartCustomer Load (0.5ms)  SELECT `smart_customers`.* FROM `smart_customers` WHERE `smart_customers`.`id` = 1 LIMIT 1
=> #<Student id: nil, smart_customer_id: 1, name: "xxx", gender: true, birthday: nil, card_id: nil, f_telephone: nil, m_telephone: nil, public_school: nil, public_class: nil, address: nil, summary: nil, user_name: nil, password: nil, telephone: nil, identity_card: nil, status: nil, point: 0, money: #<BigDecimal:7fc6f71e0760,'0.0',9(18)>, operator_id: nil, created_at: nil, updated_at: nil, stage: nil, in_year: nil, school_id: nil, rno: nil, pinyin_name: nil>
[2] pry(main)> student.save
   (0.2ms)  BEGIN
  SmartCustomer Load (0.5ms)  SELECT `smart_customers`.* FROM `smart_customers` WHERE `smart_customers`.`id` = 1 LIMIT 1
  SQL (0.5ms)  UPDATE `smart_customers` SET `rno` = 7414, `updated_at` = '2014-05-06 14:45:26' WHERE `smart_customers`.`id` = 1
  SQL (0.5ms)  INSERT INTO `students` (`created_at`, `name`, `pinyin_name`, `rno`, `smart_customer_id`, `updated_at`) VALUES ('2014-05-06 14:45:26', 'xxx', 'xxx', '1-140007413', 1, '2014-05-06 14:45:26')
   (0.6ms)  COMMIT
Cache delete: Student/8440
Dalli::Server#connect localhost:11211
Cache delete: SmartCustomer/1
=> true

以上在 4.0.4 执行正常无报错 rails 4.1

Loading development environment (Rails 4.1.0)
[1] pry(main)> student = User.first.smart_customer.students.new(:name => 'xxx')
  User Load (0.4ms)  SELECT  `users`.* FROM `users`   ORDER BY `users`.`id` ASC LIMIT 1
  SmartCustomer Load (0.4ms)  SELECT  `smart_customers`.* FROM `smart_customers`  WHERE `smart_customers`.`id` = 1 LIMIT 1
=> #<Student id: nil, smart_customer_id: 1, name: "xxx", gender: true, birthday: nil, card_id: nil, f_telephone: nil, m_telephone: nil, public_school: nil, public_class: nil, address: nil, summary: nil, user_name: nil, password: nil, telephone: nil, identity_card: nil, status: nil, point: 0, money: #<BigDecimal:7ffdb6253558,'0.0',9(18)>, operator_id: nil, created_at: nil, updated_at: nil, stage: nil, in_year: nil, school_id: nil, rno: nil, pinyin_name: nil>
[2] pry(main)> student.save
   (0.2ms)  BEGIN
  SQL (0.6ms)  UPDATE `smart_customers` SET `rno` = 7415, `updated_at` = '2014-05-06 14:46:22' WHERE `smart_customers`.`id` = 1
  SQL (0.5ms)  UPDATE `smart_customers` SET `rno` = 7416, `updated_at` = '2014-05-06 14:46:22' WHERE `smart_customers`.`id` = 1
  SQL (0.6ms)  INSERT INTO `students` (`created_at`, `name`, `pinyin_name`, `rno`, `smart_customer_id`, `updated_at`) VALUES ('2014-05-06 14:46:22', 'xxx', 'xxx', '1-140007415', 1, '2014-05-06 14:46:22')
  SQL (0.7ms)  INSERT INTO `students` (`rno`) VALUES ('1-140007414')
Mysql2::Error: Field 'name' doesn't have a default value: INSERT INTO `students` (`rno`) VALUES ('1-140007414')
   (3.0ms)  ROLLBACK
ActiveRecord::StatementInvalid: Mysql2::Error: Field 'name' doesn't have a default value: INSERT INTO `students` (`rno`) VALUES ('1-140007414')

在 4.1 却执行报错,看了一下执行 sql 发现都执行了两次非常困惑

原因是找到了

entity User.first.smart_customer.students.new(:name => 'xxx')
entity.save

student.rb before_create 对 smart_customer 一个字段进行了更新保存,也估计就是这样再触发再次 save

但在 4.1 之前的版本没有这个问题,因为我是从 3.2 一直升上来的。

You need to Sign in before reply, if you don't have an account, please Sign up first.