質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • Ruby on Rails

    7673questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • データベース

    734questions

    データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

  • MVC

    235questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

  • バリデーション

    46questions

    Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

DBとビューレベルでチェックする入力項目に、モデルでのバリデーションは必要か

解決済

回答 2

投稿

  • 評価
  • クリップ 3
  • VIEW 1,357

maisumakun

ユーザーランキング総合1位

Railsでアプリを作っていたときに気になったことですが、データにチェックをかける箇所が3通り考えられます。

  1. ビューのHTML、JavaScriptレベル
  2. Railsレベル
  3. RDBMSレベル

今回の疑問としては、このうち「ビューレベル」と「DBレベル」で制約をかけた場合に、途中のRailsレベルでもさらにバリデーションをかけることには何かしらのメリットがあるのか、ということです。

もちろん、「整数の範囲」や「文字列の長さ」といった制約条件であれば、モデルに定義するのもほとんど手間が発生しませんので、3重に制約をかけても、特段のデメリットはないでしょう。

ただ、FOREIGN KEY制約については、モデルでもバリデーションをかけようとすると、「モデルレベルのチェックのために別途でDBを引く必要がある」という処理負荷が発生します。

そして、選択系の入力フォームをラジオボタン・チェックボックス・ドロップダウンといったウィジェットで構築した場合、デバッグツールなどで無理やり書き換えない限り、事前に用意した値しか書き込めません。

一方、無理やり書き換えたところで、DB側でFOREIGN KEY制約を正しくかけてあれば、不適切なデータの書き込みは不可能ですし、正当な動作でたどり着くものではありませんから、「DBエラーで食い止められるならそれでいい」ともなります。

このような状況下で、Railsのモデルレベルでもバリデーションを加えて、「不正な値に書き換えられたときにもバリデーション失敗として処理する」必要性・メリットはどの程度ありますでしょうか。

(なお、APIの場合、ビューレベルでのチェックはないので、Railsレベルでのチェックも必要だと考えています。また、リンクさせる先はマスター系なので、「入力フォームの表示後に値が不適切になる」ことも考えなくて大丈夫です。)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+5

Railsのモデルレベルでもバリデーションを加えて、「不正な値に書き換えられたときにもバリデーション失敗として処理する」必要性・メリットはどの程度ありますでしょうか。

まず、定量的な回答は難しいのでご容赦ください。

この質問には「一般的なDBを使ったCRUDアプリ」であることと、1と2と3で「同じバリデーションを行える」場合という前提が必要かと思います。

なぜかというと、2でしかバリデーションできないものもあるからです。
具体的には
1は、JavaScriptがクライアントサイドで無効化される(されている)可能性がある
3は、ミドルウェアに依存する。またトリガー等を使えたとしてもアプリで実装するよりも面倒くさい
あと、そもそも3まで到達せず、入力をそのままメール送信する等のアプリがあるからです。

前置きが長くなりましたが、上記の前提を踏まえせていただきますと、QCDのトレードオフという回答となってしまいます。
極端な話、FOREIGN KEY制約に関わらず、「整数の範囲」や「文字列の長さ」においても、最後の砦であるRDBMSで完璧なバリデーションを行っていれば問題はないはずです。
しかし、質問者さんもご認識の通り、DBアクセスの結果を見るまで不正データかわからないため、無駄な処理負荷が発生します。あと、最後の砦のみで完璧なバリデーションと言っても不安はありますよね。ある程度大規模なアプリでは、ステークホルダーへの説得も難しいと思います。

そのため、基本的には2と3のバリデーションは最低限必要だと考えています。
考え方の1つとして、
DBアクセスを伴う「参照整合性」などは、2ではバリデーションしない。(2でバリデーションしても3の結果を見て判断することになるため)
DBアクセスを伴わない「整数の範囲」などは、2でバリデーションする。(無駄な処理不可を避けて、即座に再入力を促したいため)
は良いかなと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/02 08:35

    たしかに、Railsレベルでないとチェックが難しいもの(文字列を正規表現でチェックするなど)もありますし、MySQLはCHECK制約がないためにDBレベルで簡単にできることも限られてはしまいます。

    キャンセル

0

個人的には、現代においては「2.Railsレベル」に集中して書くべきかと思います。


まず「1.ビューのHTML、JavaScriptレベル」が要らない理由です。

「1.ビューのHTML、JavaScriptレベル」は前の方が仰るように、
JavaScriptが無効にされていた場合に意味がありません。
それに、HTML、JavaScriptレベルでのバリデーションは、かつて通信速度や
サーバ性能が今よりずっと劣っていた時代に、サーバを介して数秒待たずとも、
クライアント内で即時応答が可能だったため広く浸透した技術だと私は学びました。

そりゃ早いにこしたことは無いですが、仮に0.5秒くらいと0.01秒くらいは数値的には
50倍ほどありますが、体感的にはいずれもストレスに感じないレベルかと思いますし
お客様にも十分納得頂けるレベルかと思っています。

また、UIを考えたときにHTML5などでのエラーの表示、JavaScriptでの
エラーの表示、DBアクセスなどを伴う「2.Railsレベル」または「3.RDBMSレベル」
でのエラーの表示を揃えるとなるとなかなか面倒な作業にもなるかと思います。
ユーザ的には「エラーなんだから種類によらず同じように出してよ」という
希望があるかと思いますし、ユーザビリティを考慮するとそうすべきでしょう。


次に「3.RDBMSレベル」についてはシステムによる特性によって必要性を検討します。

運用作業で人が直接、あるいは外部システムがRDBMSに対して作成した
アプリケーションを介さずに直接的にデータの流し込みをする、
といったことを想定している場合には前の方と同じように最後の砦として
必要だと思います。

あるいは金融や国防など、攻撃対象にされやすく社会的影響も極めて大きい
システムなど、データの整合性を極限まで厳格に担保したいといったニーズが
あればこれも実装しても良いかと思います。

ただ、そうではない場合は積極的に実装すべきではないと個人的には思います。
長い運用の間にRailsだったりRDBMSだったり、各所にバリデーション処理が
分散されるの可読性を下げ結果的にメンテナンス性を下げることになります。

また、あるカラムに対して、A機能では1か2しか登録しないが、B機能では
1~4のいずれかの値が登録される、なんて場合には結果RDBMSのバリデーションでも
ザルになってしまうため、確実性の担保ができないことにより不要と考えます。


最も柔軟かつ多様に、かつアプリケーションで必ず経由する「2.Railsレベル」に
一元的にバリデーションを記述することで、バリデーション処理が各所に分散
しませんし、かつ確実にキャッチすることもできますので一般的な
業務アプリケーションにおいては「2.Railsレベル」のみで良いかと考えます。

単に新規に作るだけではなく、運用やユーザビリティなども併せて考えられると
良いかなと思います。長文失礼しました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Ruby on Rails

    7673questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • データベース

    734questions

    データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

  • MVC

    235questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

  • バリデーション

    46questions

    Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。