Rails5「中級」チュートリアル(3-5)投稿機能: 単一の投稿(翻訳)

概要

概要

原著者の許諾を得て翻訳・公開いたします。

Rails5中級チュートリアルはセットアップが短めで、RDBMSにはPostgreSQL、テストにはRSpecを用います。
原文が非常に長いので分割します。章ごとのリンクは順次追加します。

注意: Rails中級チュートリアルは、Ruby on Railsチュートリアル(https://railstutorial.jp/)(Railsチュートリアル)とは著者も対象読者も異なります。

目次

Rails5「中級」チュートリアル(3-5)投稿機能: 単一の投稿(翻訳)

新しいブランチに切り替えます。

git checkout -b single_post

単一の投稿を表示する

現時点では、show.html.erbテンプレートやそれに対応するコントローラアクションがないので、I'm interestedボタンをクリックするとエラーが表示されます。このボタンをクリックしたら、選択した投稿のページにリダイレクトされるようにしたいと思います。

PostsControllerの内部にshowアクションを作成します。ここでクエリをかけて特定のpostオブジェクトをインスタンス変数に保存します(Gist)。

# controllers/posts_controller.rb
  def show
    @post = Post.find(params[:id])
  end

I'm interestedボタンは、選択した投稿へのリダイレクトを行います。このボタンのhref属性には投稿へのパスが保存されます。投稿を1件取得するためのGETリクエストを送信すると、Railsはshowアクションを呼び出します。このshowアクションの中ではidパラメータ(params)にアクセスします。このidは、特定の投稿を1件取得するためのGETリクエストからのものです。たとえば、ブラウザで/posts/1パスにアクセスすると、id1の投稿を取得するリクエストが送信されます。

portsディレクトリの下にshow.html.erbテンプレートを作成します。

views/posts/show.html.erb

このファイルに以下のコードを追加します(Gist)。

<!-- views/posts/show.html.erb -->
<div id="single-post-content" class="container">
  <div class="row">
    <div class="col-sm-6 col-sm-offset-3">
      <div class="posted-by">Posted by <%= @post.user.name %></div>
      <h3><%= @post.title %></h3>
      <p><%= @post.content %></p>
    </div>
  </div><!-- row -->
</div>

postsディレクトリの下にshow.scssファイルを作成し、以下のCSSを追加してページのスタイルを整えます(Gist)。

// assets/stylesheets/partials/posts/show.scss
#single-post-content {
  background: white;
  height: calc(100vh - 50px);

  h3 { 
    text-align: center;
  }
  p {
    margin: 50px 0;
  }
  .posted-by {
    font-size: 12px;
    font-size: 1.2rem;
    margin: 20px 0;
    color: rgba(0,0,0,0.5);
  }
}

ここではページの高さを100vh-50pxで定義しているので、ページのコンテンツの高さはビューポート(viewport)の高さいっぱいになります。これにより、要素内のコンテンツの量が多くても少なくても、このコンテナの色はブラウザの高さいっぱいまで白になります。vhは「ビューポートの高さ」を表すので、100vhという値を指定すると要素はビューポートの高さの100%まで引き伸ばされます。ナビゲーションバーの高さを100vh-50pxから引いておく必要があります。そうしておかないと、コンテナの高さが50px余分に伸びてしまいます。

これで、I'm interestedボタンをクリックするとページがリダイレクトされて以下のように表示されます。

show.html.erbテンプレートには後で他にも機能を追加しますので、今は変更をcommitしておきましょう。

git add -A
git commit -m "Create a show template for posts

- Add a show action and query a post to an instance variable
- Create a show.scss file and add CSS"

spec

こういうモーダルウインドウや選択した投稿のリダイレクトといった機能が正常に動くかどうかのチェックは、手動で行わず、すべてspecに含めておきましょう。capybaraを使ってユーザーのアプリ操作をシミュレートすることにします。

featuresディレクトリの下にpostsディレクトリを作成します。

spec/features/posts

このディレクトリにvisit_single_post_spec.rbファイルを作成し、feature specをそこに追加します。追加後のファイルは以下のようになります(Gist)。

# spec/features/posts/visit_single_post_spec.rb
require "rails_helper"

RSpec.feature "Visit single post", :type => :feature do
  let(:user) { create(:user) }
  let(:post) { create(:post) }

  scenario "User goes to a single post from the home page", js: true do
    post
    visit root_path
    page.find(".single-post-card").click
    expect(page).to have_selector('body .modal')
    page.find('.interested a').click
    expect(page).to have_selector('#single-post-content p', text: post.content)
  end

end

ここでは、手動での操作手順をすべて定義しています。最初にhomeページを開き、投稿をクリックすると、モーダルウインドウがポップアップすることを期待(expect)しています。I'm interestedボタンをクリックすると、投稿ページにリダイレクトしてコンテンツが表示されることを期待しています。

RSpecのhave_selectorhave_cssなどのマッチャーは、ある要素がユーザーに実際に見える状態になっているとデフォルトでtrueを返します。したがって、投稿でクリックした後にテスティングフレームワークはモーダルウインドウが表示されることを期待します。ある要素がユーザーに見えるかどうかは問題でない場合や、要素がDOMにあるかどうかだけを知りたい場合は、visible: false引数を追加します。

テストを実行してみましょう。

rspec spec/features/posts/visit_single_post_spec.rb

変更をcommitします。

git add -A
git commit -m "Add a feature spec to test if a user can go to a
single post from the home page"

single_postブランチをmasterにmergeします。

git checkout master
git merge single_post
git branch -D single_post

関連記事

新しいRailsフロントエンド開発(1)Asset PipelineからWebpackへ(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

BPSアドベントカレンダー

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