Chiroru's Diary

日々の学びをちょこちょこメモしていきます

【ゼロからわかるRuby超入門3】Ruby ハッシュ・メソッド・クラス・モジュールなど

【目次】

6-1オブジェクトを組みで扱う

ハッシュ(Hash)

クラス名はHash「キー」「値」 をセットとして、複数のデータを扱う。
キーと値にはどんな種類のオブジェクトも入れられるが、キーのオブジェクトにより書き方が異なる。

{キー: 値}
# キーが「シンボル」の時のみ

{:キー => 値}
# キーが何でも  

{"文字列のキー" => 値}
# 文字列キーの場合  

{:キー => 値}のまとまりが、ハッシュオブジェクト。

シンボルって何だっけ

ここでシンボルの確認。Ruby 2.7.0 リファレンスマニュアル

Rubyの内部実装では、メソッド名や変数名、定数名、クラス名などの名前を整数で管理しています。 これは名前を直接文字列として処理するよりも速度面で有利だからです。そしてその整数をRubyのコード上で表現したものがシンボルです。

シンボルは、ソース上では文字列のように見え、内部では整数として扱われる、両者を仲立ちするような存在です。

名前を管理するという役割上、シンボルと文字列は一対一に対応します。また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。

文字列に見える数値、のような感じだろうか。

ハッシュ値の取得

ハッシュの値を取得したい場合は、「キー」から。

ハッシュ(※変数)[キー]
# キーがシンボルだったら[:キー]  

6-2ハッシュに要素の追加・削除

追加

  • 「キー + 値」の組みを書くことで追加
  • 同じキーは複数持てないため、同じキーを追加すると上書きされる
  • 存在しないキーを取得しようとした時に返ってくる値を「default = メソッド」で設定できる。(設定なしだとnilが返ってくる)

ハッシュを統合して新しいハッシュを作るmerge

A = {a: 300}
B = {b: 600}
menu = A.merge(B)

削除

ハッシュ.delete(キー) で削除

6-3ハッシュの要素を繰り返し表示

ハッシュで繰り返し処理を行う時、キーと値の2つの変数をブロック内で使うことができる。 また、どちらか1つだけでもできる。

ハッシュ.each do |キーの変数, 値の変数|  
  処理
end
# 2つを使う時  

ハッシュ.each_key do |keyの変数|
  処理
end
# keyだけ繰り返し行う時

7-2メソッドへオブジェクトを渡す

引数を使うことで、呼び出しの時にメソッドへオブジェクトを渡すことができる。

def メソッド名(引数1, 引数2)
  処理
end
# 引数を持ったメソッドの定義  

メソッド名(引数)
# 引数を渡して、メソッドを呼び出す  

メソッドを途中で終わらせたい時の「return」

  • 「return オブジェクト」が実行されると、そのオブジェクトが戻り値となる

7-3メソッドの引数について

  • メソッドに記入した引数のデフォルト値を指定することが可能。これにより、呼び出しの際引数の省略ができるようになる
  • ただし、キーワード引数の場合のデフォルト値の設定は書き方が異なる
  • そもそもキーワード引数とは、メソッドを呼び出す際に引数を名前付きで指定できる。(→これにより、呼び出しの際に順序を変えられる)
def メソッド (引数 = "デフォルト値")
  処理
end
# 通常の引数×デフォルト値

def メソッド (キーワード引数1:, キーワード引数2:)
  処理
end
# キーワード引数
# 呼び出しは「メソッド(キーワード引数2:, キーワード引数1:)」のように指定できる  

def メソッド (キーワード引数:"デフォルト値")
  処理
end
# キーワード引数×デフォルト値

7-4ローカル変数とスコープ

  • ローカル変数は、特定のメソッド呼び出しや宣言されているクラス内、ファイルの実行の中だけで使用できる変数
  • 変数にはスコープ(見える範囲・寿命)がある
  • メソッド内で出てくるローカル変数は、メソッドの中がスコープ

他参考:Rubyにおける変数と定数の使い方

8-1 クラスについて

クラスはオブジェクトの種族を表すもので、オブジェクトは全てクラスに属す。またこのクラスに属すオブジェクトは「インスタンス」であるともいう。

「オブジェクト」と「インスタンス

これらはほとんど同じような意味だが、あえて「インスタンス」と呼ぶ際は、

  • クラスから作ったオブジェクト
  • そのクラスに属する

を強調したい時。

クラスの見分け方

あるオブジェクトのクラスを知りたい時は、以下で表示する。

オブジェクト.class

新しくオブジェクトを作る方法

あるクラスの新しいオブジェクト(インスタンス)を作りたい時。

クラス.new

例)

p Array.new(3, "aaa") #=>["aaa", "aaa", "aaa"]

8-2クラスを作る

クラスを定義する

自分でクラスを作ること=「定義」する。定義は以下のように行う。

class クラス名
end

8-3オブジェクトが呼び出せるメソッドを定義する

定義したクラスは、初め最低限の機能しかない。そのためメソッドを追加してクラスを育てていく。

メソッドが呼びだされるオブジェクトのことを、「レシーバ」と呼ぶ。
このレシーバで呼び出すことができるメソッドを確認したい場合は「methods」メソッドを使う。

レシーバ(※オブジェクト).methods.sort

しかしそもそもレシーバがどのオブジェクトかがわからないことがある。そんな時は、メソッドを呼び出したい場所で「self」を使うことで、対象のレシーバを調べることができる。

8-4オブジェクトにデータを持たせる

インスタンス変数(@)

メソッド内で使った変数を、別のメソッド内でも使いたい場合はインスタンス変数を利用する。インスタンス変数は、ローカル変数よりスコープが広く同じオブジェクトであれば、複数のメソッドで使うことが可能

オブジェクトごとに存在するインスタンス変数

