おぴよの気まぐれ日記

おぴよの気まぐれ日記

岡山やプログラミング、ファッションのこと、子育てや人生、生き方についての備忘録。

新しいRubyのバージョンがrbenvに表示されない時はgit pullする

Rubyのバージョン調べてみると2.2.3だったので、2.2.4以上をインストールすべく

$ brew update
$ brew upgrade rbenv ruby-build

をやってインストールできるバージョン一覧を表示

$ rbenv install --list
(略)
  2.2.1
  2.2.2
  2.2.3
(略)

しかし、2.2.3以上のバージョンが表示されない。。。

で、調べてみるとruby-buildgit pullすれば良いそうだ

$ cd ~/.rbenv/plugins/ruby-build
$ git pull

再度表示すると2.2.4、2.2.5が出現!!

$ rbenv install --list
(略)
  2.2.1
  2.2.2
  2.2.3
  2.2.4
  2.2.5
(略)

めでたし。めでたし。

30歳まで残り2年の僕は人生を変えるためにRailsブートキャンプを始めようと思う(第4章:前半戦)

こんちには、opiyoです。

人生の生き残りをかけて始めた「Railsブートキャンプ」ですが、今日はRailsチュートリアル第4章をやっていこうと思います。

第4章は「Ruby」のお勉強です。早速やってみましょう!

あまりにもボリューミーなので、2回に分けます。この記事では「4.3 他のデータ構造までを」。


前回までのをまとめたのはこちらからどうぞ。

opiyotan.hatenablog.com

この章から始められる場合も、3章の「セットアップ」を参考に準備してください。

カスタムヘルパー

Railsのビューからは色々な関数が定義れています。

これは、自分で定義することもでき「カスタムヘルパー」と呼びます。

ここでは、3章で作成した各ビューで定義しているタイトルをヘルパーを使って定義します。

# app/helpers/application_helper.rb
module ApplicationHelper

  # ページごとの完全なタイトルを返します。
  def full_title(page_title = '')
    base_title = "Ruby on Rails Tutorial Sample App"
    if page_title.empty? # empty?は空っぽだったら「true」を返す
      base_title
    else
      page_title + " | " + base_title
    end
  end
end

文字列とメソッド

$ rails console #ターミナルに潜り込みます
>>

このターミナルを使って簡単なRubyの勉強

  • コメントアウト
name = test * test # この「#」がコメントアウト
end
  • 足し算
> 17 +42
=> 59
  • 文字列の連結
> "foo" + "bar"
=> "foobar"
  • 式展開
> first_name = "Taku"
> "#{first_name} Nakano"
=> "Taku Nakano"
  • 出力
> puts "foo" # putsだと末尾に自動で改行コードが付与されるされる
foo
=> nil
> print "foo" # 文字が続いているのがわかる
foo=> nil
  • シングルクォート内の文字列
> first_name = 'Taku'
> '#{first_name} Nakano'
=> "\#{first_name} Nakno" # シングルクォートの場合は式展開されないので注意!
  • 演習

<問題1>city変数に適当な市区町村を、prefecture変数に適当な都道府県を代入してください。

<回答1>

 prefecture = "岡山県"
=> "岡山県"
city = "倉敷市"
=> "倉敷市"

<問題2>先ほど作った変数と式展開を使って、「東京都 新宿区」のような住所の文字列を作ってみましょう。出力にはputsを使ってください。

<回答2>

> puts prefecture + " " + city
岡山県 倉敷市
> puts "#{prefecture} #{city}"
岡山県 倉敷市

<問題3>上記の文字列の間にある半角スペースをタブに置き換えてみてください。(ヒント: 改行文字と同じで、タブも特殊文字です)

<回答3>

> puts "#{prefecture} \t #{city}"
岡山県    倉敷市

<問題4>タブに置き換えた文字列を、ダブルクォートからシングルクォートに置き換えてみるとどうなるでしょうか?

<回答4>

> puts '#{prefecture} \t #{city}'
#{prefecture} \t #{city}

オブジェクトとメッセージ

Rubyでは文字列も、nilも何でもかんでもオブジェクトです。

例えば、文字列の数を知りたい場合はkengthメソッドを使います。

> "foobar".length        # 文字列に "length" というメッセージを送る
=> 6

条件分岐

  • ifを使って処理を分岐することができる
  • 2つ以上にしたい時はelsifを使う
  • and(&&) や or(||) を使える
> if s.nil?
>   "The variable is nil"
> elsif s.empty?
>   "The string is empty"
> elsif s.include?("foo")
>   "The string includes 'foo'"
> end
=> "The string includes 'foo'"

> x = "foo"
=> "foo"
> y = ""
=> ""
> puts "Both strings are empty" if x.empty? && y.empty?
=> nil
> puts "One of the strings is empty" if x.empty? || y.empty?
"One of the strings is empty"
=> nil
> puts "x is not empty" if !x.empty?
"x is not empty"
=> nil
  • 演習

<問題1>"racecar" の文字列の長さはいくつですか? lengthメソッドを使って調べてみてください。

