0

OK、関連するトピックにはたくさんの回答がありますが、何らかの理由で、次の非常に現実的な問題に誰も興味がないようです:

とフィールドを持つTimecardモデルがあります。私は使用しており、一般的に言えば、すべて順調です。「validates_timeliness」gem も使用しています。to_datefrom_datejquery.ui.datepicker

class Timecard < ActiveRecord::Base
  ...
  validates_date :to_date
  validates_date :from_date
  ...
end

ただし、ユーザーがテキスト フィールドを手動で編集して「2013 年 2 月 29 日」のようなものを入力すると (これは無効な日付です)、この日付は「2013 年 3 月 1 日」に変換されます。次の仕様は失敗します。

describe "POST #create" do
  ...
  context "with invalid attributes (invalid date)" do
    it "re-renders the :new template" do
      timecard = fix_date_attribs_for(:timecard_feb)
       # Manually create an invalid date in the params hash - Feb only has 28 days
      timecard['to_date(3i)'] = 29
      post :create, timecard: timecard
      response.should render_template :new
    end
  end
  ...
end

timecards_controller.rbputsの以下:

def create
  @timecard = Timecard.new(timecard_params)
  puts ">>>> #{@timecard.valid?} - #{@timecard.to_yaml}"
  ...
end

上記の仕様を実行すると、次の出力が生成されます。

.>>>> true - --- !ruby/object:Timecard
attributes:
  id: 
  name: February 2013
  from_date: 2013-02-01
  to_date: 2013-03-01
  created_at: 
  updated_at: 
F

Failures:

  1) TimecardsController POST #create with invalid attributes (invalid date) re-renders the :new template
     Failure/Error: response.should render_template :new
       expecting <"new"> but rendering with <[]>
     # ./spec/controllers/timecards_controller_spec.rb:65:in `block (4 levels) in <top (required)>'

Finished in 0.28495 seconds
17 examples, 1 failure

ここで入力検証を行うにはどうすればよいですか? モデルでコールバックを使用することは、あまりにもかけ離れているように見えます (問題が以前に発生したため、コントローラーが発生したとき@timecard = Timecard.new(timecard_params))。Date.new(relevant_timecard_params)コントローラーで例外をキャッチしようとすることはできますが、errorsハッシュにアクセスできないため、コントローラーが正しいように聞こえないことは言うまでもなく、無効な日付であることをユーザーに伝えることはできません。入力検証を行う場所... 助けてください...

更新 1

以下で @Grantovich が提案したように「validate_timeliness」を使用すると (プラグインを有効にして) 、モデルに書き込まなくても「29-Feb-2013」などの無効な日付saveで失敗します。を追加すると、失敗し、検証済みのフィールドが完全に有効な入力でも設定されます (検証ロジックによると思われます)。updatevalidates_date :to_datevalidates_datesaveupdatenil

format: も指定しようとしましvalidates_date :to_date, format: 'dd-mmm-yyyy'たが、同じ結果が得られました。

4

1 に答える 1