またインスタンス変数は、オブジェクトごとに存在する。そのため、同じクラスに書かれているインスタンス変数でも、オブジェクトが異なれば、別物となる。

オブジェクトの外でインスタンス変数を取得したい

もしオブジェクトの外で、オブジェクト内で使ったインスタンス変数を取得したければ、クラスにそのインスタンス変数が戻り値となるメソッドを追記すれば良い。

ちなみに、「同じ名前のインスタンス変数を戻り値とするメソッドを定義」したい場合は、以下のものがある。

attr_reader :(@なしの)インスタンス変数名

また「同じ名前のインスタンス変数へ代入するメソッドを定義」する時は以下になる。

attr_writer :(@なしの)インスタンス変数名

上記の二つはよくセットで使用されるので、これをまとめて書くこともできる。

attr_accessor :(@なしの)インスタンス変数名

オブジェクトが持ってるインスタンス変数を知りたい

「instance_variables」メソッドを利用すれば、そのオブジェクトが持っているインスタンス変数の変数名一覧を取得できる。

8-5オブジェクトが作られるタイミングで処理をする

自動で呼び出されるinitializeメソッド

クラスが持つ特別なメソッドで、メソッドを定義すると、newなどでオブジェクトが作成される時に、自動でこのメソッドも呼び出される。

この使いどきとしては、

  • インスタンス変数初期値の設定。(メソッド内に初期値を記載、オブジェクト作成時に代入される)
  • 初期値を自由に設定したければメソッドに「引数」を受け取るようにし、オブジェクト作成時に引数を渡す

8-6クラスを使ってメソッド呼び出し

オブジェクトを作らずにクラスを使って呼び出せるメソッドを「クラスメソッド」という。(⇄インスタンスメソッド)

クラスメソッドは、例えばnewのようなクラスに対してメソッドを呼び出し、クラスのオブジェクトを作る

クラスメソッドの定義は「self .」をつける。

def self .メソッド名  
end
# クラスメソッド定義  

クラス名.メソッド名
# 呼び出す時

ちなみに「インスタンスメソッド」からクラスメソッドを呼ぶことも可能。
self.clas.クラスメソッド or クラス.クラスメソッド
(クラスメソッドからインスタンスメソッド呼び出しは不可)

8-8メソッドの呼び出しを制限する

メソッドの呼び出しを制限したい時は、クラスに「private」を書く。(⇄public)

※クラスメソッドの定義と制限について

しかしクラスメソッド(self.メソッド)を制限したい場合は、privateの代わりに 「private_class_method」 を書く。

また同じクラスメソッドの定義でも、self.メソッドの形式ではなく「class << self」を書いてからメソッドを定義する形式もあり、その場合でメソッドを制限する時はprivateを利用できるので注意。

9-1複数のクラスでメソッドを共同利用する

モジュールについて

  • メソッドを共同利用するためのもの
  • (クラスでは作れる)インスタンスを作れない
  • クラスでは「include」メソッドでモジュールを指定することで(モジュールのメソッドをインスタンスメソッドとして)使えるようになる
  • 「extend」メソッドでモジュールを指定すると、extend先のクラスメソッドとして使えるようになる

モジュールの定義

module モジュール名
end

クラスにincludeメソッド

class クラス名
  include モジュール名
end

9-2 モジュールで定義したメソッド・定数をそのまま使う

モジュールにクラスメソッドや定数を定義して、それを呼び出して使うことができる。
定数の呼び出しは以下の形式。(※クラスの場合は「モジュール名.クラスメソッド」)

モジュール名::定数

名前空間

また同じクラス名を複数の場所で使いたい時など、モジュールごとに名前をつけ分けて、クラスを使い分けることができる。
この方法を「名前空間を作る」という。

module CafeA
  class Late
    def self.info
      "美味しいラテ"  
    end
  end
end
module CafeB
  class Late
    def self.info
      "甘いラテ"  
    end
  end
end

puts CafeA::Late.info
puts CafeB::Late.info
# ↑クラスを使い分けてる

9-3別ファイルを読み込む

例えばモジュールとクラスが別ファイル同士であった場合、「require_relative」メソッドを利用して読み込むことで利用できる。

require_relative "ファイル名"

また「require」メソッドを使って読み込むこともできるが、別ファイルの読み込みが目的の時は、「require_relative」メソッドのがおすすめとのこと。

10-1 ライブラリ使い方と管理方法

Rubyには大きく分けて3つのライブラリがある。

  • 組み込みライブラリ:Integer・Array・Hashなど
  • 標準添付ライブラリ:JSONなど(requireメソッド実行で準備)
  • Gem:機能をひとまとめにしたパッケージ

この中のGemについて。複数のGemを管理するのに「bundler」が用いられる。

bundler

bundler自体もgemであり、これを使うことで複数のgemの依存関係を保ちながら管理することができる。コマンドは「bundle」。

bundlerを使うステップは以下。
1. bundlerインストール
2. Gemfileに対象のインストールしたいGemを記載
3. bundle installの実行
4. bundle exec コマンド を実行

$ gem install bundler
$ bundle -v
# bundleインストール確認  

$ bundle init
# Gemfile作成  

# gem記載  

$ bundle install
# gemのインストール

$ bundle exec コマンド
# bundlerでインストールしたgemの実行

3番目のステップ「bundle install」を済ますと、「Gemfile.lock」が作成される。
これはGemfileとセットなので、バックアップの際などは両方保管すること。

  • 「Gemfile」:インストールするgemを記述する
  • 「Gemfile.lock」:インストールされたgemのバージョンと、依存関係が記述されている
    (※自動で作成されるので、編集はしない)

bundle updateでGemバージョンアップ

gemに新しいバージョンが出たら、アップデートするために「bundle update」を実行する。ちなみにこの時、古いバージョンは残されたままになっている。

