トップ «前の日記(2005-10-21) 最新 次の日記(2005-10-24)» 編集

3 日坊主日記


2005-10-23 [長年日記]

_ [Rails] rails 0.13.1->0.14.1

0.14.1 が出たということで、互換性を検証中。

  • rake の結果
   3) Failure:
 test_ochi(CustomerTest) [./test/unit/customer_test.rb:15]:
 <"089-xxx-xxxx"> expected but was
 <"089-xxx">.
  • test/unit/
 def test_ochi
   ...
   assert_equal "089-xxx-xxxx", @ochi.tel
  • test/fixtures/
 ochi:
   tel: 089-xxx-xxx
  • DDL
 CREATE TABLE customers (
 ...
 tel varchar(7) default NULL,
 ...
 ) ENGINE=InnoDB DEFAULT CHARSET=sjis;

ええと、これはようするに tel カラムの文字列長の問題ですね。 varchar(7) だと足りないやんと思われるかもしれませんが、ここでは charset=sjis なので 1文字=2バイト。なので14バイトまで入ります。

MySQL の varchar の長さの単位はバイトではなく文字なのです。

しかしどうやら ActiveRecord 1.12.1 は文字列長をバイト数としてみてちょんぎる処理を行うようになったらしく。これはバグだよ、バグ。

まあでも、この場合はおとなしく varchar(13) に直すべきだな… (字義通り「文字」単位で見れば varchar(7) では足りないので)

そもそも varchar(13) と書いていたものが MySQL 4.0->4.1 に上げたとき varchar(7) にされてしまったのがことの始まり。

_ [Rails] rails 0.13.1->0.14.1 (2)

ええと、これは customers 1..n services のときに、ある service を更新 (save) する際、対応する customer が valid? じゃないときこの更新を失敗させる (save が false を返す) という処理 (before_save に書いた) のテストです。

  • rake の結果
   1) Failure:
 test_validate_yomi(ServiceTest) [test/unit/service_test.rb:131]:
 <false> expected but was
 <true>.
  • test/unit/
 def test_validate_yomi
   @ochi.yomi = 'オチマドカ'
   @ochi.save_without_validation # わざとvalidationを回避
   @ochi.reload
   assert_equal 'オチマドカ', @ochi.yomi
   assert_equal false, @ochi.valid?
   assert_equal false, @tamaki.save # ここでこける
   assert_equal 1, @ochi.errors.count
 end
  • app/models/
 class Service < ActiveRecord::Base
   ...
   before_save { |record| record.customer && record.customer.valid? }

で、通らなくなった原因はこれ:

 --- trunk/activerecord/lib/active_record/validations.rb	2005-10-01 19:00:28 UTC (rev 2433)
 +++ trunk/activerecord/lib/active_record/validations.rb	2005-10-02 02:00:50 UTC (rev 2434)
 @@ -657,7 +657,12 @@
      # The validation process on save can be skipped by passing false. The regular Base#save method is
      # replaced with this when the validations module is mixed in, which it is by default.
      def save_with_validation(perform_validation = true)
 -      if perform_validation && valid? || !perform_validation then save_without_validation else false end
 +      if perform_validation && valid? || !perform_validation
 +        save_without_validation
 +        true
 +      else
 +        false
 +      end
      end

えー。なんでー。 なにかまずいからこうしてるんだろうけど…

元の挙動のように失敗を捕捉したいときは、この changeset/2434 の callbacks_test.rb にあるような cancelled? を自分で書けってことなのかい?

[]