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

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

新規登録して質問してみよう
ただいま回答率
85.49%
MVC

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

Ruby on Rails

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

データベース

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

バリデーション

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

Q&A

解決済

2回答

3599閲覧

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

maisumakun

総合スコア145183

MVC

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

Ruby on Rails

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

データベース

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

バリデーション

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

2グッド

3クリップ

投稿2017/04/01 12:18

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

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

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

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

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

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

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

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

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

i50, ikuwow👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

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/01 18:41

編集2017/04/01 18:46
xenbeat

総合スコア4258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2017/04/01 23:35

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

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レベル」のみで良いかと考えます。

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

投稿2017/04/04 19:12

Koozy

総合スコア55

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問