アップデートすると、通常新しいバージョンのgemが使用されるが、Gemfileに書かれたバージョンを使いたいときは 「bundle exec」コマンドを利用する。 (⇄bundle execなしでは、システム共通のコマンドが実行される)

10-3Webへアクセス!

webページへアクセスするには

「HTTP」「HTTPS」を使う。そのためにRubyの「net/http」ライブラリを使用する。

require "net/http" ←標準ライブラリnet/http読み込み  
require "uri" ←標準ライブラリuri読み込み
uri = URI.parse("https://example.com") ←URIを扱うオブジェクト作成
puts Net::HTTP.get(uri) ←uriオブジェクト渡してHTTP GETメソッドでリクエスト送る

上記は、「Net::HTTPクラス」と「URIモジュール」を使って HTTPリクエス を投げている。

11-1 例外処理

処理がうまくいかなかった場合の処理を書くことができる。

  • 「rescue」節は例外時のみ実行される
  • 「ensure」節を使えば、例外の有無に関わらず実行される処理を書ける
  • もし処理がメソッド内・ブロック内(2.5以降)で行われる場合は、「rescue」 のみ書けばOK(beginとend省略可)  
begin 
  例外が起きる可能性のある処理
rescue (※例外クラス名)  => e
  例外時の処理
ensure
  発生有無関係なし処理
end

# ※例外クラス名は省略可
# rescue~endを「rescue節」という
# 「=> e」をつけると、変数eに例外オブジェクトが代入され取得できる

また例外について調べるため、例外を発生させる 「raise」メソッド もある。

raise (※例外クラス), "例外メッセージ"

# ※例外クラスも指定可能

11-3文字列の調査・置き換え-正規表現 -

文字列含むか判定

文字列の中から特定の文字列を探したい時は「match?」メソッドを使う。

"文字列".match?(/特定の文字列/)
# 「/」で囲まれた「特定の文字列」部分は正規表現オブジェクトであり「パターン」と呼ぶ

"文字列".match?(/特定の文字列\z/)
# 「\z」文字列末尾に、特定の文字列がマッチするかのパターン

"文字列".match?(/\A特定の文字列/)
# 「\A」文字列の先頭に、特定の文字列がマッチするかのパターン

その他

  • 「[文字群]」:書いた文字群のいずれかにマッチ
  • 「.」:「.」の部分が任意の一文字にマッチ
  • 「*」:これより前の文字が0回以上繰り返す時にマッチ

置換

「gsub」メソッドを使う。

"文字列".gsub(置換前, 置換後)

11-4 ブロックについて

ブロックは処理のかたまりをメソッド(eachやmap)に渡すもの。
ブロックを渡されたかについては「block_given?」メソッドで判別できる。渡されたブロックを実行するには「yield」を使う。

渡されたブロックを引数で受け取る

この場合、ブロックを受け取る引数は「&引数」とする。
変数に代入されたブロック(Procオブジェクトとして扱う)を実行するには「call」メソッドを使用する。

【ゼロからわかるRuby超入門2】Ruby 条件分岐、配列

【目次】

3-1 条件判断

比較メソッド

  • 「==」:等しいときにtrue
  • 「!=」:等しくないときにtrue
  • 「(booleanを返すメソッドの場合)末尾に ?」:trueかfalse

3-2条件を満たした時の処理

後置if

「end」を書く必要なし。

条件を満たさないunless(⇄if)

条件を満たさないときに処理をし、満たすときは何もしない

結果を反転する「!」

これがあると、true・falseをひっくり返す。
「!」 は、変数やオブジェクトの前につけること。

x = false  
if !x ←「!x=true」  だからifは処理する。  
unless x ←「x = false 」でunlessは処理する。  

参照:81

3-3条件を満たさないときにも処理する

ifの分岐が2つのときは「else」、3つ以上は「elsif」を使用する。

3-4複数の条件を組み合わせる

または「||」・かつ「&&」

AまたはBの時に処理 / AかつBの時に処理

if A || B
end

if A && B
end

3-5複数の中から1つ選択

ifは2択(true or false)。3択以上になった時。

case

case 変数 ←1つ選ぶ    
when A  
  変数=Aの時の処理  
when B  
  変数=Bの時の処理  
else 合致なしの時の処理  
end

また「case 変数」の変数をなくして「case」のみにすれば、一致以外の条件を書くことができる。(順にwhenの処理して一致したら処理)

3-6繰り返し

繰り返し処理など、重複を避けるプログラムを書く習慣を「DRY」。

決まった数繰返すtimes

「do~end」=「{ }」 は、「ブロック」。処理のかたまりを書ける。

  • 「{ }」:一行のとき
  • 「do~end」:複数行のとき

↑暗黙的なもので、まあどちらでも使えるので注意。

n.times do
  繰り返し  
end

条件を満たしている時に繰り返すwhile

「while~end」の形式でブロックを使わない。

4-1オブジェクトをまとめて扱う

配列は、オブジェクトをまとめて扱うもののこと。また配列自身もオブジェクトであり、そのクラスは「Array」である。

[ ] 
# 空の配列  

numbers = [1, 2, 3]
# 配列を代入する変数は、「複数形」  

menus = ["コーヒー", 300]  
# 種類の異なるオブジェクトを入れてもOK

4-2要素の取得

配列を取得する際、後ろから数えることもできる。
例えば以下の場合、colors[-1]はblue、colors[-2]はpink。

colors = ["pink", "blue"]

また最初と最後の要素を取り出すには、「first」「last」メソッドを使うこともできる。
ちなみにfirst=[0]、last=[-1]。

変数名.first or last

ここまで変数に対して「.メソッド」の形で要素を取り出していたが、直接配列から取り出すこともできる(以下)

["pink", "blue"].first 
# →pinkがでる

4-3配列に要素を追加・削除

追加

  • 「push」「<<」:末尾に要素を追加したいとき
  • 「unshift」:先頭に要素を追加したいとき
colors = ["pink", "blue"]

