LoginSignup
19

More than 5 years have passed since last update.

あとでもっかい試す用 - Ruby on Rails 4.0 チュートリアル - 第三章

Last updated at Posted at 2013-08-28

Ruby on Rails チュートリアル 実例を使ってRailsを学ぼう / Michael Hartl (マイケル・ハートル) を見ながらやったことを、あとでもう一度できるようにまとめます!!第三章!!

第三章の説明

  • 静的ページを作成する
  • テスト駆動開発をはじめる(RSpecの使い方がわかる)
  • レイアウトファイルを使う

プロジェクトを作成 & 設定

$ cd ~/workspace/ruby/rails/
$ rails new sample_app --skip-test-unit

Gemfileを修正

新しくRSpecの為のGemとRSpecのライブラリのGemが追加されてる。

$ subl Gemfile

source 'https://rubygems.org'
ruby '2.0.0'
#ruby-gemset=railstutorial_rails_4_0

gem 'rails', '4.0.0'

group :development, :test do
  gem 'sqlite3', '1.3.7'
  gem 'rspec-rails', '2.13.1'
end

group :test do
  gem 'selenium-webdriver', '2.0.0'
  gem 'capybara', '2.1.0'
end

gem 'sass-rails', '4.0.0'
gem 'uglifier', '2.1.1'
gem 'coffee-rails', '4.0.0'
gem 'jquery-rails', '2.2.1'
gem 'turbolinks', '1.1.1'
gem 'jbuilder', '1.0.2'

group :doc do
  gem 'sdoc', '0.3.20', require: false
end

group :production do
  gem 'pg', '0.15.1'
  gem 'rails_12factor', '0.0.2'
end

bundle インストール

$ bundle install --without production
$ bundle update
$ bundle install

秘密トークン初期化処理を動的に生成するように修正

ソースコードを公開する際、秘密トークンも一緒に公開することが無いように、
秘密トークンを動的に生成するようにする。

$ subl config/initializers/secret_token.rb

require 'securerandom'

def secure_token
  token_file = Rails.root.join('.secret')
  if File.exist?(token_file)
    # Use the existing token.
    File.read(token_file).chomp
  else
    # Generate a new token and store it in token_file.
    token = SecureRandom.hex(64)
    File.write(token_file, token)
    token
  end
end

SampleApp::Application.config.secret_key_base = secure_token

.gitignoreを修正

.secret に秘密トークンが記述されているので、公開リポジトリにpushしないように.gitignoreで無視するように指定している。

$ subl .gitignore

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal

# Ignore all logfiles and tempfiles.
/log/*.log
/tmp

# Ignore other unneeded files.
doc/
*.swp
*~
.project
.DS_Store
.idea
.secret

テストにRSpecを使う為の設定をする

$ rails generate rspec:install

Gitの設定

$ git init
$ git add .
$ git commit -m "Initial commit"

READMEを修正する

$ subl README.rdoc
$ git mv README.rdoc README.md
$ git commit -am "Improve the README"

Githubに公開する

$ git remote add origin https://github.com/yujiroarai/sample_app.git
$ git push -u origin master

herokuにデプロイ

$ heroku create
$ git push heroku master
$ heroku run rake db:migrate

静的ページを作成

トピックブランチを作る

$ git co -b static-pages

コントローラを生成する

$ rails generate controller StaticPages home help --no-test-framework

StaticPagesの部分がコントローラ名(ファイル名はスネークケースに変換される)。
home・helpはアクション名
--no-test-frameworkはRSpecのテストを生成しないからつけてる。

コマンドを間違えた場合は、rails destroyコマンドを使って元に戻す。

$ rails destroy controller StaticPages home help

git に commit

$ git add .
$ git commit -m "Add a StaticPages controller"

最初のテスト

テスト作成

$ rails generate integration_test static_pages
$ subl spec/requests/static_pages_spec.rb

require 'spec_helper'

describe "StaticPages" do

  describe "Home page" do
    it "should have the content'SampleApp'" do
      visit '/static_pages/home'
      expect(page).to have_content('Sample App')
    end
  end
end

テストの設定を追加

$ subl spec/spec_helper.rb  

RSpec.configure do |config|
  .
  .
  .
+ config.include Capybara::DSL
end

テストを実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=>失敗する

コードを修正

$ subl app/views/static_pages/home.html.erb

<h1>Sample App</h1>
<p>
    This is the home page for the
  <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
</p>

テストを実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=>成功する

Helpページもテストする

$ subl spec/requests/static_pages_spec.rb

+ describe "Help page" do
+   it "should have the content 'Help'" do
+     visit '/static_pages/help'
+     expect(page).to have_content('Help')
+   end
+ end

テストを実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=>失敗する

コードを修正

$ subl app/views/static_pages/home.html.erb

<h1>Help</h1>
<p>
  Get help on the Ruby on Rails Tutorial at the
  <a href="http://railstutorial.org/help">Rails Tutorial help page</a>.
  To get help on this sample app, see the
  <a href="http://railstutorial.jp/book">Rails Tutorial book</a>.
</p>

テストを実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=>成功する

About Us ページを追加する

テストを修正して赤色にする

$ subl spec/requests/static_pages_spec.rb

+ describe "About page" do
+ 
+   it "should have the content 'About Us'" do 
+     visit '/static_pages/about'
+     expect(page).to have_content('About Us')
+   end
+ end   

テスト実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=> 失敗する

Failures:

  1) StaticPages About page should have the content 'About Us'
     Failure/Error: visit '/static_pages/about'
     ActionController::RoutingError:
       No route matches [GET] "/static_pages/about"
     # ./spec/requests/static_pages_spec.rb:21:in `block (3 levels) in  <top (required)>'

↓これは、/static_pages/aboutというルートをroutesファイルに追加する必要があるということを示している。

No route matches [GET] "/static_pages/about"

ルートを追加

$ subl config/routes.rb

SampleApp::Application.routes.draw do
  get "static_pages/home"
  get "static_pages/help"
+ get "static_pages/about"
  .
  .
  .
end

テスト実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=> 失敗する

  1) StaticPages About page should have the content 'About Us'
     Failure/Error: visit '/static_pages/about'
     AbstractController::ActionNotFound:
       The action 'about' could not be found for StaticPagesController
     # ./spec/requests/static_pages_spec.rb:21:in `block (3 levels) in  <top (required)>'

↓これは、aboutアクションがStaticPagesControllerにないよ。って意味

The action 'about' could not be found for StaticPagesController

aboutアクションを追加

$ subl app/controllers/static_pages_controller.rb

class StaticPagesController < ApplicationController
  def home
  end

  def help
  end

+ def about
+ end
end

テスト実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=> 失敗する

  1) StaticPages About page should have the content 'About Us'
     Failure/Error: visit '/static_pages/about'
     ActionView::MissingTemplate:
       Missing template static_pages/about, application/about with  {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :j builder, :coffee]}. Searched in:
         * "/Users/yujiroarai/workspace/ruby/rails/sample_app/app/  views"
     # ./spec/requests/static_pages_spec.rb:21:in `block (3 levels) in  <top (required)>'

↓これは、テンプレートファイルが無いよって意味

Missing template static_pages/about

AboutUsのテンプレートファイル作成

$ touch app/views/static_pages/about.html.erb
$ subl app/views/static_pages/about.html.erb

<h1>About Us</h1>
<p>
  The <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
  is a project to make a book and screencasts to teach web  development
  with <a href="http://rubyonrails.org/">Ruby on Rails</a>. This
  is the sample application for the tutorial.
</p>

テスト実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=> 成功!!

少しだけ動的なページにする

タイトルを、「Ruby on Rails Tutorial Sample App」から「Ruby on Rails Tutorial Sample App | {ページ名}」に修正する。

タイトル変更をテストする

$ subl spec/requests/static_pages_spec.rb

require 'spec_helper'

describe "StaticPages" do

  describe "Home page" do
    it "should have the content'SampleApp'" do
      visit '/static_pages/home'
      expect(page).to have_content('Sample App')
    end

+   it "should have the right title" do
+     visit '/static_pages/home'
+     expect(page).to have_title("Ruby on Rails Tutorial Sample App | Home")
+   end
  end

  describe "Help page" do
    it "should have the content 'Help'" do
      visit '/static_pages/help'
      expect(page).to have_content('Help')
    end

+   it "should have the title 'Help'" do
+     visit '/static_pages/help'
+     expect(page).to have_title("Ruby on Rails Tutorial Sample App | Help")
+   end
  end

  describe "About page" do
    it "should have the content 'About Us'" do 
      visit '/static_pages/about'
      expect(page).to have_content('About Us')
    end

+   it "should have the title 'About Us'" do
+     visit '/static_pages/about'
+     expect(page).to have_title("Ruby on Rails Tutorial Sample App | About Us")
+   end
  end

end

テスト実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=> 失敗する

テストをパスするようにHTMLを修正する

レイアウトファイルを修正

共通のHTMLはレイアウト用のファイルに書く。

$ subl app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
<head>
  <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>
  <%= stylesheet_link_tag    "application", media: "all",
                                            "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= yield %>

</body>
</html>

Homeページを修正

変数titleにHomeと設定

$ subl app/views/static_pages/home.html.erb

<% provide(:title, 'Home') %>
<h1>Sample App</h1>
<p>
    This is the home page for the
    <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
</p>

Helpページを修正

$ subl app/views/static_pages/help.html.erb

<% provide(:title, 'Help') %>
<h1>Help</h1>
<p>
  Get help on the Ruby on Rails Tutorial at the
  <a href="http://railstutorial.org/help">Rails Tutorial help page</a>.
  To get help on this sample app, see the
  <a href="http://railstutorial.jp/book">Rails Tutorial book</a>.
</p>

Aboutページを修正

$ subl app/views/static_pages/about.html.erb

<% provide(:title, 'About Us') %>
<h1>About Us</h1>
<p>
  The <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
  is a project to make a book and screencasts to teach web development
  with <a href="http://rubyonrails.org/">Ruby on Rails</a>. This
  is the sample application for the tutorial.
</p>

テストを実行

$ bundle exec rspec spec/requests/static_pages_spec.rb
=> 成功!!

Githubにpush

$ git add .
$ git commit -m "Finish static pages"
$ git co master
$ git merge static-pages --no-ff
$ git push

herokuにデプロイ

$ git push heroku

演習: 問い合わせページを作成する

テスト作成

$ subl spec/requests/static_pages_spec.rb

+  describe "Contact page" do
+    it "should have the content 'Contact" do
+      visit '/static_pages/contact'
+      expect(page).to have_content('Contact')
+    end
+
+    it "should have the title 'Contact'" do
+      visit '/static_pages/contact'
+      expect(page).to have_title("Ruby on Rails Tutorial Sample App | Contact")
+    end
+  end

ルートを追加

$ subl config/routes.rb 

SampleApp::Application.routes.draw do
get "static_pages/home"
get "static_pages/help"
get "static_pages/about"
+ get "static_pages/contact"

アクションを追加

$ subl app/controllers/static_pages_controller.rb 

class StaticPagesController < ApplicationController
  def home
  end

  def help
  end

  def about
  end

+  def contact
+  end
end

ビューを追加

$ touch app/views/static_pages/contact.html.erb
$ subl app/views/static_pages/contact.html.erb

<% provide(:title, 'Contact') %>
<h1>Contact</h1>
<p>
  Contact Ruby on Rails Tutorial about the sample app at the
  <a href="http://railstutorial.jp/contact">contact page</a>.
</p>

テストをもっと簡単に使う為の設定

Guardによるテストの自動化

guard-rspecをGemfileに追加する。

$ subl Gemfile

group :development, :test do
  gem 'sqlite3', '1.3.7'
  gem 'rspec-rails', '2.13.1'
+  gem 'guard-rspec', '2.5.0'
end

bundle インストール

$ bundle install --without production

Guardを初期化し、RSpecと一緒に動作するようにする。

$ bundle exec guard init rspec
03:39:23 - INFO - Writing new Guardfile to /Users/yujiroarai/   workspace/ruby/rails/sample_app/Guardfile
03:39:23 - INFO - rspec guard added to Guardfile, feel free to edit it

Guardfileを修正する。

$ subl Guardfile

# A sample Guardfile
# More info at https://github.com/guard/guard#readme

+ require 'active_support/inflector'

guard 'rspec' do

Guardを起動する。

$ bundle exec guard

Sporkでテストを高速化

Gemfileを修正

$ subl Gemfile
group :development, :test do
  gem 'sqlite3', '1.3.7'
  gem 'rspec-rails', '2.13.1'
  gem 'guard-rspec', '2.5.0'
+  gem 'spork-rails', github: 'sporkrb/spork-rails'
+  gem 'guard-spork', '1.5.0'
+  gem 'childprocess', '0.3.6'
end

bundle インストール

$ bundle install

sporkの設定にbootstrapを指定。(TODOなにしてるかわからないから調べる)

$ bundle exec spork --bootstrap

環境の読み込みを一回で済ますため、spec/spec_helper.rbの中で環境をpreforkのブロックで読み込むように、RSpecの設定を変更する。

Spork.prefork doの中に設定を追加する。

Spork.prefork do
  # Loading more in this block will cause your tests to run faster. However,
  # if you change any configuration or code from libraries loaded here, you'll
  # need to restart spork for it take effect.
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'rspec/autorun'

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  # Checks for pending migrations before tests are run.
  # If you are not using ActiveRecord, you can remove this line.
  ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)

  RSpec.configure do |config|
    # == Mock Framework
    #
    # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
    #
    # config.mock_with :mocha
    # config.mock_with :flexmock
    # config.mock_with :rr

    # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
    config.fixture_path = "#{::Rails.root}/spec/fixtures"

    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, remove the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = true

    # If true, the base class of anonymous controllers will be inferred
    # automatically. This will be the default behavior in future versions of
    # rspec-rails.
    config.infer_base_class_for_anonymous_controllers = false

    # Run specs in random order to surface order dependencies. If you find an
    # order dependency and want to debug it, you can fix the order by providing
    # the seed, which is printed after each run.
    #     --seed 1234
    config.order = "random"
    config.include Capybara::DSL
  end
end

GuardにSporkを導入する

GuardのファイルにSporkの設定を導入

$ bundle exec guard init spork
$ subl 

require 'active_support/inflector'

guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' },
               :rspec_env    => { 'RAILS_ENV' => 'test' } do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch('config/environments/test.rb')
  watch(%r{^config/initializers/.+\.rb$})
  watch('Gemfile')
  watch('Gemfile.lock')
  watch('spec/spec_helper.rb') { :rspec }
  watch('test/test_helper.rb') { :test_unit }
  watch(%r{features/support/}) { :cucumber }
end

guard 'rspec', after_all_pass: false, cli: '--drb' do
  .
  .
  .
end

GuardとSporkを同時に起動する

$ bundle exec guard

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19