【Rails3.2】deviseを触ってみた

最近DSLとかばかり見ているのでたまにはプログラミングもせなあかんということで、Railsを復習がてらアプリを作成することにしました。

そこで、IDとパスを使った認証が必要になりそうだったのでdeviseというgemを使って色々やってみたのでそれの記録です。

deviseとは

gem上で使えるサインアップ、ログイン、ログアウトの仕組みを作ってくれるgemです。これを使ってモデルを作るだけで勝手にログイン画面とかを作ってくれます。

Railsでdeviseを使う

実行環境

今回はの実行環境は以下。

  • Rails 3.2.16

  • Ruby 2.0.0p481

インストール

Railsでdeviseを使うためにはGemfileに次の行を書き加えます。

/Gemfile

gem 'devise'

後に、bundle installをする。後に、関係ファイルをジェネレート。

$ bundle install
$ rails g devise:install # config/devise.rb(設定ファイル)の作成をします。

また、deviseをログインしていない状態でログインしないと入れないアクションを実行しようとした時rootにリダイレクトするのでテキトウにrootをroutes.rbに書いておきます。

/config/routes.rb

  root :to => "home#index" # home/indexをルートにする

モデルを作る

これで使う準備ができたので、deviseを使ってモデルを作成します。railsプロジェクトのルート上で以下コマンドを実行。

$ rails generate devise User
$ rake db:migrate

Userは任意のモデル名です。まあ、普通ログインシステムを作る時必要なのはユーザの情報なのでUserが一般的でしょう。

このコマンドを実行するとdevise用のモデルが作成されます。その後マイグレートしてあげましょう。

警告用のビューを足す

警告を全てのページに表示ができるようにlayoutsを編集しましょう

/app/views/layouts/application.html.erb

<p class="notice"><%= notice %></p>
  <p clss="alert"><%= alert %></p>
<%= yield %>

yieldの前に置いておくのが一番自然だと思われます。

ルーティング

rake routesを実行すると以下の様なルーティングになっています。

                    root        /                              home#index
        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
                         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
                         PUT    /users(.:format)               devise/registrations#update
                         DELETE /users(.:format)               devise/registrations#destroy

このアクションのURLを直接入力することでログイン、サインアップなどのフォームが出現します。ビューも勝手にできているようです。

ビューを編集できるようにする

ビューは初期状態では内部で処理されてしまっていますのでカスタマイズをするためにapp/viewに出しておいたほうが懸命です。以下コマンドで出力されます。

$ rails generate devise:views users

後に、devise.rbの208行目にあるconfig.scoped_viewsのコメントアウトを外し、trueにしてしまいましょう。

/config/devise.rb

  # ==> Scopes configuration
  # Turn scoped views on. Before rendering "sessions/new", it will first check for
  # "users/sessions/new". It's turned off by default because it's slower if you
  # are using only default views.
  config.scoped_views = true

ログインしないとできないページを作る

アクションのコントローラの先頭ににbefore_filterを追加します。

/app/controllers/user_controller.rb

  before_filter :authenticate_user!, :except => [:show, :index]

  class UsersController < ApplicationController
  def index
  …

:exceptパラメータで認証なしで実行可能なアクションを指定可能です。

ログイン方法をe-mailからユーザネームに変更する

ログイン方法がデフォルトではe-mail、パスの入力になっています。これを例えばユーザネームとかに変更したい場合の対処法。

とりあえずモデルに変更するカラムを足す。今回はusernameというカラムを足していきます。

$ rails g migration add_username_to_users username:string
$ rake db:migrate

次に、付け加えたカラムを認証用のキーに変更します。所謂、「主キー」の変更ですね。devise.rbの32行目config.authentication_keysを書き換えます。

config/devise.rb

 # config.authentication_keys = [ :e-mail ]
 # ↓
 config.authentication_keys = [ :username ]

このdevise.rbではdeviseの様々な設定ができるので覚えておいたほうが良いですね。

あとはビューをいじります。
emailを入力するべきところをすべてusernameを入力するように変更しましょう。とりあえずは、/app/views/users/sessions/new.html.erbと/app/views/users/registrations/new.html.erbを変更すればサインアップとサインインはできるようになります。コードは省略。

これでうまくいくかなーとおもいきや、e-mailを入れろと怒られます。バリデーションの回避がうまく行っていないようです。
以下のメソッドをUserモデルに付け加えましょう。