colors.push["green"]  
colors << ["orange"]
colors.unshift["white"]

# → ["white", "pink", "blue", "green", "orange"]  

削除

  • 「pop」:末尾から要素を削除する
  • 「shift」:先頭から要素を削除する

足し算・引き算もできる

配列同士を足したり引いたりすることで、要素の合計や差分を出すことができ、その要素を持つ新たな配列ができる。

4-4配列の繰り返し

配列.each do |変数名| 
  puts 変数名  
end

途中で終わるbreak

繰り返しの処理を途中で終えるには「break」を利用する。

配列[オブジェクト1, オブジェクト2, オブジェクト3].each do |変数名| 
  break if 変数名 == オブジェクト2
  puts 変数名  
end

# 返ってくるのはオブジェクト1のみ

飛ばして次に進むnext

繰り返し処理中に、ある箇所を飛ばして処理するには「next」
(※繰り返されるブロック内での処理をそこで終わりにし、次回の繰り返しスタート)

上記の場合だと、取得できる要素は[オブジェクト1, オブジェクト3]である。

範囲指定のRangeオブジェクト

「1~3まで」のように範囲を表すオブジェクトを「Range」という。
書き方は (1..3) のようになる。

5-1配列の便利なメソッド

要素の数sizeメソッド

配列.size
# 要素の数を返す  

配列の合計値sumメソッド

配列の全要素の合計値が出したければ、「sum」メソッドを使う。(ruby2.4~)
sumは配列の中身が小数クラスFloatであれば、Floatが返ってくる。

なお配列の中身が整数オブジェクトであれば、sizeもsumも整数オブジェクトが返ってくる。これで小数の計算をしたければ、小数に変換する「to_f」メソッドをさらに書き加える必要がある。(これをメソッドチェインという)

配列.size.to_f  

5-2メソッドの機能

uniqとuniq! 2種類のメソッドについて

「uniq」はもともと重複した要素を消した配列を返すメソッド。これに!がつく「uniq!」は、同じように重複要素を排除した配列を返すものだが、以下のような違いがある。

array1 = [1,1,2]
array2 = array1.uniq
# array1 = [1,1,2]、array2 = [1,2]
# 「uniq」を使うと、2種類のオブジェクトができる。  

array1 = [1,1,2]
array2 = array1.uniq!
# array1 = [1,2]  =  array2 = [1,2]  
# 「uniq!」を使うと、オブジェクトは1種類になり、変数名だけ異なる状態となる。  

uniq!のような「!」は、「オブジェクトを破壊的に変更する」ものが多い。

5-3 ランダムなメソッド?sample、shuffle

ランダムというキーワードに当てはまるメソッド2選。

  • 「sample」:配列の中からランダムに1 要素取得する
  • 「shuffle」:ランダムに配列を並び替える

5-4要素の並び替え

順に並べるsortメソッド

  • 要素が数値:数字の小さい順
  • 要素が文字列:abc順("cba".sortは×)
  • 要素が文字列で大文字小文字:大文字→小文字順

逆順にするreverseメソッド

配列の要素を逆順にする。もしsort(小さい順)を逆(大きい順)にしたければこれらを組み合わせれば良い。

配列.sort.reverse

5-5 配列と文字列を組み合わせる

文字列を連結するjoinメソッド

配列の中の文字列を連結することができる。返ってくるのは「文字列」。

["A", "B", "C"].join
# ABC  

["A", "B", "C"].join("&")  
# A&B&C のように、joinの引数を間に入れ込んで連結する  

文字列を分割するsplitメソッド

文字列の中の文字ごとに分割する。返ってくるのは「配列」。

"A B C".split  
# ["A", "B", "C"]  

"A&B&C".split("&")  
# ["A", "B", "C"]

5-6各要素を変換する

各要素を変換して配列を作るmapメソッド

各要素を変換処理後、それらをもつ新しい配列を作成。
また要素を他の種類のオブジェクトへ変換することもできる。

numbers = [1,2,3].map do |変数名|
  変数名 * 3  
end
p numbers
# [3,6,9]が返ってくる  

numbers = [1,2,3].map {|変数名| 変数名 * 3}  
p numbers
# 上記を短くしたver  

またmapメソッドのような、要素に対してあるメソッドを呼び出すだけの場合、もっとシンプルに書くことができる。

numbers = ["123","234"].map(&:reverse)
p numbers

mapとeachについて

ブロックを渡して各要素に処理を行う似たような処理を行うが、目的が異なる。

  • 「each」:各要素にブロックで処理を行うことが目的
  • 「map」:各要素を変換して、新しい配列を作ることが目的

のことが多い。

Rubyインストール・ゼロからわかるRuby超入門1

【目次】

Rubyインストールの手順

rubyのインストールには以下の点より、rbenvを使う。

  • 複数のバージョンの切り替えができる
  • 複数のアプリで異なるバージョンのRubyの使い分けができる

またこのrbenvのインストールには、パッケージマネージャのhomebrewを使うのでまずはそれからインストールをする。なお私は以前入れているので、インストールを確認をした。

$ brew doctor
# 「Your system is ready to brew.」であればOK

rbenvのインストール

homebrewがインストールできたらrbenvのインストールを行う。私はrbenvも以前入れているので、その確認を行なった。

$ brew list --versions rbenv
# homebrew rbenvのバージョンを表示  

または

$ rbenv -v  
# バージョン表示されたらOK

なお$ brew listだとhomebrewで管理しているインストール済みパッケージの一覧が表示される。

ちなみにrbenvインストールに際して、パスを通す必要があるので確認しておく。 編集は $ vim ~/.bash_profile

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
# 上記を追記
# if~という記述は、rbenvが確実にあれば必要なし

$ source ~/.bash_profile 
# 再読み込み

rbenv補足

rbenvでインストールするrubyは、ruby-buildで提供されている。 ruby-buildを更新することでrubyのバージョンの一覧を更新できる。

