Tambourine作業メモ

主にスキル習得のためにやった作業のメモ。他人には基本的に無用のものです。

Rails チュートリアルをやってみる(11) 5.1 テンプレートまわり

5章に入る。

5.1

5.1.1でまずはHTMLにdivタグとclass設定で構造を入れる。この時点ではCSSを当ててないので、しょっぱい。演習はcurlコマンドを使ってみろとかなので省略。

5.1.2でBootstrapを適用する。まずはgemをインストール

> vi Gemfile
> git diff Gemfile
diff --git a/Gemfile b/Gemfile
index ad03f0d..384a66b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,7 @@
 source 'https://rubygems.org'
 
 gem 'rails',        '5.1.6'
+gem 'bootstrap-sass','3.3.7'
 gem 'puma',         '3.9.1'
 gem 'sass-rails',   '5.0.6'
 gem 'uglifier',     '3.2.0'
> bundle install
Fetching gem metadata from https://rubygems.org/.........
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using rake 12.3.1
Using concurrent-ruby 1.1.3
Using i18n 1.1.1
Using minitest 5.10.3
Using thread_safe 0.3.6
Using tzinfo 1.2.5
Using activesupport 5.1.6
Using builder 3.2.3
Using erubi 1.7.1
Using mini_portile2 2.3.0
Using nokogiri 1.8.5
Using rails-dom-testing 2.0.3
Using crass 1.0.4
Using loofah 2.2.3
Using rails-html-sanitizer 1.0.4
Using actionview 5.1.6
Using rack 2.0.6
Using rack-test 1.1.0
Using actionpack 5.1.6
Using nio4r 2.3.1
Using websocket-extensions 0.1.3
Using websocket-driver 0.6.5
Using actioncable 5.1.6
Using globalid 0.4.1
Using activejob 5.1.6
Using mini_mime 1.0.1
Using mail 2.7.1
Using actionmailer 5.1.6
Using activemodel 5.1.6
Using arel 8.0.0
Using activerecord 5.1.6
Using ansi 1.5.0
Using execjs 2.7.0
Fetching autoprefixer-rails 9.3.1
Installing autoprefixer-rails 9.3.1
Using bindex 0.5.0
Using rb-fsevent 0.10.3
Using ffi 1.9.25
Using rb-inotify 0.9.10
Using sass-listen 4.0.0
Using sass 3.7.2
Fetching bootstrap-sass 3.3.7
Installing bootstrap-sass 3.3.7
Using bundler 1.17.1
Using byebug 9.0.6
Using coderay 1.1.2
Using coffee-script-source 1.12.2
Using coffee-script 2.4.1
Using method_source 0.9.2
Using thor 0.20.3
Using railties 5.1.6
Using coffee-rails 4.2.2
Using formatador 0.2.5
Using ruby_dep 1.5.0
Using listen 3.1.5
Using lumberjack 1.0.13
Using nenv 0.3.0
Using shellany 0.0.1
Using notiffany 0.1.1
Using pry 0.12.2
Using guard 2.13.0
Using guard-compat 1.2.1
Using guard-minitest 2.4.4
Using multi_json 1.13.1
Using jbuilder 2.7.0
Using jquery-rails 4.3.1
Using ruby-progressbar 1.10.0
Using minitest-reporters 1.1.14
Using puma 3.9.1
Using sprockets 3.7.2
Using sprockets-rails 3.2.1
Using rails 5.1.6
Using rails-controller-testing 1.0.2
Using tilt 2.0.8
Using sass-rails 5.0.6
Using spring 2.0.2
Using spring-watcher-listen 2.0.1
Using sqlite3 1.3.13
Using turbolinks-source 5.2.0
Using turbolinks 5.0.1
Using uglifier 3.2.0
Using web-console 3.5.1
Bundle complete! 21 Gemfile dependencies, 80 gems now installed.
Gems in the group production were not installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

カスタムCSSファイルを作る。

> ls
application.css   static_pages.scss
> touch custom.scss
> ls
application.css   custom.scss       static_pages.scss
> vi custom.scss 
> cat custom.scss 
@import "bootstrap-sprockets";
@import "bootstrap";

これで、bootstrapのCSSが適応されるらしい。ほうほう。

f:id:Tambourine:20181127113811p:plain

こんなしょっぱい画面がこうなる・・・と

f:id:Tambourine:20181127113742p:plain

あり?

<ul class="nav navbar-nav navbar-right">
  <li><a href="#">Home</a></li>
  <li><a href="#">Help</a></li>
  <li><a href="#">Log in</a></li>
</ul>

FireFoxの開発ツールでみると、navbar-rightが当たってないように見える。うーむ・・・

CSSを開発ツールで確認してみると、

@media (min-width: 768px) {
  .navbar-right .dropdown-menu {
    right: 0;
    left: auto;
  }
}

あー、ブラウザの幅が狭すぎただけだ。

f:id:Tambourine:20181127155120p:plain

広げたらちゃんと収まりました。

custom.scssにいろいろいれて遊んでみる演習はパス。

5.1.3はpartial。要するに、HTMLテンプレートのモジュール化で、renderコマンドでインポートするようなイメージだと。ふむふむ

Rails チュートリアルをやってみる(10) 4章 Rubyについて

Rails風味のRuby」とのこと。味わってみよう。

4.1

リスト4.1で例として、app/views/layouts/application.html.erbの以下のコードを取り上げている。

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>

Rubyを知らなければ、この表記は戸惑うんだろうなあ。Ruby的には

stylesheet_link_tag( 'application', media: 'all', {'data-turbolinks-track': 'reload' })

なので、引数3つのメソッド呼び出しである。

ちなみに、キーワード引数がなかった昔のRubyではこれは

stylesheet_link_tag( 'application', {:media => 'all', 'data-turbolinks-track' => 'reload'} )

だった。そして、実はあんまりキーワード引数の仕様にくわしくないので、この辺りの私の理解は曖昧だ。

それはいいとして、これを「Railsの組込関数」と表現されると悩ましい。 Rubyではすべてはメソッドで、「Rubyの組込関数」とはKernelモジュールのメソッドのことだからだ。

Rails APIのリファレンスへのリンクが示されているのでそこを見ると、このメソッドは ActionView::Helpers::AssetTagHelperのメソッドらしい。 ということは、このERBが評価されるコンテキストではAssetTagHelperがincludeされているということだ。 しかし、「なんだこのメソッド?」と思ったときに所属しているクラスを突き止めるのは大変そうだな。

・・・などと思うんだけど、それはたぶん先を読めば書いてある(笑)。先に進もう。

4.1.2はカスタムヘルパーだ。置き場所としてapp/helpers/application_helper.rbが最初から作られてるので、 そこにメソッドを作ってみようとのこと。ふむふむ。

楽しみのために仕様を理解して、リスト4.2を見ないで作ってみる。

module ApplicationHelper
    def full_title(page_title = '')
        out = ["Ruby on Rails Tutorial Sample App"]
        out.unshift page_title unless page_title.empty?
        out.join(" | ")
    end
end

テストがないと不安だな。これをレイアウトに適用してみる。うん、ちゃんと動いているようだ。

あとは4.2からこの章の最後まで、バージョン1.4から付き合っているRubyistとしては特に新しい知識はなかった。

Rails チュートリアルをやってみる(9) 3章完了 minitest reporterとGuard

3.6

3.6.1 minitest reporters

見やすくなるらしい

f:id:Tambourine:20181123001435p:plain

REDになってないとありがたみがないなあ

3.6.2 Guard

初期化する

> bundle exec guard init
00:16:27 - INFO - Writing new Guardfile to /Users/tambara/study/rails_study/sample_app/Guardfile
00:16:27 - INFO - minitest guard added to Guardfile, feel free to edit it

Guardfileを修正する。3.45のソースに置き換える。

ついでに、テストをわざと失敗するようにしておく。

実行する。

