Open14

Ruby学習 基本

ゆずゆず

Rubyについて学習した内容をまとめていきます

ゆずゆず

ドットインストールを使って学習

# いろいろな出力方法
print "hello woeld"
puts "hello world" # 改行あり
p "hello world" # デバッグ用

# オブジェクト
human = {
    name: "taro",
    age: 20,
    gender: "男性"
}

p human
# {:name=>"taro", :age=>20, :gender=>"男性"}
# 1行コメント

=begin
複数行コメント
複数行コメント
=end
実行 ruby {ファイル名}
ゆずゆず

変数・定数

=begin
変数名は小文字で始める
変数名はスネークケースで書く
変数名は数字で始めることはできない
変数名はアルファベットの大文字小文字、数字、_が使える
変数名は同じ名前を使えない
変数名は予約語を使えない
変数名は名前をつけることでコードの意味がわかりやすくなる
=end

msg = "hello world"
puts msg

# 上書きも出来る
msg = "hello world again"
puts msg

=begin
定数名は大文字で始める
=end

VERSION = 1.1
puts VERSION

VERSION = 1.2
puts VERSIONv

warning
hello.rb:24: warning: already initialized constant VERSION
hello.rb:21: warning: previous definition of VERSION was here

ゆずゆず

数値


# 数値
# p 4.8.class
# p 4.8.methods

p 4.8.floor # 小数点以下切り捨て
p 4.8.ceil # 小数点以下切り上げ
p 4.8.round # 四捨五入
ゆずゆず

式展開

name = "Alice"
p "Hello, #{name}!" 
p 'Hello, #{name}!' # シングルクォートだと式展開されない
ゆずゆず

真偽値はシンプルで、下記のようになっている

偽: false nil
真: それ以外

ゆずゆず

rubyの短絡評価

左辺でfalseが出た場合、右辺はそもそも処理しない。
この特性を利用して

user

user || user.email_veryfied # userがnilやfalseの場合、右辺処理を行わない
というようにコードを書いたりする
ゆずゆず

条件分岐

boy = 'men'
girl = 'women'

def gender(human)
    if human == "men"
        puts "男です" 
    elsif human == "women"
        puts "女です"
    else
        puts "不明です"
    end
end

gender(boy) # 男です
gender(girl) # 女です

後置if


# 後置if
human = {
    age: 20,
    name: "Alice"
}

puts "Aliceです" if human[:name] == "Alice"

unless


# unless
hoge = false

unless hoge
    puts "falseです"
else
    puts "trueです"
end

case

animal = "cat"

case animal
when "dog"
    puts "犬です"
when "cat"
    puts "猫です"
when "bird"
    puts "鳥です"
else
    puts "それ以外です"
end

三項演算子

score = 100

# 条件式 ? 真の時の処理 : 偽の時の処理
puts score > 80 ? "great" : "bad"
ゆずゆず

メソッド定義

def メソッド名
  # 処理
end

?と!で終わるメソッド
Rubyのメソッドには、nil?のように?や!が付くメソッドがあります。

基本的に?が付くメソッドは、真偽値を判定しているメソッドになります。

!が付くメソッドは破壊的なものになる
破壊的とは、オブジェクトの中身を変更してしまうものなどの事になる
(基本的には、破壊的メソッドの仕様は控えた方がよさそう!)

ゆずゆず

配列

# 色々な書き方がある
testArr = [1, 2, 3, 4, 5]
p testArr[0] # 1
p testArr[1] # 2
p testArr[-1] # 5
p testArr[-10] # nil 
p testArr[0..2] # [1, 2, 3]

# 要素の変更
testArr[7] = 10
p testArr # [1, 2, 3, 4, 5, nil, nil, 10] # 存在しない要素に代入すると間の要素はnilで埋められる

# testArr[-10] = 10
# p testArr # 負の数では、存在しない要素に代入するとエラーになる

# <<を使うと配列の最後に要素を追加できる
testArr << 6 
p testArr

# pushを使っても配列の最後に要素を追加できる
testArr.push(7) 
p testArr

# 配列に連続して追加できる
testArr  << 6 << 7

配列の分割
splitメソッドを使うと、文字列を自然に変換した配列を得ることができます。
デフォルトでは、空白で分割する

# 文字列を3つの要素を持つ配列に分割する
"foo bar     baz".split 
=> ["foo", "bar", "baz"]

# 好きな文字で分割するように、指定することも出来る
>> "fooxbarxbaz".split('x')
=> ["foo", "bar", "baz"]

範囲(range)は、配列と密接に関係しています。to_aメソッドを使って配列に変換すると理解しやすいと思います。

# 丸カッコを使い、範囲オブジェクトに対してto_aを呼びましょう
(0..9).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 範囲は、配列の要素を取り出すのに便利です。
# %wを使って、文字列の配列に変換することも出来る
a = %w[foo bar baz quux]         
=> ["foo", "bar", "baz", "quux"]

# 範囲で取得できる
a[0..2]
=> ["foo", "bar", "baz"]
ゆずゆず

ハッシュとシンボル

ハッシュは、他で言語でいうオブジェクトとか、連想配列

シンボルの特徴

  • 文字列(string)と似てる
  • ふるまいが似ているが、若干異なるので適材適所で使用する
  • そもそも、文字列っぽいけど内部では整数として扱われている
    • その為、より高速に比較ができる
  • 同じ名前のシンボルならば、同じオブジェクトになる
    • idなどが同じになる
  • 破壊的メソッドが使えない(immutable:変更不可)