<回答1>

> "racecar".length
=> 7

<問題2>reverseメソッドを使って、"racecar"の文字列を逆から読むとどうなるか調べてみてください。

<回答2>

> "racecar".reverse
=> "racecar"

<問題3>変数sに “racecar” を代入してください。その後、比較演算子 (==) を使って変数sとs.reverseの値が同じであるかどうか、調べてみてください。

<回答3>

> s = "racecar"
=> "racecar"
irb(main):013:0> s == s.reverse
=> true

<問題4>リスト 4.9を実行すると、どんな結果になるでしょうか? 変数sに “onomatopoeia” という文字列を代入するとどうなるでしょうか? ヒント: 上矢印 (またはCtrl-Pコマンド) を使って以前に使ったコマンドを再利用すると一からコマンドを全部打ち込む必要がなくて便利ですよ。)

<回答4>

> puts "It's a palindrome!" if s == s.reverse
It's a palindrome!
=> nil

> s = "onomatopoeia"
=> "onomatopoeia"
> puts "It's a palindrome!" if s == s.reverse
=> nil

メソッドの定義

メソッドは先ほど作ったカスタムヘルパーや、homeアクションやhelpアクションなどもそうですね。

  • def hogehoge(メソッド名) endで定義できる
  • 引数にデフォルト値を含めることが可能def string_message(str = '')

    • この場合は引数を指定しないとstr = ''がセットされる
  • 演習 <問題1>リスト 4.10のFILL_INの部分を適切なコードに置き換え、回文かどうかをチェックするメソッドを定義してみてください。ヒント: リスト 4.9の比較方法を参考にしてください。  ※回文・・・上から読んでも下から読んでも、同じ言葉になる文句

<回答1>

> def palindrome_tester(s)
>   if s == s.reverse
>     puts "It's a palindrome!"
>   else
>     puts "It's not a palindrome."
>   end
> end

<問題2>上で定義したメソッドを使って “racecar” と “onomatopoeia” が回文かどうかを確かめてみてください。1つ目は回文である、2つ目は回文でない、という結果になれば成功です。

<回答2>

> palindrome_tester("racecar")
It's a palindrome!
=> nil
> palindrome_tester("onomatopoeia")
It's not a palindrome.
=> nil 

<問題3>palindrome_tester(“racecar”)に対してnil?メソッドを呼び出し、戻り値がnilであるかどうかを確認してみてください (つまりnil?を呼び出した結果がtrueであることを確認してください)。このメソッドチェーンは、nil?メソッドがリスト 4.10の戻り値を受け取り、その結果を返しているという意味になります。

<回答3>

> palindrome_tester("racecar").nil?
It's a palindrome!
=> true

> if palindrome_tester("racecar").nil?
>   puts "TRUE"
> end
It's a palindrome!
TRUE

配列と範囲演算子

  • 文字列の分割
> "foo bar     baz".split # デフォルトは「空白」で分割する
=> ["foo", "bar", "baz"]
> "fooxbarxbazx".split('x') # 引数を指定すればそれで分割できる
=> ["foo", "bar", "baz"]
  • 配列の中身を取り出す
a = [42, 8, 17]
=> [42, 8, 17]
> a[0] # 0が一番目の要素になるので要注意!
=> 42
> a[1]
=> 8
> a[2]
=> 17
> a[-1] # マイナスの場合は後ろから数える!
=> 17

> a.first
=> 42
> a.second
=> 8
> a.last
=> 17
> a.last == a[-1]
=> true
  • いろいろなメソッド
a
=> [42, 8, 17]
> a.empty? # 配列が空であればtrue、1つ以上何か値があればfalseを返します。
=> false
> a.include?(42)
=> true
> a.sort
=> [8, 17, 42]
> a.reverse
=> [17, 8, 42]
> a.shuffle
=> [8, 42, 17]
> a
=> [42, 8, 17] # いろいろやっても値は「変わらない!」ことに気をつけましょう。
> a.sort! # 「!」などの破壊的メソッドと呼ばれるメソッドを使うと強制的に値を書き換えます。
=> [8, 17, 42]
> a
=> [8, 17, 42]
  • 値の追加
> a.push(6)
=> [42, 8, 17, 6]
irb(main):044:0> a << 7
=> [42, 8, 17, 6, 7]
irb(main):045:0> a << "foo" << "bar"
=> [42, 8, 17, 6, 7, "foo", "bar"]
  • 結合
> a
=> [42, 8, 17, 6, 7, "foo", "bar"]
> a.join
=> "4281767foobar"
> a.join(",")
=> "42,8,17,6,7,foo,bar"
  • 範囲
> 0..9
=> 0..9
irb(main):064:0> 0..9.to_a
NoMethodError: undefined method `to_a' for 9:Integer # 9に対して`to_a`してるのでエラーになります
Did you mean?  to_s
               to_c
               to_f
               to_i
               to_d
               to_r
.
.
  from -e:1:in `<main>'
