2011年9月24日土曜日

Rails3を初歩から学ぶ #23 関連テーブルのコントローラ

この一連のエントリは
Ruby on Rails 3 Tutorial: Learn Rails by Example (Addison-Wesley Professional Ruby Series)
で参考に学んだことを凝縮してお送りしています。

今回はUserテーブルとMovieテーブルを結ぶFanテーブルに対応するコントローラを作成していきます。仕様としては、映画の一覧から選択すると好きな映画として登録、削除を選ぶと好きな映画の対象から外すというものとします。
インターフェースは映画情報の一覧画面(Moviesコントローラのindexアクション)を使うことにして、Fansコントローラとしてはcreate(Fanテーブルへの追加)とdestroy(Fanテーブルからの削除)のみになります。
> rails generate controller Fans
ではテストを作成していきましょう。

# -*- coding: utf-8 -*-
require 'spec_helper'
describe FansController do
describe "アクセスコントロールの検証" do
it "未認証ユーザーによるcreate要求はサインイン画面へ" do
post :create
response.should redirect_to(new_session_path)
end
it "未認証ユーザーによるdestroy要求はサインイン画面へ" do
delete :destroy, :id => 1
response.should redirect_to(new_session_path)
end
end #アクセスコントロールの検証
describe "POST 'create'" do
before(:each) do
@user = Factory(:user)
@movie = Factory(:movie)
controller.sign_in(@user)
end
it "お気に入り登録できること" do
lambda do
post :create, :fan => { :movie_id => @movie }
response.should be_redirect
end.should change(Fan, :count).by(1)
end
end #POST 'create'
describe "DELETE 'destroy'" do
before(:each) do
@user = Factory(:user)
@movie = Factory(:movie)
controller.sign_in(@user)
@user.favorite_movie!(@movie)
@fan = @user.fans.find_by_movie_id(@movie)
end
it "お気に入り解除できること" do
lambda do
delete :destroy, :id => @fan
response.should be_redirect
end.should change(Fan, :count).by(-1)
end
end #DELETE 'destroy'
end
対応するコードを書いていきます。
まずはルートを定義しましょう。
resources :fans, :only => [:create, :destroy]
createとdestroyアクションしか不要なので「:only」で限定しています。
そしてapp/controller/fans_controller.rbを編集します。

class FansController < ApplicationController
before_filter :authenticate
def create
@movie = Movie.find(params[:fan][:movie_id])
current_user.favorite_movie!(@movie)
redirect_to movies_path
end
def destroy
@movie = Fan.find(params[:id])
current_user.unfavorite_movie!(@movie)
redirect_to movies_path
end
end
これでテストは全てパスできます。
最後にviewをつくって完成です。
映画情報の個別ページ(showアクション)にお気に入り登録/解除するボタンを設置しましょう。


<h1>タイトル:<%= @movie.name %><h1>

<% if current_user.favorite?(@movie) %>
<%= form_for current_user.fans.find_by_movie_id(@movie), :html => { :method => :delete } do |f| %>
<div class="actions"><%= f.submit "お気に入り解除" %></div>
<% end %>

<% else %>

<%= form_for current_user.fans.build(:movie_id => @movie.id) do |f| %>
<div><%= f.hidden_field :movie_id %></div>
<div class="actions"><%= f.submit "お気に入り" %></div>
<% end %>

<% end %>


「favorite?」メソッドの結果に応じてお気に入りに登録するか解除するか、表示するボタンを切り替えています。
「form_for」に指定するリソースはお気に入り登録時はbuildメソッドで生成した(DB保存前の)新しいリソース、解除時は渡された映画情報IDから検索して取得したリソースを指定しています。
登録時はPOSTで映画情報IDを渡したいのでhiddenフィールドで指定しています。

今回までで一通りRails3のおおまかな説明はおしまい!

0 件のコメント:

コメントを投稿