> bundle exec guard
00:57:23 - INFO - Guard::Minitest 2.4.4 is running, with Minitest::Unit 5.10.3!
00:57:23 - INFO - Guard is now watching at '/Users/tambara/study/rails_study/sample_app'
/Users/tambara/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/guard-2.13.0/lib/guard/jobs/pry_wrapper.rb:279: warning: method Pry#input_array is deprecated. Use Pry#input_ring instead
[1] guard(main)> 
00:57:25 - INFO - Run all
00:57:25 - INFO - Running: all tests
/Users/tambara/study/rails_study/sample_app/db/schema.rb doesn't exist yet. Run `rails db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter /Users/tambara/study/rails_study/sample_app/config/application.rb to limit the frameworks that will be loaded.
Started with run options --seed 652

 FAIL["test_should_get_contact", StaticPagesControllerTest, 0.5823930000187829]
 test_should_get_contact#StaticPagesControllerTest (0.58s)
        <Cantact | Ruby on Rails Tutorial Sample App> expected but was
        <Contact | Ruby on Rails Tutorial Sample App>..
        Expected 0 to be >= 1.
        test/controllers/static_pages_controller_test.rb:35:in `block in <class:StaticPagesControllerTest>'

  5/5: [=============================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.61163s
5 tests, 10 assertions, 1 failures, 0 errors, 0 skips


/Users/tambara/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/guard-2.13.0/lib/guard/jobs/pry_wrapper.rb:279: warning: method Pry#input_array is deprecated. Use Pry#input_ring instead

実行させた。失敗してる。

ここでファイルを正しくして保存すると、勝手にテストが走る。

00:57:44 - INFO - Running: test/controllers/static_pages_controller_test.rb
/Users/tambara/study/rails_study/sample_app/db/schema.rb doesn't exist yet. Run `rails db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter /Users/tambara/study/rails_study/sample_app/config/application.rb to limit the frameworks that will be loaded.
Started with run options --seed 38941

  5/5: [=============================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.54086s
5 tests, 10 assertions, 0 failures, 0 errors, 0 skips


/Users/tambara/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/guard-2.13.0/lib/guard/jobs/pry_wrapper.rb:279: warning: method Pry#input_array is deprecated. Use Pry#input_ring instead
[1] guard(main)> 

おおー、便利だ・・・。

Rails チュートリアルをやってみる(8) 3.4〜3.5 ちょっと動的っぽいページ

3.4

理由はわからないけど、レイアウトファイルをリネームしておけと言われるので、する

> mv app/views/layouts/application.html.erb layout_file
> ls
Gemfile      README.md    app          config       db           lib          package.json test         vendor
Gemfile.lock Rakefile     bin          config.ru    layout_file  log          public       tmp

画面の内容をテストするらしい。それってコントローラーのテストなの?感はあるけど、そんなことはどうでもいいのだ。 こんな感じでtitleタグの中身がチェックできるらしい。

test/controllers/static_pages_controller_test.rb

  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Home | Ruby on Rails Tutorial Sample App"
  end

helpもaboutも同じようにして、テスト。レッドになる。

> bundle exec rails t test/controllers/static_pages_controller_test.rb 
(例)

# Running:

FFF

Finished in 0.360505s, 8.3217 runs/s, 16.6433 assertions/s.

  1) Failure:
StaticPagesControllerTest#test_should_get_help [/Users/tambara/study/rails_study/sample_app/test/controllers/static_pages_controller_test.rb:13]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.

  2) Failure:
StaticPagesControllerTest#test_should_get_home [/Users/tambara/study/rails_study/sample_app/test/controllers/static_pages_controller_test.rb:7]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.

  3) Failure:
StaticPagesControllerTest#test_should_get_about [/Users/tambara/study/rails_study/sample_app/test/controllers/static_pages_controller_test.rb:19]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.

3 runs, 6 assertions, 3 failures, 0 errors, 0 skips

これを通すために、各ビューを修正するわけだ。まあ、そりゃ通るだろう。 今のビューは完全なHTMLになっていないので、<body>にパックされている。 これを完全なHTMLにする。

app/views/static_pages/about.html.erb

<!DOCTYPE html>
<html>

<head>
    <title>About | Ruby on Rails Tutorial Sample App</title>
</head>

<body>
    <h1>About</h1>
    <p>
        <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
        is a <a href="https://railstutorial.jp/#ebook">book</a> and
        <a href="https://railstutorial.jp/#screencast">screencast</a>
        to teach web development with
        <a href="http://rubyonrails.org/">Ruby on Rails</a>.
        This is the sample application for the tutorial.
    </p>
</body>

</html>

テストすると、ちゃんとレッド減ってる。

> bundle exec rails t test/controllers/static_pages_controller_test.rb 
(略)
# Running:

F.F

Finished in 0.347614s, 8.6303 runs/s, 17.2605 assertions/s.

  1) Failure:
StaticPagesControllerTest#test_should_get_home [/Users/tambara/study/rails_study/sample_app/test/controllers/static_pages_controller_test.rb:7]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.

  2) Failure:
StaticPagesControllerTest#test_should_get_help [/Users/tambara/study/rails_study/sample_app/test/controllers/static_pages_controller_test.rb:13]:
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.

3 runs, 6 assertions, 2 failures, 0 errors, 0 skips

演習は、テストにsetupを追加して重複を消すこと。これは特に疑問ないね。

3.4.3に進む。

リネームしていたレイアウトファイルを戻して、タイトルの動的生成を組み込む。

provideは各ページ別のテンプレートに入れて、それをyieldする方はレイアウトファイルに入れる。

演習で、Contactを追加する。修正はこんな感じでいいはず。

> git diff
diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb
index 19f79a9..d304760 100644
--- a/app/controllers/static_pages_controller.rb
+++ b/app/controllers/static_pages_controller.rb
@@ -7,4 +7,7 @@ class StaticPagesController < ApplicationController
 
   def about
   end
+
+  def contact
+  end
 end
diff --git a/config/routes.rb b/config/routes.rb
index a286a2a..74028be 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,6 +2,7 @@ Rails.application.routes.draw do
   get 'static_pages/home'
   get 'static_pages/help'
   get 'static_pages/about'
+  get 'static_pages/contact'
 
   root 'application#hello'
 end
diff --git a/test/controllers/static_pages_controller_test.rb b/test/controllers/static_pages_controller_test.rb
index 636f458..a0fc70b 100644
--- a/test/controllers/static_pages_controller_test.rb
+++ b/test/controllers/static_pages_controller_test.rb
@@ -23,4 +23,9 @@ class StaticPagesControllerTest < ActionDispatch::IntegrationTest
     assert_select "title", "About | #{@base_title}"
   end
 
+  test "should get contact" do
+    get static_pages_contact_url
+    assert_response :success
+    assert_select "title", "Contact | #{@base_title}"
+  end
 end
(END)

あ、あとapp/views/static_pages/contact.html.erbを作った。これ、git diffに出てこないのどうしたらいいのかわからない。

続いて、3.4.4。ここは最初にいい加減につくったルートページをやめて、 ここで作ったHomeのページにする。

> git diff config/routes.rb 
diff --git a/config/routes.rb b/config/routes.rb
index a286a2a..d3be50f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,7 +1,7 @@
 Rails.application.routes.draw do
+  root 'static_pages#home'
   get 'static_pages/home'
   get 'static_pages/help'
   get 'static_pages/about'
-
-  root 'application#hello'
+  get 'static_pages/contact'
 end

演習はこれのテストの追加。

最後にコミットしたあと、masterブランチにマージして、Herokuにプッシュして終了。

> git checkout master
Switched to branch 'master'
> git branch
* master
  static-pages
> git merge static-pages 
Updating 9fcb567..abe4bbf
Fast-forward
 app/assets/javascripts/static_pages.coffee       |  3 +++
 app/assets/stylesheets/static_pages.scss         |  3 +++
 app/controllers/application_controller.rb        |  4 ----
 app/controllers/static_pages_controller.rb       | 13 +++++++++++++
 app/helpers/static_pages_helper.rb               |  2 ++
 app/views/layouts/application.html.erb           |  2 +-
 app/views/static_pages/about.html.erb            | 10 ++++++++++
 app/views/static_pages/contact.html.erb          |  6 ++++++
 app/views/static_pages/help.html.erb             |  9 +++++++++
 app/views/static_pages/home.html.erb             |  7 +++++++
 config/routes.rb                                 |  6 +++++-
 test/controllers/static_pages_controller_test.rb | 37 +++++++++++++++++++++++++++++++++++++
 12 files changed, 96 insertions(+), 6 deletions(-)
 create mode 100644 app/assets/javascripts/static_pages.coffee
 create mode 100644 app/assets/stylesheets/static_pages.scss
 create mode 100644 app/controllers/static_pages_controller.rb
 create mode 100644 app/helpers/static_pages_helper.rb
 create mode 100644 app/views/static_pages/about.html.erb
 create mode 100644 app/views/static_pages/contact.html.erb
 create mode 100644 app/views/static_pages/help.html.erb
 create mode 100644 app/views/static_pages/home.html.erb
 create mode 100644 test/controllers/static_pages_controller_test.rb
