Ruby on Rails Tutorial (19)
朝練メモ。最近盛り込みが複雑になってきたのもあるけれど、ミスが多い。
10.3 Manipulating microposts
microposts の routing は作るか消すしかない模様。config/routes.rb に以下を追加な模様。
resources :microposts, only: [:create, :destroy]
で、保存して確認。
$ bundle exec rake routes users GET /users(.:format) users#index POST /users(.:format) users#create new_user GET /users/new(.:format) users#new edit_user GET /users/:id/edit(.:format) users#edit user GET /users/:id(.:format) users#show PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy sessions POST /sessions(.:format) sessions#create new_session GET /sessions/new(.:format) sessions#new session DELETE /sessions/:id(.:format) sessions#destroy microposts POST /microposts(.:format) microposts#create micropost DELETE /microposts/:id(.:format) microposts#destroy root / static_pages#home signup /signup(.:format) users#new signin /signin(.:format) sessions#new signout DELETE /signout(.:format) sessions#destroy help /help(.:format) static_pages#help about /about(.:format) static_pages#about contact /contact(.:format) static_pages#contact
知らない間にこんなに育っちまった。
10.3.1 Access control
signin してないと作成および削除はできない、と。当り前ですね。それを試験する spec が以下になるのかな。
spec/requests/authentication_pages_spec.rb (一部のみ)
describe "in the Microposts controller" do describe "submitting to the create action" do before { post microposts_path } specify { response.should redirect_to(signin_path) } end describe "submitting to the destroy action" do before { delete micropost_path(FactoryGirl.create(:micropost)) } specify { response.should redirect_to(signin_path) } end end
上記は "for non-signed-in users" なブロックの中に置かれます。のでリダイレクトされるべき、なんですね。試験は当然 red 終了。試験パスにもってくにはちょっとした refactoring が必要、ってありますね。
ええと users_controller.rb にある signed_in_user メソドを app/helpers/session_helper.rb 方面に持ってけ、ということなのかな。
これで microposts な controller でもこのメソドが呼び出せる、ということなのか。before_filter に盛り込んでおけば
def signed_in_user unless signed_in? store_location redirect_to signin_url, notice: "Please sign in." end end
signin なソレにリダイレクトされる、と。つうか microposts_controller.rb が無いな。面倒なのでそのまま作るか。
class MicropostsController < ApplicationController before_filter :signed_in_user, only: [:create, :destroy] def index end def create end def destroy end end
これで試験実行。green 終了確認。
10.3.2 Creating microposts
投稿関連。ユーザ登録で似たようなことしてるよね、とのこと。とりあえず試験を作成。
$ rails generate integration_test micropost_pages invoke rspec create spec/requests/micropost_pages_spec.rb
で、以下を盛り込み。
spec/requests/micropost_pages_spec.rb
require 'spec_helper' describe "MicropostPages" do subject { page } let(:user) { FactoryGirl.create(:user) } before { sign_in user } describe "micropost creation" do before { visit root_path } describe "with invalid information" do it "should not create a micropost" do expect { click_button "Post" }.not_to change(Micropost, :count) end describe "error messages" do before { click_button "Post" } it { should have_content('error') } end end describe "with valid information" do before { fill_in 'micropost_content', with: "Lorem ipsum" } it "should create a micropost" do expect { click_button "Post" }.to change(Micropost, :count).by(1) end end end end
ええと、よくよく見るに subject とかって確認した方が良いですね。visit root_path とかも若干微妙。この場合は入力画面になるのかどうか。つうかやっぱ全部盛り込み終わった時点で全部ざくっと確認しないとマズいですね。理解が微妙な部分が多すぎる。ざっくりは理解できてるんですがorz
試験保存して red 終了確認。
controller 方面に 10.30 を盛り込みます。
def create @micropost = current_user.microposts.build(params[:micropost]) if @micropost.save flash[:success] = "Micropost created!" redirect_to root_url else render 'static_pages/home' end end
試験パスするまで道が長いですが盛り込んでみます。
- app/views/static_pages/home.html.erb
- app/views/shared/_user_info.html.erb
- app/views/shared/_micropost_form.html.erb
- app/controllers/static_pages_controller.rb
- app/views/shared/_error_messages.html.erb
ここで以下が green との記述あり。がしかし red 終了。ちょい時間切れなので別途確認の方向でエントリは投入しときます。対処などおそらく追記されるはず。
追記
app/views/shared/_error_messages.html.erb の盛り込み漏れが原因でした。@user.errors な記述が残っておりました。でもまだ試験 red ですね。
あ、原因は typo でした。とほほ。試験 green 確認してます。
残りもう少しなのでそのまま盛り込み続行。
- app/views/users/new.html.erb
- app/views/users/edit.html.erb
これらは両方 render 'shared/error_messages' してる箇所ですね。
これで全ての試験が green 終了のはず。green 終了でした。よかった。
$ bundle exec rspec spec/ Rack::File headers parameter replaces cache_control after Rack 1.5. ............................................................................................................. Finished in 35.92 seconds 109 examples, 0 failures Randomized with seed 15328
さらに追記
エントリを改めるのもアレなのでそのまま続けて、ということにて。
10.3.3 A proto-feed
ええと、自分の feed を表示させるのか。w3m だと mock 見ながら云々できなくてちょい不便。user model に feed というメソドが追加になるんですかね。あら、follow が云々という話が出てきてますね。とりあえず Listing 10.38 な試験を盛り込んでおきます。
- feed という属性 (メソド) があること
- フォローしていないユーザのポストは feed に含まれないこと
つうか
describe "status" do let(:unfollowed_post) do FactoryGirl.create(:micropost, user: FactoryGirl.create(:user)) end
な記述が色々と微妙なんですがorz
あと、include は配列なオブジェクトのメソドなんすね。で、_とりあえず_ feed なメソドは以下な記述に、とのこと。id はちゃんとエスケイプする手段があるはずなんですが、ここでは_とりあえず_なのだろうな。
def feed # This is preliminary. See "Following users" for the full implementation. Micropost.where("user_id = ?", id) end
上記盛り込んで試験実行してみましたが、green 終了してしまいました。以降順次盛り込んでいきたいと思います。
- spec/requests/static_pages_spec.rb
- root_path にアクセスしたら feed なコンテンツが出てること
- app/controllers/static_pages_controller.rb
- signed_in? なら feed 表示の用意
- app/views/shared/_feed.html.erb
- app/views/shared/_feed_item.html.erb
- こいつが id 付きの li を吐いてるのか
- app/views/static_pages/home.html.erb
- app/controllers/microposts_controller.rb
- 保存に失敗した場合、@feed_items に [] を代入
これで試験 green になるはず、とありますがどうなのか。つうか盛り込んだだけなんだけどこれで良いのか(とは言え、ざっくりは理解できてますが)。
試験 green は確認済みです。
10.3.4 Destroying microposts
この節で 10 は終わりらしいのでそのまま続けてみます。最後に削除を実装して終わりな模様。削除なリンクは投稿者のみ、という形なのかな。
とりあえず partial なソレについて削除リンクを追加してます。
- app/views/microposts/_micropost.html.erb
- app/views/shared/_feed_item.html.erb
この試験は spec/requests/micropost_pages_spec.rb で以下を追加とのこと。
describe "micropost destruction" do before { FactoryGirl.create(:micropost, user: user) } describe "as correct user" do before { visit root_path } it "should delete a micropost" do expect { click_link "delete" }.to change(Micropost, :count).by(-1) end end end
試験的には signin 前提になっております、念の為。
$ bundle exec rspec spec/requests/micropost_pages_spec.rb
あら、red 終了だな。controller にも盛り込みが必要なのかな。そもそも destroy というメソドが空でした。
app/controllers/microposts_controller.rb に before_filter 追加して
class MicropostsController < ApplicationController before_filter :signed_in_user, only: [:create, :destroy] before_filter :correct_user, only: :destroy
必要なメソドの記述を追加。
def destroy @micropost.destroy redirect_to root_url end private def correct_user @micropost = current_user.microposts.find_by_id(params[:id]) redirect_to root_url if @micropost.nil? end
ぐ、また試験 red だな。以下が NG な模様。
describe "with valid information" do before { fill_in 'micropost_content', with: "Lorem ipsum" } it "should create a micropost" do expect { click_button "Post" }.to change(Micropost, :count).by(1) end end end describe "micropost destruction" do before { FactoryGirl.create(:micropost, user: user) } describe "as correct user" do before { visit root_path } it "should delete a micropost" do expect { click_link "delete" }.to change(Micropost, :count).by(-1) end end end
ん、_feed_item.html.erb?
コピペで済ませてて以下になってましたorz
<% if current_user?(micropost.user) %> <%= link_to "delete", micropost, method: :delete, data: { confirm: "You sure?" }, title: micropost.content %> <% end %>
正しくは以下。
<% if current_user?(feed_item.user) %> <%= link_to "delete", feed_item, method: :delete, data: { confirm: "You sure?" }, title: feed_item.content %> <% end %>
とほほ杉orz
試験 green 確認してます。
後始末
git および heroku へのナニを云々。
ちなみに heroku pg:reset ができませんでした。いっかいアプリを削除して再度 push とかしてみようかな。
確認必要なソレ
- request な試験に出てくる subject について