findとfind_by
find
各モデルをidを検索キーとしてデータを取得するメソッド。
id以外の条件で検索不可。
存在しないユーザーを指定すると、例外が発生する。
(ActiveRecord::RecordNotFound)
User.find(1)
find_by
各モデルをid以外で検索するメソッド。
idでも検索可能。
複数の検索条件指定可能。
存在しないユーザーを指定するとnilが返る。
User.find_by(email: "user@example.com")
authenticateメソッド
authenticateメソッドは、
has_secure_passwordメソッドをユーザーモデルで呼び出すだけで使えるようになるメソッド。
authetnticateメソッドはパスワードを引数として使う。
誤ったパスワードを渡されるとfalseを返す。
正しいパスワードを渡されるとtrueを返す。
user&.authenticate(session_params[:password])
なんでここで&.(ぼっち演算子)を使ってメソッドを呼び出すのか?
→レシーバー(user)がnilでも、NoMethodErrorが出ないでnilを返すことができるから。
もしここでぼっち演算子を使わないと、
フォームにパスワードが格納されずに送られた場合、エラーが出てしまう。
(パスワードがnilだったらfalseの扱い)
def create user = User.find_by(email: session_params[:email]) if user&.authenticate(session_params[:password]) session[:user_id] = user.id redirect_to root_url else render :new end end
送られてきたメールアドレスでユーザーを検索する。
ユーザーが見つかったら、送られてきたパスワードを使ってメールアドレスとパスワードが一致するユーザーを探す。
一致するとセッションにuser_idを格納してroot_urlへ飛ぶ。
一致しない = falseかnilが返るとnewにレンダリングされる。
namespace
namespace
namespaceを使うとURLを新しく指定して、新たに作ったアクションにリクエストが飛ぶようになる。
管理画面のルーティングを作るときに用いられる。
rails generate migration ファイル名
を使ってadmin用のマイグレーションファイルを作る。
7つの基本的なアクションが作られる。
rails generate controller Admin::Users getアクション名
を使ってコントローラを作る。
マイグレーションファイルとコントローラを作ったら、ルーティングを定義する。
namespace :admin do resources :users end
この結果、admin/usersというURLが送られると、adminのusersコントローラのindexアクションに飛ぶ。
get '/admin/users', to: 'admin/users#index'
他にもよく似たscope、scope moduleがある。
scopeはURLだけを新たに指定することができる。
scope moduleはURLは変えずに、新たに作ったアクションにリクエストが飛ぶようになる。
rails generate
rails generateコマンドで生成されるファイルを把握していなかったので、簡単にまとめておく。
rails generate model User name:string
Userモデルを作って、nameカラムを作成する
生成されるファイル
* モデル
* マイグレーション
* テスト
rails generate migration ChangeTasksNameNotNull
tasksテーブルのnameをnull不可にする
テーブルのカラムの内容を変更するときに使う。
ファイルの名前は何を変えるのかわかりやすい名前にする。
生成されるファイル
* マイグレーション
* テスト
rails generate controller tasks index show
indexとshowのアクションを追加する
生成されるファイル
* コントローラ
* ビュー
* アセット
* ルート
* テスト
* ヘルパー
scope
繰り返し利用される絞り込み条件を読みやすくすることができる。
絞り込み条件とは
クエリー(SQLを実行したときにデータベースに送る命令文)のメソッドを使って、データベースのデータを絞り込むときに使う。
(例) Userのidを降順にして5つデータを表示する。
User.order(id: desc).limit(5)
scopeを使う
上記のメソッドを使ったデータはカンマでたくさん区切ってあって、
重複しているところに何度も同じコードを書くのも面倒で、コードを読むのも大変。
なのでscopeを使って書き換えてみる。
models/user.rb
scope :recent, -> { order(id: :desc).limit(5) }
users_controller.rb
def index @users = User.recent end
recentにクエリーの情報が含まれてメソッドとして使えるから、
コントローラーで複数のクエリーを書かなくて済む。
renderとredirect_toの使い分け
render
別のアクションを経由せずに、直接ビューを表示する。
使用目的 : エラーなどで処理が正常に完了せず、元の画面に戻したいだけの時に使用する。
def create render :new # 表示するviewファイルを指定 end
→ 登録に失敗したら、新規登録画面を表示する。
controller → view
(createアクション) → (新規登録画面)
redirect_to
他のURLに転送する。
使用目的 : データの追加(create)、更新(update)、削除(destroy)をしたいときに使用する。
def create task = Task.new(task_params) task.save! redirect_to tasks_url end
→ 登録画面で入力されたデータがデータベースに保存されて、一覧画面(tasks_url)に移動する
controller → URL → route → controller → view
(createアクション) → (HTTPリクエストを受け取る) → (リクエストを処理) → (indexアクション) → (一覧画面)
※ render、redirect_toを記述しないと、renderで処理される。(renderは省略可)
登録が成功するとき(データベースに変化があるとき)は、redirect_toを使う。
この認識でいいのかな〜。。