これでログインページをリロードしてみてください。サイドメニューの表示が消えましたか?
このように、認証をかけるときは、必ずコントローラとテンプレートの両方に認証をかけるよ うにしてください。
commit
(2) . ユーザ管理画面の作成
認証の設定ができましたが、このままではどのページにもアクセスできず、実装をすすめら れませんので、管理用のユーザーを db/seeds.rb に作っておきましょう。いま、User モデルはメールアドレスとパスワードしかありませんから、その2つを設定すればOKです。
ただ、パスワードは、confirmationフィールドを利用するので、
.find_or_create_by
に直接与えることはできません。どのようにすればいいか考えてdb/seeds.rbに実装し、rails db:seed
の実行までおこなってください。参考のコードを以下にはっておきます。admin = User.where(email: '[email protected]') unless admin.present?
User.create(email: '[email protected]', password: 'monka_project', password_confirmation: 'monka_project')
end
これからは、このメールアドレスとパスワードを使って、ログインしてから作業を進めてくだ
「他人が作った無料の認証システムで不安だ」という声があるかもしれません。少し考えて見ま しょう。そもそも、いまこのアプリケーションをRails/Rubyで作っていますが、そのRails/
Rubyを作ったのは誰でしょうか?それに対して、対価は支払われているのでしょうか?オープン ソースは、一人で何かを独占しようというものではありません。これらのコードはすべてプロジェク トとして、世界中のすばらしいプログラマー達によって、いいものを作ろうという意識の上に成り 立っています。それは、お互いを監視しているようにも見えますが、お互いを信頼しているように も見えます。少なくとも、プログラミングを初めていく年もたたないプログラマーが一人で作る 認証システムよりは、世界の精鋭プログラマーが作った認証システムのほうが、はるかに信頼がお けると思います。オープンソースを利用することは無料です(著作権が微妙に異なる場合があり ますので、新しいものを使うときは注意してください)。ただし、その対価を払う代わりに、オープ ンソースで作ったものは、自分で育ててメンテナンスしていかなければならないという側面もあり ます。RubyやRailsがバージョンアップしても、誰もフォローはしてくれません。アンテナをはって、
常にコミュニティーの情報を取りに行く姿勢が求められます。それを面倒と思うかどうか、どれを 選択していくかはプログラマー次第です。
commit
gemdeviseでユーザモデルとログインなどのテンプレートを作りました。このテンプレー トは認証用のコントローラで管理されているもので、ユーザデータを直接操作できるもので はありません。ユーザの情報を見たり、必要に応じて追加・編集をするためのコントローラ を作成しましょう。
ここで必要なのは、コントローラとそれに対応するテンプレートだけです。
rails
generate
にはコントローラとテンプレートだけを作成するコマンドがあります。次の通り 実行してください。username:~/workspace (master) $ rails generate scaffold_controller User
Running via Spring preloader in process 2299
Expected string default value for '--jbuilder'; got true (boolean) create app/controllers/users_controller.rb
invoke erb
create app/views/users
create app/views/users/index.html.erb create app/views/users/edit.html.erb create app/views/users/show.html.erb create app/views/users/new.html.erb create app/views/users/_form.html.erb invoke rspec
create spec/controllers/users_controller_spec.rb create spec/views/users/edit.html.erb_spec.rb create spec/views/users/index.html.erb_spec.rb create spec/views/users/new.html.erb_spec.rb create spec/views/users/show.html.erb_spec.rb create spec/routing/users_routing_spec.rb invoke rspec
create spec/requests/users_spec.rb invoke helper
create app/helpers/users_helper.rb invoke rspec
create spec/helpers/users_helper_spec.rb invoke jbuilder
create app/views/users/index.json.jbuilder create app/views/users/show.json.jbuilder create app/views/users/_user.json.jbuilder
ちなみに、
rails destroy scaffold_controller User を実行すると、今実行し
たことを帳消しにしてくれます。コントローラ名を間違えたときなど、generate直後に使 うと便利です。このコマンドではルーティングは追加してくれませんので、
config/routes.rb にusers
コントローラへのルーティングを追加してください。Rails.application.routes.draw do devise_for :users
resources :users # 追加
resources :tags, except: :show resources :books do
resources :taggings, only: [:new, :edit, :create, :update, :destroy]
end end
そうして https://projectname-username.c9users.io/users にアクセスしてみて、
ユーザーの一覧が表示されていればOKです。テンプレートのデザインはRailsのデフォ ルトのままですので、Bookを参考にしながら変更しておきましょう。
commit
ここで、
users#edit からusers#update をするところで注意が必要です。パスワー
ドは基本的に見えないようになっています。変更しないからと思って空欄で更新しようとすると、以下のようにバリデーションのエラーになってしまいます。
gemdeviseが設定しているパスワードのバリデーションで、モデルを共有しているため に何も設定したつもりがなくても通知されます。しかし、ユーザー情報を編集するたびにパ スワードも変更していては大変ですので、
users#update に少し細工をしましょう。この
バリデーションは、PATCH をリクエストしたときのパラメータにパスワード関係のフィール
ドがあるときに判定されます。ですので、パスワードの変更がないときにはパラメータを除いてあげれば大丈夫です。変更後の users#update は以下のようになります。
def update
_user_params = user_params
_user_params.delete(:password) if user_params[:password].blank?
_user_params.delete(:password_confirmation) if
user_params[:password_confirmation].blank?
respond_to do |format|
if @user.update(_user_params) bypass_sign_in(@user)
format.html { redirect_to @user, notice:
'User was successfully updated.' }
format.json { render :show, status: :ok, location: @user } else
format.html { render :edit }
format.json { render json: @user.errors,
status: :unprocessable_entity }
end end end
念のため、テストが通ることを確認しておいてください。
commit
また、サイドメニューのTagsの下に、Usersへのリンクも追加します。
app/views/layouts/application.html.erb
<ul class="nav nav-sidebar">
<li class="active"><a href="#">Books</a></li>
<li><a href="#">Tags</a></li>
<li><a href="#">Users</a></li>
</ul>
ここはまだリンクを設定していませんでした。aタグをlink_toに置き換えましょう。
<ul class="nav nav-sidebar">
<li class="active"><%= link_to 'Books', books_path %></li>
<li><%= link_to 'Tags', tags_path %></li>
<li><%= link_to 'Users', users_path %></li>
</ul>
htmlに class="active" の設定があります。残念ながら、これを自動的に別のliタグ へ付け替えてくれる魔法はありません。やり方はいろいろあります。javascript(coffee
script)でもできますが、Railsのヘルパーの練習を兼ねて、Rubyで設定するやり方を紹 介します。
Railsの ActionDispatch::Request に original_fullpath という現在表示 しているpathを取得するメソッドがあります。それを使って、どこのメニューに当てはまる
か判定をします。該当のpathのときにhtmlのclassをactiveにするというものです。
ヘルパーの方は次のようになります。
app/helpers/application_helper.rb
module ApplicationHelperdef active_class(path_name)
request.original_fullpath.include?(path_name) ? 'active' : ""
end end
そして、テンプレートのサイドメニューは以下のように書き換えます。
<ul class="nav nav-sidebar">
<li class="<%= active_class('books') %>">
<%= link_to 'Books', books_path %></li>
<li class="<%= active_class('tags') %>">
<%= link_to 'Tags', tags_path %></li>
<li class="<%= active_class('users') %>">
<%= link_to 'Users', users_path %></li>
</ul>
少しマニアックな使い方かもしれませんが、erbタグをhtmlのclassにも使えるというの は面白いところだと思います。そういえば、books#indexやbooks#showで、発 売フィールドのbooleanをtrue/falseのままにしていました。こういうところもヘルパー を使ってコードをスッキリ書くことができますので、ぜひ使ってみてください。
commit
(3) . ログイン認証必須に伴うテスト修正
ここでテストを実行してみましょう。ログイン認証を追加しましたから、いろいろなエラー が出ていると思います。ブラウザと同じように、テストでも認証を追加しないと動きません。
gemdeviseとしてテスト用の設定が必要ですので、順番に以下の内容を設定してください。
まず、テスト用デ ータベ ースにユー ザ ーモデルを反 映するため、