/app/model/user.rb

  def email_required?
    false
  end

これでバリデーションを無視することが出来ました。本当はe-mailカラムを削除しておかないといけませんが、まあとりあえずはこれで変更が可能ですね。e-mailは後で任意で入れさせるようにするかもしれないので今回は放っておきます。

参考

 

Dockerを触ってみた。

おはようございます。レモンです。

友人がDockerすげえ、やべえって言っててかつ一緒に作ってるサービスもDockerで運用する予定だと言い出したのでこれは僕もある程度触れるようになっておかないとまずいっちゅうわけで少し触ってみました、というお話。どっちかというと使い方というよりは所感と言った感じです。

そもそもDockerって何さ

さて、そもそもDockerとは何なんでしょうか?自分も彼に紹介されるまで全く知りませんでした。

詳しくは公式ページを見てもらえればいいのですが当たり前のように英語なのでちょっとわかりにくいですよね。

ざっくりというと、めっちゃ省スペースなVMと考えて差し支えないと自分は思いました。

細かく言うと従来の変更の度に既存のサーバに変更を加えるやり方ではなく、Immutable Infrastructureと呼ばれる既存の環境をイチから作り直し、古いものを切り捨ててしまうという考え方によるものであります。
これを実現するためにDockerではコンテナとイメージという単位でOSを管理していき、Gitのようにバージョン管理を行いながら逐次更新したり削除していきながらOSを操作していきます。
そして、これがすごいんですが、ある構築した環境を別のDockerがインストールされている環境へまるまるコピーができるわけです。こうすることで、環境移行のときにわざわざ前の設定を思い出しながらLinuxを泣きながらいじるという手間をDockerさえ入れてしまえばSkipできてしまう!というわけなんです。なぜ、省スペースなのか、というと元となるイメージが最小構成(bashくらいしか動いてない)なのと、差分で環境を管理しているためなんだそうです。そのため、起動や破棄、リソース量などが従来のVMと比べて軽い上、差分で管理しているためGitでDockerの設定状況を管理する!みたいなこともできるんだそうです。すげー。

コンテナとイメージ

さて、Dockerを使う上で必ず覚えなくちゃいけない概念がこのコンテナとイメージというものです。この2つをやりとりすることがDockerの基本的な操作になります。

詳しくは@IT様のこちらのページがわかりやすいなーと思いました。

まあ自分なりにも説明してみます。

まず、イメージというものはOSのモトとなるもので所謂テンプレートです。オブジェクト指向でいう「クラス」にあたりますね、このクラス、もといイメージからDockerはコンテナを作ることが出来ます。
ちょうど、クラスからオブジェクトを生成するのとおなじ感覚でいいと思います。自分はその感覚が完全にしっくり来ました。

オブジェクト指向と異なる部分はここからで、イメージから生成されたコンテナを作ってあげるとその中のOSを起動し、いじることができます。例えばapt-get updateをしてあげたり、vimをインストールしたり、apacheを入れたりと様々なLinuxでできる操作を行うことが出来ます。ホストOSとDockerで起動中のコンテナ上のOSもコマンド一発で行き来できます。(後述)

ある程度変更が完了したら、コンテナの変更状況をイメージに書き込みます。イメージに書き込んであげるとコンテナの変更状況を反映したイメージが再び生成されます。普通に生成してあげるともともとあったイメージと、新しく変更を反映したイメージどちらとも残ります。これらは作業の進行状況に合わせて削除したり残しておいたりすることができます。と言った感じです。

また、変更作業中以外は基本的にはコンテナは使いきりで、変更が終了したら必ずイメージに反映させ、中途半端な変更をしたコンテナを残さないようにすることで変更作業が混乱することがなくなるようです。

図示すると以下の様な感じでしょうか。

 

Docker

 

実際に使う

さて、じゃあ実際に使う場合にはどうすりゃいいのよって話なんですがそんなに難しくないです。

参考:いまさら聞けないDocker入門(2):ついに1.0がリリース! Dockerのインストールと主なコマンドの使い方 – @IT