$ brew update
$ brew upgrade ruby-build

$ ruby-build --version
# 現在のバージョン確認  

※ちなみにruby-build

ruby-buildはrbenvのプラグインで、自動でrubyをビルドするもの。

いよいよrubyインストール

まずは公式サイトで最新バージョンを確認する。

確認できたらそれをインストール。

$ rbenv install -l  
# インストールできるrubyのバージョン一覧をこれでも確認できる    

$ rbenv install <バージョン>

$ ruby -v  
# 確認

$ rbenv versions  
# 管理されてるrubyのバージョン一覧を確認  
# ※この時表示される「sytem」はホストOSにインストールされたrubyのこと  

また実行されるrubyのパスやgemのインストール先の詳細は$ gem environmentで確認できる。

rubyのバージョンを切り替える

バージョン切り替えには、ディレクトリのみの設定orデフォ設定の2種類がある。

$ rbenv local <バージョン>
# 実行したディレクトリ配下で使うrubyのバージョンを変更  
# 指定バージョンの .ruby-version が作成される  

$ rbenv global <バージョン>  
# デフォルトで使うrubyのバージョンを変更

$ rbenv local --unset   
# ローカルバージョン指定の取消し  

上記の通り、アプリごとに異なるバージョンのrubyを利用したい場合は、各ディレクトリでrbenv localを実行して、rubyのバージョンを指定。

ちなみにこれらのコマンドを実行すると、現在のディレクトリに 「.ruby-version」 というファイルが作成される。これは自動で使用するrubyのバージョンを変えるもの。

その他:openssl

opensslはhttpsを使用するためのパッケージ。

$ which openssl
$ brew list openssl  
$ openssl version

参考:Mountain Lion に rbenv を導入

ゼロからわかるRuby超入門の学習

2-3オブジェクト

オブジェクトはデータを持ってたり、操作対象になる「もの」。 クラスはオブジェクトの種類。(整数オブジェクト=Integer)

2-2文字列⇄整数

3…整数オブジェクト/ 0.3…小数オブジェクト

オブジェクトに対して何かする型のメソッドは、大抵 「オブジェクト.メソッド」

puts 3.to_s + "3"  
# 「to_s」整数→文字列  

puts 3 + "3".to_i  
# 「to_i」文字列→整数

2-3式展開

文字列に計算結果を埋め込むときに使う記法。 #{ }

puts "1 + 2は#{1 + 2}"

ここで登場したメソッド

メソッド 意味
gets キーボードで入力した値を実行する
chomp 末尾の改行文字を取り除く

2-4コメントする

# 基本はこれ  

=begin
長文の場合は
これ
=end

2-5 irb

入力したプログラムを一行ずつすぐ実行できるもの。これを使うことでコマンドの世界でRuby言語を使えるようになる。

irb
# 起動  

exit
# 終了  

binding.irb
# プログラムを一時停止したい位置に書く
# 実行例は以下
    1: require "irb"
    2: # ruby2.5以降は省略可  
    3: a = 1
 => 4: binding.irb
    5: puts a

irb(main):001:0> a
=> 1

2-6デバッグ

デバッグ は問題が起こって動かない場所の原因を調べて正すこと。 pメソッドを利用。pの後ろに書いた変数やオブジェクトを画面に表示する。

参考

参考:ゼロからわかるRuby超入門
参考:現場で使えるRuby on Rails5 速習実践ガイド
参考:rbenvの役割
参考:OS X で rbenv を使って ruby 1.9.3 or 2.0.0 の環境を作る
参考:複数のバージョン管理も楽々!rbenvを利用したruby管理方法チュートリアル
参考:今さらだけどHomebrewのコマンドをちゃんと理解して使おう
参考:いまさらだけどGitを基本から分かりやすくまとめてみた

プルリクに関して

【目次】

Pull Request

同じリポジトリを共有しその中で行うPR

PRされたものを、ローカルで動作確認したければ以下。 (※特に他人のPRを受けた時のようなブランチが存在していない場合)

$ git fetch  
# 変更を取得  

$ git branch -a 
# ブランチを確認
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/update-readme

$ git checkout -b update-readme origin/update-readme  
# チェックアウト・動作確認

参考:GitHub初心者はForkしない方のPull Requestから入門しよう

github 空のPRの作り方

作業を始めるにあたり、初めにプルリクエストを作る。PRには何かしらのcommitが必要。それに際して 空のcommit を送ることでPRをスタートする方法がある。

# git clone <URL>
# git checkout -b <ブランチ名>  

$ git commit --allow-empty -m "PRのタイトル"    
# 空のコミット  

$ git push origin <ブランチ名> 
# リモートブランチに push
# ※まだリモートブランチに紐づいていない  

$ git branch -u origin/<リモートブランチ名>  
# リモートブランチと紐付け

$ git branch -vv  
# ローカルブランチがどのリモートブランチと紐づいてるか確認

参考:github で 空のプルリクエストを作る手順

※上記について追記。

$ git push origin <ブランチ名> 
# リモートブランチに push
# ※まだリモートブランチに紐づいていない  

$ git branch -u origin/<リモートブランチ名>  
# リモートブランチと紐付け

↑これを書いていた時、リモートブランチってなんだ?master? 前チーム開発の時やってなかったような?と、まとめながら気になった。 そこで知人に質問し、整理した結果

  • リモートブランチと紐づけ=上流ブランチ設定(指定)
  • $ git push origin <ローカルブランチ名>=リモート追跡ブランチ作成

ローカルブランチとリモート追跡ブランチを紐づけることでgit pushだけでpushできるようになる。ので、$ git branch -u origin/<リモートブランチ名> はマストではないということ。

参考:Gitのリモート追跡ブランチ・追跡ブランチ・上流ブランチ

PR前のチェックリスト

