読者です 読者をやめる 読者になる 読者になる

Rails3.2でなにか作る(1)

Ruby on Rails Ruby

Qiitaのアドベントカレンダーを見ているとなにか作りたくなったので。いままでのRailsの経験はアジャイル本をひと通り読んでMarkdownブログを作ってみたぐらい。一言でいうとビギナー。


では早速いくつかの良さげなプラグインの使い方を学ぶために小さなアプリを作っていく。「複数人のユーザーが投稿できるブログアプリ」を作るのが目標。

使いたいプラグインの一覧

アプリ作成

まずは作成。

$ rails new our-blog

Devise導入

初めにDeviseを導入してみる。Deviseについては次のサイトや記事が参考になった。

まずはGemfileをいじる。gem 'jquery-railsの下あたりに追加。バージョン指定はサンプルアプリの受け売り…。

# Gemfile
...
gem 'devise', '>= 2.1.2'
...

で、bundle installしてrails g devise:installする。

$ bundle install
…
$ rails g devise:install
…

Deviseをインストールすると次にするべきことを指示されるので一応従う。

  1. 確認用のメーラのための設定?やらなくても当分問題ないと思うけど、念のためconfig/environments/development.rbにconfig.action_mailer.default_url_optionsを追加。productionはとりあえず後回し。
  2. 未ログインのユーザーをリダイレクトさせるためにroot用のコントローラーを設定する。
    • とりあえず$ rails g controller home indexして、
    • config/routes.rbにroot :to => "home#index"を追加。
    • public/index.htmlが邪魔なので削除。
  3. ログイン後のフラッシュメッセージなどの表示設定。Twitter Bootstrap導入後に設定する。
  4. 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を導入する。

参考サイト

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に上げるつもり。

post script

はてなブログがMarkdown記法対応になって快適。はてなブログ(・∀・)イイ!!