###マイクロポストを削除する
マイクロポストリソースにポストを削除する機能を追加.
これはユーザー削除と同様に、"delete" リンクで実現します
今回は自分が投稿したマイクロポストに対してのみ削除リンクが動作するようにします。
####マイクロポストのパーシャルに削除リンクを追加する
app/views/microposts/_micropost.html.erb
<li id="micropost-<%= micropost.id %>">
<%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
<span class="user"><%= link_to micropost.user.name, micropost.user %></span>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
<!--メソッド名の表すとおりですが、「3分前に投稿」といった文字列を出力します。-->
<% if current_user?(micropost.user) %>
<!--もし自分の投稿だったら-->
<%= link_to "delete", micropost, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</span>
</li>
####Micropostsコントローラのdestroyアクション
app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
# create,destroyを行う前にログインを求めらえれる。
before_action :correct_user, only: :destroy
def create
@micropost = current_user.microposts.build(micropost_params)
# 慣習的に関連するモデルを生成するときは、buildを使う
if @micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
# redirect_to は、view の表示には直接は関係なく、新たな HttpRequest が発行されます。
else
@feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
# action で view を指定しない場合、規約に従って、リソース名 や
# action名を元に、表示する view が決まります。
end
end
def destroy
@micropost.destroy
flash[:success] = "Micropost deleted"
redirect_to request.referrer || root_url
# request.referrer 一つ前のURLを返します
# || または
end
private
def micropost_params
params.require(:micropost).permit(:content)
# マイクロポストのcontentカラムだけ取り出すことができる。
end
def correct_user
@micropost = current_user.microposts.find_by(id: params[:id])
# idをもとにユーザーのマイクロぽすとを探す
redirect_to root_url if @micropost.nil?
# マイクロポストが空であればホーム画面に行く
end
end
###演習
1.
マイクロポストを作成し、その後、作成したマイクロポストを削除してみましょう。次に、Railsサーバーのログを見てみて、DELETE文の内容を確認してみてください。
確認
redirect_to request.referrer || root_urlの行をredirect_back(fallback_location: root_url)と置き換えてもうまく動くことを、ブラウザを使って確認してみましょう(このメソッドはRails 5から新たに導入されました)。
確認
かっこなしでも動くらしい
###フィード画面のマイクロポストをテストする
Micropostsコントローラの認可をチェックする短いテストと、それらをまとめる統合テストを書くことです。
マイクロポスト用のfixtureに、別々のユーザーに紐付けられたマイクロポストを追加
####別のユーザーに所属しているマイクロポストを追加する
test/fixtures/microposts.yml
.
.
.
ants:
content: "Oh, is that what you want? Because that's how you get ants!"
created_at: <%= 2.years.ago %>
user: archer
zone:
content: "Danger zone!"
created_at: <%= 3.days.ago %>
user: archer
tone:
content: "I'm sorry. Your words made sense, but your sarcastic tone did not."
created_at: <%= 10.minutes.ago %>
user: lana
van:
content: "Dude, this van's, like, rolling probable cause."
created_at: <%= 4.hours.ago %>
user: lana
####間違ったユーザーによるマイクロポスト削除に対してテストする
test/controllers/microposts_controller_test.rb
.
.
.
test "should redirect destroy for wrong micropost" do
log_in_as(users(:michael))
micropost = microposts(:ants)
assert_no_difference 'Micropost.count' do
# 削除されていないことを確認?
delete micropost_path(micropost)
# 削除することを要求
end
assert_redirected_to root_url
# root_urlにリダイレクトされるか?
end
end
####統合テスト
ubuntu:~/environment/sample_app (user-microposts) $ rails generate integration_test microposts_interface
Running via Spring preloader in process 9548
invoke test_unit
create test/integration/microposts_interface_test.rb
####マイクロポストのUIに対する統合テスト
test/integration/microposts_interface_test.rb
require 'test_helper'
class MicropostsInterfaceTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test "micropost interface" do
# 完全に削除されたか?
log_in_as(@user)
# ログインさせる
get root_path
# ホーム画面に転送することを要求
assert_select 'div.pagination'
# 要求が認められページネートが表示されているか?
# 無効な送信
assert_no_difference 'Micropost.count' do
# 投稿が無効
post microposts_path, params: { micropost: { content: "" } }
# 空の投稿
end
assert_select 'div#error_explanation'
# エラ〜メッセージが表示されているか?
assert_select 'a[href=?]', '/?page=2'
# 正しいページネーションリンク
# ページネートが2ページに行くか?
content = "This micropost really ties the room together"
# 有効なマイクロポスト
assert_difference 'Micropost.count', 1 do
# 投稿の数の差が1かどうか?
post microposts_path, params: { micropost: { content: content } }
# 投稿する
end
assert_redirected_to root_url
# root_urlにリダイレクトされているか?
follow_redirect!
# 後から調べる
assert_match content, response.body
# マイクロポストの数があれば、コンテントがあるか?
# 投稿を削除する
assert_select 'a', text: 'delete'
# aタグにdeleteがあるか?
first_micropost = @user.microposts.paginate(page: 1).first
#1枚目の 1番目のマイクロポストを返す
assert_difference 'Micropost.count', -1 do
# 削除して一つ減っているか?
delete micropost_path(first_micropost)
# 先のマイクロポストを削除する
end
# 違うユーザーのプロフィールにアクセス(削除リンクがないことを確認)
get user_path(users(:archer))
# archerのuser_pathに行くことを要求
assert_select 'a', text: 'delete', count: 0
# aタグのdeleteが表示されていないか?
end
end
####演習
1.
リスト 13.56で示した4つのコメント(「無効な送信」など)のそれぞれに対して、テストが正しく動いているか確認してみましょう。具体的には、対応するアプリケーション側のコードをコメントアウトし、テストが red になることを確認し、元に戻すと green になることを確認してみましょう。
飛ばす。
サイドバーにあるマイクロポストの合計投稿数をテストしてみましょう。このとき、単数形(micropost)と複数形(microposts)が正しく表示されているかどうかもテストしてください。ヒント: リスト 13.58を参考にしてみてください。
.
.
.
require 'test_helper'
class MicropostsInterfaceTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
.
.
.
test "micropost sidebar count" do
log_in_as(@user)
# ログインさせる
get root_path
# ログインできたらホームページへの移動を要求
assert_match "#{@user.microposts.count} microposts", response.body
# ページの中に{@user.microposts.count}があるか?
# まだマイクロポストを投稿していないユーザー
other_user = users(:malory)
# malory
log_in_as(other_user)
# maloryをログインさせる
get root_path
# root_path(ホーム画面)への要求
assert_match "0 microposts", response.body
# 0 micropostsがページのどこかにあるか?
other_user.microposts.create!(content: "A micropost")
# マイクロポストを作成する
get root_path
assert_match "1 micropost", response.body
# 1 micropostがページのどこかに表示されているか?
end
end