以下は読みながらこちらを書き出した。
参考:初心者がRailsプロジェクトへの初PRする前に見るチェックリスト

  • Files changedを確認
    PRを作ったら必ず確認すること。

  • lintが通っているか
    rubyだったらrubocop、jsだったらeslintを通すこと。

  • ファイルの末尾に改行が無いか
    自動設定にしておくこと。

  • 同じコミットログが続いていないか・英語/日本語になってないか・雑でないか
    言語は統一した方が良い。プロジェクトのルールに従う。後から見たときにわかりやすいよう意識する。

  • コミットしたユーザーアイコンがOctcatになっていないか
    gitクライアントに設定したメアドがGitHubのユーザーのメアドと違う場合に起こる。 他の人から見ると誰だこいつとなるので注意。

  • 無意味なファイルがないか
    ジェネレータなどが作成した中身のないファイル(module・test・fixturesなど)は消すこと。そのファイルの意味をきちんと調べる。

  • gemのgroupを確認

  • 不要なrespond_to
    scaffoldなどでできる不要なrespond_toやformatを消すこと。

  • リファクタリング」を多用しない
    リファクタリングはプログラムの振る舞いを変えずに内部構造を変えること。

  • 秘密情報がコミットされていないか

    oauthのsecretとか。コード中では環境変数にしておこう。 これをやると、gitで過去を修正したとしてもGitHubのキャッシュに残ってしまい、完全に消すにはGitHubのサポートに連絡するとか面倒なことになる。

  • .gitignoreは適切か
    特定の環境の人向けのファイルは.gitignoreに書かず、自分のマシン固有の設定に書くこと。(.DS_Storeはmacだけのファイルみたいな)

  • 大量の依存gemがコミットされていないか

    gemのインストール場所をvendro/bundleとかにしてあって、その中にある大量のgemのファイルがコミットされてしまっていないか確認

  • マジックナンバーが含まれていないか

  • メソッドが長すぎないか

GitHubへのアクセス

一般的にはsshより、httpsでのアクセスが推奨されているのでそちらを使うこと。
(理由はhttpsの方が負荷分散ができ、GitHub的に都合が良いため)

  • GitHubへのアクセス(ログイン)はより安全な2要素認証を使う。(設定済み)

2 要素認証の有効化後は、GitHubコマンドラインからアクセスする際にPWの代わりに個人アクセストークンor SSH キーを使わなければいけない。

Terminalから個人アクセストークンでアクセス

httpsアクセスで認証時のPW入力の際、取得したアクセストークンを貼り付け使用する。

Githubの基本理解

【目次】

関連gitのコマンド(?)

$ git init
//フォルダをGitリポジトリとして初期化する

$ git fetch --dry-run  
// Pullする前にリモート上で行われた変更を見る

$ git pull <リモートリポジトリ名> <ブランチ名>
// 変更をPullする

$ git remote -v
// remoteの設定を確認する

$ git push <リモートリポジトリ名> <ブランチ名>
// 変更をPushする

$ git fsck --full  
// リポジトリの正当性チェック  

$ git stash  
// 現在の作業ツリーの状態を一時的に保管  
// 作業中の状態をコミットせず、他ブランチで作業したい時など

$ git stash list  
// 一時保存している作業リストの確認 

$ git stash pop   
// 一時保存したものを再度呼び出す  

fork

リポジトリをフォークすると、自分のGitHub内にそのリポジトリのコピーができ、remoteリポジトリの1つとして使える。 フォーク後は、 clone (コピー) してGitHubからローカルへ。

$ git clone <URL FROMGITHUB>  

元のリポジトリに変更が加わった際、その変更もpullできる別のremoteを設定する。
元のリポジトリupstreamという名前をつけることが多い。

$ git remote add upstream <元のリポジトリのURL>

ローカルでマージする

プルリクがマージされたら、 変更を自分のフォークバージョンにもアップデートするために、リポジトリのメインブランチにマージする。

$ git checkout <マージしたいブランチ名>
// マージしたいブランチ(メインブランチ)へ

$ git merge <取り込みたいブランチ名>  
// 作業してた取り込みたいブランチをマージ

$ git branch -d <ブランチ名>
// 作業してたブランチ削除

$ git push <リモートリポジトリ名> --delete <ブランチ名>
// GitHub上にあるリポジトリからも作業してたブランチ削除

git pullとgit pull --rebaseの違いについて

  • git pull:git fetch + 「git merge」

  • git pull --rebase:git fetch + 「git rebase」

git pull --rebaseを使うと、マージコミットが作られない(その分履歴も綺麗にはなる)

なお、git rebaseについては33・34日目にまとめてある。

その他参考:git pull

改めてgit fetchについて

※33日目の日報ではfetchについて以下のようにまとめた。

マージせず、単にリモートリポジトリの内容を確認したい時に使用。 実行するとリモートリポジトリの最新の履歴の取得だけを行い、取得したコミットは、名前の無いブランチとして取り込まれる。(※ブランチはFETCH_HEADでチェックアウトできる)

git fetchでリモートのコピーをローカルにダウンロードしてくる。この際コピーは、 ローカルのリモート追跡ブランチ(リモートのコピー置き場)にコピーされるのでワーキングツリーに影響なし。

手順は以下。

  • リモートのコピーを要求
  • ローカルとの差分を確認。リモートリポジトリが変更や新規ブランチをリモート追跡ブランチに渡す
  • リモート追跡ブランチが更新される

リモート追跡ブランチ

リモートのmasterブランチを追跡するもの。このブランチの内容確認や、ローカルブランチへのマージはorigin/ブランチ名でアクセス。

※masterブランチ:ローカルの中心となる「統合ブランチ」
※origin/masterブランチ:ローカルにある「リモート追跡ブランチ」

参考:git fetch

gitignore

.gitignoreはバージョン管理をしないファイルを指定(記載)するために作成する。
→しかしいちいち追加するのが面倒くさい場合、グローバルで管理する方法がある。

