心はいつもAirPucci (空元気でもいいから)

毎日がPucciを着ているような気分

RailsTutorial4.0を高速で復習する。11.2.4章。

   


11.2.4[フォローする] ボタン (標準的な方法)、です。

仕様

それぞれのユーザーページで、フォローしていないユーザーには「フォローする」
しているユーザーには「解除する」ボタンがある。
それらを動作させる。

テストを書く

スト11.32 Follow/Unfollowボタンをテストする。
spec/requests/user_pages_spec.rb

require 'spec_helper'

describe "User pages" do
略
  describe "profile page" do
    let(:user) { FactoryGirl.create(:user) }
略
    describe "follow/unfollow buttons" do
      let(:other_user) { FactoryGirl.create(:user) }
      before { sign_in user }

      describe "following a user" do
        before { visit user_path(other_user) }

        it "should increment the followed user count" do
          expect do
            click_button "Follow"
          end.to change(user.followed_users, :count).by(1)
        end

        it "should increment the other user's followers count" do
          expect do
            click_button "Follow"
          end.to change(other_user.followers, :count).by(1)
        end

        describe "toggling the button" do
          before { click_button "Follow" }
          it { should have_xpath("//input[@value='Unfollow']") }
        end
      end

      describe "unfollowing a user" do
        before do
          user.follow!(other_user)
          visit user_path(other_user)
        end

        it "should decrement the followed user count" do
          expect do
            click_button "Unfollow"
          end.to change(user.followed_users, :count).by(-1)
        end

        it "should decrement the other user's followers count" do
          expect do
            click_button "Unfollow"
          end.to change(other_user.followers, :count).by(-1)
        end

        describe "toggling the button" do
          before { click_button "Unfollow" }
          it { should have_xpath("//input[@value='Follow']") }
        end
      end
    end
  end
略
end

リスト11.33 Relationshipsコントローラの認可をテストする。
spec/requests/authentication_pages_spec.rb

require 'spec_helper'

describe "Authentication" do
略
  describe "authorization" do

    describe "for non-signed-in users" do
      let(:user) { FactoryGirl.create(:user) }
略
      describe "in the Relationships controller" do
        describe "submitting to the create action" do
          before { post relationships_path }
          specify { expect(response).to redirect_to(signin_path) }
        end

        describe "submitting to the destroy action" do
          before { delete relationship_path(1) }
          specify { expect(response).to redirect_to(signin_path) }
        end
      end
略
    end
  end
end

実装する

リスト11.34 Relationshipsコントローラ。
app/controllers/relationships_controller.rb

class RelationshipsController < ApplicationController
  before_action :signed_in_user

  def create
    @user = User.find(params[:relationship][:followed_id])
    current_user.follow!(@user)
    redirect_to @user
  end

  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow!(@user)
    redirect_to @user
  end
end

テストはパスします。

11.2.5[フォローする] ボタン (Ajax)、です。

仕様

ユーザーのフォロー、アンフォローの度に自分のページに戻らなくて済むようにしたい。

Ajax化する

リスト11.35 フォロー用のフォームでAjaxを使用する。
app/views/users/_follow.html.erb
[/code]
<%= form_for(current_user.relationships.build(followed_id: @user.id), remote: true) do |f| %>

<%= f.hidden_field :followed_id %>

<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
[/code]

リスト11.36 フォロー解除用のフォームでAjaxを使用する。
app/views/users/_unfollow.html.erb
[/code]
<%= form_for(current_user.relationships.find_by(followed_id: @user), html: { method: :delete }, remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
[/code]

テストを書く

リスト11.37 RelationshipsコントローラがAjaxリクエストに応答することをテストする。
spec/controllers/relationships_controller_spec.rb

require 'spec_helper'

describe RelationshipsController do

  let(:user) { FactoryGirl.create(:user) }
  let(:other_user) { FactoryGirl.create(:user) }

  before { sign_in user, no_capybara: true }

  describe "creating a relationship with Ajax" do

    it "should increment the Relationship count" do
      expect do
        xhr :post, :create, relationship: { followed_id: other_user.id }
      end.to change(Relationship, :count).by(1)
    end

    it "should respond with success" do
      xhr :post, :create, relationship: { followed_id: other_user.id }
      expect(response).to be_success
    end
  end

  describe "destroying a relationship with Ajax" do

    before { user.follow!(other_user) }
    let(:relationship) { user.relationships.find_by(followed_id: other_user) }

    it "should decrement the Relationship count" do
      expect do
        xhr :delete, :destroy, id: relationship.id
      end.to change(Relationship, :count).by(-1)
    end

    it "should respond with success" do
      xhr :delete, :destroy, id: relationship.id
      expect(response).to be_success
    end
  end
end

実装する

リスト11.38 RelationshipsコントローラでAjaxリクエストに応答する。
app/controllers/relationships_controller.rb

class RelationshipsController < ApplicationController
  before_action :signed_in_user

  def create
    @user = User.find(params[:relationship][:followed_id])
    current_user.follow!(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow!(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end
end

リスト11.39 JavaScript組み込みRubyを使用してフォローのリレーションシップを作成する。
app/views/relationships/create.js.erb

$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= @user.followers.count %>')

リスト11.40 Ruby JavaScript (RJS) を使用してフォローのリレーションシップを削除する。
app/views/relationships/destroy.js.erb

$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= @user.followers.count %>')

テストはパスします。
次は、
11.3ステータスフィード
です。

 - テクニカル ,

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

  関連記事

no image
MacBookAir 1日め

ようやくMacBookAir を購入しました。Dellノートがずっと調子悪かった …

no image
RailsTutorial4.0を高速で復習する。5.6章。演習2問目のつづき。

5.6章。演習2問目です。TDDにこだわり、あえてこの問題をするまで、ヘッダーや …

no image
RailsTutorial4.0を高速で復習する。6.3.3章。

6.3.3ユーザー認証、です。 新規ユーザー登録のときは入力で、:passwor …

no image
ToDoの管理方法

東大生はノートがきれいだとか、、 きれいに書いている暇があったら、頭に書いて覚え …

no image
RailsTutorial4.0を高速で復習する。9.3.4章。

9.3.4パーシャルのリファクタリング、です。 テストパスしているのでリファクタ …

herokuのWe’re sorry, but something went wrong.に苦しんだ

Rails3.2環境に戻してアプリを作ろうとしています。 herokuにpush …

no image
「Follow me」バッジのつけ方。

ブログの横についている「Follow me」バッジ。いろんな方がつけているのを見 …

MacBookAirの容量が足りない

当ブログairpucciで人気なのがMacBookAirに関するエントリ。ありが …

Objective-C苦節3ヶ月アプリ作れるようになった

このブログairpucci.comのメニューにアプリ開発追加しました。 昨年秋よ …

no image
RailsTutorial4.0を高速で復習する。3.3.2章。

3.3.2タイトルのテストをパスさせる。です。 ひとまず、静的ページをhtmlの …