セキュリティ系の勉強、その他開発メモとか雑談. GithubはUnity触っていた頃ものがメイン Twitterフォローもよろしくです

ruby チュートリアル 3章メモ

モデルとか

scaffoldで生成したモデルはApplicationRecordクラスを継承している。ApplicationRecordクラスは、Active Recordが提供する基本クラス ActiveRecord::Base を継承している。これによりモデルオブジェクトはデータベースにアクセスできるようになる。 コントローラも基本的には同じで、ApplicationControllerがActionController::Baseというクラスを継承している。このクラスは、RailsのAction Packというライブラリが提供しているコントローラの基本クラス。ActionController::Baseを継承しているのでモデルオブジェクトの操作や、送られてくるHTTP requestのフィルタリング、ビューのHTML出力が可能となる。コントローラは必ずApplicationControllerを継承しているので、Applicationコントローラで定義したルールは、アプリケーションのすべてのアクションに反映される。

命名規則

チュートリアルに従うのであれば、コントローラはキャメルケース、アクション名は小文字を使用する。コントローラはこうする事で、スネークケースにしたファイルを自動で生成してくれる(ex, StaticPages -> static_pages_controller.rb)

コントローラの生成(generateコマンド)

自分のrailsを呼び出すまでがまず長いので順番が曖昧になりがち。railsgenerateコマンドで何を生成するかでcontrollerを指定するイメージ。

bundle exec rails g controller Foo bar baz

テスト駆動開発 (TDD)

先に正しいコードがないと成功しないテストコードを作成してから、本編のコーディングを行う手法。TDDの是非については両者の意見があるが、テストは必要なものである事には一致している。

Rspecの導入

チュートリアルではMinitestを使用している。(rubyネイティブではMinitestのが良い?!)

group :development, :test do #Gemfileに書き込み
  ..
  gem 'rspec-rails', '3.6.0'
  gem 'factory_girl_rails', '~> 4.2.1' #テストコードを簡単に作成できるらしい
end
$bundle install --without production --path=vendor/bundle 
$ bundle exec rails g rspec:install 
$ bundle exec rspec #テストの実行

現状だと空なのでそのまま終わる。

** コントローラのテスト rubyチュートリアル的に初めのテストはコントローラのテストになりそう。チュートリアルだとaboutのテストを作成するが、まず既存のアクションに対するテストを作成してみる。

require 'rails_helper'

RSpec.describe StaticPagesController, type: :controller do
  describe 'GET #home' do
    it 'has a 200 status code' do
      get 'home'
      expect(response).to have_http_status(:ok)
    end
  end
  describe 'GET #help' do
    it 'has a 200 status code' do
      get 'help'
      expect(response.status).to eq(200) #この書き方でもok
    end
  end
end

するとこんなエラーが、、

require File.expand_path('../../config/environment', __FILE__)

解決法はこちらのサイトにありました。以下の3行をconfig/application.rbの先頭に追記します。 理由まではちょっとまだわからないです。

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'

無事テスト完了しました。

$ bundle exec rspec
..

Finished in 0.02094 seconds (files took 8.91 seconds to load)
2 examples, 0 failures

** aboutのテストエラーを解決していく 上のテストコードにaboutアクションについて同じテストを書きました。その後のテストのエラーは以下。

Failures:

  1) StaticPagesController GET #about has a 200 status code
     Failure/Error: get 'about'

     ActionController::UrlGenerationError:
       No route matches {:action=>"about", :controller=>"static_pages"}
     # ./spec/controllers/static_pages_controller_spec.rb:18:in `block (3 levels) in <top (required)>'

ルートマッチがうまくいっていないとのこと。チュートリアル通り、config/routes.rbに追記します。おそらく次のエラーはアクションがありませんのエラーです。

 1) StaticPagesController GET #about has a 200 status code
     Failure/Error: get 'about'

     AbstractController::ActionNotFound:
       The action 'about' could not be found for StaticPagesController
     # ./spec/controllers/static_pages_controller_spec.rb:18:in `block (3 levels) in <top (required)>'

最後はビューがないよってエラーです。少し長いですが、上に出てくるエラーはチュートリアルと同じですね。

 1) StaticPagesController GET #about has a 200 status code
     Failure/Error: get 'about'

     ActionController::UnknownFormat:
       StaticPagesController#about is missing a template for this request format and variant.

       request.formats: ["text/html"]
       request.variant: []

       NOTE! For XHR/Ajax or API requests, this action would normally respond with 204 No Content: an empty white screen. Since you're loading it in a web browser, we assume that you expected to actually render a template, not nothing, so we're showing an error to be extra-clear. If you expect 204 No Content, carry on. That's what you'll get from an XHR or API request. Give it a shot.
     # ./spec/controllers/static_pages_controller_spec.rb:18:in `block (3 levels) in <top (required)>'

aboutに対応したviewのファイルを作ってあげて終了です。テストもうまくいくはずです。緑の文字が気持ちいいです。

...

Finished in 0.06586 seconds (files took 10.31 seconds to load)
3 examples, 0 failures

rspecが認識するファイル

接尾辞として_spec.rbがついていること、specディレクトリ以下にあることがテスト時に実行される条件。例えば、hoge_pages_controller.rbならhoge_pages_controller_spec.rbに、application.html.erbならapplication.html_spec.rbにテストを記述してあげる。

ページ要素の検証

初めはcapybaraを使おうとか考えましたが、チュートリアルのテストコードがそのまま使えるようです。(assert_selectのやつ)it~endの間に追加して終わりです。
注意としては以下の1行を追加すること。render_viewsを書けばviewの内容も確認できる。これはcontrollerは元々アクション等の振る舞いのみをテストしてほしいからっぽい。 そもそもviewのテストは複雑になるのでテストもあまりしないらしい。

describe StaticPagesController, type: :controller do
  render_views
 ...


erb「埋め込みRuby」(Embedded Ruby)

書き方として<% %><%= %>がある。前者は中のコードが実行されるが、出力しない。後者は実行した後、記述部に出力が挿入される。viewの部分でよく使用する。

yield

今回<%=yield ... %>の書き方が出てきた。yieldは渡されたブロックを走らせてくれる。ブロックは{}do~endで囲まれた部分のこと。rubyはデフォルトでブロックを引数として受け取っているらしいのでそれをyieldで走らせているっぽい。デフォルトで生成されたapplication.html.erbではbody部分をyield記述しているので、レイアウトを各ページに反映していると考えられる。



課題

テストのヘルパーの使い方がわからない。RSpecからだと呼べないのか、書く場所がよくないのか?