irb(main):065:0> (0..9).to_a # ()を付けて範囲に対して`to_a`していることを伝えてあげます
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

> a = %w(foo bar baz quux)
=> ["foo", "bar", "baz", "quux"]
> a[0..2]
=> ["foo", "bar", "baz"]

> ('a'..'e').to_a # 文字でも使える!すごいねRuby!
=> ["a", "b", "c", "d", "e"]
  • 演習 <問題1>文字列 “A man, a plan, a canal, Panama” を “, ” で分割して配列にし、変数aに代入してみてください。

<回答1>

> a = "A man, a plan, a canal, Panama".split(",")
=> ["A man", " a plan", " a canal", " Panama"]

<問題2>今度は、変数aの要素を連結した結果 (文字列) を、変数sに代入してみてください。

<回答2>

> s = a.join
=> "A man a plan a canal Panama"

<問題3>変数sを半角スペースで分割した後、もう一度連結して文字列にしてください (ヒント: メソッドチェーンを使うと1行でもできます)。リスト 4.10で使った回文をチェックするメソッドを使って、(現状ではまだ) 変数sが回文ではないことを確認してください。downcaseメソッドを使って、s.downcaseは回文であることを確認してください。

<回答3>

> s.split(" ")
=> ["A", "man", "a", "plan", "a", "canal", "Panama"]
> s.split(" ").join
=> "AmanaplanacanalPanama"

> s_down = s.downcase
=> "amanaplanacanalpanama"
> s_down == s_down.reverse
=> true

<問題4>aからzまでの範囲オブジェクトを作成し、7番目の要素を取り出してみてください。同様にして、後ろから7番目の要素を取り出してみてください。(ヒント: 範囲オブジェクトを配列に変換するのを忘れないでください)

<回答4>

> az = ("a".."z").to_a
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
> az[7 - 1]
=> "g"
> az[-7]
=> "t"

ブロック

  • ブロックは「{ }」のことで、「do end」で囲って表現する場合もあります。
  • 短い1行のブロックには波かっこを使用し、長い1行や複数行のブロックにはdo..end記法を使うのが一般的

例えば、以下は1~5を順番に変数iに渡してputs 2 * iを実行するというような処理になります。

> (1..5).each { |i| puts 2 * i }
2
4
6
8
10
=> 1..5

> (1..5).each do |i|
*   puts i * 2
> end
2
4
6
8
10
=> 1..5
  • mapメソッド
> 3.times { puts "Betelgeuse!" }   # 3.timesではブロックに変数を使用していない
"Betelgeuse!"
"Betelgeuse!"
"Betelgeuse!"
=> 3

> (1..5).map { |i| i**2 }          # 「**」記法は冪乗 (べき乗) 
=> [1, 4, 9, 16, 25] # 配列で帰ってくる
# 同じ結果をeachでやるには、こんな感じ?
> array = []
=> []
> (1..5).each do |i|
*   array << i ** 2
> end
=> 1..5
> array
=> [1, 4, 9, 16, 25]

> %w[a b c]
=> ["a", "b", "c"]
> %w[a b c].map {|char| char.upcase}
=> ["A", "B", "C"]
> %w[a b c].map {|char| char.downcase}
=> ["a", "b", "c"]

> %w[A B C].map(&:downcase) # 省略できる
=> ["a", "b", "c"]
  • 演習 <問題1>範囲オブジェクト0..16を使って、各要素の2乗を出力してください。

<回答1>

> (0..16).map {|i| puts i ** 2}
0
1
4
9
16
25
36
49
64
81
100
121
144
169
196
225
256

<問題2>yeller (大声で叫ぶ) というメソッドを定義してください。このメソッドは、文字列の要素で構成された配列を受け取り、各要素を連結した後、大文字にして結果を返します。例えばyeller([’o’, ’l’, ’d’])と実行したとき、"OLD"という結果が返ってくれば成功です。ヒント: mapとupcaseとjoinメソッドを使ってみましょう。

<回答2>

> def yeller(array)
>   puts array.join.upcase
> end
=> :yeller

> yeller(%w(o l d))
OLD

<問題3>random_subdomainというメソッドを定義してください。このメソッドはランダムな8文字を生成し、文字列として返します。ヒント: サブドメインを作るときに使ったRubyコードをメソッド化したものです。

<回答3>

> def random_subdomain
>   ('a'..'z').to_a.shuffle[0..7].join
> end
=> :random_subdomain

> random_subdomain
=> "ikzbpahe"

<問題4>リスト 4.12の「?」の部分を、それぞれ適切なメソッドに置き換えてみてください。ヒント:split、shuffle、joinメソッドを組み合わせると、メソッドに渡された文字列 (引数) をシャッフルさせることができます。

<回答4>

> def string_shuffle(s)
>   s.split("").shuffle.join # splitに「""」を渡すと1文字ずつ分割してしてくれる
> end
> string_shuffle("foobar")
=> "oobfra"

ハッシュとシンボル

  • ハッシュとはインデックス([]の中身)に整数値以外のものも使用できる点が配列と違う
  • ハッシュは「{}」を使って表記する
  • ブロックの「{}」とは全く違う
  • ハッシュでは要素の「並び順」が保証されない
 user = {}