.gitignore_global
参照記事はこちら。大まかな流れは以下。(※「.gitignore_globalに追記」する内容は参照記事で確認)

$ git config --global core.excludesfile ~/.gitignore
// グローバルの.gitignoreファイル作成  

// .gitignore_globalに追記  

$ git config --global core.excludesfile ~/.gitignore_global
// ファイルの有効化

参考:Gitが面白いほどわかる、基本の使い方33(70~71)

configの下に gitignoreの設定を置く

よくグローバルな設定をする際、上記(取り消し線箇所)のような.gitignore_globalの設定をする記事を見かけるが、以下のように設定することで、excludefilesを指定しなくてもよくなった。

記事まだ .gitconfig に core.excludesfile を設定しているの?を教えてもらいました!

特別な理由が無い限り、 $HOME/.config/git/ignore にグローバルな設定を置くのがgitの流儀となります。

入れておくと便利なtig

コンソール上で使えるgitブラウザ。git logのような感じだけど、addやcommitもできる模様。

  • $ brew install tigでインストール
  • Ctrl+Cで終了

参考:tigでgitをもっと便利に! addやcommitも

その他参考サイト

Gitの基本理解

【目次】

gitの基本

ブランチの統合

「今いるブランチに別のブランチの内容を取り込む」には、mergeを使う方法と・rebaseを使う方法の2種類ある。

  • merge
    変更内容の履歴はそのまま残るが、履歴が複雑になる。
  • rebase
    過去のコミット履歴を書き換える操作。リポジトリ全体の状態を変えてしまうことがあるので、原則的にはプッシュ前のコミットについてのみ使うことにするのが良いかも。 競合箇所を修正した場合、--continueオプションを指定して実行(※コミットではない)

参考:サルでもわかるGit入門 ブランチの統合

git rebase

rebaseのイメージは「branchが生えている場所(コミット)を変更する」
作業中のブランチにgit rebase masterした場合、作業中のブランチにあるコミットを一時的に保存し、リベース先(master)のブランチに git reset --hard する。(→masterと同じ状態にする)
リセットした後、保存してたコミットを作業中のブランチの上にのせる形になる。
このサイトリベースで何が起きた?がわかりやすい

⚠️注意点

リベースは特定のコミットをどこか別のコミットの後ろに移動するだけの作業に見えるかもしれませんが、実際は移動ではなく、新規コミットを作っているので、当然コミットIDも変わります。したがって、他の開発者のローカルにあるコミットをリベースしちゃうと、コミットIDが変わり、すでに存在している同じコミットと区別がつかなくなり、重複してしまいますよね。 ですから、他人のコミットを決してリベースしてはいけないのです。

参考:git rebase とは
参考:git reset (--hard/--soft)ワーキングツリー、インデックス、HEADを使いこなす方法

git実践編

$ git branch -d <ブランチ名>
# ブランチ削除  

$ git branch  
# 確認  

$ git tag <タグ名>    
# タグを追加  

$ git tag -a <タグ名>
# 注釈付きタグ  

$ git tag  
# 確認  

$ git log --decorate  
# タグ情報を含んだ履歴を表示  

$ git tag -d <タグ名>  
# タグ削除  

fetch

マージせず、単にリモートリポジトリの内容を確認したい時に使用。
実行するとリモートリポジトリの最新の履歴の取得だけを行い、取得したコミットは、名前の無いブランチとして取り込まれる。(※ブランチはFETCH_HEADでチェックアウトできる)

pull

pullというのは内部でfetch + merge

発展編 コミット書換え

git commit --amend

直前のコミット修正。上書きコミット。
同じブランチの直前のコミットに対して、内容の追加・コメント修正ができる。
利用シーン:コメント修正、コミット漏れしたファイルを追加など

revert

打ち消し。ある特定のコミットだけをなかったことにしたい時に利用。過去に行なった作業の「逆を行う作業」を新たに行なってコミットする。

そのため訂正の経緯が新しいコミットとして記録され、ブランチには過去のコミットが全て残った状態となる。他ブランチとのマージの際も問題が起こらない。

$ git log

$ git revert [打ち消しコミット]  

参考:Gitが面白いほどわかる、基本の使い方33(140~142)

reset

resetについてよくわからなかったので調べた。

git reset コマンドは、checkout中のブランチを指定コミットに紐づけ直すという動作をします。

このサイトの説明がわかりやすかった!
git reset 解説

git resetの3つのオプション

こちらのサイトの説明がわかりやすかった!
2. git resetを使いこなす

  • reset --soft:commitのみ 取り消す(順番間違えたときとか)
  • reset --mixed:commitadd 取り消し
  • reset --hard:commitaddファイル変更 全て取り消す
$ git reset --soft HEAD^
// 直前のコミット取り消し(コミットのみ)  

$ git reset --hard HEAD^  
// 直前コミットまるっと取り消し

$ git reset --hard HEAD  
// コミット後の変更 全削除  

リセットは「ブランチの状態を過去のある時点に巻き戻す」ことのため、中央リポジトリのコミットが残っている場合、リセット前にコミットした分先行きした状態となり、プルするとリセット分が復活してしまうこともある。

またreset前のコミットはORIG_HEADで参照。間違えてresetした場合、ORIG_HEADにresetし、reset前の状態に戻す。

$ git reset --hard ORIG_HEAD

【過去の状態に戻す機能3種まとめ 】

checkout

  • HEADの指すブランチを変更
  • 作業ファイルの状態を変更する機能

revert

  • 指定したコミットで行なった変更の「逆の作業」を行なったことにして、過去の作業を打ち消す

reset

  • ブランチの状態を過去のある時点に巻き戻す
  • ブランチの指すコミットを変更
  • ブランチの状態を変更する機能

参考:Gitが面白いほどわかる、基本の使い方33(132~137)