参考ってか、これのインストール以降部分を噛み砕いて説明って感じです(・ω・`)

インストール

まず、Dockerをインストールしましょう。今回はCentOS7を使いましたが、Ubuntuとかでも多分大丈夫です。ただ、インストールが一番楽なのはCentOSなんだとか。

 $ sudo yum install docker 

これだけでOKです。ただ、バージョンが低いので最新版が欲しい場合はEPELを用いてパッケージを引っ張ってきてください。

dockerのベースイメージをダウンロードする

Dockerが入ったので元となるイメージをDockerから引っ張ってきましょう。現在安定しているOSがUbuntuしかないのでとりあえずUbuntuで。
他にも、CentOSや各サービス(MySQL,WordPress,PostgreSQL,nodejsなど)が引っ付いたUbuntuイメージも引っ張ってこれるのですが、今回はまっさらなUbuntuイメージを持ってきます。
また、CentOSは現在安定版が存在せず致命的なバグが多いためあまり使わないほうが懸命のようです。

「引っ張ってくる」のでdocker pullを使います↓

 $ sudo docker pull ubuntu:latest 

pullのあとにOS名:タグ名と入れてあげるとDLが可能です。タグ、というのはバージョンごとに付いている名前のようなものです。ここに載っています。

DLができたら確認をしましょう。

 $ sudo docker images 

これで現在インストールされているイメージの一覧を表示することが出来ます。

イメージからコンテナを生成する

イメージが引っ張ってこれたので今度はここからコンテナを作って実行してみます。

「実行」するのでdocker runですね。

 $ sudo docker run -it --name ubuntu-container ubuntu /bin/bash 

でOKです。これでubuntu-containerというコンテナを作成し、実行することが出来ます。オプションなどはDocker公式@ITのページなどを参考にしてください。一応-itでコンテナの標準入力を開き(-i)、かつtty(端末デバイス)を確保する(-t)という意味みたいです。まあ、上のコマンドを最初のウチは呪文のように打っておいても問題なさそうです。

無事にrunできるとrootでDockerコンテナ上のOSのbashが起動し、いじることができるようになります。あとは、ここから普通のUbuntuと同じように色々インストールをしたり、ネットワーク設定をしたりしてあげればOKです。

また、Dockerコンテナ上のOSからホストOSに戻るにはCtrlを押しながらpを押した後、qを押します。

また、ホストOS上で現在起動しているコンテナを確認するためには以下のコマンドを実行します。

 $ sudo docker ps -a 

コンテナからイメージを生成する

さて、コンテナの調整ができたらイメージを作ってとりあえず作業は一段落ですよね。

ということでイメージを作ります。まず、ホストOS側にCtrl-p-qで戻りましょう。そして、現在起動しているdockerコンテナOSを停止させます。OSなので起動中にイメージの生成とかできません。

 $ sudo docker stop ubuntu-container 

イメージの生成ではdocker commitというコマンドを使います。Gitのリポジトリにcommitしている感覚でしょうか。コミット前にdocker psでコンテナがきちんと止まっているかも確認しておくと安心です。

 $ sudo docker commit ubuntu-container myubuntu-image1 

commitの後にコンテナの名前とイメージ名を入れればOKです。上ではmyubuntu-image1というイメージ名で作成しました。

この後に、

 $ sudo docker images 

と打ってあげれば作ったイメージが在ることが確認できるかと思います。

既存のイメージを削除したいときには

 $ sudo docker rmi (イメージ名) 

と打てばOKです。

また、止めてしまったコンテナはdocker startというコマンドで再開することもできます。

 $ sudo docker start -i ubuntu-container 

 

基本的には以上の操作の繰り返しなんだそうです。ここまでくれば、作ったイメージからまたコンテナ作っていじってイメージ作っていらないイメージ消してーといったやりとりが出来ますよね。
僕がいじったのはここまでなので他のことはあんまし言えません。他にもDockerfileなるものとかもあるみたいですが、今回は触れていないので、No Touch!で。

所感

友人の彼いわく、これの実用的な使い方としてはテスト用の鯖と本番用の鯖を2つ同じような環境(例えば同ネットワーク内など)に用意して、両方にDockerを入れ、変更をテスト用の鯖にDockerを使って反映しながらテストを行い、それがうまく行ったら本番用の鯖を一瞬止めてテスト用鯖で作ったイメージを本番用鯖に突っ込み、コンテナを生成&起動してしまえばメンテ時間がめちゃくちゃ短くなる!みたいなことを語気荒く説明してくれました。

もしこれが本当に実用で使うようになればサーバ管理に革命が起きそうだなーと思います。このDockerなんでもまだ作られて1年立ってないとからしいのでめちゃくちゃHOTなサービスです。今後も注目ですねー(`・ω・´)