娯楽開発

娯楽開発

開発は娯楽。遊び心で開発をすすめるブログ。

Ruby初心者によるRuby初心者のためのRuby基礎

Rubyはいろいろ柔軟すぎてまったくコードが読めなかったので備忘録も兼ねてざっと整理してみました。

まだRubyRailsを触り始めて2〜3週間程度なのでなにか間違っていた場合はご指摘お願いします。

※ちょくちょく余談で深めな部分に言及してますがあまり気にしないでください。

文字列

  • ダブルクォート(")、シングルクォート(')どちらでも括れる
  • シングルクォート(')では変数が文字列展開されない
  • カラ文字はカラ文字扱い
>>  "foo"
=> "foo"
>>  'foo'
=> "foo"
>>  ""
=> ""
  • +で結合できる
>>  "foo" + "bar"
=> "foobar"
>>  "foo" + ""
=> "foo"

変数

変数の初期化

  • 宣言 -> 必要なし。どこでも使い始められる。
  • 型の指定 -> 必要なし
  • 数値、文字列ともに代入可能
  • 命名規則 -> 小文字のみを使う。単語は_で繋ぐ(snake_case)
#変数の宣言、型の宣言は必要なし
#代入と共にいきなり使える
>> valu = 1
=> 1
>> char = "foo"
=> "foo"

変数の文字列展開

  • #{変数名}でダブルクォート内(" ")でも格納している文字列を展開できる
  • シングルクォート内(' ')では展開できない
  • 「#{変数名}」を出力したい場合は'#{変数名}'もしくは"\#{変数名}"
>> char = "foo"
=> "foo"
>> char + "bar"
=> "foobar"
>> "char" + "bar"
=> "charbar"
>> "#{char}" + "bar"
=> "foobar"
>> "#{char}bar"
=> "foobar"
>> '#{char}bar'
=> "\#{char}bar"
>> "\#{char}bar"
=> "\#{char}bar"

変数のスコープ

>> def puts_name
>>   name = "Tanaka Taro"
>>   puts name
>> end
=> :puts_name
>> puts_name
Tanaka Taro
=> nil
>> puts name
Traceback (most recent call last):
        1: from (irb):11
NameError (undefined local variable or method `name' for main:Object)

メソッド内で初期化された変数は初期化されたメソッド内からしか呼び出せない。

上の例ではputs_nameメソッドで初期化された変数nameputs_name内では呼び出せるが、puts_name外から呼び出そうとするとエラーになる。

※余談

  • printメソッドやputsメソッドでは"\n"が改行を意味する
  • 「\」もしくは「''」で普通表示されない特殊文字を表示できる
>> print "foo"
foo=> nil
>> print "foo\n"
foo
=> nil
>> print "foo\\n"
foo\n=> nil
>> print 'foo\n'
foo\n=> nil
>> puts "foobar"
foobar
=> nil
>> puts "foo\nbar"
foo
bar
=> nil
>> puts "foo\\nbar"
foo\nbar
=> nil
>> puts 'foo\nbar'
foo\nbar
=> nil

 配列

 配列の基本

  • 変数同様宣言や型の指定は必要ない
  • 配列の中にどんなオブジェクトも格納可能
    • 数値や文字列、nilを同時に格納可能
  • []Array.newで初期化できる
  • 要素への参照は要素番号(0~)を指定
>> []  #中身のないカラの配列
=> []
>> Array.new  #ArrayはArrayクラスのオブジェクト
=> []
>> [] == Array.new
=> true
>> array = [1, 2, "three", 4, "five", nil]
=> [1, 2, "three", 4, "five", nil]
>> array[0]
=> 1
>> array[2]
=> "three"
>> array[5]
=> nil

 配列の大きさ取得

  • 配列の大きさはlengthもしくはsizeで取得
>> array = [1, 2, "three", 4, "five", nil]
=> [1, 2, "three", 4, "five", nil]
>> array.length
=> 6
>> array.size
=> 6

 配列の各要素への繰り返し処理

  • eachもしくはmapを使う
  • 処理の書き方は{}もしくはdo-end
>> array = [1, 2, "three", 4, "five", nil]
=> [1, 2, "three", 4, "five", nil]
>>
>> # {}を使った記述
>> array.each{ |value| puts "value = #{value}"}
value = 1
value = 2
value = three
value = 4
value = five
value = nil
=> [1, 2, "three", 4, "five", nil]
>>
>> # do-end を使った記述
>> array.each do |value|
>>   puts "value = #{value}"
>> end
value = 1
value = 2
value = three
value = 4
value = five
value = nil
=> [nil, nil, nil, nil, nil, nil]

 ※余談

eachmapの違い

each

処理1

>> def hoge
>>   (1..10).to_a.each do |i|
>>     unk = i + 1
>>   end
>> end
=> :hoge
>> ihr = hoge
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

処理2

>> array = [1, 2, 3, 4, 5]
>> i = 0
>> array.each do |value|
>>   puts "value = #{value}"
>>   puts "i     = #{i}"
>>   i = value + 1
>>   puts "i     = value + 1"
>>   puts "i     = #{i}"
>>   puts"-------------------"
>> end
value = 1
i     = 0
i     = value + 1
i     = 2
-------------------
value = 2
i     = 2
i     = value + 1
i     = 3
-------------------
value = 3
i     = 3
i     = value + 1
i     = 4
-------------------
value = 4
i     = 4
i     = value + 1
i     = 5
-------------------
value = 5
i     = 5
i     = value + 1
i     = 6
-------------------
=> [1, 2, 3, 4, 5]

参考:each (Array) | Rubyリファレンス

参考:rubyのeach, mapの違い

eachメソッドは、配列の要素の数だけブロックを繰り返し実行します。繰り返しごとにブロック引数には各要素が順に入ります。戻り値はレシーバ自身です。

map

処理1

>> def huga
>>   (1..10).to_a.map do |i|
>>     unk = i + 1
>>   end
>> end
=> :huga
>> ihr2 = huga
=> [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

処理2

>> array = [1, 2, 3, 4, 5]
>> i = 0
>> array.map do |value|
>>   puts "value = #{value}"
>>   puts "i     = #{i}"
>>   i = value + 1
>>   puts "i     = value + 1"
>>   puts "i     = #{i}"
>>   puts"-------------------"
>> end
value = 1
i     = 0
i     = value + 1
i     = 2
-------------------
value = 2
i     = 2
i     = value + 1
i     = 3
-------------------
value = 3
i     = 3
i     = value + 1
i     = 4
-------------------
value = 4
i     = 4
i     = value + 1
i     = 5
-------------------
value = 5
i     = 5
i     = value + 1
i     = 6
-------------------
=> [nil, nil, nil, nil, nil]

参考:map, map! (Array) | Rubyリファレンス

参考:rubyのeach, mapの違い

mapメソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作成して返します。collectメソッドの別名です。

eachでは配列の要素(処理1のi, 処理2のvalue)を返す。処理1では配列の要素iを返し、処理2ではvalueを返す。いずれの処理においても処理内で要素自身を更新していないため処理後に返る値は入力された配列のまま。

一方mapではブロックの戻り値を返す。処理1ではhogeメソッドが返す値unkを返し、処理2ではブロックをメソッド化していないためブロックは値を返さない。よって処理1では元の配列に1が足され、処理2ではnilが返る。

ちなみにmapはどうやらメソッドの最後に評価した値を返すようで、上記処理2の例ではputs "-------------------"の評価値を返している。putsnilを返すため、配列はnilが入った状態で返ってくる。 よってmap処理の最後の行にj = 1という処理を追加した場合、返る配列は以下のように[1, 1, 1, 1, 1]になる。

>> array = [1, 2, 3, 4, 5]
>> i = 0
>> array.map do |value|
>>   puts "value = #{value}"
>>   puts "i     = #{i}"
>>   i = value + 1
>>   puts "i     = value + 1"
>>   puts "i     = #{i}"
>>   puts"-------------------"
>>   j = 1
>> end
...
...
(省略)
...
=> [1, 1, 1, 1, 1]

メソッド

メソッドの定義

  • クラス内で定義されたメソッドはそのクラスから作成されたオブジェクト(インスタンス)に対してのみ使用できる。
  • 引数の()は省略可能
def メソッド名(引数1, 引数2, ..., 引数n)
  実行する処理1
  実行する処理2
  ...
end

メソッドの呼び出し

  • オブジェクトに続いて.で繋ぐことで、そのオブジェクトのクラスで定義されているメソッドを呼び出すことができる。
  • 引数の()は省略可能
メソッド名(引数1, 引数2, ..., 引数n)
メソッド名 引数1, 引数2, ..., 引数n

オブジェクト名.メソッド名(引数1, 引数2, ..., 引数n)
オブジェクト名.メソッド名 引数1, 引数2, ..., 引数n
  • メソッド命名規則
    • 一般的に全て小文字
    • 単語間は_で繋ぐ(snake_case)
>> def sum_puts(num1, num2)
>>   puts(num1 + num2)
>> end
=> :sum_puts
>> sum_puts(1, 2)
3
=> nil
>> sum_puts 1, 2
3
=> nil
  • メソッドの定義位置はメソッドの呼び出し前
  • 定義前に呼び出すとエラーになる
>> sum_puts(1, 2)
Traceback (most recent call last):
        1: from (irb):1
NoMethodError (undefined method `sum_puts' for main:Object) 
>> def sum_puts(num1, num2)
>>   puts num1 + num2
>> end
=> :sum_puts
>> sum_puts(1, 2)
3
=> nil

※余談

値渡しと参照渡し

要はrubyではメソッド引数での値の渡し方は値渡しである、ということ。

値渡しと参照渡しについては以下の記事が詳しく解説している。

参考:値渡しと参照渡しの違いを理解する | Rubyist Magazine

簡単にサンプルコードを書いてみた。

>> def sample(num_method)
>>   i = num_method
>>   puts "i = num_method"
>>   puts "---------------------"
>>   puts "num_method    = #{num_method}"
>>   puts "i             = #{i}"
>>   puts "---------------------"
>>   puts "num_method id = #{num_method.object_id}"
>>   puts "i id          = #{i.object_id}"
>>   puts "---------------------"
>>   i = i + 1
>>   puts "i = i + 1"
>>   puts "---------------------"
>>   puts "num_method    = #{num_method}"
>>   puts "i             = #{i}"
>>   puts "---------------------"
>>   puts "num_method id = #{num_method.object_id}"
>>   puts "i id          = #{i.object_id}"
>>   puts "---------------------"
>>   num_method = num_method + 3
>>   puts "num_method = num_method + 3"
>>   puts "---------------------"
>>   puts "num_method    = #{num_method}"
>>   puts "i             = #{i}"
>>   puts "---------------------"
>>   puts "num_method id = #{num_method.object_id}"
>>   puts "i id          = #{i.object_id}"
>> end
=> :sample
>> num = 10
=> 10
>> num.object_id
=> 21
>> sample(num)
i = num_method
---------------------
num_method    = 10
i             = 10
---------------------
num_method id = 21
i id          = 21
---------------------
i = i + 1
---------------------
num_method    = 10
i             = 11
---------------------
num_method id = 21
i id          = 23
---------------------
num_method = num_method + 3
---------------------
num_method    = 13
i             = 11
---------------------
num_method id = 27
i id          = 23
=> nil
>> num
=> 10
>> num.object_id
=> 21

sampleメソッド内の num_method,iともに始めのうちは引数numと同じ値、同じobject_idを持っている。

その後メソッド内で変数の中身が書き換わると同時にそれぞれの変数のobject_idが変化している。

最終的にどちらも元の変数numと違うobject_idとなり、numの値は元のものから変化しない。

破壊的メソッドによる値の渡し方

強制的にレシーバーの値を変更する破壊的メソッドではどのように値を渡しているのかを検証。

破壊的メソッドを使用する前後でのobject_idを調べる。

>> # sample メソッド
>> def sample(str)
>>   puts "str           = #{str}"
>>   puts "str id        = #{str.object_id}"
>> end 
=> :sample
>> 
>> # sample_upcase! メソッド
>> def sample_upcase(str)
>>   puts "str            = #{str}"
>>   puts "str id         = #{str.object_id}"
>>   puts "str.upcase     = #{str.upcase}"
>>   puts "str.upcase id  = #{str.upcase.object_id}"
>>   i = str.upcase
>>   puts "i              = #{i}"
>>   puts "i id           = #{i.object_id}"
>>   puts "str            = #{str}"
>>   puts "str id         = #{str.object_id}"
>> end
=> :sample_upcase
>>
>> # sample_upcase! メソッド
>> def sample_upcase!(str)
>>   puts "str            = #{str}"
>>   puts "str id         = #{str.object_id}"
>>   puts "str.upcase!    = #{str.upcase!}"
>>   puts "str.upcase! id = #{str.upcase!.object_id}"
>>   i = str.upcase!
>>   puts "i              = #{i}"
>>   puts "i id           = #{i.object_id}"
>>   puts "str            = #{str}"
>>   puts "str id         = #{str.object_id}"
>> end
=> :sample_upcase!
>>
>> # str 変数に "hello" を代入、object_id 確認
>> str = "hello"
=> "hello"
>> puts "str id         = #{str.object_id}"
str id         = 70154707881220
=> nil
>>
>> # sample メソッド呼び出し
>> sample(str)
str           = hello
str id        = 70154707881220
=> nil
>>
>> # str 変数に格納されている文字列と object_id の確認
>> puts "str            = #{str}"
str            = hello
=> nil
>> puts "str id         = #{str.object_id}"
str id         = 70154707881220
=> nil
>>
>> #sample_upcase メソッド呼び出し
>> sample_upcase(str)
str            = hello
str id         = 70154707881220
str.upcase     = HELLO
str.upcase id  = 70154697977560
i              = HELLO
i id           = 70154719397600
str            = hello
str id         = 70154707881220
=> nil
>>
>> # str 変数に格納されている文字列と object_id の確認
>> puts "str            = #{str}"
str            = hello
=> nil
>> puts "str id         = #{str.object_id}"
str id         = 70154707881220
=> nil
>>
>> # sample_upcase! メソッド呼び出し
>> sample_upcase!(str)
str            = hello
str id         = 70154707881220
str.upcase!    = HELLO
str.upcase! id = 8
i              = 
i id           = 8
str            = HELLO
str id         = 70154707881220
=> nil
>>
>> # str 変数に格納されている文字列と object_id の確認
>> puts "str            = #{str}"
str            = HELLO
=> nil
>> puts "str id         = #{str.object_id}"
str id         = 70154707881220
=> nil

この例からわかること

  • strの参照するobject_idは破壊的メソッド(upcase!)使用前後で変わらない。
  • 破壊的でないメソッドではレシーバー(str)とは違うobject_idに値を返す。

肝心のsample_upcase!メソッドの挙動ですが、iに空文字かnilが入っているなど少し挙動がおかしいようなのでもう少し検証。

>> str = "hello"
=> "hello"
>> str.object_id
=> 70287705130100
>> str.upcase!
=> "HELLO"
>> str.upcase!
=> nil
>> str
=> "HELLO"
>> str.object_id
=> 70287705130100
>> str.upcase!.object_id
=> 8
>> nil.object_id
=> 8

破壊的メソッドupcase!によって大文字変換を行う際に、対象の文字列がすでにすべて大文字だとnilが返ってくる。

そしてnilオブジェクトのobject_idが8。

つまり先ほどの例ではsample_upcase!メソッド内のputs "str.upcase! = #{str.upcase!}"処理によってstr内の文字列が大文字に変換され、それ以降の処理puts "str.upcase! id = #{str.upcase!.object_id}", i = str.upcase!ではnilが参照されていたことになる。

それでは肝心の破壊的メソッドupcase!が実行される瞬間はどこを参照しているのかというと、

>> str = "hello"
=> "hello"
>> str.object_id
=> 70287705130100
>> str.upcase!.object_id
=> 70287705130100
>> str
=> "HELLO"
>> str.object_id
=> 70287705130100

きちんとレシーバーであるstrobject_idを参照している。

結論、

  • 非破壊的メソッドupcaseはレシーバーと異なるobject_idで文字列変換を行う
  • 破壊的メソッドupcese!はレシーバーと同じobuject_idで文字列変換を行う
  • 破壊的メソッドを使用してレシーバーの値から変更がない場合、破壊的メソッドはnilを返す

参考:Rubyの破壊的メソッドについて

クラス

クラスの定義

  • 定義位置はクラスの呼び出し前
  • クラスの命名規則
    • 頭文字は大文字
    • 単語の頭文字を大文字にして単語を区切る(CamelCase)
# クラスの定義
class クラス名
end
>> JapanesePeople.class # classメソッド = オブジェクトのクラスを返すメソッド
Traceback (most recent call last):
        1: from (irb):1
NameError (uninitialized constant JapanesePeople) # クラスの定義前なのでエラー出力
>> class JapanesePeople
>> 
>> end
=> nil
>> JapanesePeople.class
=> Class   # JapanesePeopleクラスが作成されていることが確認された

オブジェクトの生成

  • オブジェクトを生成するとクラス内のinitializeメソッドが実行される。
  • initializeメソッドはクラス定義時に省略可能。
  • initializeメソッドを使うことでオブジェクト生成時に必ず行うべき処理を実行することができる。
# オブジェクトの生成
オブジェクト名 = クラス名.new()
>> class JapanesePeople
>>   def initialize(name, age, from)
>>     @name = name
>>     @age  = age
>>     @from = from
>>     puts "name: #{@name}, age: #{@age}, from: #{@from}"
>>   end
>> end
=> :initialize
>> tanaka = JapanesePeople.new("Tanaka", 25, "Tokyo")
name: Tanaka, age: 25, from: Tokyo
=> #<JapanesePeople:0x00007fcd2640abc8 @name="Tanaka", @age=25, @from="Tokyo">

インスタンス変数

  • クラス内の全てのメソッドで共有できる変数。
  • 変数名の頭に@をひとつ付ける
  • クラスから作成されるインスタンスごとに独立した変数
>> class JapanesePeople
>>   def initialize(name, age, from)
>>     @name = name
>>     @age  = age
>>     @from = from
>>     puts "name: #{@name}, age: #{@age}, from: #{@from}"
>>   end
>>   def introduction
>>     puts "#{@from}出身の#{@name}です。#{@age}歳です。"
>>   end
>> end
=> :introduction
>> tanaka = JapanesePeople.new("Tanaka", 25, "Tokyo")
name: Tanaka, age: 25, from: Tokyo
=> #<JapanesePeople:0x00007fcd2640abc8 @name="Tanaka", @age=25, @from="Tokyo">
>> suzuki = JapanesePeople.new("Suzuki", 30, "Fukuoka")
name: Suzuki, age: 30, from: Fukuoka
=> #<JapanesePeople:0x00007fcd2642b620 @name="Suzuki", @age=30, @from="Fukuoka">
>> tanaka.introduction
Tokyo出身のTanakaです。25歳です。
=> nil
>> suzuki.introduction
Fukuoka出身のSuzukiです。30歳です。
=> nil

インスタンス変数はtanakasuzukiで独立しているが、どちらもJapanesePeopleクラスなのでintroductionメソッドは共通。

クラス変数

  • 同じクラスであればインスタンスを超えて参照可能な変数。
    • もちろんクラス内のどのメソッドからも参照可能。
  • 変数名の頭に@@を付ける。
>> class JapanesePeople
>>   def initialize(name, age, from)
>>     @name = name
>>     @age  = age
>>     @from = from
>>     @@like = "kome"
>>     puts "name: #{@name}, age: #{@age}, from: #{@from}, like: #{@@like}"
>>   end
>>   def introduction
>>     puts "#{@from}出身の#{@name}です。#{@age}歳です。#{@@like}が好きです。"
>>   end
>>   def like_change_kome
>>     @@like = "kome"
>>   end
>>   def like_change_sakura
>>     @@like = "sakura"
>>   end
>> end
=> :like_change_sakura
>> tanaka = JapanesePeople.new("Tanaka", 25, "Tokyo")
name: Tanaka, age: 25, from: Tokyo, like: kome
=> #<JapanesePeople:0x00007fcd26b9a118 @name="Tanaka", @age=25, @from="Tokyo">
>> suzuki = JapanesePeople.new("Suzuki", 30, "Fukuoka")
name: Suzuki, age: 30, from: Fukuoka, like: kome
=> #<JapanesePeople:0x00007fcd28c5e2c8 @name="Suzuki", @age=30, @from="Fukuoka">
>> tanaka.introduction
Tokyo出身のTanakaです。25歳です。komeが好きです。
=> nil
>> suzuki.introduction
Fukuoka出身のSuzukiです。30歳です。komeが好きです。
=> nil
>> tanaka.like_change_sakura
=> "sakura"
>> tanaka.introduction
Tokyo出身のTanakaです。25歳です。sakuraが好きです。
=> nil
>> suzuki.introduction
Fukuoka出身のSuzukiです。30歳です。sakuraが好きです。
=> nil
>> suzuki.like_change_kome
=> "kome"
>> tanaka.introduction
Tokyo出身のTanakaです。25歳です。komeが好きです。
=> nil
>> suzuki.introduction
Fukuoka出身のSuzukiです。30歳です。komeが好きです。
=> nil

クラス変数である@@likeJapanesePeopleクラスのtanaka, suzukiどちらにも常に共通であり、どちら側のメソッドからも参照して値を変更することが可能。

クラスの継承

  • クラスの継承方法
class クラス名 < 継承したいクラス名
end

クラスを継承することで、継承元のクラスで定義したメソッドなどを継承先のクラスでも使用することができる。

>> class Person
>>   def introduction
>>     puts "私は人間です。"
>>   end
>> end
=> :introduction
>> class Japanese < Person
>> end
=> nil
>> Tanaka = Japanese.new()
=> #<Japanese:0x00007ffb0099f3b0>
>> Tanaka.introduction
私は人間です。
=> nil

JapaneseクラスはPersonクラスを継承しているため、JapaneseクラスのインスタンスであるTanakaJapaneseクラスで定義されていなくてもPersonクラスのintroductionメソッドを使用することができる。

シンボル

:symbolなど、:が前置された文字列のこと。

変数と違い、シンボル自身に値や文字列を格納することはできない。

シンボルを表すクラス。シンボルは任意の文字列と一対一に対応するオブジェクトです。

文字列の代わりに用いることもできますが、必ずしも文字列と同じ振る舞いをするわけではありません。 同じ内容のシンボルはかならず同一のオブジェクトです。

参考:Ruby 2.3.0 リファレンスマニュアル

文字列との違い

文字列は、同じ文字列でも参照するたびにobject_idの違うオブジェクトが参照されている。

何度参照しても表面上の文字列としては同じものだが、参照するたびにオブジェクトとしては違うものという判定になる。

>> "symbol".object_id
=> 70193690175060
>> "symbol".object_id
=> 70193690258700
>> "symbol".object_id
=> 70193693840280
>> "symbol" == "symbol"
=> true
>> "symbol".object_id == "symbol".object_id
=> false

一方シンボルは文字列の組み合わせに対して常に同じobject_idをとる。

何度参照しても常に同じobject_idとなり、同じオブジェクトとみなされる。

>> :symbol.object_id
=> 392008
>> :symbol.object_id
=> 392008
>> :symbol.object_id
=> 392008
>> :symbol == :symbols
=> true
>> :symbol.object_id == :symbol.object_id
=> true

ハッシュ

ハッシュの定義

  • 配列と似た構造
  • キーを指定してオブジェクト(値)を格納する。
    • 配列番号のみでなく任意の数値や文字列でオブジェクトを取り出せる。
  • {}は省略可能
  • キーには数値、文字列、シンボルなどを始めあらゆるオブジェクトを採用可能。
    • niltrue, false, クラス, モジュールなど
# キーが数値、文字列の場合
ハッシュ名{キー1 => オブジェクト1, キー2 => オブジェクト2, ...}
ハッシュ名 キー1 => オブジェクト1, キー2 => オブジェクト2, ...

# キーがシンボルの場合
ハッシュ名{:キー1 => オブジェクト1, :キー2 => オブジェクト2, ...}
ハッシュ名 :キー1 => オブジェクト1, :キー2 => オブジェクト2, ... 

ハッシュ名{キー1: オブジェクト1, キー2: オブジェクト2, ...}
ハッシュ名 キー1: オブジェクト1, キー2: オブジェクト2, ...

# ハッシュにオブジェクトを追加
ハッシュ名[キー] = オブジェクト

# ハッシュの値を参照
ハッシュ名[キー]
  • 変数や配列、ハッシュは中身のオブジェクトがキーとして割り当てられる
    • よって中身が変わるとエラーとなる
>> greet = "hello"
=> "hello"
>> array = [1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]
>> person = {name: "tanaka", age: 25}
=> {:name => "tanaka", :age => 25}
>> hash = {greet => "hoge", array[0] => "fuga", person[:name] => "hogefuga"}
=> {"hello"=>"hoge, "1=>"fuga", "tanaka"=>"hogefuga"}

ハッシュをハッシュにネストする

ハッシュのオブジェクトにハッシュを持っている状態

>> family = {
>>   name: family_name = {  
>>     dat: "toshio",    
>>     mam: "kaori",    
>>     son: "yuta",    
>>     daughter: "saori"    
>>   },  
>>   num: 4
>> }  
=> {:name=>{:dat=>"toshio", :mam=>"kaori", :son=>"yuta", :daughter=>"saori"}, :num=>4}

モジュール

モジュールの定義

  • 定義位置はモジュールの呼び出し前
  • モジュールの命名規則
    • 頭文字は大文字
    • 単語の頭文字を大文字にして単語を区切る(CamelCase)
module モジュール名
  処理
end
>> module Person
>>   def introduction
>>     puts "私は人間です。"
>>   end
>> end
=> :introduction

モジュールについてはこちらの記事がわかりやすかったのでここでは簡単な紹介程度で。

参考:【Ruby入門】Rubyのモジュールの使い方

上記の記事で、

  • モジュールはインスタンスを作れない
  • モジュールは継承できない

とあったので、これだけ確認しておきます。

モジュールはインスタンス(オブジェクト)を生成できない

  • そもそもModuleクラスにはインスタンスを生成するnewメソッドは用意されていない。
>> module Person
>>   def introduction
>>     puts "私は人間です。"
>>   end
>> end
=> :introduction
>> Person.new()
NoMethodError: undefined method `new' for Person:Module
from (pry):10:in `__pry__'  

モジュールは継承できない

  • モジュールを継承しようとするとエラーが出力される。
>> module Person
>>   def introduction
>>     puts "私は人間です。"
>>   end
>> end
=> :introduction
>> module Japanese < Person
SyntaxError: unexpected '<'
module Japanese < Person
                ^
>> class Japanese < Person
>> end
TypeError: superclass must be a Class (Module given)
from (pry):6:in `__pry__'

おわりに

何かご指摘やご要望があれば遠慮なくコメントお願いします。