Pictweetの作成
必要なファイルを準備
アプリケーションの以下のディレクトリにある同名のファイルと入れ替える方法。
- app
- views
- layouts
- application.html.erb
- layouts
- views
入れ替える際は、以下の動画のようにすると便利。まずはfinder
を開き、その状態で別タブを開きます。別タブを開くためには、command + tキー
を押す。その後、
pictweet/app/views/layouts
ディレクトリまで開く。
続いて元からあった方のタブに移動し、ダウンロードしたapplication.html.erb
をドラッグ&ドラッグして先ほどの方に移動させ、置き換える。
「style.scss」と「setting.css」を下記のディレクトリに配置
style.scss
setting.css
※ファイルを追加する際、既に同じ名前のファイルが存在する場合は上書き保存する
- app
- assets
- stylesheets
- style.scss
- setting.css
- stylesheets
- assets
リンク先のファイルをダウンロードして「arrow_top.png」を下記のディレクトリに配置
arrow_top.png
- app
- assets
- images
- arrow_top.png
- images
- assets
デバッグツールの使い方
pry-rails
pry-railsはRails向けに開発されたデバッグツール。デバッグツールとは、作業の際にバグの有無を確認したり、処理を止めてソースコードが正しいかを確認する際に使用するツール。デバッグツールを使いこなすことで、より開発がしやすくなる。
pry-railsはGemとして提供されており、本開発では最初にGemのインストールを行った際にインストールしてある。
また、Gemをインストールした際は、サーバーを立ち上げ直す必要がある。それはインストールしたGemが反映されるタイミングがサーバーを立ち上げるときだから。
41 |
gem 'pry-rails'
|
pry-railsの機能の中で最も使用するのはbinding.pry(バインディングプライ)という機能。これは、binding.pry
という文字列をソースコードの中に記述することで、binding.pry
という文字列が存在する部分でRailsの処理を止めることができるというもの。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
以上のようにbinding.pry
という文字列を記述した上でローカルサーバーを立ち上げる。binding.pry
を記述したのはツイートを作成する部分の処理。つまり、PicTweetでツイートの投稿を行うと処理が止まる。
処理が止まると、以下のような画面がターミナルに表示される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Started POST "/tweets" for ::1 at 2012-03-22 09:18:00 +0900
Processing by TweetsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"FONntu/x3bU5uJ6hJmWtv792TnR7qaOUL7Vv42ObM8OBm3ETF61mgvbaXzEwrby2RDlxQmZApmmR5KpuIgC+tQ==", "name"=>"hoge", "image"=>"http://sample.jpg", "text"=>"Hello World!"}
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 6 ORDER BY `users`.`id` ASC LIMIT 1
Unpermitted parameters: utf8, authenticity_token, name
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `tweets` (`image`, `text`, `created_at`, `updated_at`) VALUES ('http://sample.jpg', 'Hello World!', '2015-03-31 05:32:52.087499', '2015-03-31 05:32:52.087499')
(0.4ms) COMMIT
From: /Users/hoge/projects/pictweet/app/controllers/tweets_controller.rb @ line 12 TweetsController#create:
10: def create
11: Tweet.create(tweet_params)
=> 12: binding.pry
13: end
[1] pry(#<TweetsController>)>
|
ここでは、この時点での変数の値を出力したりすることができる。仮に実装を行った際にエラーが出た場合、複数個のbinding.pry
を記述することで処理が正しく行われているのかを確認することができる。
binding.pry
で処理を止めた際には、コンソールとほぼ同じことができるので、変数を出力したい際などには出力したい変数を入力することで内容を出力できる。
1 2 3 4 5 6 7 8 9 10 11 |
From: /Users/hoge/projects/pictweet/app/controllers/tweets_controller.rb @ line 12 TweetsController#create:
10: def create
11: Tweet.create(tweet_params)
=> 12: binding.pry
13: end
[1] pry(#<TweetsController>)> tweet_params
Unpermitted parameters: utf8, authenticity_token
=> {"name"=>"hoge", "image"=>"http://images.sample.jpg", "text"=>"Hello World!"}
[2] pry(#<TweetsController>)>
|
処理を再開させたい場合にはexit
というコマンドを入力する。exit
コマンドを入力すると止まっていた処理が再開し、処理が再開される。また、exit!
とコマンドを入力するとローカルサーバーを終了させることもできる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
From: /Users/hoge/projects/pictweet/app/controllers/tweets_controller.rb @ line 12 TweetsController#create:
10: def create
11: Tweet.create(tweet_params)
=> 12: binding.pry
13: end
[1] pry(#<TweetsController>)> tweet_params
Unpermitted parameters: utf8, authenticity_token
=> {"name"=>"hoge", "image"=>"http://images.sample.jpg", "text"=>"Hello World!"}
[2] pry(#<TweetsController>)> exit
Rendered tweets/create.html.erb within layouts/application (0.0ms)
Completed 200 OK in 356078ms (Views: 69.0ms | ActiveRecord: 3.0ms)
Started GET "/assets/setting-6304eaa3803ad71fa1d106214a7dcf02.css?body=1" for ::1 at 2012-03-22 09:18:00 +0900
Started GET "/assets/users-bfd9b813b3d5121ad480bb8a65fd9bbc.css?body=1" for ::1 at 2012-03-22 09:18:00 +0900
|
binding.pryを利用してparams
を取得
では、binding.pryを使ったデバックを体験するために、実際にbinding.pryを利用して処理を止め、ビューから送られてくるパラメータであるparams
(パラムス)を表示する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
項目を入力して「SENT」ボタンを押す
「imageURL」「text」各欄を入力し、「SENT」ボタンを押す。すると、ページ遷移せずに現在の画面にとどまり続ける。
サーバーを立ち上げているターミナル画面を開き、params
と入力する
この時、サーバーを立ち上げているターミナル(rails s
コマンドを実行したターミナル画面)を見ると、以下のようにコマンドが入力できるようになっている。
中断した部分までで定義されている変数やメソッドを呼び出すことができるので、params
と入力する。以下のようなハッシュが表示されれば成功。
1 2 3 4 5 6 7 8 |
[1] pry(TweetsController)> params
#paramsと入力し、実行
=> {"utf8"=>"✓",
"authenticity_token"=>"/3QchQigdEcpc2VaOn+6IGIV14x1iJ5bDsM7GI5NA6k=",
"image"=>"http://sample/aaaabbbbccc.jpg",
"text"=>"hello!",
"action"=>"create",
"controller"=>"tweets"}
|
投稿フォームではhtmlのinput要素を使う。
「SENT」ボタンが押されリクエストされると、input要素の属性としてname="〇〇"と書いた部分がparams
内のキーに、入力欄に入力された文字がそのキーの値になり送信される。
binding.pry
で処理を中断している間はその時点で使える変数やメソッドを呼び出せるので、params
はこのcreateアクションの中で使うことができるハッシュのようなもの、ということになります。
ターミナルからparams[:text]
と入力し、実行
続いて、params
はハッシュなのでのキーを指定してそのキーの値を表示してみる。そのままターミナルにparams[:text]
と入力し、実行する。
1 2 3 |
[1] pry(TweetsController)> params[:text]
#params[:text]と入力し、実行
=> "hello!"
|
このように、先ほど投稿ページの「text」欄で入力したテキストが表示される。
ターミナル上でexit
コマンドを実行
このままではいつまで経っても、サーバーの処理がbinding.pry
で中断されたまま。exit
コマンドを実行し、処理を再開する。
1 2 |
TweetController>exit
#処理を再開
|
先ほどtweetsコントローラに追記したbinding.pry
を削除する。
binding.pryが残っていると、また同じ操作をした際に処理が中断してしまう。忘れずに消去する。
params/ストロングパラメーターに関する解説動画
paramsやストロングパラメーターに関しては処理の流れが複雑ですので、以下の動画を見て学習内容を整理する。
参考書参照
「プロになるためのWeb技術入門」p70 ~, 項3.4
1:ルートパスを追加
ツイート一覧のページを、アプリケーションのトップページに設定。
ルートパス
ウェブサイトへアクセスする際などに使用するURLには、ホスト名とパスの2つの部分が存在。「localhost:3000」や「pictweet.me」のように、パスを付けないホスト名だけのURLのことをルートパスと言う。
現在のPicTweetは「/tweets」にアクセスするとツイートの一覧画面が表示される。今回はルーティングを追記してルートパスにアクセスした際にツイート一覧画面が表示されるようにする。そのためには、routes.rbにルートパス専用のルーティングを設定する必要がある。以下の例のように、root コントローラ名#アクション名
と書く。
1 2 3 |
Rails.application.routes.draw do
root 'コントローラ名#アクション名'
end
|
問題1:ルートパスにアクセスした際にツイート一覧画面が表示されるようにする
作業ファイル:config/routes.rb
ヒント:ルートパスにアクセスした際にツイートの一覧画面を表示するためには、ルートパスに「/tweets」へアクセスした際と同じアクションを定義する。
ルートパスにアクセス
http://localhost:3000にアクセスして、ルートパスががきちんと反映されているか確認する。
こちらにアクセスすると、http://localhost:3000/tweetsにアクセスした画面と同じ画面になっているのが確認できる。これは、ルートパスによってtweets_controllerのindexアクションが動いているということ。
2:ツイートを最新順に並び替える
現在のPicTweetは、新しく投稿したツイートが1番下に表示されている。この表示の順番を最新のツイートが一番上に来るように表示させる。
orderメソッド
order
メソッドは、テーブルから取得してきたインスタンスたちを並び替えるメソッド。例えば「contents」という名前のテーブルがあり、以下のようにContentクラスからallメソッドを利用して全てのレコードを取得してきたとする時、order
メソッドを利用して取得してきたレコードを並び変えることができる。
1 2 3 |
def index
@contents = Content.all.order("id DESC")
end
|
all
メソッドを利用した場合、通常であればレコードはid順に取得されるが、上記のようにorder
メソッドの引数として("id DESC")
とすれば、レコードは逆順に並び替えられる。order
メソッドは引数として("テーブルのカラム名 並び替える順序")
という形を取る。並び替える順序には、ASC(昇順)
とDESC(降順)
の2種類がある。
問題2:最新のツイートが一番上に来るように表示させる
作業ファイル:app/controllers/tweets_controller.rb
ヒント:ツイートが作成された日時は、「created_at」カラムに記録される。
実際にhttp://localhost:3000でツイートを投稿して確認。
このサンプル画像のURLを使って投稿してみる。
最新順になっていれば以下の画像のようにトップページの一番上に投稿したツイートが表示される。
3:ページネーションを実装
ツイートの一覧画面にページネーションを実装して、1ページに表示されるツイートの数を5件にする。5件以降は次ページを作成して、そこに表示されるようにする。
ページネーション
ページネーションとは長い文章を複数のページに分割して、各ページへのリンクを並べアクセスしやすくすること。検索サイトのGoogleなども検索結果の表示にはページネーションを使用している。
作業内容
1.Gemをインストールしてサーバーを立ち上げ直す
2.コントローラファイルを編集する
3.ビューファイルを編集する
1.Gemをインストールしてサーバーを立ち上げ直す
ページネーションを実装する際には「kaminari」というGemをインストールして使用。またGemをインストールした後はrails s
をし直し、サーバーを立ち上げ直す必要がある。インストールしたGemが反映されるタイミングがサーバーを立てるときだから。
kaminari
kaminariはRubyのGemの一種。このGemをインストールすることによって、簡単にページネーションを実装することができる。
①Gemfileの最後の行に下記の記述を追記
kaminariをインストールするために、Gemfileの最終行に以下のように追記する。
1 2 |
(省略)
gem 'kaminari' # 最終行に追記してください
|
②bundle installを実行
③ローカルサーバーを再起動
1 |
$ rails s
|
2.コントローラファイルを編集
1ページに表示されるツイートの情報を5件にするということは、コントローラからビューに送るツイート情報も5件のみになる。その数を制御するために、kaminariをインストールすると使える2つのメソッドを利用する。
kaminari:pageメソッド
kaminariを導入すると、モデルクラスにpageメソッドが定義される。このメソッドは、ページネーションにおけるページ数を指定する。
ビューのリクエストの際params
の中にpageというキーが追加されて、その値がビューで指定したページ番号となる。なので、pageの引数はparams[:page]
となる。
kaminari:perメソッド
perメソッドもpageメソッドと同様、kaminariというgemをインストールすることで利用できるメソッド。1ページあたりに表示する件数を指定する。perメソッドに引数として渡した数字が、ページネーションが実装されたビューで1ページあたりに表示する件数になる。
上記2つのメソッドは、よく以下のように使われる。
1 |
変数名 = クラスを利用して取得したレコードのインスタンス.page(params[:page]).per(ここに1ページで表示したい件数を入力)
|
今回ページネーションを実装したいのはindexアクションのビューであり、コントローラで定義しビューに渡すのはtweetsテーブルのレコードである。
問題3:「page」と「per」メソッドを利用して@tweetsを定義する
作業ファイル:app/controllers/tweets_controller.rb
ヒント:当該ファイルに既にある、@tweetsへ代入している箇所(右辺)を書き換えましょう。orderメソッドの後ろに書き加える形。
3.ビューファイルを編集
ページネーションを実装する際にはコントローラだけでなくビューにも編集を加える必要がある。
kaminari:paginateメソッド
ページネーションのリンクを表示したいときに使用するメソッド。kaminariをインストールすると利用できる。paginateメソッドの引数は、コントローラで定義した変数を指定する。
1 2 3 4 5 6 7 8 9 |
これで、ページネーションを実装することができた。
このときデータベースのtweetsテーブルにレコードが6個以上ないとページネーションが表示されない。
tweetsテーブルにレコードを6個以上作成する。
tweetsテーブルにレコードが6つ以上あるか確認し、なければ、レコード数が6個以上になるようレコードを作成する。
http://localhost:3000にアクセス
下の方に、以下のようにページネーションが表示されていれば成功。
4:ログイン機能を作成
Twitterなどのウェブサイトにはログイン機能がある。この機能はサインアップしたユーザーに対してアカウントを発行し、そのアカウントで情報を管理することができる機能である。Railsの場合、ログイン機能は「devise」というGemを使用することで簡単に実装することができる。
以下の動画のように、ヘッダーにログイン/新規登録のボタンを置き、実際にログインするとその部分が登録したユーザー名と投稿するボタンになる。
今回はログイン機能を実装することで、ログインしたユーザーのみがツイートの投稿を行えるようにする。ツイートの閲覧に関してはログインにかかわらずできるようにする。
- ツイート閲覧時
- ツイート投稿時
作業内容
1.Gemをインストールしてサーバーを立ち上げ直す
2.コマンドを利用してdeviseの設定ファイルを作成する
3.コマンドを利用してUsersモデルを作成する
4.未ログイン時にはログインと新規登録ボタンを表示する
5.コントローラにリダイレクトを設定する
1.Gemをインストールしてサーバーを立ち上げ直す
ログイン機能を実装する際には「devise」というGemをインストールして使用する。またGemをインストールした後はrails s
をし直しサーバーを立ち上げ直す必要がある。これはインストールしたGemが反映されるタイミングがサーバーを立てるときだから。
devise
deviseは、ログイン機能を簡単に作成することができるGem。ログイン機能をGem無しで実装するのは非常に大変。しかし、このGemを使うことで比較的簡単に実装することができる。
①Gemfileの最終行に以下のように追記
1 2 |
(省略)
gem 'devise' # 最終行に追記してください
|
②bundle installを実行
③ローカルサーバーを再起動
1 |
$ rails s
|
2.コマンドを利用してdeviseの設定ファイルを作成
deviseを使用するためには、Gemのインストールに加えてdevise専用のコマンドを利用して設定ファイルを作成する必要がある。
1 2 |
$ rails g devise:install
# deviseの設定ファイルを作成
|
新規作成されるファイル
- config/initializers/devise.rb
- config/locales/devise.en.yml
3.コマンドを利用してUserモデルを作成
deviseを利用する際にはアカウントを作成するためのUserモデルを新しく作成する。作成には通常のモデルの作成方法ではなく、deviseのモデルの作成用コマンドを使用する。
rails g devise コマンド
deviseで、ログイン機能をつける概念のモデルを作成する際に利用するコマンド。モデルに加えて、ログイン機能のために必要なカラムが追加されるマイグレーションファイルなどが生成される。
①rails g deviseコマンドでuserモデルを作成する
1 2 |
$ rails g devise user
# deviseコマンドでモデルを作成
|
新規作成されるファイル
- app/models/user.rb
- db/migrate/2014XXXXXXXXXX_devise_create_users.rb
- test/fixtures/users.yml
- test/models/user_test.rb
また、config/routes.rbに以下の様な記述が自動的に追記される。
1 2 3 |
Rails.application.routes.draw do
devise_for :users
#以下略
|
devise_for
devise_forはログインまわりに必要なルーティングを一気に生成してくれるdeviseのヘルパーメソッド。
例えばdevise_for :users
の記述により、以下のように「ログイン・新規登録」で必要なルーティングが生成される。
また、後ほど登場するcurrent_user
やuser_signed_in?
などのヘルパーメソッドも利用できるようになる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Prefix Verb URI Pattern Controller#Action
root GET / tweets#index
tweets_new POST /tweets/new(.:format) tweets#new
tweets POST /tweets(.:format) tweets#create
GET /users/:user_id(.:format) users#show
DELETE /tweets/:id(.:format) tweets#destroy
GET /tweets/:id/edit(.:format) tweets#edit
PATCH /tweets/:id(.:format) tweets#update
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
|
②rake db:migrateを実行
1 2 |
$ rake db:migrate
# 作成されたマイグレーションファイルを実行
|
SequelProを開き、usersテーブルが作成されているか確認する
以下のように、usersテーブルが作成されていれば成功。
マイグレーションファイルを実行してもusersテーブルが表示されない場合は、データベース選択から「データベースを再読み込み」
を押すか、左下の再読み込みボタン
を押してみる。
user.rbを開き、5行目の「:trackable」を削除する。
:trackable
のみを削除する。:trackable
の記述がない場合はこの作業を行う必要ない。
1 2 3 4 5 6 |
lass User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
|
↓
1 2 3 4 5 6 |
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
end
|
4.未ログイン時にはログインと新規登録ボタンを表示
誰かが未ログイン時にツイート一覧画面を表示した際に、ヘッダーに投稿ボタンの代わりにログインと新規登録ボタンを表示するようにする。
Rubyタグ
<%=
と%>
で囲まれた部分をRubyタグと言う。Rubyタグは拡張子が「erb」のビューファイルで使用することができる。Rubyタグを使用して記述されたコードはビューファイルが読み込まれる際にHTMLコードとなって読み込まれる。また-%>
のように閉じるタグに-
をつける形もある。このようにすることで、余計な改行を取り除くことができる。
<%= %>と<% %>の違いは、Rubyタグに囲まれた処理の返り値をビューに出力するか、しないかという違いがある。
例1<%= tweet.text %>
これは計算結果を出力したいので<%= %>を使う。
例2<% if user.name == "たなかたろう" %>
これは条件分岐の処理に使いたいだけで、user_signed_in? の返り値は特に出力する必要はない。
状況に応じて、使い分ける。
link_toメソッド
link_to
はRubyタグの中で使用することができるメソッド。このメソッドは引数を指定することで様々なリンクを生成する。
通常HTMLコード内でリンクを生成する際にはaタグ
を使用する。link_to
メソッドを使って記述を行うと、HTMLコードが読み込まれる際にaタグ
に変換されるので、サイトを表示した際にはaタグ
と同様に、リンクとして表示される。今回の実装で追加するログインや新規登録ボタンもこのメソッドを利用して生成する。
1 2 |
<%= link_to 'ツイート一覧へ', '/tweets' %>
# link_toメソッドを使ってリンクを生成
|
また、htmlの要素に指定できるclass
などの属性は、以下のように続けてclass: 'sample'
などと書くことで付与することができる。
1 2 |
<%= link_to 'ツイート一覧へ', '/tweets', class: 'sample' %>
# 作成したaタグに`class="sample"`属性を付与
|
link_to
メソッドがビューファイルとして読み込まれる際には、以下の様なHTMLコードになる
1 |
<a class="sample" href="/tweets">ツイート一覧へ</a>
|
user_signed_in?
deviseでログイン機能を実装すると、user_signed_in?
というメソッドを使用することができる。これは、ユーザーがサインインしているかどうか検証するメソッド。
サインインしている場合にはtrue
を返し、サインインしていない場合にはfalse
を返す。
1 2 3 |
<% if user_signed_in? %>
# ユーザーがサインインしている場合に実行する処理
<% end %>
|
user_signed_in?
が返す値は最終的にtrue
かfalse
になるので、上記のようにif文または、unless文とともに使用する。
prefix
Prefix(プレフィックス)とは、ルーティングのパスが入る変数のこと。コントローラやビューなどで呼び出すことで、prefixに入っているパスやURL情報を取得できるようになる。Prefixは、routes.rbの各リクエストにオプションとして設定するが、記述によっては自動的に作成される場合もある。
これを確認するには、ターミナルからrake routes
コマンドを実行する。すると、以下のような表示になる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#rake routesコマンドの実行
$rake routes
#実行結果
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root GET / tweets#index
tweets_new GET /tweets/new(.:format) tweets#new
tweets POST /tweets(.:format) tweets#create
GET /users/:id(.:format) users#show
DELETE /tweets/:id(.:format) tweets#destroy
GET /tweets/:id/edit(.:format) tweets#edit
PATCH /tweets/:id(.:format) tweets#update
|
上記の表示でわかる通り、Prefixが設定されている場合は表の一番左に示される。
deviseを導入した場合、ユーザーの新規登録やログインに関するprefixは予め決まっており、以下のようになる。
deviseによって設定されるprefixの一部
リクエスト | prefix | パス |
---|---|---|
devise/sessions#new | new_user_session | /users/sign_in |
devise/sessions#create | user_session | /users/sign_in |
devise/sessions#destroy | destroy_user_session | /users/sign_out |
実際にprefixを利用する場合は、new_user_session_path
のように、最後に_path
とつける必要がある。
ヘッダー部分のhtmlは、全てのビューの共通のテンプレートであるapplication.html.erbに書く。
問題4:ログインしている時とそうでない時で表示するビューを変更する
作業ファイル:app/views/layouts/application.html.erb
ヒント:下記の例をもとに、user_signed_in?メソッドを利用。
【例】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<header class="header">
<div class="header__bar row">
<h1 class="grid-6"><a href="/">PicTweet</a></h1>
<% if ユーザーがサインインしている場合 %>
<div class="user_nav grid-6">
<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
<a class="post" href="/tweets/new">投稿する</a>
</div>
<% サインインしていない場合 %>
<div class="grid-6">
<%= link_to "ログイン", new_user_session_path, class: 'post' %>
<%= link_to "新規登録", new_user_registration_path, class: 'post' %>
</div>
<% 閉じタグ %>
</div>
</header>
|
localhost:3000でログインしている時としていない時でヘッダー部分の表示が変わることを確認する
ログインしていない時
「ログイン」「新規作成」ボタンの2つが表示されていることが確認できる。
ログインしている時
「ログアウト」「投稿する」ボタンの2つが表示されていることが確認できる。
5. コントローラにリダイレクトを設定
上記の作業で未ログインユーザーがツイートの一覧画面を表示しても投稿ボタンが表示されなくなった。しかし、未ログインユーザーであっても直接/tweets/new
というパスにアクセスすることで投稿ができてしまう。
localhost:3000/tweets/new にアクセスする
ログインしてない状態でもlocalhost:3000/tweets/newにアクセスできるのが確認できる。
そこで、未ログインユーザーが投稿画面など直接アクセスしてきた際にはルートパスに遷移するように設定を行う。
unless文
ここまで条件分岐にはif文を使用してきたが、似た制御構造を持つものとしてunless文がある。unless文は条件式が偽(false)の場合の処理を記述するのに使われる。ユーザーがログインしていない場合の条件分岐の最も基本的なunless文の書き方。
1 2 3 |
unless 条件式
# 条件式が偽(false)のときに実行する処理
end
|
また条件分岐の中が一行で記述できる場合は、if/unless文は以下のように一行で記述することができる。記述が簡単で見やすくなるので、一行で記述できる場合は一行で記述する。
1 2 3 4 5 6 |
puts 'ログインをしてください' unless user_signed_in?
# 以下と同義
unless user_signed_in?
puts 'ログインをしてください'
end
|
redirect_toメソッド
Railsでは通常、アクション内の処理が終了すると自動的にアクション名と同名のビューが表示される。
ただしredirect_toメソッドをアクション内で利用すると、そこからさらに別のアクションを実行したり、ビューに遷移させたりできる。
引数にはaction: :index
という形で、キーがaction:
バリューが:index
であるハッシュを指定する。このようにバリューにはアクションの名前のシンボル型を利用する。丁寧に書くのであれば{ action: :index }
となるが、Railsの内部では特別にハッシュの括弧{}
を省略することができる。
indexアクションを実行させるために、redirect_to action: :index
とする
1 2 3 4 5 6 7 8 9 10 11 12 |
class TweetsController < ApplicationController
def index
@tweets = Tweet.page(params[:page]).per(5).order("created_at DESC")
end
private
def move_to_index
redirect_to action: :index
# indexアクションを強制的に実行する
end
end
|
before_action
Railsではコントローラでbefore_action :メソッド名と記述することで、コントローラのアクションが実行される前にそのメソッドを実行することができる。
また、オプションonlyやexceptを使うことにより、before_actionを実行することをアクションごとに制限をかけることができる。
indexアクション以外でbefore_actionを実行したい場合
1 2 3 4 5 6 7 8 9 10 11 12 13 |
問題5:ログインしていないときに新規投稿しようとすると、indexアクションにリダイレクトされるようする
作業ファイル:app/controllers/tweets_controller.rb
ヒント:before_actionは全てのアクションの実行前に強制的に実行されるメソッドを設定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
class TweetsController < ApplicationController
before_action :move_to_index, indexアクションの場合は実行しない条件をつける
def index
@tweets = Tweet.page(params[:page]).per(5).order("created_at DESC")
end
def new
end
def create
Tweet.create(tweet_params)
end
private
def tweet_params
params.permit(:name, :image, :text)
end
def move_to_index
# ログインしていなかった場合、「index」アクションを実行する
end
end
|
5:ログイン・サインアップ画面のビューを変更
deviseを使用してログイン機能を実装すると自動的にログイン画面とサインアップ画面が生成される。元のままの見た目だと味気ないため、以下画像のようなサインイン/サインアップ画面に変更する。
作業内容
1.devise用のビューファイルを作成する
2.ログイン・サインアップ画面のビューファイルを編集する
devise用のビューファイルを作成
deviseでログイン機能を実装すると、ログイン・サインアップ画面は自動的に生成されるがビューファイルとしては生成されない。これは、deviseのGem内に存在するビューファイルを読み込んでいるため。
ビューファイルに変更を加えるためには、deviseのコマンドを利用してビューファイルを生成する必要がある。
1 |
$ rails g devise:views
|
新規作成されるファイル
app/views/devise
以下のディレクトリにあるビューファイル各種
ログイン・サインアップ画面のビューファイルを編集
devise用の生成されたビューファイルを編集してレイアウトを変更していく。
- サインアップ画面は
app/views/devise/registrations/new.html.erb
、ログイン画面のビューはapp/views/devise/sessions/new.html.erb
というビューファイルが対応している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<div class="contents row">
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email %>
</div>
<div class="field">
<%= f.label :password %>
<% if @validatable %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
</div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<div class="contents row">
<h2>Log in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<% if devise_mapping.rememberable? -%>
<div class="field">
<%= f.label :remember_me %><br />
<%= f.check_box :remember_me %>
</div>
<% end -%>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
</div>
|
変更できたか確認
localhost:3000/users/sign_inにアクセスし、
以下の画面になっていることを確認。
localhost:3000/users/sign_upにアクセスし、
以下の画面になっていることを確認。
6:サインアップ時にニックネームを登録
現在、サインアップ時に登録する情報はメールアドレスとパスワードの2つ。これに加えてニックネームを登録できるようにする。
作業内容
1.ユーザーテーブルにカラムを追加する
2.登録画面のビューを編集する
3.ストロングパラメーターを編集する
1.ユーザーテーブルにカラムを追加
ニックネームを登録するために、usersテーブルにニックネームを保存するためのカラムを追加する。追加したカラムに、サインアップ時に登録するニックネームを保存する。
カラムを追加するマイグレーションファイルの作成
カラムを追加するマイグレーションファイルを作成するためには、下記のコマンドを実行する。
$ rails g migration Addカラム名To追加先テーブル名 追加するカラム名:型
userの自己紹介を保存するためのカラム、introductionカラムをusersテーブルにtext型で追加したい時は、以下の例のように書く。
1 2 |
この時、「Add」「Introduction」「To」「Users」と、単語の頭文字が大文字になっている。この表記方法について。
スネークケースとキャメルケース
プログラムが単語の区切りを認識する際、2通りの方法がある。それらをそれぞれ「スネークケース、キャメルケース」と呼ぶ。
スネークケースは、例えば「sample_hoge_huga」のように「_」で単語を区切る方法。対してキャメルケースは、「SampleHogeHuga」のように単語の頭文字を大文字にすることで単語を区切る。
問題6:usersテーブルに、nicknameカラムをstring型で追加しましょう
Addカラム名To追加先テーブル
のカラム名の部分は、必ずしも厳密なカラム名を入力する必要はない。
今回はnicknameというカラムを追加するので今回はNicknameと記述する。
実際にカラムが追加された確認
SequelProを起動し、usersテーブルを開きます。一番右にスクロールして新しく追加されたnicknameカラムを確認する。
2.登録画面のビューを編集
これでDB側の準備は整ったので、続いてユーザーの新規登録画面にニックネームを登録するためのフォームを追加する。ユーザーの新規登録画面のビューは、app/views/devise/registrations/new.html.erb
です。その際、オプションをつけることで入力できる文字数を6文字以下にする。
text_field:maxlengthオプション
maxlengthは、text_fieldというinputタグを生成するヘルパーメソッドにつけることができるオプション。
6 7 8 |
<div class="field">
<%= f.text_field :nickname, autofocus: true, maxlength: "6" %>
</div>
|
この場合、生成されたフォームに7文字以上入力すると、エンターキーを押した瞬間に6文字までカットされる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<div class="contents row">
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :nickname %> <em>(6 characters maximum)</em><br />
<%= f.text_field :nickname, autofocus: true, maxlength: "6" %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email %>
</div>
<div class="field">
<%= f.label :password %>
<% if @validatable %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
</div>
|
3.ストロングパラメーターを編集
サインアップ時に入力する情報はパラメーターとしてサーバーに送信される。通常のリクエストの場合は、コントローラに記述してあるストロングパラメーターで受け取れるパラメーターを制限する。
しかし、deviseでログイン機能を実装した場合のパラメーターの受け取り方は通常とは異なる。ログイン時に送られてくるパラメーターを制限するストロングパラメーターは、deviseのGem内に記述されているため編集することはできない。
今回追加したニックネームを受け取れるようにするにはdeviseが提供しているconfigure_permitted_parametersメソッドを利用する。
configure_permitted_parametersメソッド
deviseでは初期状態でサインアップ時にメールアドレスとパスワードのみを受け取るようにストロングパラメーターが設定してあるので、追加したキーのパラメーターは許可されていない。追加のパラメーターを許可したい場合は、application_controller
においてbefore_action
にconfigure_permitted_parametersメソッド
を設定する。
1 2 3 4 5 6 7 8 9 10 |
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:ストロングパラメーターを追加したいアクション名, keys: [:追加するキー])
end
end
|
sign_upアクションに対してnicknameというキーのパラメーターを追加で許可する。
1 2 3 4 5 6 7 8 9 10 |
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
end
end
|
登録画面のビューを確認してみる
localhost:3000/users/sign_upにアクセスして、nicknameを入力するフォームができていることを確認。
ここまでできたら、実際にユーザーを作成してニックネームが登録できるか確かめてみる
pictweetのトップページから、新規でユーザーを作成してみる。
localhost:3000/users/sign_upにアクセスして、nicknameを保存する。
きちんと保存できているかどうかSequelProで確認してみましょう。