railsコマンド(rails) - - Railsドキュメントより引用. しかし作ったModelやControllerを削除するにはどうしたらいいのか? googletag.defineSlot('/21812778492/blog_300x250_common_sidemiddle01_adsense', [[300, 250], [336, 280]], 'div-gpt-ad-1565198726712-0').addService(googletag.pubads()); googletag.pubads().collapseEmptyDivs(); 「def change」文があるので、「def change」ブロック内に googletag.defineSlot('/21812778492/blog_728x90_common_overlay_adsence', [728, 90], 'div-gpt-ad-1583302554779-0').addService(googletag.pubads()); Kaizen Platformさんのプロダクトは日々着実に拡大を続けていて、githubの社内リポジトリ数も今や200を超えていますが、そんなKaizenのプロダクトも最初期には単一のRailsリポジトリからスタートしました。 rails destroy model (削除する)モデル名, 2.マイグレーションファイル作成(コマンド) Ruby on Railsで作成したdbに存在するテーブルを削除する方法 (2, 'admin', '1', TRUE, NOW(), NOW(), FALSE, FALSE, 'MembershipRole::Organization'), (3, 'member', '1/2', FALSE, NOW(), NOW(), FALSE, FALSE, 'MembershipRole::Organization'), Google Colaboratory で Qiita:Team の全投稿を取得して、可視化したり、…, AWS 上で利用している SSL/TLS 証明書を一括管理するツール aws-cert-utils …, 「not 緊急 but 重要」に取り組む1週間 / Kaizen Week #7を開催しました, 若手エンジニア × CTO 対談(後編) ~ Kaizen Platformの課題とこれから, 若手エンジニア × CTO 対談(前編) ~ Kaizen Platformに入社してみてどうだった?. →フェイスブックはこちら, 初心者でもかんたん!Ruby on Rails の開発環境の構築手順(Mac/Windows 両対応), 【Rails入門】saveがすべて成功したことを保証する(transaction), 「id:3, user_id:3,title:"昨日の出来事" ,month:12」, 「id:4, user_id:3,title:"山登りに行きました" ,month:8」, 「id:8, user_id:3,title:"Ruby on Railsの日" ,month:9」, id:5, user_id:4,title:"友人が結婚しました" ,month:4, id:7, user_id:4,title:"ランニングのコツ" ,month:9. 以下のような時ですね↓, Modelの名前ミスって作っちゃった! RailsでBootstrapを使う場合は、gemを使ってインストールする方法が一般的です。 Bootstrapは内部でjQueryを利用しているので、こちらもあわせてインストールしましょう。 Gemfileに以下を追記して、bundle installを実行し … ModelやControllerを作成する時は「generate」というコマンドを使ったわけですが、削除する時は「destroy」というコマンドを使用します。, そしてコマンドを実行すると先程作成してくれたファイルを削除してくれていることが分かります。, ControllerもModelの時と一緒。 var pbjs=pbjs||{}; マイグレーション実行を忘れない事っぽそう。 なるほど、便利なコマンドですね!₍₍ (ง ˙ω˙)ว ⁾⁾, 先程のサイトでは、その他に削除出来るものも一覧で出ていますので、是非参考にしてみて下さい。 ユーザーの一覧ページはついに完了しました。残るはdestroyだけです。これを実装することで、RESTに準拠した正統なアプリケーションとなります。この節では、ユーザーを削除するためのリンクを追加します。 googletag.pubads().enableSingleRequest(); なので、以下のように書いた場合はエラーになります。, 「じゃあscaffoldも削除出来るの?」と思って調べたら、scaffoldも同じでした。, destroyで「helper」や「migration」なども削除出来るようです。 まず、 「rails destroy model unitprice」 でモデルを作成時にできたファイルを削除する。 $ rails destroy model unitprice Running via Spring preloader in process 21471 invoke active_record remove db/migrate/20181007144100_create_unitprices.rb remove app/models/unitprice.rb googletag.defineSlot('/21812778492/blog_300x250_common_sidetop01_adsense', [[300, 250], [336, 280]], 'div-gpt-ad-1565330658303-0').addService(googletag.pubads()); rollback of DropLegacyTables does't restore legacy tables. 「1」でcreateマイグレーションファイルが削除されているけど、 図9.1のモックアップを動くページにするためには、Usersコントローラにeditアクションを追加して、それに対応するeditビューを実装する必要があります。editアクションの実装から始めますが、ここではデータベースから適切なユーザーデータを読み込む必要があります。ここで注意して頂きたいのは、表7.1ではユーザー編集ページの正しいURLが/users/1/editとなっていることです (ユーザーのidが1の場合)。ユーザーのidはparams[:id]変数で取り出すことができるのを思い出してください。つまり、リスト9.1のコードを使えばそのユーザーを指定できるということです。, ユーザー編集ページに対応するビュー を、リスト9.2に示します (このファイルは手動で作成する必要があります)。このコードがリスト7.13と極めて似通っていることに注目してください。重複が多いということは、それらのコードの繰り返しをパーシャルにまとめることができるということです。パーシャルにまとめる作業は演習の課題 (9.6) に回します。, 上のコードでは、7.3.3で導入したerror_messagesパーシャルを再利用しています。ところで、Gravatarへのリンクでtarget="_blank"が使われていますが、これを使うとリンク先を新しいタブ (またはウィンドウ) で開くようになるので、別のWebサイトへリンクするときなどに便利です。, リスト9.1の@userインスタンス変数使うと、編集ページがうまく描画されるようになります (図9.2)。図9.2の"Name"や"Email"の部分を見ると、Railsによって名前やメールアドレスのフィールドに値が自動的に入力されていることがわかります。これらの値は、@user変数の属性情報から引き出されています。, 図9.2のHTMLソースを見てみると、少しだけ違う箇所もありますが、おおよそformタグは期待どおりに表示されています (リスト9.3)。。, WebブラウザはネイティブではPATCHリクエスト (表7.1でRESTの慣習として要求されている) を送信できないので、RailsはPOSTリクエストと隠しinputフィールドを利用してPATCHリクエストを「偽造」しています2。, ここでもう1つ微妙な点を指摘しておきたいと思います。リスト9.2のform_for(@user)のコードは、リスト7.13のコードと完全に同じです。だとすると、Railsはどうやって新規ユーザー用のPOSTリクエストとユーザー編集用のPATCHリクエストを区別するのでしょうか。その答えは、Railsは、ユーザーが新規なのか、それともデータベースに存在する既存のユーザーであるかを、Active Recordのnew_record?論理値メソッドを使用して区別できるからです。, Railsは、form_for(@user)を使用してフォームを構成すると、@user.new_record?がtrueのときにはPOSTを、falseのときにはPATCHを使用します。, 仕上げに、ナビゲーションバーにあるユーザー設定へのリンクを更新します。表7.1で示したedit_user_pathという名前付きルートと、 リスト8.36で定義したcurrent_userというヘルパーメソッドを使うと、実装が簡単です。, 本項では、7.3のユーザー登録に失敗したときと似た方法で、編集に失敗した場合について扱っていきます。まずはupdateアクションの作成から進めますが、これはリスト9.5にあるように、update_attributes (6.1.5) を使って送信されたparamsハッシュに基いてユーザーを更新します。無効な情報が送信された場合、更新の結果としてfalseが返され、elseに分岐して編集ページをレンダリングします。このパターンは以前にも出現したことを覚えているでしょうか。この構造はcreateアクションの最初のバージョン (リスト7.16) と極めて似通っています。, update_attributesへの呼び出しでuser_paramsを使用していることに注目してください。7.3.2でも説明したように、ここではStrong Parametersを使用してマスアサインメントの脆弱性を防止しています。, Userモデルのバリデーションとエラーメッセージのパーシャルが既にあるので (リスト9.2)、無効な情報を送信すると役立つエラーメッセージが表示されるようになっています (図9.3)。, 9.1.2では編集フォームの失敗時を実装しました。次に、コラム3.3で説明したテストのガイドラインに従って、エラーを検知するための統合テストを書いていきましょう。まずはいつものように、統合テストを生成するところから始めます。, 最初は編集失敗時の簡単なテストを追加します (リスト9.6)。リスト9.6のテストでは、まず編集ページにアクセスし、editビューが描画されるかどうかをチェックしています。その後、無効な情報を送信してみて、editビューが再描画されるかどうかをチェックします。ここで、PATCHリクエストを送るためにpatchメソッドを使っていることに注目してください。これはgetやpost、deleteメソッドと同じように、HTTPリクエストを送信するためのメソッドです。, 今度は編集フォームが動作するようにしましょう。プロファイル画像の編集は、画像のアップロードをGravatarに任せてあるので、既に動作するようになっています。図9.2の [change] リンクをクリックすれば、図9.4のようにGravatarを編集できます。ではそれ以外の機能の実装にとりかかりましょう。, そろそろ、より快適にテストをするためには、アプリケーション用のコードを「実装する前に」統合テストを書いた方が便利だと気付いた読者もいるかもしれません。実際、そういったテストのことは「受け入れテスト (Acceptance Tests)」として呼ばれていて、ある機能の実装が完了し、受け入れ可能な状態になったかどうかを決めるテストとして知られています。実際に体験してもらうために、今回はテスト駆動開発を使ってユーザーの編集機能を実装してみましょう。, まずは、リスト9.6のテストを参考にして、ユーザー情報を更新する正しい振る舞いをテストで定義します (今回は有効な情報を送信するように修正します)。次に、flashメッセージが空でないかどうかと、プロフィールページにリダイレクトされるかどうかをチェックします。また、データベース内のユーザー情報が正しく変更されたかどうかも検証します。変更の結果をリスト9.8に示します。このとき、リスト9.8のパスワードとパスワード確認が空であることに注目してください。ユーザー名やメールアドレスを編集するときに毎回パスワードを入力するのは不便なので、(パスワードを変更する必要が無いときは) パスワードを入力せずに更新できると便利です。また、6.1.5で紹介した@user.reloadを使って、データベースから最新のユーザー情報を読み込み直して、正しく更新されたかどうかを確認している点にも注目してください。(こういった正しい振る舞いというのは一般に忘れがちですが、受け入れテスト (もしくは一般的なテスト駆動開発) では先にテストを書くので、効果的なユーザー体験について考えるようになります。), テストにパスする必要のある、リスト9.8のupdateアクションは、リスト9.9に示したように、createアクション (リスト8.22) の最終的なフォームとほぼ同じです。, リスト9.9のキャプションにも書いておきましたが、このテストはまだREDのままのはずです。というのも、パスワードの長さに対するバリデーション (リスト6.39) があるので、パスワードやパスワード確認の欄を空にしておくとこれに引っかかってしまうからです (リスト9.8)。テストがGREENになるためには、パスワードのバリデーションに対して、空だったときの例外処理を加える必要があります。こういったときに便利なallow_nil: trueというオプションがあるので、これを validatesに追加します (リスト9.10)。, リスト9.10によって、新規ユーザー登録時に空のパスワードが有効になってしまうのかと心配になるかもしれませんが、安心してください。6.3.3で説明したように、has_secure_passwordでは (追加したバリデーションとは別に) オブジェクト生成時に存在性を検証するようになっているため、空のパスワードが新規ユーザー登録時に有効になることはありません。(それだけでなく、実は空のパスワードを入力すると存在性のバリデーションとhas_secure_passwordのバリデーションがそれぞれ実行され、2つの同じエラーメッセージが表示されるというバグがあったのですが、この問題も解決できてしまいます。), このコードを追加したことにより、ユーザー編集ページが動くようになります (図9.5)。すべてのテストを走らせてみて、成功したかどうか確かめてみてください。, ウェブアプリケーションの文脈では、認証 (authentication) はサイトのユーザーを識別することであり、認可 (authorization) はそのユーザーが実行可能な操作を管理することです。第8章で認証システムを構築したことで、認可のためのシステムを実装する準備もできました。, 9.1のeditアクションとupdateアクションはすでに完全に動作していますが、セキュリティ上の大穴が1つ空いています。 どのユーザーでもあらゆるアクションにアクセスでき、ログインさえしていれば他のユーザーの情報を編集できてしまいます。この節では、ユーザーにログインを要求し、かつ自分以外のユーザー情報を変更できないようにするセキュリティモデルを構築しましょう。, 9.2.1では、ログインしていないユーザーが保護されたページにアクセスしようとした際のケースについて対処していきます。こういったケースはアプリケーションを使っていると普通に起こることなので、ログインページに転送して、そのときに分かりやすいメッセージも表示するようにしましょう。モックアップを図9.6に示します。一方で、許可されていないページに対してアクセスするログイン済みのユーザーがいたら (たとえば他人のユーザー編集ページにアクセスしようとしたら)、ルートURLにリダイレクトさせるようにします (9.2.2)。, 図9.6のように転送させる仕組みを実装したいときは、Usersコントローラの中でbeforeフィルターを使います。beforeフィルターは、before_actionメソッドを使って何らかの処理が実行される直前に特定のメソッドを実行する仕組みです3。今回はユーザーにログインを要求するために、リスト9.12のようにlogged_in_userメソッドを定義してbefore_action :logged_in_userという形式で使います, デフォルトでは、beforeフィルターはコントローラ内のすべてのアクションに適用されるので、ここでは適切な:onlyオプションハッシュを渡すことによって:editと:updateアクションにのみこのフィルタが適用されるように制限をかけています。, beforeフィルターを使って実装した結果 (リスト9.12) は、一度ログアウトしてユーザー編集ページ (/users/1/edit) にアクセスしてみることで確認できます (図9.7)。, 原因は、editアクションやupdateアクションでログインを要求するようになったため、ログインしていないユーザーだとこれらのテストが失敗するようになったためです。, このため、editアクションやupdateアクションをテストする前にログインしておく必要があります。解決策は簡単で、 8.4.6で開発したlog_in_asヘルパー (リスト8.50) を使うことです。修正した結果をリスト9.14に示します。, (リスト9.14のsetupメソッド内でログイン処理をまとめてしまうことも可能です。しかし、9.2.3で片方のテストをログインする前に編集ページにアクセスするように変更したいので、ここでまとめてしまっても結局は元に戻すことになってしまいます。), これでテストスイートがパスするようになりましたが、実はbeforeフィルターの実装はまだ終わっておりません。セキュリティモデルに関する実装を取り外してもテストがGREENになってしまうかどうか、実際にコメントアウトして確かめてみましょう (リスト9.16)。なんと悪いことに、すべてのテストが成功してしまいました。beforeフィルターをコメントアウトして巨大なセキュリティーホールが作られたら、テストスイートでそれを検出できるべきです。つまり、リスト9.16のコードはREDにならなければいけないのです。テストを書いて、この問題に対処しましょう。, beforeフィルターは基本的にアクションごとに適用していくので、Usersコントローラのテストもアクションごとに書いていきます。具体的には、正しい種類のHTTPリクエストを使ってeditアクションとupdateアクションをそれぞれ実行させてみて、flashにメッセージが代入されたかどうか、ログイン画面にリダイレクトされたかどうかを確認してみましょう。表7.1から、適切なリクエストはそれぞれGETとPATCHであることがわかります。したがって、テスト内ではgetメソッドとpatchメソッドを使います。修正した結果をリスト9.17に示します。, 上のコードでは、Railsの慣習によってid: @userという引数が自動的に@user.idに変換されています (これはコントローラでリダイレクトしたときと同様です)。2つ目のケースでは、ルーティングで正しく処理されるようにuserというハッシュも渡しています。(実は第2章のToyアプリケーションのUsersコントローラではテストも生成されていて、中を見ると上と同じコードになっています。), この時点では、(beforeフィルターが無効のままなので) テストスイートはREDになるはずです。beforeフィルターのコメントアウトを元に戻して、GREENになるかどうか確かめてみましょう (リスト9.18)。, これらのテストを実装したことによって、うっかり誰でも編集できてしまうバグがあっても、すぐに検知できるようになりました。, 当然のことですが、ログインを要求するだけでは十分ではありません。ユーザーが自分の情報だけを編集できるようにする必要があります。9.2.1では、深刻なセキュリティ上の欠陥を見逃してしまうテストを見てきました。そこで本項では、セキュリティモデルが正しく実装されている確信を持つために、テスト駆動開発で進めていきます。したがって、Usersコントローラのテスト (リスト9.17) を補完するように、テストを追加するところから始めていきます。, まずはユーザーの情報が互いに編集できないことを確認するために、サンプルユーザーをもう一人追加します。ユーザー用のfixtureファイルに2人目のユーザーを追加してみましょう (リスト9.20)。, 次に、 リスト8.50で定義したlog_in_asメソッドを使って、editアクションとupdateアクションをテストします (リスト9.21)。このとき、既にログイン済みのユーザーを対象としているため、ログインページではなくルートURLにリダイレクトしている点に注意してください。, 別のユーザーのプロフィールを編集しようとしたらリダイレクトさせたいので、correct_userというメソッドを作成し、beforeフィルターからこのメソッドを呼び出すようにします (リスト9.22)。beforeフィルターのcorrect_userで@user変数を定義しているため、リスト9.22ではeditとupdateの各アクションから、@userへの代入文を削除している点にも注意してください。, 最後に、リファクタリングではありますが、一般的な慣習に倣ってcurrent_user?という論理値を返すメソッドを実装します。correct_userの中で使えるようにしたいので、Sessionsヘルパーの中にこのメソッドを追加します (リスト9.24)。このメソッドを使うと今までの, 先ほどのメソッドを使って比較演算していた行を置き換えると、リスト9.25になります。, ここまででWebサイトの認可機能は完成したかのように見えますが、後1つ小さなキズがあります。保護されたページにアクセスしようとすると、問答無用で自分のプロファイルページに移動させられてしまいます。別の言い方をすれば、ログインしていないユーザーが編集ページにアクセスしようとしていたなら、ユーザーがログインした後にはその編集ページにリダイレクトされるようにするのが望ましい動作です。リダイレクト先は、ユーザーが開こうとしていたページにしてあげるのが親切というものです。, 実際のコードは少し複雑ですが、フレンドリーフォワーディングのテストは非常にシンプルに書くことができます。ログインした後に編集ページへのアクセスする、という順序を逆にしてあげるだけです (リスト9.14)。リスト9.26が示すように、実際のテストはまず編集ページにアクセスし、ログインした後に、(デフォルトのプロフィールページではなく) 編集ページにリダイレクトされているかどうかをチェックするといったテストです。(なお、リダイレクトによってedit用のテンプレートが描画されなくなったので、リスト9.26では該当するテストを削除しています), 失敗するテストが書けたので、ようやくフレンドリーフォワーディングを実装する準備ができました4。ユーザーを希望のページに転送するには、リクエスト時点のページをどこかに保存しておき、その場所にリダイレクトさせる必要があります。この動作をstore_locationとredirect_back_orの2つのメソッドを使用して実現してみましょう。なお、これらのメソッドはSessionsヘルパーで定義しています (リスト9.27)。, 転送先のURLを保存する仕組みは、8.2.1でユーザーをログインさせたときと同じで、session変数を使います。また、リクエスト先のURLを取得するために、リスト9.27ではrequestオブジェクトも使っています (request.urlでリクエスト先が取得できます)。, リスト9.27のstore_locationメソッドでは、 リクエストが送られたURLをsession変数の:forwarding_urlキーに格納しています。ただし、GETリクエストが送られたときだけ格納するようにしておきます。これによって、たとえばログインしていないユーザーがフォームを使って送信した場合、転送先のURLを保存させないようにできます。これは稀なケースですが起こり得ます。たとえばユーザがセッション用のcookieを手動で削除してフォームから送信するケースなどです。こういったケースに対処しておかないと、POSTや PATCH、DELETEリクエストを期待しているURLに対して (リダイレクトを通して) GETリクエストが送られてしまい、場合によってはエラーが発生します。このため、if request.get?という条件文を使ってこのケースの対策しています5。, 先ほど定義したstore_locationメソッドを使って、早速beforeフィルターのlogged_in_userを修正してみます (リスト9.28)。, フォワーディング自体を実装するには、redirect_back_orメソッドを使用します。リクエストされたURLが存在する場合はそこにリダイレクトし、ない場合は何らかのデフォルトのURLにリダイレクトします。デフォルトのURLは、Sessionコントローラのcreateアクションに追加し、サインイン成功後にリダイレクトします (リスト9.29)。redirect_back_orメソッドでは、次のようにor演算子||を使用します。, このコードは、値がnilでなければsession[:forwarding_url]を評価し、nilであれば与えられたデフォルトのURLを使用しますリスト9.27では、session.delete(:forwarding_url) という式を通して転送用のURLを削除している点に注意してください。これをやっておかないと、次回ログインしたときに保護されたページに転送されてしまい、ブラウザを閉じるまでこれが繰り返されてしまいます (このコードのテストは9.6の演習とします)。ちなみに、最初にredirect文を実行しても、セッションが削除される点を覚えておくとよいでしょう。実は、明示的にreturn文やメソッド内の最終行が呼び出されない限り、リダイレクトは発生しません。したがって、redirect文の後にあるコードでも、そのコードは実行されるのです。, これで、リスト9.26のフレンドリーフォワーディング用統合テストはパスするはずです。成功すれば、基本ユーザー認証機能とページ保護機能の実装は完了です。いつものように、以下を実行してテストスイートが 緑色 (成功) になることを確認してから先に進みましょう。, この節では、いよいよ最後から2番目のユーザーアクションであるindexアクションを追加しましょう。このアクションは、すべてのユーザーを一覧表示します。その際、データベースにサンプルデータを追加する方法や、将来ユーザー数が膨大になってもindexページを問題なく表示できるようにするためのユーザー出力のページネート (paginate=ページ分割) の方法を学びます。ユーザーの一覧、ページネーション用リンク、移動用の [Users] リンクのモックアップを図9.8に示します6。, ユーザーの一覧ページを実装するために、まずはセキュリティモデルについて考えてみましょう。ユーザーのshowページについては、今後も (ログインしているかどうかに関わらず) サイトを訪れたすべてのユーザーから見えるようにしておきますが、ユーザーのindexページはログインしたユーザーにしか見せないようにし、未登録のユーザーがデフォルトで表示できるページを制限します7。, indexページを不正なアクセスから守るために、まずはindexアクションが正しくリダイレクトするか検証するテストを書いてみます (リスト9.31)。, 次に、beforeフィルターのlogged_in_userにindexアクションを追加して、このアクションを保護します (リスト9.32)。, 今度はすべてのユーザーを表示するために、全ユーザーが格納された変数を作成し、順々に表示するindexビューを実装します。Toyアプリケーションにも同じindexアクションがあったことを思い出してください (リスト2.5)。そのときと同様に、User.allを使ってデータベース上の全ユーザーを取得し、ビューで使用可能な@usersというインスタンス変数に代入させます (リスト9.33)。(すべてのユーザーを一気に読み出すとデータ量が多い場合に問題が生じるのではないかと思われた方、そのとおりです。このキズは9.3.3で修正します。), 実際のインデックスページを作成するには、ユーザーを列挙してユーザーごとにliタグで囲むビューを作成する必要があります。ここではeachメソッドを使用してこれを行います。それぞれの行をリストタグulで囲いながら、各ユーザーのGravatarと名前を表示します (リスト9.34)。