=> {}
> user["first_name"] = "Michael"
=> "Michael"
> user["last_name"] = "Hartl"
=> "Hartl"
> user["first_name"]
=> "Michael"
> user
=> {"first_name"=>"Michael", "last_name"=>"Hartl"}
> user = { "first_name" => "Michael", "last_name" => "Hartl" }
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}
  • シンボルとはコロンが前に置かれている文字列
  • 文字列と似ているが異なる
  • Railsでは文字列よりもシンボルを使用する
  • 文字列と違って全ての文字が使えるわけではない
  • ハッシュもeachメソッド
> "name".split('')
=> ["n", "a", "m", "e"]
> :name.split('')
NoMethodError: undefined method `split' for :name:Symbol
> "foobar".reverse
=> "raboof"
> :foobar.reverse
NoMethodError: undefined method `reverse' for :foobar:Symbol

> :foo-bar
NameError: undefined local variable or method `bar' for main:Object
> :2foo
SyntaxError

> user = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
> user[:name]
=> "Michael Hartl"
> user[:password]
=> nil

> h1 = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
> h2 = { name: "Michael Hartl", email: "michael@example.com" } # 別の書き方 これもよく見る
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
> h1 == h2
=> true

> params = {}
=> {}
> params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" }
=> {:name=>"Michael Hartl", :email=>"mhartl@example.com"}
> params
=> {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}}
>  params[:user][:email]
=> "mhartl@example.com"
  • 演習 <問題1>キーが’one’、’two’、’three’となっていて、それぞれの値が’uno’、’dos’、’tres’となっているハッシュを作ってみてください。その後、ハッシュの各要素をみて、それぞれのキーと値を"’#{key}’のスペイン語は’#{value}’"といった形で出力してみてください。

<回答1>

> hash
=> {:one=>"uno", :two=>"dos", :three=>"tres"}
* hash.each do |k,v|
* puts "#{k}のスペイン語は#{v}です"
> end
oneのスペイン語はunoです
twoのスペイン語はdosです
threeのスペイン語はtresです
=> {:one=>"uno", :two=>"dos", :three=>"tres"}

<問題2>person1、person2、person3という3つのハッシュを作成し、それぞれのハッシュに:firstと:lastキーを追加し、適当な値 (名前など) を入力してください。その後、次のようなparamsというハッシュのハッシュを作ってみてください。1.) キーparams[:father]の値にperson1を代入、2). キーparams[:mother]の値にperson2を代入、3). キーparams[:child]の値にperson3を代入。最後に、ハッシュのハッシュを調べていき、正しい値になっているか確かめてみてください。(例えばparams[:father][:first]がperson1[:first]と一致しているか確かめてみてください)

<回答2>

> params[:father] = person1
=> {:first=>"nakano", :last=>"taku"}
> params[:mother] = person2
=> {:first=>"nakano", :last=>"haku"}
> params[:child] = person3
=> {:first=>"nakano", :last=>"toma"}

> params[:father][:first] == person1[:first]
=> true
> params[:mother][:first] == person2[:first]
=> true
> params[:child][:first] == person3[:first]
=> true

<問題3>userというハッシュを定義してみてください。このハッシュは3つのキー:name、:email、:password_digestを持っていて、それぞれの値にあなたの名前、あなたのメールアドレス、そして16文字からなるランダムな文字列が代入されています。

<回答3>

> user = {}
=> {}
> user[:name] = "Taku"
=> "Taku"
> user[:email] = "kosmo.waizu0804@gmail.com"
=> "kosmo.waizu0804@gmail.com"
> > user[:password_digest] = ("a".."z").to_a.shuffle[0..15].join
=> "fpnewraocjbhustg"
> user
=> {:name=>"Taku", :email=>"kosmo.waizu0804@gmail.com", :password_digest=>"fpnewraocjbhustg"}

<問題4>Ruby API (訳注: もしくはるりまサーチ) を使って、Hashクラスのmergeメソッドについて調べてみてください。次のコードを実行せずに、どのような結果が返ってくるか推測できますか? 推測できたら、実際にコードを実行して推測があっていたか確認してみましょう。

<回答4>

> { "a" => 100, "b" => 200 }.merge({ "b" => 300 })
=> {"a"=>100, "b"=>300}
  • その他 app/views/layouts/application.html.erbに書かれている以下の2行は色々な要素が省略されているのに注意!
stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'
# メソッド呼び出しの丸かっこは省略可能。
stylesheet_link_tag('application', media: 'all',
                                   'data-turbolinks-track': 'reload')
# 最後の引数がハッシュの場合、波かっこは省略可能。
stylesheet_link_tag 'application', { media: 'all',
                                     'data-turbolinks-track': 'reload' }

# htmlだとこうなります
<link data-turbolinks-track="true" href="/assets/application.css" media="all"
rel="stylesheet" />

その他メモ

  • 新しいブランチの作り方
$ git checkout -b rails-flavored-ruby
Switched to a new branch 'rails-flavored-ruby'
$ git branch
  master
* rails-flavored-ruby

第4章まだ途中ですが、ここで一度アップ!

1万文字超えてるではないか…

ユニクロではなく無印良品を選ぶ3つの理由

こんにちは。opiyoです。

岡山は今梅雨入り初めての雨が降っていますが、「晴れたらやりたいこと」は何でしょうか?

私は熱狂的なユニクロファンで赤色の靴下、パンツ、ジーパン、Tシャツ、パーカー全てがユニクロです。

先日痛くないハイヒールを作っている瀧見サキ」さんの記事を書きましたが、この瀧見サキさんの格好が個人的にはドストライクで、めちゃくちゃ格好良いのですよ。

www.instagram.com

これ、無印っぽいので久しぶりに岡山イオンの無印良品に遊びに行ったのですが、そこには僕の知らないアイテム達が待ち構えていました

VネックTシャツ 2枚組(1490円)

無印良品って昔は多分Uネックしかなかったんじゃないかなぁ。

https://www.muji.net/store/cmdty/detail/4549738732082?searchno=11

タンクトップ 2枚組(1490円)

タンクトップも昔は無印良品なかったんじゃないかなぁと思うんだけど、自信ないな。

今はビックシルエットが流行ってるから旨味がないかもだけど、白のTシャツ着るときはグレーのタンクトップ着て1cmくらいTシャツから飛び出して見せると全体が引き閉まるからオススメです!

https://www.muji.net/store/cmdty/detail/4549738536451?searchno=1

ポケット付きTシャツ

通販サイトでは見つからなかった。こういうちょっとオシャレなものって全然なかったと思うんだど。どうだろうか。

これは普通にメンズだけじゃなくてレディースもいけると思う。

オシャレコーデ

WEAR

wear.jp

wear.jp

wear.jp

wear.jp

wear.jp

無印良品は間違いなく今後くる〜

昔から無印は好きだったのですが、2つ気にくわないところがありました

  • 種類がが少なすぎる。
  • 高い

例えばTシャツならUネックしかないとかだったけど、ご覧の通り。これだけ種類があれば満足する方結構いると思う。

あとは値段だけど、この前各アイテム値下げを発表みたいな記事読んだのでもう少し安くなるかも。

こーなってくると、高いから無印良品は買わないって人多かったと思うけど値段が同じならば無印良品で買うって人は出てくると思う。

何となく無印良品の方が高いブランドイメージ付いてるし。多分…

ということで今日はここまで。

22歳でパパになって良かったと思うこと/思わないこと

こんちには。opiyoです。

昨日ですかね、私が尊敬している元リクルートで副業家の西村さんがNEW PEACE代表の高木新平さんの記事を見て書いたというブログを見ました。

内容は簡単に言うと「若くして家族を持つことも悪くないよ!」って話だとぼくは解釈しました。

ぼくも22歳で結婚。次の年には長男が生まれ、その次の年には長女が生まれました。

全く同じでは無いですが、とても近い状況な僕にとっては改めて「家族」について考えるきっかけになりました。

みんな違って、みんないい。

こんな言葉があったような気がしますが、こんな感じになりそうです。

良かったと思うこと

仕事の第一次ピークに全力になれる

仕事の第一次ピークは、33〜38歳にやってくる
子育てがひと段落した状態で「仕事の第一次ピーク」を迎えられる

高木さんの記事では、仕事の第一次ピークは、33〜38歳と書かれています。

僕は今27歳。8月で28歳になる。

つまり、仕事の第一次ピークを迎えるのは5年後、2022年頃には

  • 長男・・・10歳(小4)
  • 長女・・・9歳(小3)

僕が30歳になる2年後であっても長男は小1、長女は年長になるので、この頃にはほとんど手はかからなくなりそうです。

これは、良い点ですね。いざという時に全力で走れます。

一番体力がある時に子育てができる

仕事の先輩、幼稚園パパを見るとやっぱり僕の優位は明らかです。

偉そうなこと言ってごめんなさい。でも、これだけは自信をもって子供たちに誇れるポイントです。

僕自身が3人目として生まれたので周りに比べると僕の両親はジジババでした。

なので公園行って走り回った記憶も無いです。唯一の楽しみはキャッチボールでした。

だから若い!ってのはそれだけで子どもと一緒に遊ぶ体力があるので良い事ばかりです。

コミュニティができる

子どもがいると幼稚園、習いごとなど絶対に繋がらないであろう人達と交流ができるってのは間違いなく良い所だと思います。

良くないなと思ったこと

20代という一番楽しい時間を自分だけに使う事ができない

もーこれです。 羨ましいに決まってるじゃないですか。何を強がっているのか。

僕が結婚した前後くらいから皆がiphone持つようになって今みたいな何処とでも繋がっている素晴らしい世界になってきました。そんな状況にも関わらず家と会社を往復する日々。自分に使う時間ってよりかはお金が無いので何も出来ない。そんな状況です。

旅したい。カメラ欲しい。遊びたい。

残念ながら今はできません。

周りの方が経済的に豊か

当たり前ですが皆さん僕より年上です。一回りも違う人だっています。ですから当たり前のように家があるから遊びに行って帰ってくると子どもは「なぜうちは階段が無いのか」聞いてくる。これは結構きついですよ。

待ってろよ。絶対どうにかしてやるからな。

みんな違って、みんな良い

よかったこと、よくないなと思ったこと自分なりに整理してきました。

結局ぼくは何が言いたいのだろうか。正直良く分かりません。

だけど、僕が歩んできた道に後悔はありません。家族には本当に感謝しています。

ありがとうね。


ということで「みんな違って、みんな良い」

あの人がこうだから…ではなくて、自分が良いと思える道をきちんと選んで生きていきましょう。

30歳まで残り2年の僕は人生を変えるためにRailsブートキャンプを始めようと思う(第3章)

こんちには、opiyoです。

人生の生き残りをかけて始めた「Railsブートキャンプ」ですが、今日はRailsチュートリアル第3章をやっていこうと思います。

前回までのをまとめたのはこちらからどうぞ。

opiyotan.hatenablog.com

opiyotan.hatenablog.com

セットアップ

繰り返しの復習は大事です。人間はすぐに忘れてしまう動物なので。

改めてrails newして最低限のところまでを作ります!

https://railstutorial.jp/chapters/static_pages?version=5.0#sec-sample_app_setup

  • $ rails _5.0.0.1_ new sample_app
  • Gemfileをいじります
source 'https://rubygems.org'

gem 'rails',        '5.0.0.1'
gem 'puma',         '3.4.0'
gem 'sass-rails',   '5.0.6'
gem 'uglifier',     '3.0.0'
gem 'coffee-rails', '4.2.1'
gem 'jquery-rails', '4.1.1'
gem 'turbolinks',   '5.0.1'
gem 'jbuilder',     '2.4.1'

group :development, :test do
  gem 'sqlite3', '1.3.11'
  gem 'byebug',  '9.0.0', platform: :mri
end

group :development do
  gem 'web-console',           '3.1.1'
  gem 'listen',                '3.0.8'
  gem 'spring',                '1.7.2'
  gem 'spring-watcher-listen', '2.0.0'
end

group :test do
  gem 'rails-controller-testing', '0.1.1'
  gem 'minitest-reporters',       '1.1.9'
  gem 'guard',                    '2.13.0'
  gem 'guard-minitest',           '2.4.4'
end

group :production do
  gem 'pg', '0.18.4'
end

# Windows環境ではtzinfo-dataというgemを含める必要があります
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
  • $ bundle install --without production
    • エラーが出たら $ bundle update する
  • gitを使ってsample_appをバージョン管理下にする
  • トップページ(hogehoge.com/)にhello worldを表示されるようにコードを修正する
  • herokuの設定を行いpushします
  • heroku openしてhello worldが表示されればOK

githerokuの設定はチュートリアルを見ずにやってみることで、覚えているかの復習になりますね!

3.1 演習

<問題1> BitbucketがMarkdown記法のREADME (リスト 3.3) をHTMLとして正しく描画しているか、確認してみてください。

<回答1> ぼくは、githubで作業しているのですが問題なく描画されていますね。

  • h1は大きな文字
  • h2は少し大きな文字
  • リンクは青色で
  • コード部分は灰色になる

https://github.com/nakanoTaku/railstutorial_3

<問題2> 本番環境 (Heroku) のルートURLにアクセスして、デプロイが成功したかどうか確かめてみてください。

<回答2> hello worldが表示されているのでOKですね! heroku logsでログを見ることも出来ます。

コントローラーの作り方

  • 表記はキャメルケース = 単語の先頭を大文字になる(StaticPages)
  • アクション名は全て小文字にする
  • 出来上がるコントローラーファイル名はスネークケース = 単語をアンダーバー_でつなぎ合わせた名前になる
$ rails g 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
  • routes.rbが自動的に更新される
Rails.application.routes.draw do
  get 'static_pages/home' # 自動的に追加されたよ
  get 'static_pages/help' # 自動的に追加されたよ
  root 'application#hello'
end

このgetは、/static_pages/home/というURLでアクセスされたら、static_pagesコントローラーのhomeアクションと結びつく設定になります。

3.2.1 演習

<問題1> Fooというコントローラを生成し、その中にbarとbazアクションを追加してみてください。

<回答1>

$ rails g controller Foo bar baz

class FooController < ApplicationController
  def bar
  end
  def baz
  end
end

<問題2> コラム 3.1で紹介したテクニックを駆使して、Fooコントローラとそれに関連するアクションを削除してみてください。

<回答2>

$ rails destroy controller Foo bar baz

テスト駆動開発 (TDD)

考え方

テストの手法のひとつで、最初に「正しいコードがないと失敗するテスト」を書き、次に本編のコードを書いてそのテストがパスするようにする考え、やり方かな。

テストをするメリットはチュートリアルのコラムの中で書かれてますが、引用します。

  1. テストが揃っていれば、機能停止に陥るような回帰バグ (Regression Bug: 以前のバグが再発したり機能の追加/変更に副作用が生じたりすること) を防止できる。
  2. テストが揃っていれば、コードを安全にリファクタリング (機能を変更せずにコードを改善すること) ができる。
  3. テストコードは、アプリケーションコードから見ればクライアントとして動作するので、アプリケーションの設計やシステムの他の部分とのインターフェイスを決めるときにも役に立つ。

さらに詳細までみたいな場合は、こちらからどうぞ(コラム3-3.です)

https://railstutorial.jp/chapters/static_pages?version=5.0#sec-custom_static_pages

当たり前ですが、何か問題があるとお客様に迷惑をかけます。それは本当に申し訳無いところなのですが、お客様以外のところで凄く面倒なことになります。

だからテストを書くのです。もーこれだけ。

テストコードの書き方

テストコードはrails g controllerを実行した時点で作成されます。

require 'test_helper'

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

これを日本語で表すと、「Homeページのテスト。GETリクエストをhomeアクションに対して発行 (=送信) せよ。そうすれば、リクエストに対するレスポンスは[成功]になるはず。」となります。

テストの実行方法は

$ rails test
# Running:

..
Finished in 1.467940s, 1.3625 runs/s, 1.3625 assertions/s.
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips

0 errorsとなっているので、成功(GREEN)したことが分かりますね。

もしエラーになる場合は、こちらに回避方法書いたので参考にしてください。 opiyotan.hatenablog.com

このように、テストと一緒にコードを書いていくことが最近は推奨されています。

3.3.1では、TDDの考えに基づき失敗するエラーを書いて成功させリファクタリングするという流れでテストする方法が乗っていますので是非チャレンジしてみてください。

動的にタイトルを変更する

先ずは各ページのタイトルをチェックするテストを書きます。 もちろん、viewtitleタグは何も変更していないのでエラー(RED)になります。

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Home | Ruby on Rails Tutorial Sample App" # ここ追加しました。"title"タグに書かれた文字列をチェックするテストです
  end
end

では、次にviewtitleタグを修正していきます。始めにapp/views/static_pages/home.html.erbファイルから。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Home | Ruby on Rails Tutorial Sample App</title> # この部分ですね
  </head>
  <body>
    <h1>Sample App</h1>
    <p>
      This is the home page for the
      <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
    </p>
  </body>
</html>

この状態でテストを実行するとhomeアクションについては修正したのでエラーじゃなくなりますが他の2つのアクションがエラーになります

$ rails test
# Running:

.F

Failure:
StaticPagesControllerTest#test_should_get_about [/Users/taku/rails/railstutorial/sample_app/test/controllers/static_pages_controller_test.rb:19]:
<About | Ruby on Rails Tutorial Sample App> expected but was
<SampleApp>..
Expected 0 to be >= 1.

bin/rails test test/controllers/static_pages_controller_test.rb:16

F

Failure:
StaticPagesControllerTest#test_should_get_help [/Users/taku/rails/railstutorial/sample_app/test/controllers/static_pages_controller_test.rb:13]:
<Help | Ruby on Rails Tutorial Sample App> expected but was
<SampleApp>..
Expected 0 to be >= 1.

bin/rails test test/controllers/static_pages_controller_test.rb:10

Finished in 0.649278s, 4.6205 runs/s, 9.2410 assertions/s.
3 runs, 6 assertions, 2 failures, 0 errors, 0 skips

なので、エラー(RED)にならないようhelpaboutも修正し成功(GREEN)させます。

3.4.2 演習

テストを一部リファクタリングします。

3つのアクションで同じように使われている文字列「Ruby on Rails Tutorial Sample App」を変数に代入し、使い回すようにします。

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  def setup
    @base_title = "Ruby on Rails Tutorial Sample App" # setupというテストが実行される前に処理されるメソッド内で文字列を変数にセットしておきます。
  end

  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Home | #{@base_title}" # 変数を参照するように修正します。
  end
end

リファクタリング

今までは全てのviewファイルに直接titleタグを書き込んでいました。なので当然表示されるタイトルも変わってきます。

これらを今テストでやったように共通にできるところは共通化し、違う部分だけを設定するように修正していきます。

このように同じコードを繰り返し書かないようにする考え方を「DRY(Don’t Repeat Yourself: 繰り返すべからず) 」と言います。

では早速やってみます。先ずは各ページに動的に変更する部分を書いていきます。

app/views/static_pages/home.html.erb

<% provide(:title, "Home") %> # 各ビュー毎に文字列をセットする
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title> # 設定した文字列をyield関数を使って反映させる
  </head>
  <body>
    <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>
  </body>
</html>

次に共通のビューになるapplication.html.erbtitleyield関数を使って表示されるようにします

<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title> # ここですねー
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all',
                                              'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %> # ここで各ページを読み込んでいるから、各ビューでは`head`タグとかがいらないんですね
  </body>
</html>

それぞれのページでは違う処理だけ書く。共通部分はapplication.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>

3.4.4 演習

<問題1> リスト 3.41にrootルーティングを追加したことで、root_urlというRailsヘルパーが使えるようになりました (以前、static_pages_home_urlが使えるようになったときと同じです)。リスト 3.42のFILL_INと記された部分を置き換えて、rootルーティングのテストを書いてみてください。

<回答1>

  test "should get root" do
    get root_url
    assert_response :success
  end

<問題2> 実はリスト 3.41のコードを書いていたので、先ほどの課題のテストは既に green になっているはずです。このような場合、テストを変更する前から成功していたのか、変更した後に成功するようになったのか、判断が難しいです。リスト 3.41のコードがテスト結果に影響を与えていることを確認するため、リスト 3.43のようにrootルーティングをコメントアウトして見て、 red になるかどうか確かめてみましょう (なおRubyのコメント機能については4.2.1で説明します)。最後に、コメントアウトした箇所を元に戻し (すなわちリスト 3.41に戻し)、テストが green になることを確認してみましょう。

<回答2> ちゃんとREDになるし、GREEMにもなる

httpメソッド

HTTP (HyperText Transfer Protocol) には4つの基本的な操作があり、それぞれGET、POST、PATCH、DELETEという4つの動詞に対応づけられています。クライアント (例えばFirefoxやSafariなどのWebブラウザ) とサーバー (ApacheやNginxなどのWebサーバー) は、上で述べた4つの基本操作を互いに認識できるようになっています

  • get

主にWeb上のデータを読み取る (get) ときに使われるリクエストです。

  • post

ページ上のフォームに入力した値を、ブラウザから送信する時に送られるリクエストです。

テストをパワーアップする

minitest reporters

テストの成功(RED)失敗(GREEN)の見栄えをよくしてくれます。

準備するのはこれだけ、是非試してみてください!

# ファイル名:test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters"
Minitest::Reporters.use!

class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all

  # Add more helper methods to be used by all tests here...
end

f:id:opiyotan:20170620173015p:plain

Guard

ファイルの変更を検出して必要なテストだけを自動実行してくれるそうです。

例えば、「home.html.erbファイルが変更されたらstatic_pages_controller_test.rbを自動的に実行する」といったことをGuardで設定することができます。

これヤバいですね。今はまだ変更するファイルも少ないですし何をしたか全部記憶できるくらいしかないですが絶対面倒になって忘れますよね。

詳細な設定方法はRailsチュートリアルを参照してください。

https://railstutorial.jp/chapters/static_pages?version=5.0#sec-guard

手順だけ簡単にまとめておきます。

  • 初期化
$ bundle exec guard init

初期化を実行すると、「/Guardfile」が作成されます。

  • Guardfileを編集する
  • .gitignoreにSpringを追加する
  • Guardの実行
$ bundle exec guard

なんか実行すると「Ctrl + D」か「テストが成功」するまで終わらないのだけど、これは正しい動きなのか?

ずっとバックグラウンドで動かしておいて、常に監視させておくってことなのかな…

あーすごい便利かなーと思ったけど、これは使わないかもしれない。邪魔っちー

その他メモ

  • gitでaddとcommitを一回でやる!
$ git commit -am "Improve the README"
  • herokuへpushした時に何かエラー
$ heroku logs
  • 新しいブランチの作り方
$ git checkout -b hogehoge
  • 今チェックアウトしているブランチは?
$ git branch
  master
* static-pages
  • ブランチを指定してpushするには?
$ git push origin hogehoge
  • rails g をやり直したい!
$ rails destroy  controller StaticPages home help
$ rails destroy model User
  • Unixプロセスの確認
$ ps aux
$ ps aux | grep spring
$ ps aux | grep spring
taku              7781   0.0  0.2  2518224  19900   ??  S     5:23PM   0:00.42 spring server | sample_app | started 31 mins ago
taku              8561   0.0  0.0  2423376    216 s003  R+    5:55PM   0:00.00 grep spring
taku              7782   0.0  0.9  2577420  73224   ??  Ss    5:23PM   0:02.75 spring app    | sample_app | started 31 mins ago | test mode

$ spring stop
$ ps aux | grep spring
taku              8604   0.0  0.0  2434840    804 s003  S+    5:57PM   0:00.00 grep spring # 「7781」「7782」が無くなった!

まとめ

3章ではテスト駆動開発 (TDD)に沿って、開発を進めてきました。 簡単にまとめるこんな感じでしょうか?

  • 何事も繰り返し行うことで覚えることができる
    • rails new
    • git init ~ git pushまでの流れ
  • rails g controller ControllerName アクション名でコントローラーが作れる
  • RailsのビューはRubyのコードが使える
  • テスト駆動開発 (TDD)は、「RED」「GREEN」「REFACTOR」のサイクルを繰り返して開発をすることだ


では、最後にぼくが一番尊敬している先輩エンジニアからの名言でお別れしましょー

テストコードが仕様書だ