Rails のお勉強をしばらく放置してたが、久しぶりに再開する。今回はそれなりに実用的なアプリケーションを作ってみる。
お題は、一言でいうと「SSL 証明書の有効期限を管理するシステム」が欲しい。名前は “Certs” としよう。
要件
ふんわりとした要件は以下の通り。
- 複数の SSL 証明書の有効期限とベンダー名を管理する
- 有効期限とベンダー名は…
- 自動的に取得する
- cron で定期的に更新する
- 日付でなく残り日数で表示する
- 証明書ごとにメモを残せるようにする
- ページ送り処理を実装する
- 検索機能を付ける
前提
開発は Mac で行なう。以下の環境が既に用意されているものとする。
$ ruby -v
ruby 1.9.3p448 (2013-06-27 revision 41675) [x86_64-darwin12.5.0]
$ rails -v
Rails 3.2.14
$ mysql --version
mysql Ver 14.14 Distrib 5.5.29, for osx10.6 (i386) using EditLine wrapper
コードは Git で管理し、GitHub にリポジトリを置く。端折った手順やコードの詳細はリポジトリを参照して欲しい。
開発開始
それでは早速作り始める。まずは新しいアプリケーションを作成する。
$ rails new certs
$ cd certs
Rails の development 環境の DB は SQLite がデフォルトだが、MySQL に変更する (commit)。MySQL のユーザや DB はあらかじめ作っておくこと。
$ vi Gemfile
$ vi config/database.yml
$ bundle install
scaffold
scaffold で骨組みを作る。
$ rails g scaffold certificate \
common_name:string \
ipv4addr:string \
port:integer \
organization:string \
issuer:string \
expired_at:datetime \
checked_at:datetime \
note:text
DB にテーブルを作成する。
$ rake db:migrate
WEBrick で Web サーバを起動してみる。
$ rails s
Web ブラウザでアクセスする。
http://localhost:3000/certificates
ここまでの作業で以下のようになる。
Twitter Bootstrap
デザインに Twitter Bootstrap を適用する (commit)。
$ vi Gemfile
$ bundle install
$ rails g bootstrap:install
$ rails g bootstrap:layout application fluid
$ rails g bootstrap:themed certificates
view のレイアウトを調整する (commit)。
$ vi app/views/layouts/application.html.erb
これで次のような感じになる。
入力バリデーション
入力バリデーションを設定する (commit)。内容は次の通り。
- common_name
- 入力必須
- 文字数: 最大255
- フォーマット: 正規表現で指定
- ipv4addr
- 文字数: 最大15
- フォーマット: 正規表現で指定
- port
- 数値のみ
- 空を許容
- 0 より大きい
- 65535 未満
- 数値のみ
この他に使用できるバリデーションルールはドキュメントを参照のこと。
ルールは model で指定する。
$ vi app/models/certificate.rb
これでバリデーションエラーが発生すると次のようになる。本当はエラーメッセージが表示されるはずなのだが出てない。Twitter Bootstrap を適用した影響みたいなので後でどうにかしよう。
モジュールの作成
証明書の有効期限を OpenSSL で取得するモジュールを作成する (commit)。OpenSSL の使用法は下記の記事を参考にした。
$ vi lib/cert_util.rb
$ vi config/application.rb
$ vi app/models/certificate.rb
$ vi app/controllers/certificates_controller.rb
ついでに index の view も調整しておく。
$ vi app/views/certificates/index.html.erb
これで登録時と更新時に、自動的に有効期限を取得できるようになる。
残り日数の表示
有効期限が日付だとわかりづらいので、残り日数で表示するようにする (commit)。日数は ActiveSupport::TimeWithZone クラスのオブジェクトと Time.now の差分で算出できる。
$ vi app/models/certificate.rb
$ vi app/views/certificates/index.html.erb
これで残り日数 (有効期限と本日の差分) で表示されるようになった。
ページ送り
表示件数が多くなったときのために、kaminari という gem を用いてページ送り機能を付ける (commit)。
$ vi Gemfile
$ bundle install
$ rails g kaminari:views bootstrap
$ vi app/controllers/certificates_controller.rb
$ vi app/models/certificate.rb
$ vi app/views/certificates/index.html.erb
Twitter Bootstrap とも親和性が高くて良い感じ。
ジョブキュー
OpenSSL で有効期限を取得するのは多少時間がかかることがあるため、delayed_job というジョブキューを使用して、バックグラウンドで処理するようにする (commit)。
$ vi Gemfile
$ bundle install
$ rails g delayed_job:active_record
$ rake db:migrate
DB に delayed_jobs という名前のキュー用のテーブルが生成される。
あとはバックグラウンドで処理したいメソッドの前に .delay と付け加えるだけ。
$ vi app/controllers/certificates_controller.rb
ジョブキューのデーモンを起動するには次のようにする。なお Rails 標準の .gitignore だと tmp ディレクトリが消えて、起動時にエラーになるので注意。
$ ./script/delayed_job start
検索機能
当然検索機能も欲しいので、Ransack という gem を用いて実装する (commit)。kaminari との相性も良い。
$ vi Gemfile
$ bundle install
$ vi app/controllers/certificates_controller.rb
$ vi app/views/certificates/index.html.erb
これで common_name を対象にキーワード検索できるようになる。
cron で実行
有効期限は cron で定期的に更新できるようにしたい。つまりコマンドのインターフェイスを実装すれば良い (wget か curl で叩いても良いけどかっこ悪いよね)。これは rake の task で実現できる (commit)。
$ vi lib/tasks/certificates.rake
次のようにして task を実行できる。
$ rake certificates:update_expirations
ただし cron に登録するときは PATH が通るように気を付ける。例えば次のように。
cd /var/www/certs; /home/HOGE/.rbenv/shims/rake certificates:update_expirations
まとめ
で、できあがったものがこちら (一番上の画像)。それなりに使えるアプリケーションを手軽に作成することができた。興味があれば GitHub から clone してみて欲しい。
今後の課題としては、以下のようなことを考えている。
- 検索性能の向上
- AND 検索
- 一つのキーワードで複数のカラムを対象に
- テストの作成、実行
- 本番環境へのデプロイ
コメント
[…] 参考: 2時間で作る実用 Rails アプリ : あかぎメモ […]