> git push heroku master
Counting objects: 68, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (67/67), done.
Writing objects: 100% (68/68), 6.03 KiB | 771.00 KiB/s, done.
Total 68 (delta 35), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Ruby app detected
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.4.5
remote: -----> Installing dependencies using bundler 1.15.2
remote:        Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
remote:        Warning: the running version of Bundler (1.15.2) is older than the version that created the lockfile (1.17.1). We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.
remote:        Fetching gem metadata from https://rubygems.org/.........
remote:        Fetching version metadata from https://rubygems.org/..
remote:        Fetching dependency metadata from https://rubygems.org/.
remote:        Using rake 12.3.1
remote:        Using concurrent-ruby 1.1.3
remote:        Using minitest 5.10.3
remote:        Using thread_safe 0.3.6
remote:        Using builder 3.2.3
remote:        Using erubi 1.7.1
remote:        Using mini_portile2 2.3.0
remote:        Using crass 1.0.4
remote:        Using rack 2.0.6
remote:        Using nio4r 2.3.1
remote:        Using websocket-extensions 0.1.3
remote:        Using mini_mime 1.0.1
remote:        Using arel 8.0.0
remote:        Using bundler 1.15.2
remote:        Using coffee-script-source 1.12.2
remote:        Using execjs 2.7.0
remote:        Using method_source 0.9.2
remote:        Using thor 0.20.3
remote:        Using ffi 1.9.25
remote:        Using multi_json 1.13.1
remote:        Using pg 0.20.0
remote:        Using puma 3.9.1
remote:        Using rb-fsevent 0.10.3
remote:        Using tilt 2.0.8
remote:        Using turbolinks-source 5.2.0
remote:        Using i18n 1.1.1
remote:        Using nokogiri 1.8.5
remote:        Using tzinfo 1.2.5
remote:        Using rack-test 1.1.0
remote:        Using sprockets 3.7.2
remote:        Using mail 2.7.1
remote:        Using websocket-driver 0.6.5
remote:        Using uglifier 3.2.0
remote:        Using coffee-script 2.4.1
remote:        Using rb-inotify 0.9.10
remote:        Using turbolinks 5.0.1
remote:        Using loofah 2.2.3
remote:        Using activesupport 5.1.6
remote:        Using rails-dom-testing 2.0.3
remote:        Using globalid 0.4.1
remote:        Using activemodel 5.1.6
remote:        Using jbuilder 2.7.0
remote:        Using rails-html-sanitizer 1.0.4
remote:        Using sass-listen 4.0.0
remote:        Using activejob 5.1.6
remote:        Using activerecord 5.1.6
remote:        Using actionview 5.1.6
remote:        Using sass 3.7.2
remote:        Using actionpack 5.1.6
remote:        Using actioncable 5.1.6
remote:        Using actionmailer 5.1.6
remote:        Using railties 5.1.6
remote:        Using sprockets-rails 3.2.1
remote:        Using coffee-rails 4.2.2
remote:        Using jquery-rails 4.3.1
remote:        Using rails 5.1.6
remote:        Using sass-rails 5.0.6
remote:        Bundle complete! 20 Gemfile dependencies, 57 gems now installed.
remote:        Gems in the groups development and test were not installed.
remote:        Bundled gems are installed into ./vendor/bundle.
remote:        Bundle completed (3.32s)
remote:        Cleaning up the bundler cache.
remote:        Warning: the running version of Bundler (1.15.2) is older than the version that created the lockfile (1.17.1). We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.
remote:        The latest bundler is 2.0.0.pre.1, but you are currently running 1.15.2.
remote:        To update, run `gem install bundler --pre`
remote: -----> Installing node-v8.10.0-linux-x64
remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote:        Running: rake assets:precompile
remote:        Yarn executable was not detected in the system.
remote:        Download Yarn at https://yarnpkg.com/en/docs/install
remote:        I, [2018-11-22T15:04:09.227093 #396]  INFO -- : Writing /tmp/build_71b6afdcc7eaadb5213bbf0960c620b0/public/assets/application-86a3fd3b1e217ceb8f2069261313e734793e5074b3f462c54a813438e80e7839.js
remote:        I, [2018-11-22T15:04:09.227761 #396]  INFO -- : Writing /tmp/build_71b6afdcc7eaadb5213bbf0960c620b0/public/assets/application-86a3fd3b1e217ceb8f2069261313e734793e5074b3f462c54a813438e80e7839.js.gz
remote:        Asset precompilation completed (3.03s)
remote:        Cleaning assets
remote:        Running: rake assets:clean
remote: -----> Detecting rails configuration
remote: 
remote: ###### WARNING:
remote: 
remote:        You have not declared a Ruby version in your Gemfile.
remote:        To set your Ruby version add this line to your Gemfile:
remote:        ruby '2.4.5'
remote:        # See https://devcenter.heroku.com/articles/ruby-versions for more information.
remote: 
remote: ###### WARNING:
remote: 
remote:        No Procfile detected, using the default web server.
remote:        We recommend explicitly declaring how to boot your server process via a Procfile.
remote:        https://devcenter.heroku.com/articles/ruby-default-web-server
remote: 
remote: 
remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> console, rake, web
remote: 
remote: -----> Compressing...
remote:        Done: 41M
remote: -----> Launching...
remote:        Released v7
remote:        https://salty-eyrie-75181.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/salty-eyrie-75181.git
   9fcb567..abe4bbf  master -> master

Rails チュートリアルをやってみる(7) 3.1〜3.3 静的なページとコントローラーのテスト

3章を始める。これから作るサンプルは、長くいじることになるらしい。

3.1

> bundle exec rails _5.1.6_ new sample_app --skip-bundle
      create  
      create  README.md
      create  Rakefile
      create  config.ru
      create  .gitignore
      create  Gemfile
         run  git init from "."
Initialized empty Git repository in /Users/tambara/study/rails_study/sample_app/.git/
      create  app
      create  app/assets/config/manifest.js
      create  app/assets/javascripts/application.js
      create  app/assets/javascripts/cable.js
      create  app/assets/stylesheets/application.css
      create  app/channels/application_cable/channel.rb
      create  app/channels/application_cable/connection.rb
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/jobs/application_job.rb
      create  app/mailers/application_mailer.rb
      create  app/models/application_record.rb
      create  app/views/layouts/application.html.erb
      create  app/views/layouts/mailer.html.erb
      create  app/views/layouts/mailer.text.erb
      create  app/assets/images/.keep
      create  app/assets/javascripts/channels
      create  app/assets/javascripts/channels/.keep
      create  app/controllers/concerns/.keep
      create  app/models/concerns/.keep
      create  bin
      create  bin/bundle
      create  bin/rails
      create  bin/rake
      create  bin/setup
      create  bin/update
      create  bin/yarn
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/secrets.yml
      create  config/cable.yml
      create  config/puma.rb
      create  config/spring.rb
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/application_controller_renderer.rb
      create  config/initializers/assets.rb
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/cookies_serializer.rb
      create  config/initializers/cors.rb
      create  config/initializers/filter_parameter_logging.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/new_framework_defaults_5_1.rb
      create  config/initializers/wrap_parameters.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  lib
      create  lib/tasks
      create  lib/tasks/.keep
      create  lib/assets
      create  lib/assets/.keep
      create  log
      create  log/.keep
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/apple-touch-icon-precomposed.png
      create  public/apple-touch-icon.png
      create  public/favicon.ico
      create  public/robots.txt
      create  test/fixtures
      create  test/fixtures/.keep
      create  test/fixtures/files
      create  test/fixtures/files/.keep
      create  test/controllers
      create  test/controllers/.keep
      create  test/mailers
      create  test/mailers/.keep
      create  test/models
      create  test/models/.keep
      create  test/helpers
      create  test/helpers/.keep
      create  test/integration
      create  test/integration/.keep
      create  test/test_helper.rb
      create  test/system
      create  test/system/.keep
      create  test/application_system_test_case.rb
      create  tmp
      create  tmp/.keep
      create  tmp/cache
      create  tmp/cache/assets
      create  vendor
      create  vendor/.keep
      create  package.json
      remove  config/initializers/cors.rb
      remove  config/initializers/new_framework_defaults_5_1.rb
> cd sample_app/
> vi Gemfile
> bundle install --without production
Fetching gem metadata from https://rubygems.org/.........
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies....
Using rake 12.3.1
Using concurrent-ruby 1.1.3
Using i18n 1.1.1
Using minitest 5.10.3
Using thread_safe 0.3.6
Using tzinfo 1.2.5
Using activesupport 5.1.6
Using builder 3.2.3
Using erubi 1.7.1
Using mini_portile2 2.3.0
Using nokogiri 1.8.5
Using rails-dom-testing 2.0.3
Using crass 1.0.4
Using loofah 2.2.3
Using rails-html-sanitizer 1.0.4
Using actionview 5.1.6
Using rack 2.0.6
Using rack-test 1.1.0
Using actionpack 5.1.6
Using nio4r 2.3.1
Using websocket-extensions 0.1.3
Using websocket-driver 0.6.5
Using actioncable 5.1.6
Using globalid 0.4.1
Using activejob 5.1.6
Using mini_mime 1.0.1
Using mail 2.7.1
Using actionmailer 5.1.6
Using activemodel 5.1.6
Using arel 8.0.0
Using activerecord 5.1.6
Fetching ansi 1.5.0
Installing ansi 1.5.0
Using bindex 0.5.0
Using bundler 1.17.1
Using byebug 9.0.6
Fetching coderay 1.1.2
Installing coderay 1.1.2
Using coffee-script-source 1.12.2
Using execjs 2.7.0
Using coffee-script 2.4.1
Using method_source 0.9.2
Using thor 0.20.3
Using railties 5.1.6
Using coffee-rails 4.2.2
Using ffi 1.9.25
Fetching formatador 0.2.5
Installing formatador 0.2.5
Using rb-fsevent 0.10.3
Using rb-inotify 0.9.10
Using ruby_dep 1.5.0
Using listen 3.1.5
Fetching lumberjack 1.0.13
Installing lumberjack 1.0.13
Fetching nenv 0.3.0
Installing nenv 0.3.0
Fetching shellany 0.0.1
Installing shellany 0.0.1
Fetching notiffany 0.1.1
Installing notiffany 0.1.1
Fetching pry 0.12.2
Installing pry 0.12.2
Fetching guard 2.13.0
Installing guard 2.13.0
Fetching guard-compat 1.2.1
Installing guard-compat 1.2.1
Fetching guard-minitest 2.4.4
Installing guard-minitest 2.4.4
Using multi_json 1.13.1
Using jbuilder 2.7.0
Using jquery-rails 4.3.1
Fetching ruby-progressbar 1.10.0
Installing ruby-progressbar 1.10.0
Fetching minitest-reporters 1.1.14
Installing minitest-reporters 1.1.14
Using puma 3.9.1
Using sprockets 3.7.2
Using sprockets-rails 3.2.1
Using rails 5.1.6
Fetching rails-controller-testing 1.0.2
Installing rails-controller-testing 1.0.2
Using sass-listen 4.0.0
Using sass 3.7.2
Using tilt 2.0.8
Using sass-rails 5.0.6
Using spring 2.0.2
Using spring-watcher-listen 2.0.1
Using sqlite3 1.3.13
Using turbolinks-source 5.2.0
Using turbolinks 5.0.1
Using uglifier 3.2.0
Using web-console 3.5.1
Bundle complete! 20 Gemfile dependencies, 78 gems now installed.
Gems in the group production were not installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
> git add --all
> git commit -m "Initialize repository"
(略)

外部のリポジトリにpushするのは面倒なので今回も止める。世の中に死ぬほどあるだろうし。

> vi app/controllers/application_controller.rb 
> vi config/routes.rb 
> git commit -am "Add hello"
[master 9fcb567] Add hello
 2 files changed, 5 insertions(+), 1 deletion(-)
> heroku create
Creating app... done, ⬢ salty-eyrie-75181
https://salty-eyrie-75181.herokuapp.com/ | https://git.heroku.com/salty-eyrie-75181.git
> git push heroku master
Counting objects: 90, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (76/76), done.
Writing objects: 100% (90/90), 20.32 KiB | 1.20 MiB/s, done.
Total 90 (delta 6), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote:  !     Warning: Multiple default buildpacks reported the ability to handle this app. The first buildpack in the list below will be used.
remote:             Detected buildpacks: Ruby,Node.js
remote:             See https://devcenter.heroku.com/articles/buildpacks#buildpack-detect-order
remote: -----> Ruby app detected
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.4.5
remote: -----> Installing dependencies using bundler 1.15.2
remote:        Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
remote:        Warning: the running version of Bundler (1.15.2) is older than the version that created the lockfile (1.17.1). We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.
remote:        Fetching gem metadata from https://rubygems.org/.........
remote:        Fetching version metadata from https://rubygems.org/..
remote:        Fetching dependency metadata from https://rubygems.org/.
remote:        Fetching rake 12.3.1
remote:        Fetching concurrent-ruby 1.1.3
remote:        Fetching minitest 5.10.3
remote:        Installing minitest 5.10.3
remote:        Installing rake 12.3.1
remote:        Installing concurrent-ruby 1.1.3
remote:        Fetching thread_safe 0.3.6
remote:        Installing thread_safe 0.3.6
remote:        Fetching builder 3.2.3
remote:        Installing builder 3.2.3
remote:        Fetching erubi 1.7.1
remote:        Installing erubi 1.7.1
remote:        Fetching mini_portile2 2.3.0
remote:        Fetching crass 1.0.4
remote:        Installing mini_portile2 2.3.0
remote:        Installing crass 1.0.4
remote:        Fetching rack 2.0.6
remote:        Fetching nio4r 2.3.1
remote:        Fetching websocket-extensions 0.1.3
remote:        Installing rack 2.0.6
remote:        Installing websocket-extensions 0.1.3
remote:        Fetching mini_mime 1.0.1
remote:        Installing nio4r 2.3.1 with native extensions
remote:        Installing mini_mime 1.0.1
remote:        Fetching arel 8.0.0
remote:        Installing arel 8.0.0
remote:        Using bundler 1.15.2
remote:        Fetching coffee-script-source 1.12.2
remote:        Installing coffee-script-source 1.12.2
remote:        Fetching execjs 2.7.0
remote:        Fetching method_source 0.9.2
remote:        Installing execjs 2.7.0
remote:        Installing method_source 0.9.2
remote:        Fetching thor 0.20.3
remote:        Fetching ffi 1.9.25
remote:        Installing thor 0.20.3
remote:        Fetching multi_json 1.13.1
remote:        Installing multi_json 1.13.1
remote:        Installing ffi 1.9.25 with native extensions
remote:        Fetching pg 0.20.0
remote:        Installing pg 0.20.0 with native extensions
remote:        Fetching puma 3.9.1
remote:        Installing puma 3.9.1 with native extensions
remote:        Fetching rb-fsevent 0.10.3
remote:        Installing rb-fsevent 0.10.3
remote:        Fetching tilt 2.0.8
remote:        Installing tilt 2.0.8
remote:        Fetching turbolinks-source 5.2.0
remote:        Installing turbolinks-source 5.2.0
remote:        Fetching tzinfo 1.2.5
remote:        Installing tzinfo 1.2.5
remote:        Fetching nokogiri 1.8.5
remote:        Installing nokogiri 1.8.5 with native extensions
remote:        Fetching i18n 1.1.1
remote:        Installing i18n 1.1.1
remote:        Fetching websocket-driver 0.6.5
remote:        Installing websocket-driver 0.6.5 with native extensions
remote:        Fetching mail 2.7.1
remote:        Installing mail 2.7.1
remote:        Fetching rack-test 1.1.0
remote:        Installing rack-test 1.1.0
remote:        Fetching sprockets 3.7.2
remote:        Installing sprockets 3.7.2
remote:        Fetching coffee-script 2.4.1
remote:        Installing coffee-script 2.4.1
remote:        Fetching uglifier 3.2.0
remote:        Installing uglifier 3.2.0
remote:        Fetching turbolinks 5.0.1
remote:        Installing turbolinks 5.0.1
remote:        Fetching rb-inotify 0.9.10
remote:        Installing rb-inotify 0.9.10
remote:        Fetching activesupport 5.1.6
remote:        Installing activesupport 5.1.6
remote:        Fetching sass-listen 4.0.0
remote:        Installing sass-listen 4.0.0
remote:        Fetching globalid 0.4.1
remote:        Installing globalid 0.4.1
remote:        Fetching activemodel 5.1.6
remote:        Installing activemodel 5.1.6
remote:        Fetching jbuilder 2.7.0
remote:        Installing jbuilder 2.7.0
remote:        Fetching sass 3.7.2
remote:        Installing sass 3.7.2
remote:        Fetching activejob 5.1.6
remote:        Installing activejob 5.1.6
remote:        Fetching activerecord 5.1.6
remote:        Installing activerecord 5.1.6
remote:        Fetching rails-dom-testing 2.0.3
remote:        Fetching loofah 2.2.3
remote:        Installing rails-dom-testing 2.0.3
remote:        Installing loofah 2.2.3
remote:        Fetching rails-html-sanitizer 1.0.4
remote:        Installing rails-html-sanitizer 1.0.4
remote:        Fetching actionview 5.1.6
remote:        Installing actionview 5.1.6
remote:        Fetching actionpack 5.1.6
remote:        Installing actionpack 5.1.6
remote:        Fetching actioncable 5.1.6
remote:        Fetching actionmailer 5.1.6
remote:        Fetching railties 5.1.6
remote:        Installing actioncable 5.1.6
remote:        Installing actionmailer 5.1.6
remote:        Installing railties 5.1.6
remote:        Fetching sprockets-rails 3.2.1
remote:        Installing sprockets-rails 3.2.1
remote:        Fetching jquery-rails 4.3.1
remote:        Fetching coffee-rails 4.2.2
remote:        Fetching rails 5.1.6
remote:        Installing rails 5.1.6
remote:        Installing coffee-rails 4.2.2
remote:        Fetching sass-rails 5.0.6
remote:        Installing sass-rails 5.0.6
remote:        Installing jquery-rails 4.3.1
remote:        Bundle complete! 20 Gemfile dependencies, 57 gems now installed.
remote:        Gems in the groups development and test were not installed.
remote:        Bundled gems are installed into ./vendor/bundle.
remote:        Post-install message from sass:
remote:        
remote:        Ruby Sass is deprecated and will be unmaintained as of 26 March 2019.
remote:        
remote:        * If you use Sass as a command-line tool, we recommend using Dart Sass, the new
remote:          primary implementation: https://sass-lang.com/install
remote:        
remote:        * If you use Sass as a plug-in for a Ruby web framework, we recommend using the
remote:          sassc gem: https://github.com/sass/sassc-ruby#readme
remote:        
remote:        * For more details, please refer to the Sass blog:
remote:          http://sass.logdown.com/posts/7081811
remote:        
remote:        Bundle completed (43.05s)
remote:        Cleaning up the bundler cache.
remote: -----> Installing node-v8.10.0-linux-x64
remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote:        Running: rake assets:precompile
remote:        Yarn executable was not detected in the system.
remote:        Download Yarn at https://yarnpkg.com/en/docs/install
remote:        I, [2018-11-22T02:24:18.141798 #1380]  INFO -- : Writing /tmp/build_3949dec4a1dcf549174b4a04a8a8dadb/public/assets/application-7e084e44b9a13db0cda25bad2ac6fdbbfe31462ec93176e245cd0bcbc079f436.js
remote:        I, [2018-11-22T02:24:18.142211 #1380]  INFO -- : Writing /tmp/build_3949dec4a1dcf549174b4a04a8a8dadb/public/assets/application-7e084e44b9a13db0cda25bad2ac6fdbbfe31462ec93176e245cd0bcbc079f436.js.gz
remote:        I, [2018-11-22T02:24:18.148641 #1380]  INFO -- : Writing /tmp/build_3949dec4a1dcf549174b4a04a8a8dadb/public/assets/application-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css
remote:        I, [2018-11-22T02:24:18.148797 #1380]  INFO -- : Writing /tmp/build_3949dec4a1dcf549174b4a04a8a8dadb/public/assets/application-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css.gz
remote:        Asset precompilation completed (2.60s)
remote:        Cleaning assets
remote:        Running: rake assets:clean
remote: -----> Detecting rails configuration
remote: 
remote: ###### WARNING:
remote: 
remote:        You have not declared a Ruby version in your Gemfile.
remote:        To set your Ruby version add this line to your Gemfile:
remote:        ruby '2.4.5'
remote:        # See https://devcenter.heroku.com/articles/ruby-versions for more information.
remote: 
remote: ###### WARNING:
remote: 
remote:        Detecting rails configuration failed
remote:        set HEROKU_DEBUG_RAILS_RUNNER=1 to debug
remote: 
remote: ###### WARNING:
remote: 
remote:        No Procfile detected, using the default web server.
remote:        We recommend explicitly declaring how to boot your server process via a Procfile.
remote:        https://devcenter.heroku.com/articles/ruby-default-web-server
remote: 
remote: 
remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> console, rake, web
remote: 
remote: -----> Compressing...
remote:        Done: 41M
remote: -----> Launching...
remote:        Released v6
remote:        https://salty-eyrie-75181.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/salty-eyrie-75181.git
 * [new branch]      master -> master

ここまではいままでと同じ。

3.2

まず、ブランチを切る。うん、正しいな。

> git checkout -b static-pages
Switched to a new branch 'static-pages'
> git branch
  master
* static-pages

コントローラーをgenerateする

> bundle exec rails generate controller StaticPages home help
      create  app/controllers/static_pages_controller.rb
       route  get 'static_pages/help'
       route  get 'static_pages/home'
      invoke  erb
      create    app/views/static_pages
      create    app/views/static_pages/home.html.erb
      create    app/views/static_pages/help.html.erb
      invoke  test_unit
      create    test/controllers/static_pages_controller_test.rb
      invoke  helper
      create    app/helpers/static_pages_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/static_pages.coffee
      invoke    scss
      create      app/assets/stylesheets/static_pages.scss

これでテンプレは作られる

3.2.1の演習をやってみよう。Fooというコントローラーを作って、消す。

> bundle exec rails g controller Foo bar baz
      create  app/controllers/foo_controller.rb
       route  get 'foo/baz'
       route  get 'foo/bar'
      invoke  erb
      create    app/views/foo
      create    app/views/foo/bar.html.erb
      create    app/views/foo/baz.html.erb
      invoke  test_unit
      create    test/controllers/foo_controller_test.rb
      invoke  helper
      create    app/helpers/foo_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/foo.coffee
      invoke    scss
      create      app/assets/stylesheets/foo.scss
> bundle exec rails destroy controller Foo bar baz
      remove  app/controllers/foo_controller.rb
       route  get 'foo/baz'
       route  get 'foo/bar'
      invoke  erb
      remove    app/views/foo
      remove    app/views/foo/bar.html.erb
      remove    app/views/foo/baz.html.erb
      invoke  test_unit
      remove    test/controllers/foo_controller_test.rb
      invoke  helper
      remove    app/helpers/foo_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      remove      app/assets/javascripts/foo.coffee
      invoke    scss
      remove      app/assets/stylesheets/foo.scss

ふむ。

表示されるページの内容は、app/views/static_pages/home.html.erbなどを変更すれば変えられる。 チュートリアルの通りに変更して、表示を確認しておく。

3.3

テストだ。10年前に触ったときは、まだRSpecは生まれたてホヤホヤだった。なので、Railsのテスト周りはなんもしらない。

自動生成されたコントローラーのテストはこうなってる。test/controllers/static_pages_controller_test.rb

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    get static_pages_home_url
    assert_response :success
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
  end

end

全然意味わからない。いや、やりたいことの意味はわかるけど、getは何をするメソッドで、static_pages_home_urlってどこで作られるの?まあ、別にこれに限った話じゃないんだけど。

とりあえず、グリーンであることを確かめる。アプリのトップでテストを実行してみよう。

> bundle exec rails test
/Users/tambara/study/rails_study/sample_app/db/schema.rb doesn't exist yet. Run `rails db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter /Users/tambara/study/rails_study/sample_app/config/application.rb to limit the frameworks that will be loaded.
Run options: --seed 49031

# Running:

..

Finished in 0.642428s, 3.1132 runs/s, 3.1132 assertions/s.

2 runs, 2 assertions, 0 failures, 0 errors, 0 skips

まだDBがありまへんけど?とツッコミが入るが、実行は出来る。何が実行されたのかさっぱりわからないので、指定してみる。

> bundle exec rails t test/controllers/static_pages_controller_test.rb 
/Users/tambara/study/rails_study/sample_app/db/schema.rb doesn't exist yet. Run `rails db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter /Users/tambara/study/rails_study/sample_app/config/application.rb to limit the frameworks that will be loaded.
Run options: --seed 49255

# Running:

..

Finished in 0.536100s, 3.7306 runs/s, 3.7306 assertions/s.

2 runs, 2 assertions, 0 failures, 0 errors, 0 skips

テストが一個しかないのか、おんなじだった。まあ、実行の仕方はこれでいいんだろう。

チュートリアルに従って、HelpをコピってAboutのテストを作って、レッドにしてみる。

> bundle exec rails t test/controllers/static_pages_controller_test.rb 
/Users/tambara/study/rails_study/sample_app/db/schema.rb doesn't exist yet. Run `rails db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter /Users/tambara/study/rails_study/sample_app/config/application.rb to limit the frameworks that will be loaded.
Run options: --seed 20205

# Running:

E..

Finished in 0.615610s, 4.8732 runs/s, 3.2488 assertions/s.

  1) Error:
StaticPagesControllerTest#test_should_get_about:
NameError: undefined local variable or method `static_pages_about_url' for #<StaticPagesControllerTest:0x00007ff1784b0cf0>
    test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'

3 runs, 2 assertions, 0 failures, 1 errors, 0 skips

static_pages_about_urlなんか知らんと言っている。うん私もしらん。

これはルーティングをセットすれば良いらしい。

Rails.application.routes.draw do
  get 'static_pages/home'
  get 'static_pages/help'
  get 'static_pages/about'

  root 'application#hello'
end

もう一度、テストしてみる。

> bundle exec rails t test/controllers/static_pages_controller_test.rb 
(略)
# Running:

..E

Finished in 0.563292s, 5.3258 runs/s, 3.5506 assertions/s.

  1) Error:
StaticPagesControllerTest#test_should_get_about:
AbstractController::ActionNotFound: The action 'about' could not be found for StaticPagesController
    test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'

アクションがないと言ってる。ということは、static_pages_about_urlは見つかったのかな?

とりあえず、アクション足して再実行。

> bundle exec rails t test/controllers/static_pages_controller_test.rb 
(略)
# Running:

.E.

Finished in 0.709277s, 4.2297 runs/s, 2.8198 assertions/s.

  1) Error:
StaticPagesControllerTest#test_should_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.
    test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'

3 runs, 2 assertions, 0 failures, 1 errors, 0 skips

missing a templateって言ってる。そうだね。app/views/static_pages/about.html.erbを作ってやろう。touchで空のファイルを作る。さて、またテスト。

> bundle exec rails t test/controllers/static_pages_controller_test.rb 
(略)

# Running:

...

Finished in 0.600782s, 4.9935 runs/s, 4.9935 assertions/s.

3 runs, 3 assertions, 0 failures, 0 errors, 0 skips

グリーンになった。

Rails チュートリアルをやってみる(6) 2.3.4〜2.4 DBを使うアプリをHerokuにデプロイ

2.3.4 から読む。

ApplicationRecordとか、ApplicationControllerって昔からあったっけ? なんか昔はActiveRecord::Baseを直接継承していたような気もするけど、気のせいのような気もする。ここの演習は、特にどうということもないので、パス。

2.3.5 でデプロイ。そうか、デプロイした先はSQLiteじゃないんだよな。

> git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   config/routes.rb

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    app/assets/javascripts/microposts.coffee
    app/assets/javascripts/users.coffee
(中略)
    test/system/users_test.rb

no changes added to commit (use "git add" and/or "git commit -a")
> git add --all
> git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   app/assets/javascripts/microposts.coffee
    new file:   app/assets/javascripts/users.coffee
(中略)
    new file:   test/system/users_test.rb

> git commit -m "Fnish toy app"
[master 6acfa6f] Fnish toy app
 39 files changed, 629 insertions(+)
 create mode 100644 app/assets/javascripts/microposts.coffee
 create mode 100644 app/assets/javascripts/users.coffee
(中略)
 create mode 100644 test/system/users_test.rb
> git push heroku
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream heroku master

あれ、お手本通りなのに・・・まあ、確かに.git/configが更新されるようなことしてないか。 わかったようでわかってないなあ・・・この辺りも。

> git push heroku master
Counting objects: 58, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (55/55), done.
Writing objects: 100% (58/58), 8.88 KiB | 908.00 KiB/s, done.
Total 58 (delta 10), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Ruby app detected
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.4.5
remote: -----> Installing dependencies using bundler 1.15.2
remote:        Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
remote:        Warning: the running version of Bundler (1.15.2) is older than the version that created the lockfile (1.17.1). We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.
remote:        Fetching gem metadata from https://rubygems.org/.........
remote:        Fetching version metadata from https://rubygems.org/..
remote:        Fetching dependency metadata from https://rubygems.org/.
remote:        Using rake 12.3.1
(中略)
remote:        Using rails 5.1.6
remote:        Using sass-rails 5.0.6
remote:        Bundle complete! 15 Gemfile dependencies, 57 gems now installed.
remote:        Gems in the groups development and test were not installed.
remote:        Bundled gems are installed into ./vendor/bundle.
remote:        Bundle completed (2.99s)
remote:        Cleaning up the bundler cache.
remote:        Warning: the running version of Bundler (1.15.2) is older than the version that created the lockfile (1.17.1). We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.
remote:        The latest bundler is 2.0.0.pre.1, but you are currently running 1.15.2.
remote:        To update, run `gem install bundler --pre`
remote: -----> Installing node-v8.10.0-linux-x64
remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote:        Running: rake assets:precompile
remote:        Yarn executable was not detected in the system.
remote:        Download Yarn at https://yarnpkg.com/en/docs/install
remote:        I, [2018-11-21T23:54:30.804003 #414]  INFO -- : Writing /tmp/build_8ff5bb0b6a68b700c5ccd050ae96d2ca/public/assets/application-7441e90aaeea08ce2c76b4123cab0e756e62755c6fc9732dae8cff9bdd6bdd5d.js
remote:        I, [2018-11-21T23:54:30.814388 #414]  INFO -- : Writing /tmp/build_8ff5bb0b6a68b700c5ccd050ae96d2ca/public/assets/application-7441e90aaeea08ce2c76b4123cab0e756e62755c6fc9732dae8cff9bdd6bdd5d.js.gz
remote:        I, [2018-11-21T23:54:30.854991 #414]  INFO -- : Writing /tmp/build_8ff5bb0b6a68b700c5ccd050ae96d2ca/public/assets/application-35729bfbaf9967f119234595ed222f7ab14859f304ab0acc5451afb387f637fa.css
remote:        I, [2018-11-21T23:54:30.855157 #414]  INFO -- : Writing /tmp/build_8ff5bb0b6a68b700c5ccd050ae96d2ca/public/assets/application-35729bfbaf9967f119234595ed222f7ab14859f304ab0acc5451afb387f637fa.css.gz
remote:        Asset precompilation completed (2.94s)
remote:        Cleaning assets
remote:        Running: rake assets:clean
remote: -----> Detecting rails configuration
remote: 
remote: ###### WARNING:
remote: 
remote:        You have not declared a Ruby version in your Gemfile.
remote:        To set your Ruby version add this line to your Gemfile:
remote:        ruby '2.4.5'
remote:        # See https://devcenter.heroku.com/articles/ruby-versions for more information.
remote: 
remote: ###### WARNING:
remote: 
remote:        No Procfile detected, using the default web server.
remote:        We recommend explicitly declaring how to boot your server process via a Procfile.
remote:        https://devcenter.heroku.com/articles/ruby-default-web-server
remote: 
remote: 
remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> console, rake, web
remote: 
remote: -----> Compressing...
remote:        Done: 41.1M
remote: -----> Launching...
remote:        Released v7
remote:        https://sleepy-tundra-20972.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/sleepy-tundra-20972.git
   b08b557..6acfa6f  master -> master

WARNINGが2つ出てる。一つは、Rubyのバージョンを指定してねということ。 もう1つはProcfileを作ってねということ。Procfileってのが何かは知らないけど、Webサーバの設定みたいね、書きっぷりに依ると。

そして、サーバでもdb:migrateを動かす。

> heroku run rails db:migrate
Running rails db:migrate on ⬢ sleepy-tundra-20972... up, run.4540 (Free)
D, [2018-11-22T00:30:22.087474 #4] DEBUG -- :    (2478.1ms)  CREATE TABLE "schema_migrations" ("version" character varying NOT NULL PRIMARY KEY)
D, [2018-11-22T00:30:22.296513 #4] DEBUG -- :    (192.4ms)  CREATE TABLE "ar_internal_metadata" ("key" character varying NOT NULL PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
D, [2018-11-22T00:30:22.300757 #4] DEBUG -- :    (2.4ms)  SELECT pg_try_advisory_lock(5716602264330689130)
D, [2018-11-22T00:30:22.890142 #4] DEBUG -- :    (3.2ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
I, [2018-11-22T00:30:22.900519 #4]  INFO -- : Migrating to CreateUsers (20181121083708)
D, [2018-11-22T00:30:22.909231 #4] DEBUG -- :    (6.2ms)  BEGIN
== 20181121083708 CreateUsers: migrating ======================================
-- create_table(:users)
D, [2018-11-22T00:30:23.199084 #4] DEBUG -- :    (288.6ms)  CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "email" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
   -> 0.2895s
== 20181121083708 CreateUsers: migrated (0.2898s) =============================

D, [2018-11-22T00:30:23.211820 #4] DEBUG -- :   SQL (4.5ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20181121083708"]]
D, [2018-11-22T00:30:23.220505 #4] DEBUG -- :    (8.1ms)  COMMIT
I, [2018-11-22T00:30:23.220809 #4]  INFO -- : Migrating to CreateMicroposts (20181121142643)
D, [2018-11-22T00:30:23.222889 #4] DEBUG -- :    (1.4ms)  BEGIN
== 20181121142643 CreateMicroposts: migrating =================================
-- create_table(:microposts)
D, [2018-11-22T00:30:23.353304 #4] DEBUG -- :    (129.3ms)  CREATE TABLE "microposts" ("id" bigserial primary key, "content" text, "user_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
   -> 0.1302s
== 20181121142643 CreateMicroposts: migrated (0.1306s) ========================

D, [2018-11-22T00:30:23.356405 #4] DEBUG -- :   SQL (1.3ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20181121142643"]]
D, [2018-11-22T00:30:23.361482 #4] DEBUG -- :    (4.5ms)  COMMIT
D, [2018-11-22T00:30:23.376553 #4] DEBUG -- :   ActiveRecord::InternalMetadata Load (4.0ms)  SELECT  "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2  [["key", "environment"], ["LIMIT", 1]]
D, [2018-11-22T00:30:23.392515 #4] DEBUG -- :    (6.6ms)  BEGIN
D, [2018-11-22T00:30:23.400575 #4] DEBUG -- :   SQL (6.6ms)  INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key"  [["key", "environment"], ["value", "production"], ["created_at", "2018-11-22 00:30:23.393033"], ["updated_at", "2018-11-22 00:30:23.393033"]]
D, [2018-11-22T00:30:23.405696 #4] DEBUG -- :    (4.6ms)  COMMIT
D, [2018-11-22T00:30:23.412499 #4] DEBUG -- :    (6.4ms)  SELECT pg_advisory_unlock(5716602264330689130)

すげー。なんでDBに接続できてるのか全然わかんないけど、DBできとる・・・。

さて、動いたので早速ユーザーを作ってみよう。新規登録をすると・・・

f:id:Tambourine:20181122093749p:plain

落ちる。これはたぶんUser.microposts.firstがnilを返すためで、チュートリアルにも演習の部分は戻してねと書いてある。

しかし、ログはどうやって見るんだ・・・。herokuコマンドのヘルプを見ると、logsと言うコマンドがある。

> heroku logs
2018-11-22T00:34:44.792223+00:00 heroku[router]: at=info method=GET path="/users/1" host=sleepy-tundra-20972.herokuapp.com request_id=07f66d18-b44c-4056-893f-7af6583dfd99 fwd="163.131.137.128" dyno=web.1 connect=1ms service=41ms status=500 bytes=1827 protocol=https
2018-11-22T00:34:44.752424+00:00 app[web.1]: I, [2018-11-22T00:34:44.752292 #4]  INFO -- : [07f66d18-b44c-4056-893f-7af6583dfd99] Started GET "/users/1" for 163.131.137.128 at 2018-11-22 00:34:44 +0000
2018-11-22T00:34:44.753370+00:00 app[web.1]: I, [2018-11-22T00:34:44.753294 #4]  INFO -- : [07f66d18-b44c-4056-893f-7af6583dfd99] Processing by UsersController#show as HTML
2018-11-22T00:34:44.753448+00:00 app[web.1]: I, [2018-11-22T00:34:44.753383 #4]  INFO -- : [07f66d18-b44c-4056-893f-7af6583dfd99]   Parameters: {"id"=>"1"}
2018-11-22T00:34:44.761960+00:00 app[web.1]: D, [2018-11-22T00:34:44.761881 #4] DEBUG -- : [07f66d18-b44c-4056-893f-7af6583dfd99]   User Load (1.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
2018-11-22T00:34:44.763717+00:00 app[web.1]: I, [2018-11-22T00:34:44.763660 #4]  INFO -- : [07f66d18-b44c-4056-893f-7af6583dfd99]   Rendering users/show.html.erb within layouts/application
2018-11-22T00:34:44.786902+00:00 app[web.1]: D, [2018-11-22T00:34:44.786783 #4] DEBUG -- : [07f66d18-b44c-4056-893f-7af6583dfd99]   Micropost Load (6.8ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."user_id" = $1 ORDER BY "microposts"."id" ASC LIMIT $2  [["user_id", 1], ["LIMIT", 1]]
2018-11-22T00:34:44.789702+00:00 app[web.1]: I, [2018-11-22T00:34:44.789635 #4]  INFO -- : [07f66d18-b44c-4056-893f-7af6583dfd99]   Rendered users/show.html.erb within layouts/application (25.8ms)
2018-11-22T00:34:44.789984+00:00 app[web.1]: I, [2018-11-22T00:34:44.789918 #4]  INFO -- : [07f66d18-b44c-4056-893f-7af6583dfd99] Completed 500 Internal Server Error in 36ms (ActiveRecord: 21.4ms)
2018-11-22T00:34:44.790936+00:00 app[web.1]: F, [2018-11-22T00:34:44.790843 #4] FATAL -- : [07f66d18-b44c-4056-893f-7af6583dfd99]
2018-11-22T00:34:44.790997+00:00 app[web.1]: F, [2018-11-22T00:34:44.790936 #4] FATAL -- : [07f66d18-b44c-4056-893f-7af6583dfd99] ActionView::Template::Error (undefined method `content' for nil:NilClass):
2018-11-22T00:34:44.791148+00:00 app[web.1]: F, [2018-11-22T00:34:44.791090 #4] FATAL -- : [07f66d18-b44c-4056-893f-7af6583dfd99]     12:
2018-11-22T00:34:44.791151+00:00 app[web.1]: [07f66d18-b44c-4056-893f-7af6583dfd99]     13: <p>
2018-11-22T00:34:44.791153+00:00 app[web.1]: [07f66d18-b44c-4056-893f-7af6583dfd99]     14:   <strong>Content:</strong>
2018-11-22T00:34:44.791155+00:00 app[web.1]: [07f66d18-b44c-4056-893f-7af6583dfd99]     15:   <%= @user.microposts.first.content %>
2018-11-22T00:34:44.791157+00:00 app[web.1]: [07f66d18-b44c-4056-893f-7af6583dfd99]     16: </p>
2018-11-22T00:34:44.791159+00:00 app[web.1]: [07f66d18-b44c-4056-893f-7af6583dfd99]     17:
2018-11-22T00:34:44.791160+00:00 app[web.1]: [07f66d18-b44c-4056-893f-7af6583dfd99]     18: <%= link_to 'Edit', edit_user_path(@user) %> |
2018-11-22T00:34:44.791209+00:00 app[web.1]: F, [2018-11-22T00:34:44.791142 #4] FATAL -- : [07f66d18-b44c-4056-893f-7af6583dfd99]
2018-11-22T00:34:44.791264+00:00 app[web.1]: F, [2018-11-22T00:34:44.791209 #4] FATAL -- : [07f66d18-b44c-4056-893f-7af6583dfd99] app/views/users/show.html.erb:15:in `_app_views_users_show_html_erb__2495298628157736775_47439747321080'

親切だ。"undefined method `content' for nil:NilClass"となっているのでここで落ちているわけ。 チュートリアルは戻せと言っているけど、直しちゃおう。

app/views/users/show.html.erbを

<%= @user.microposts.first.content %>

から

 <%= @user.microposts.first&.content or "No post" %>

にするだけで良いはず。ああ、ラクだなあ、Rubyは。修正してデプロイ。

f:id:Tambourine:20181122095620p:plain

さて、DBの中を見るにはどうしたら良いんだ・・・heroku psqlってのがあるぞ?

> heroku psql
--> Connecting to postgresql-metric-47854
 ▸    The local psql command could not be located. For help installing psql, see https://devcenter.heroku.com/articles/heroku-postgresql#local-setup

はうっ。なるほど。ローカルにPostgreSQLをインストールされてないとダメなのか。

> brew install postgresql
==> Installing dependencies for postgresql: icu4c
==> Installing postgresql dependency: icu4c
==> Downloading https://homebrew.bintray.com/bottles/icu4c-62.1.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring icu4c-62.1.high_sierra.bottle.tar.gz
==> Caveats
icu4c is keg-only, which means it was not symlinked into /usr/local,
because macOS provides libicucore.dylib (but nothing else).

If you need to have icu4c first in your PATH run:
  echo 'set -g fish_user_paths "/usr/local/opt/icu4c/bin" $fish_user_paths' >> ~/.config/fish/config.fish
  echo 'set -g fish_user_paths "/usr/local/opt/icu4c/sbin" $fish_user_paths' >> ~/.config/fish/config.fish

For compilers to find icu4c you may need to set:
  set -gx LDFLAGS "-L/usr/local/opt/icu4c/lib"
  set -gx CPPFLAGS "-I/usr/local/opt/icu4c/include"

For pkg-config to find icu4c you may need to set:
  set -gx PKG_CONFIG_PATH "/usr/local/opt/icu4c/lib/pkgconfig"

==> Summary
🍺  /usr/local/Cellar/icu4c/62.1: 250 files, 67.3MB
==> Installing postgresql
==> Downloading https://homebrew.bintray.com/bottles/postgresql-10.5.high_sierra.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring postgresql-10.5.high_sierra.bottle.1.tar.gz
==> /usr/local/Cellar/postgresql/10.5/bin/initdb /usr/local/var/postgres
==> Caveats
To migrate existing data from a previous major version of PostgreSQL run:
  brew postgresql-upgrade-database

To have launchd start postgresql now and restart at login:
  brew services start postgresql
Or, if you don't want/need a background service you can just run:
  pg_ctl -D /usr/local/var/postgres start
==> Summary
🍺  /usr/local/Cellar/postgresql/10.5: 3,395 files, 39.6MB
==> Caveats
==> icu4c
icu4c is keg-only, which means it was not symlinked into /usr/local,
because macOS provides libicucore.dylib (but nothing else).

If you need to have icu4c first in your PATH run:
  echo 'set -g fish_user_paths "/usr/local/opt/icu4c/bin" $fish_user_paths' >> ~/.config/fish/config.fish
  echo 'set -g fish_user_paths "/usr/local/opt/icu4c/sbin" $fish_user_paths' >> ~/.config/fish/config.fish

For compilers to find icu4c you may need to set:
  set -gx LDFLAGS "-L/usr/local/opt/icu4c/lib"
  set -gx CPPFLAGS "-I/usr/local/opt/icu4c/include"

For pkg-config to find icu4c you may need to set:
  set -gx PKG_CONFIG_PATH "/usr/local/opt/icu4c/lib/pkgconfig"

==> postgresql
To migrate existing data from a previous major version of PostgreSQL run:
  brew postgresql-upgrade-database

To have launchd start postgresql now and restart at login:
  brew services start postgresql
Or, if you don't want/need a background service you can just run:
  pg_ctl -D /usr/local/var/postgres start

リトライ

> heroku psql
--> Connecting to postgresql-metric-47854
psql (10.5, server 10.6 (Ubuntu 10.6-1.pgdg14.04+1))
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

sleepy-tundra-20972::DATABASE=> SELECT * FROM users;
 id |        name        |   email   |         created_at         |         updated_at         
----+--------------------+-----------+----------------------------+----------------------------
  1 | ルイス・ハミルトン | lh@ex.com | 2018-11-22 00:34:44.387942 | 2018-11-22 00:34:44.387942
(1 row)

おー、なんか扱えそうな気がしてきたよ。

というところで、2章は終わり。うーん、先は長い。

Rails チュートリアルをやってみる(5) 2.3.1〜2.3.3 validationとrelation

2.3.1からやってみよう。

投稿(Micropost)の方も同じようにgenerateする。

> bundle exec rails generate scaffold Micropost content:text user_id:integer
      invoke  active_record
      create    db/migrate/20181121142643_create_microposts.rb
      create    app/models/micropost.rb
      invoke    test_unit
      create      test/models/micropost_test.rb
      create      test/fixtures/microposts.yml
      invoke  resource_route
       route    resources :microposts
      invoke  scaffold_controller
      create    app/controllers/microposts_controller.rb
      invoke    erb
      create      app/views/microposts
      create      app/views/microposts/index.html.erb
      create      app/views/microposts/edit.html.erb
      create      app/views/microposts/show.html.erb
      create      app/views/microposts/new.html.erb
      create      app/views/microposts/_form.html.erb
      invoke    test_unit
      create      test/controllers/microposts_controller_test.rb
      invoke    helper
      create      app/helpers/microposts_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/microposts/index.json.jbuilder
      create      app/views/microposts/show.json.jbuilder
      create      app/views/microposts/_micropost.json.jbuilder
      invoke  test_unit
      create    test/system/microposts_test.rb
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/microposts.coffee
      invoke    scss
      create      app/assets/stylesheets/microposts.scss
      invoke  scss
   identical    app/assets/stylesheets/scaffolds.scss
> bundle exec rails db:migrate
== 20181121142643 CreateMicroposts: migrating =================================
-- create_table(:microposts)
   -> 0.0039s
== 20181121142643 CreateMicroposts: migrated (0.0040s) ========================

db/migrateのタイムスタンプはUTCなんだね。

スキーマを確認しておこう。

sqlite> .schema microposts
CREATE TABLE IF NOT EXISTS "microposts" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "content" text, "user_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);

textってデータ型使ったことないなあ・・・。

SQLiteで利用可能なデータ型 - SQLite入門

SQLite3でカラムに指定できるデータ型は「TEXT」「NUMERIC」「INTEGER」「REAL」「NONE」の5つです。

な、なるほど?ここで作られるテーブルスキーマRDBMSによって違うのかな。TEXTがないDBもあるよね?つか、DB2にはないよね?

さて、演習。1は前と同じなのでパス。2はContentもUserも空にしたらどうなるか。空のレコードが作られるね。

sqlite> SELECT id, content, user_id FROM microposts WHERE user_id is NULL;
4||

今度はNULLが入ったっぽい。

演習3。長いのをいれるとどうなるか。SQLite3のTEXT型の制約とかあるのかな?

sqlite> SELECT id, content, user_id FROM microposts WHERE id = 3;
3|みっつめ。ながーいポスト。Ruby(ルビー)は、まつもとゆきひろ(通称 Matz)により開発されたオブジェクト指向スクリプト言語であり、スクリプト言語が用いられてきた領域でのオブジェクト指向プログラミングを実現する。 また日本で開発されたプログラミング言語としては初めて国際電気標準会議で国際規格に認証された事例となった。Ruby は1993年2月24日に生まれ、1995年12月にfj上で発表された。名称の Ruby は、プログラミング言語 Perl が6月の誕生石である Pearl(真珠)と同じ発音をすることから、まつもとの同僚の誕生石(7月)のルビーを取って名付けられた。競合言語として Perl の他に Python があり、「Matz(まつもと) が Python に満足していれば Ruby は生まれなかったであろう」と公式のリファレンスの用語集で言及されている[5]。機能として、クラス定義、ガベージコレクション、強力な正規表現処理、マルチスレッド、例外処理、イテレータ、クロージャ、Mixin、利用者定義演算子などがある。Perl を代替可能であることが初期の段階から重視されている。Perlと同様にグルー言語としての使い方が可能で、C言語プログラムやライブラリを呼び出す拡張モジュールを組み込むことができる。

Ruby 処理系は、主にインタプリタとして実装されている(詳しくは#実装を参照)。

可読性を重視した構文となっている。Ruby においては整数や文字列なども含めデータ型はすべてがオブジェクトであり、純粋なオブジェクト指向言語といえる。

長らく言語仕様が明文化されず、まつもとによる実装が言語仕様に準ずるものとして扱われて来たが、2010年6月現在、JRuby や Rubinius といった互換実装の作者を中心に機械実行可能な形で明文化する RubySpec という試みが行われている。公的規格としては2011年3月22日にJIS規格(JIS X 3017)が制定され、その後2012年4月1日に日本発のプログラム言語では初めてISO/IEC規格(ISO/IEC 30170)として承認された [4]。

フリーソフトウェアとしてバージョン1.9.2までは Rubyライセンス(Ruby License や Ruby'sと表記されることもある。GPLかArtisticに似た独自ライセンスを選択するデュアルライセンス)で配布されていたが、バージョン1.9.3以降は2-clause BSDLで配布されている。 |3

普通に入った。validationがないよねって確認か。4は削除。別に普通に削除できる。

さて、2.3.2だ。validationを入れてみようのコーナー。

class Micropost < ApplicationRecord
  validates :content, length: { maximum: 15}
end

例は140字までになっているけど、それじゃ確かめるのが面倒なので、15文字にしてみる。

f:id:Tambourine:20181122001110p:plain

おお、ちゃんと機能してるね。画面はちょっとアレだけど。演習2でエラー画面を見てみようとなっている。 こんな感じ。

<div id="error_explanation">
      <h2>1 error prohibited this micropost from being saved:</h2>

      <ul>
        <li>Content is too long (maximum is 15 characters)</li>
      </ul>
</div>
<div class="field">
    <div class="field_with_errors"><label for="micropost_content">Content</label></div>
    <div class="field_with_errors"><textarea id="micropost_content" name="micropost[content]">15文字制限をつけてみたんだけど、どうかな?</textarea></div>
</div>

ふむふむ。

では、2.3.3。テーブルの関連すな。

app/models/user.rb

class User < ApplicationRecord
  has_many :microposts
end

app/models/micropost.rb

class Micropost < ApplicationRecord
  belongs_to :user
  validates :content, length: { maximum: 15}
end

これで、ActiveRecordがちゃんと関連を認識してくれるかどうか。 rails consoleで確認してみる。rails consoleってirbなんだね。

> bundle exec rails console
Loading development environment (Rails 5.1.6)
irb(main):001:0> first_user = User.first
  User Load (0.7ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "太郎冠者", email: "taro@ex.com", created_at: "2018-11-21 11:49:49", updated_at: "2018-11-21 11:49:49">
irb(main):002:0> first_user.microposts
  Micropost Load (0.3ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? LIMIT ?  [["user_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 1, content: "いっこめ。ほげほげ", user_id: 1, created_at: "2018-11-21 14:41:07", updated_at: "2018-11-21 14:41:07">]>
irb(main):003:0> mp = first_user.microposts.first
  Micropost Load (0.4ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."id" ASC LIMIT ?  [["user_id", 1], ["LIMIT", 1]]
=> #<Micropost id: 1, content: "いっこめ。ほげほげ", user_id: 1, created_at: "2018-11-21 14:41:07", updated_at: "2018-11-21 14:41:07">
irb(main):004:0> mp.user
Traceback (most recent call last):
        1: from (irb):4
NoMethodError (undefined method `user' for #<Micropost:0x00007f959e832080>)
Did you mean?  user_id

あれ?最後動いてないぞ?あ、micropost.rbが保存されてなかった。

> bundle exec rails console
Loading development environment (Rails 5.1.6)
irb(main):001:0> mp = Micropost.first
  Micropost Load (0.1ms)  SELECT  "microposts".* FROM "microposts" ORDER BY "microposts"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<Micropost id: 1, content: "いっこめ。ほげほげ", user_id: 1, created_at: "2018-11-21 14:41:07", updated_at: "2018-11-21 14:41:07">
irb(main):002:0> mp.user
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "太郎冠者", email: "taro@ex.com", created_at: "2018-11-21 11:49:49", updated_at: "2018-11-21 11:49:49">

つまり、この関連の設定は別に繋がっている訳じゃなくて、それぞれmicropostsとuserというメソッドを 作る設定をしているってことね。

さて、演習1。/users/1にポストを表示してみる。viewを触るだけで十分。

app/views/show.html.erb

<p>
  <strong>Content:</strong>
  <%= @user.microposts.first.content %>
</p>

これを追加するだけやね。表示してみる。

f:id:Tambourine:20181122004402p:plain

おっけーっぽい。

演習2。validationの追加。

app/models/micropost.rb

class Micropost < ApplicationRecord
  belongs_to :user
  validates :content, length: { maximum: 15}, presence: true
end

f:id:Tambourine:20181122004616p:plain

おっけー。

演習3。Userにも存在チェックを追加

app/models/user.rb

class User < ApplicationRecord
  has_many :microposts
  validates :name, presence: true
  validates :email, presence: true
end

f:id:Tambourine:20181122004835p:plain