ハッシュなどのキーにはシンボルをよく使う

money = {
:taro => 100,
:hanako => 200
}

キーにシンボルを使う場合、省略した書き方ができる(JavaScriptのオブジェクトに似た書き方なので、良さそう)

money = {
taro: 100,
hanako: 200
}

さらにメソッドの最後がハッシュの場合 {}も省略できるので、初見で意味不明な形にもなります

def print_hello(greet, options)
  puts options
  puts greet
end

# 省略の流れ
print_hello('hello', {taro: 100, hanako: 200})
print_hello 'hello', {taro: 100, hanako: 200} # メソッドの()は省略可能
print_hello 'hello', taro: 100, hanako: 200 # メソッドの引数の最後が、ハッシュなので{}を省略

ゆずゆず

Rubyのオブジェクトの注意点

インスタンス変数がおかしい場合でも、errorを吐かず、nilが入ってしまうので注意
(initializeに入っているものは、値が入れられない場合nilを返すのだと思う)

インスタンス変数は外部から参照することは出来ない

ゲッター

インスタンス変数の値を取得したい場合、それ用のメソッドを作る必要がある

class Human
 def initialize(name, age)
  @name = name
  @age = age
 end
 
 def description
   puts "#{@name}と申します。年齢は#{@age}です。"
 end

 def name
  @name
 end
end

セッター

インスタンス変数の値を変更したい場合、=で終わるメソッドを定義する

class Human
 def initialize(name, age)
  @name = name
  @age = age
 end
 
 def description
   puts "#{@name}と申します。年齢は#{@age}です。"
 end

 def name
  @name
 end

 def name=(new_name)
  @name=new_name
 end
end

ただ、毎回ゲッター、セッターを書くのは冗長なので省略する書き方が存在する
attr_accessorと書くことで、ゲッターとセッターを書いたとみなされる

下記のbeforeとafterは同じように使えるコードになる

before

class Human
 def initialize(name, age)
  @name = name
  @age = age
 end
 
 def description
   puts "#{@name}と申します。年齢は#{@age}です。"
 end

 def name
  @name
 end

 def name=(new_name)
  @name=new_name
 end
end

after

class Human
 attr_accessor :name

 def initialize(name, age)
  @name = name
  @age = age
 end
 
 def description
   puts "#{@name}と申します。年齢は#{@age}です。"
 end
end

さらに、読み取りだけしたい場合

attr_reader

書き込みだけしたい場合は

attr_writer

という書き方も出来る

クラスメソッド

2種類の書き方

基本的にはこちらを使う

def self.メソッド名
 puts "このメソッドを実行"
end

複数のメソッドを定義する場合は、こちらの方が効率が良い

class << self
 def メソッド名
  puts "このメソッドを実行"
 end

 def メソッド名2
  puts "このメソッド2を実行"
 end
end

クラス内の定数と変数

スコープが異なり
定数はインスタンスメソッドや、クラスメソッド内からも呼び出せる

class Human
 attr_accessor :name
 RURU = "どこからでも呼び出せる"
 ruru = "呼び出す場所は同スコープ内のみ"

 def initialize(name, age)
  @name = name
  @age = age

  puts RURU # どこからでも呼び出せる
  puts ruru # エラー
 end
 
 def description
   puts "#{@name}と申します。年齢は#{@age}です。"
 end
end


# 外部からも参照できる
puts Human::RURU # どこからでも呼び出せる

privateメソッドについて

privateメソッドはクラス内部でのみ使うことが出来る
※ privateと書いた以降の記述はすべてprivateになる

class Human
 attr_accessor :name

 def initialize(name, age)
  @name = name
  @age = age
 end

 private # ここから下の記述はprivateになる
 
 def walk
  puts '毎日歩いています'
 end 
end

継承

書き方はシンプルで以下のように書くだけ
継承したクラスの事は、スーパークラスと呼ぶ(親クラス)、子クラスはサブクラスと呼ばれる
親クラスと同じメソッド名の場合、superと記述することで、親の挙動をそのまま使える

子クラス側で、同名メソッドを上書きすることをオーバーライドと呼ぶ

class クラス名(大文字から始まる) < 継承するクラス名
ゆずゆず

ブロック

下記処理の説明

範囲オブジェクトである(1..5)に対してeachメソッドを呼び出しています
| i |で、変数が縦棒「|」に囲まれているのが、ブロック変数のRubyの構文です。

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

波カッコ の替わりに doとend で囲んで示すこともできる

(1..5).each do |i|
 puts 2 * i
end

symbol-to-procという記法もあり、&:メソッド名で省略して書くことも出来る

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

# これをsymbol-to-procを使って書くと
%w[A B C].map(char:downcase) # と書くことも出来る
=> ["a", "b", "c"]

ここまでに学習した書き方を使うとこのようになる。

def yellar(stringArray)
   stringArray.map(&:upcase).join
end

array = ['a', 'b', 'c']

yellar(array)
=> ABC
ゆずゆず

新しく覚えたこと

配列操作

.uniq

配列から重複する値を除いたものを返す

array.uniq

.map

配列の各要素に対して処理を行った結果を配列で返してくれるメソッドです。

# 基本構文
配列.map { |item| 実行する処理 }

# 実行する処理が複数行に渡る場合
配列.map do |item|
  実行する処理
end