打ち消し(revert)かリセットか?

過去の作業内容に間違いがあり訂正したい時は「打ち消し」を利用するのが適切。

「リセット」はローカルリポジトリ専用の作業ブランチ(masterとか中央リポジトリに影響しない)などで、ブランチ内容の書き換えが必要な時などに使うと良い。

参考:Gitが面白いほどわかる、基本の使い方33(142)

プルリクエスト編

コンフリクトが起きた際

手動でマージする。ここを参照
ざっくりまとめると以下の流れ。

  • 作業中のブランチに、プルリクをプルしてもらう対象のブランチをマージする。
  • ローカルで競合を確認し、修正する。
  • 再度コミット&プッシュ

参考

nginx オレオレ証明書/Let's EncryptでSSL証明書

【目次】

オレオレ証明書を作る

SSL証明書を作る。なぜオレオレかというと、本来別物の「サーバ管理者」と「認証局」の2役を自分でやるから。

手順

  • サーバ管理者が秘密鍵ファイル(server.key)を作成
  • サーバ管理者が秘密鍵ファイルから、公開鍵(Public Key)と秘密鍵のハッシュを組合わせ、証明書署名要求ファイル(server.csr)を作成、認証局に送付。
  • 認証局は自分の秘密鍵で証明書署名要求ファイルに署名し、サーバ証明書(server.crt)を作成し返却。
    (認証局が自分の秘密鍵でサーバの公開鍵を署名している)

CSR作成時にできたサーバの秘密鍵は、サーバ管理者が保持。

対象 ファイル名
秘密鍵 (Private Key) server.key
証明書署名要求 (CSR) server.csr
サーバ証明書(CRT) server.crt

server.key (秘密鍵) ・ server.csr (証明書署名要求)・ server.crt (サーバ証明書)
各種の保存先は/etc/nginx配下にした。

さっそく作業をしていく。

$ openssl genrsa 2048 > server.key
 # 秘密鍵作成

$ openssl req -new -key server.key > server.csr 
# 証明書署名要求(CSR)の作成


# 情報をいろいろ入力  
# この際Common Name (e.g. server FQDN or YOUR name) []: には  
# Virtual Hostのドメイン名を入れること!


$ openssl req -text < server.csr
 # 作成されたserver.csrの中身を確認


$ openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crt
# CSRに署名、サーバ証明書(CRT)作成
# getting Private keyと出る  

$ openssl x509 -text < server.crt 
# 作成されたserver.crtの中身を確認

$ sudo vim /etc/nginx/sites-available/XXX.work 
# Virtual Hostの設定ファイル修正

Virtual Hostの設定ファイルを修正。

server {
    listen 443 ssl;
    server_name www.XXX.work  XXX.work ;
    ssl on;
    ssl_certificate /etc/nginx/server.crt;
    ssl_certificate_key /etc/nginx/server.key;
    access_log /srv/XXX.work /log/access.log;
    error_log /srv/XXX.work /log/error.log;
      location / {
        root /srv/XXX.work /public/;
        index index.html index.php;
    }
}
  • /etc/nginx/server.crtはCRTの置き場のこと。
  • /etc/nginx/server.keyはkeyの置き場のこと。

これで設定は完了。
あとはnginxを再起動させる前に、文法チェック。

$ sudo nginx -t  
# 設定ファイルが正しい文法で書けているか確認  

$ sudo service nginx reload   
# nginx.confを再読込  

これでhttps://www.XXX.workにアクセスできればOK
オレオレSSLのため、この段階だと警告が出る。

f:id:chiroru_memo:20200309144051p:plain
警告

警告なくすぞ!Let's EncryptでSSL証明書を作る

オレオレ証明書の警告をなくすため、SSL証明書を取得する。
Let's Encryptは無料なのでそちらを利用。ちなみにLet's Encryptは、HTTPSの普及のために無料で証明書を発行してくれるCA。

certbotをインストール

SSL証明書の発行にはcertbotを利用するので、まずはこちらをインストール。
参考:Certbot

$ sudo apt-get install certbot python-certbot-nginx  

$ sudo certbot certonly --nginx  
# 証明書の取得(certonlyなしだと、同時にnginx confを自動編集する)  

$  sudo certbot renew    
# 証明書を自動更新する  

HTTPS通信の設定

httpsで表示されるように設定する。

まずは/etc/letsencrypt/live/XXX.work #ls -lで発行された証明書たちを確認する。

f:id:chiroru_memo:20200309232541p:plain
証明書たち確認

ファイル名 正体
cert.pem 証明書
chain.pem 中間証明書
fullchain.pem 証明書+中間証明書の連結ファイル
privkey.pem 秘密鍵

これらのうち、confファイルには
ssl_certificate:証明書+中間証明書の連結ファイル(fullchain.pem)
ssl_certificate_key秘密鍵(privkey.pem)
を設定する。

$ sudo vim etc/nginx/sites-available/XXX.work でファイルを編集する。

server {
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/XXX.work /fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/XXX.work /privkey.pem;
  server_name www.XXX.work  XXX.work ;
  access_log /srv/XXX.work /log/access.log;
  error_log /srv/XXX.work /log/error.log;
  location / {
    root /srv/XXX.work /public/;
    index index2.html index.php;
    }
}

server {
  listen 80;
  server_name www.XXX.work ;
  access_log /srv/XXX.work /log/access.log;        
  error_log /srv/XXX.work /log/error.log;
  location / {
    root /srv/XXX.work/public/;
    index index.html index.php;
  }
}

再起動してhttps://www.XXX.workが見られるようになっている! (URLのとこにも鍵マークがついている!)

参考サイト

参考:プログラミングビギナーNekoteniがあなたに贈る!NginxでSSLの巻

参考:オレオレ証明書をopensslで作る(詳細版)

参考:Certbot

参考:SSLの暗号化通信のしくみ