Rails3.2でなにか作る(1)
Qiitaのアドベントカレンダーを見ているとなにか作りたくなったので。いままでのRailsの経験はアジャイル本をひと通り読んでMarkdownブログを作ってみたぐらい。一言でいうとビギナー。
では早速いくつかの良さげなプラグインの使い方を学ぶために小さなアプリを作っていく。「複数人のユーザーが投稿できるブログアプリ」を作るのが目標。
使いたいプラグインの一覧
- Devise 認証エンジン
- ActsAsTaggableOn タグ機能
- Twitter Bootstrap for Rails Twitter BootstrapのRails用プラグイン
アプリ作成
まずは作成。
$ rails new our-blog
Devise導入
初めにDeviseを導入してみる。Deviseについては次のサイトや記事が参考になった。
- Railsの第4世代認証エンジンDeviseのREADMEを翻訳してみた
- RailsでDeviseを使ってみた
- plataformatec / devise(本家)
- Devise Example-Applications
まずはGemfileをいじる。gem 'jquery-rails
の下あたりに追加。バージョン指定はサンプルアプリの受け売り…。
# Gemfile ... gem 'devise', '>= 2.1.2' ...
で、bundle install
してrails g devise:install
する。
$ bundle install … $ rails g devise:install …
Deviseをインストールすると次にするべきことを指示されるので一応従う。
- 確認用のメーラのための設定?やらなくても当分問題ないと思うけど、念のためconfig/environments/development.rbに
config.action_mailer.default_url_options
を追加。productionはとりあえず後回し。 - 未ログインのユーザーをリダイレクトさせるためにroot用のコントローラーを設定する。
- とりあえず
$ rails g controller home index
して、 - config/routes.rbに
root :to => "home#index"
を追加。 - public/index.htmlが邪魔なので削除。
- とりあえず
- ログイン後のフラッシュメッセージなどの表示設定。Twitter Bootstrap導入後に設定する。
- Rails3.1でHerokuにデプロイする場合の設定。3.2を使っているので飛ばす。
これで導入完了。
Deviseによる認証機能の作成
さっそく認証機能を作る。
まずは認証用のモデルを作成。
$ rails g devise User
これで認証用のモデルが生成できるようになる。けど、このままだとUserにはメールアドレスとパスワードしか登録できなくて寂しいのでUserモデルにnameカラムを追加するマイグレーションファイルを作る。
$ rails g migration AddNameToUsers name:string
これでマイグレートする。
$ rake db:migrate
新しくカラムが増えたのでapp/models/user.rbのattr_accessibleに:name
を追加。それと、ユーザー登録や編集用のビューも変更する。
元来Deviseはエンジンのため、ビューはGemパッケージのなかに内包されている。けど、ありがたい規約のおかげでapp/views/deviseにビューファイルがあればそっちを優先して描画してくれる。
また、このビューファイルの生成のためのコマンドも用意してくれているので、それを使ってビューファイルを編集すればいい。コマンドは次のようになる。
$ rails g devise:views
これでapp/views/devise以下にdevise用のビューファイルがザクザクと入ってくる。変更するべきなのは登録・編集用のビュー(registrations)だけなので、これとこれの描画に必要な共通ビュー(shared)以外のディレクトリは削除しておく。
ビュー(edit.html.erbとnew.html.erb)の編集は簡単で、フォームに下のような名前用のフィールドを追加するだけ。
<div><%= f.label :name %><br /> <%= f.text_field :name %></div>
これで認証機能はOK(バリデーション設定してないけど)。
Twitter Bootstrap導入
参考サイト
- twitter bootstrap railsを使ったら職が見つかり彼女も出来て背も3センチ伸びました。
- Twitter Bootstrap + Rails 3.2.3 の使い方を知るためにスパイクしました
- Twitter Bootstrap Basics
Gemfileにgem 'twitter-bootstrap-rails'
を追加。assetsグループの中に入れるのがよさそう。
次にコマンドラインで
$ bundle install … $ rails g bootstrap:install …
と入力すれば導入完了。
layouts/application.html.erbの編集
最初にちょこっとapp/stylesheets/のapplication.cssとbootstrap_and_overrides.css.lessを編集する。application.cssに
.main { margin-left: 5px; }
を追加して、bootstrap_and_overrides.css.lessから
body { padding-top: 60px; } @import "twitter/bootstrap/responsive";
の部分を削除する。デザインの好みの問題なのでやらなくても問題ない。むしろやったほうが問題起きるかもしれない。
次にapp/views/layouts/application.html.erbを編集する。ユーザーがログインしていたらユーザーの情報をナビバーに表示、ログインしていなかったらログインへリンクを表示、といったレイアウトを作る。application.html.erbの書き方はここが参考になる(実は使ってるTBSのGemが違うけど、まあ問題ない)。
使ったDeveseの機能
ここを参考に。
user_signed_in?
… 文字通りユーザーがサインインしてるかどうか。
current_user
… 今のユーザーのモデル。current_user.name
とすると名前を表示できたり。
new_user_session_path
… いわゆるログイン画面へのパス。
new_user_registration_path
… 新規登録画面へのパス。
edit_user_registration_path
… ユーザー編集画面へのパス。名前やパスワードを変えるやつ。
destroy_user_session_path
… ログアウトのためのパス。セッションを破棄するという副作用があるため、DELETEメソッドを使う(こういうのを「れすとふる」な実装というらしい)。
これでlayoutは一応完成。
Scaffold!
ようやくアプリの開発に取り掛かれる。ブログ記事の大まかな土台をサクッとscaffoldで作る。
$ rails g scaffold Article title:string body:text user_id:integer … $ rake db:migrate …
Userとのリレーションを設定する。app/models/の中、users.rbにhas_many :articles
を追加、article.rbにbelongs_to :user
を追加。これで@article.user
とかcurrent_user.articles
とかできるようになる。
Articleコントローラーとビューの編集
ログイン機能に合うようにコントローラーやビューを編集していく。
ゲストユーザーの制限
まず、ログインしていないユーザーはindexとshowしか見れないようにする。articles_controller.rbにbefore_filter
を使ってauthenticate_user!
をするように設定すればいい。
before_filter :authenticate_user!, :except => ["index", "show"]
記事作成者の処理
createのとき、新しいarticleのuser_idをcurrent_user.idに設定。edit,update,destroyのとき、対象のarticleのuser_idがcurrent_user.idと違う場合403コードを返す。
また、ビューのarticleの_form.html.erbの中のuser_id入力用のフィールドを削除しておく。
思い付く必要な処理はこれぐらい。他にもあるかも。
とりあえずこれでブログ機能は完成。
ActsAsTaggableOnの導入
タグ機能を追加してみる。タグ機能の実装はhas_and_belongs_to_manyを使ってもいいけど、やっぱりプラグインを使ったほうが便利そうなのでそっちにする。
参考サイト
Gemfileにgem 'acts-as-taggable-on'
を追加。
次のようにコマンドを実行。
$ rails g acts_as_taggable_on:migration … $ rake db:migrate …
これで導入完了。
記事にタグ機能を追加
ActsAsTaggableOnでタグ機能を追加するには、対象のモデルファイルに次のよう記述すればいい。
acts_as_taggable_on :タグの名称
例えばこう、複数指定もできる。
acts_as_taggable_on :tags, :categories
:tags
の場合は次のようなエイリアスも用意されている。
acts_as_taggable
これをapp/models/articl.rbに追加。ついでにattr_accessibleに:tag_list
を追加しておく。
使い方
Articleからタグを取得する方法は二つある。
article.tags
とすれば、その記事が持つタグのモデルオブジェクトの配列を取得できる。
article.tags => [#<ActsAsTaggableOn::Tag id: 1, name: "rails">, #<ActsAsTaggableOn::Tag id: 2, name: "ruby">, #<ActsAsTaggableOn::Tag id: 3, name: "web">]
article.tag_list
とすればその記事が持つタグの名前(文字列)の配列を取得できる。
article.tag_list => ["rails", "ruby", "web"]
tag_listにタグの配列や文字列を代入してsaveすればタグが追加される。配列を渡す代わりにコンマで区切られた文字列を渡してもいい。
article.tag_list = "rails, ruby" article.tag_list << "web" article.save article.reload article.tags => [#<ActsAsTaggableOn::Tag id: 1, name: "rails">, #<ActsAsTaggableOn::Tag id: 2, name: "ruby">, #<ActsAsTaggableOn::Tag id: 3, name: "web">]
次に記事のタグを編集・閲覧できるようにビューを書き換える。
_form.html.erbに次のようなフィールドを追加する。
<div class="field"> <%= f.label :tag_list %><br /> <%= f.text_field :tag_list %>
そして、indexやshowのビューにタグを表示する記述を追加する。これだけ。コントローラーは変更しなくてもいい。
終わり
長くなったのでここまでで一旦終わり。あとでソースもGitHubに上げるつもり。