この記事について
ruby学習中のため、その備忘録です。railsの話はほぼ出てきません。
rubyを学習していて特に分かりにくかったところなどを中心に書いています。
他言語からRubyへ
PHPやPython等他言語を使ってる人に対しては、Ruby公式サイトにそれぞれの言語とRubyの違いについて書かれたページがあります。
メソッド呼び出しのカッコ省略、return省略
引数無しのメソッド呼び出しのカッコ省略
rubyではメソッド呼び出しの際カッコを省略することができます。
def hello
puts 'hello!'
end
hello() # hello!
hello # hello!
引数ありのメソッド呼び出しのカッコ省略
引数がある時もカッコの省略ができます。
引数が複数ある場合は,で繋ぎます。
def hello_name(name)
puts "hello #{name}!"
end
hello_name('suzuki') # hello suzuki!
hello_name 'suzuki' # hello suzuki!
def hello_name2(name1, name2)
puts "hello #{name1}, #{name2}!"
end
hello_name2('suzuki', 'sato') # hello suzuki, sato!
hello_name2 'suzuki', 'sato' # hello suzuki, sato!
returnの省略
また、メソッド内の最終行で戻り値を返す場合はreturnを省略できます。
def plus10(n)
n + 10 # return n + 10
end
def double(n)
n * 2
end
puts plus10 3 # 13
puts double plus10 3 # 26 ← puts double( plus10(3) )
メソッド定義のカッコ省略
メソッド定義でもカッコが省略できます。
引数無しの場合だけでなく、引数ありの場合でも省略できるみたいです。
ただ、実際に引数ありのメソッド定義でカッコを省略して書いている人は少ないように感じました。
def bye_name name
puts "bye #{name}!!"
end
def bye_name2 name1, name2
puts "bye #{name1}, #{name2}!!"
end
bye_name 'suzuki' # bye suzuki!!
bye_name2 'suzuki', 'sato' # bye suzuki, sato!!
メソッドの別名
メソッドの別名を付ける際はaliasやalias_methodを使用します。
alias_methodはclassの外では使えません。
def method1
puts 'method!'
end
# これはメソッドの別名を付けてる訳ではなく、戻り値を代入している
not_method = method1 # method!
method1 # method!
not_method # 何も出力されない
puts not_method # nil ← putsの戻り地はnil
alias :method2 :method1
method2 # method!
メソッドのオプション引数、ハッシュの波カッコ省略
オプション引数
引数にデフォルト値を設定してオプション引数とすることで、メソッド呼び出し時に省略できるようになります。
def pow(n, m=2)
n ** m # nのm乗
end
puts pow 3 # 9
puts pow 3, 4 # 81
ハッシュの波カッコ省略
引数の最後がハッシュの場合は{}を省略できる
def filter_high_persons(min, persons)
persons.filter {|k,v| v > min}
end
puts filter_high_persons(170, {suzuki: 175, sato: 165, tanaka: 180}) # {:suzuki=>175, :tanaka=>180}
puts filter_high_persons 170, suzuki: 175, sato: 165, tanaka: 180 # {:suzuki=>175, :tanaka=>180}
railsでも基本()や{}を省略して書かれることが多いです。
例えばルーティングのところは省略せずに書くと以下のようになります。
get 'test1', to: 'tests#test1', as: 'test_action1'
get('test1', {to: 'tests#test1', as: 'test_action1'})
その他
命名
識別子に!や?を使えます。
慣習的に戻り値が真偽値のメソッドには名前の最後に?を付けることが多く、isやcan等はあまり使いません。
例えばis_successではなく、success?と命名します。
慣習的に破壊的メソッドには名前の最後に!を付けることが多いです。
例えばArrayのsortメソッドは非破壊的ソートを行い、sort!メソッドは破壊的ソートを行います。
メソッド名に!が付いていなければ絶対に破壊的メソッドではない、という訳ではありません。
また、処理失敗時にfalse等を返すメソッドには!を付けず、処理失敗時に例外を発生させるメソッドには!を付けるといった命名もされています。
例えばRailsのsaveは成功したかどうか真偽値を返しますが、save!メソッドは失敗時に例外を発生させます。
標準出力
標準出力するメソッドにputs, print, pがあり、それぞれ出力の仕方が少しずつ異なっています。
主に改行の入り方が違うようです。
| メソッド | 引数毎の改行 | 配列の要素間の改行 | nil | 補足 |
|---|---|---|---|---|
| puts | 入る | 入る | 空行を出力 | 配列の[]の表示なし |
| p | 入る | 入らない |
nilと出力 |
|
| 入らない | 入らない | 何も出力されない | スペースも入らない |
puts 'suzuki', 'sato' # suzuki(改行)sato(改行)
puts ['suzuki', 'sato'] # suzuki(改行)sato(改行)
puts name: 'suzuki', age: 20 # {:name=>"suzuki", :age=>20}(改行)
puts nil # (空行)
p 'suzuki', 'sato' # "suzuki"(改行)"sato"(改行)
p ['suzuki', 'sato'] # ["suzuki", "sato"](改行)
p name: 'suzuki', age: 20 # {:name=>"suzuki", :age=>20}(改行)
p nil # nil
print 'suzuki', 'sato' # suzukisato
print ['suzuki', 'sato'] # ["suzuki", "sato"]
print name: 'suzuki', age: 20 # {:name=>"suzuki", :age=>20}
print nil # 何も出力されない
式と文に違いはない
式と文に違いはなく、全ては値をもつ。
x = 10
res = if 0 <= x
'0以上'
else
'0未満'
end
puts res # 0以上
シンボル
シンボルは単なる軽量文字列ではない。
シンボルはオブジェクトの実体を指すもので、同じシンボルであればメモリ上の同じ場所を参照する。
puts :test.object_id == :test.object_id # true ← メモリ上の全く同じ場所にある
puts 'test'.object_id == 'test'.object_id # false ← 値が同じだけでメモリ上の別々の場所にある
型、インスタンスの調べ方
型・クラスはclassメソッドで調べられます。
インスタンスが特定のクラスのものか調べる際はkind_of?やinstance_ofメソッドを用います。
kind_of?はそのクラスの直接のインスタンスか、そのクラスを継承しているクラスのインスタンスであればtrueとなります。
instance_of?はそのクラスの直接のインスタンスの時のみtrueとなります。
puts Time.class # Class
puts Time.kind_of?(Class) # true
puts Time.kind_of?(Time) # false
time = Time.now
puts time.class # Time
puts time.kind_of?(Class) # false
puts time.kind_of?(Time) # true
class MyTime < Time
end
my_time = MyTime.now
puts MyTime.class # Class
puts my_time.class # MyTime
puts my_time.kind_of?(Time) # true ← MyTimeはTimeを継承しているため
puts my_time.kind_of?(MyTime) # true
puts my_time.instance_of?(Time) # false ← MyTimeのインスタンスであってTimeのインスタンスではない
puts my_time.instance_of?(MyTime) # true
nil (null)
&.演算子
nilに対して&.演算子を用いるとundefined methodエラーを回避できます。
nilが入る可能性がある変数のメソッドを直接呼び出す書き方をしているとnilになった時にエラーが出てしまう為、そういった場合に&.演算子を使うことがあります。
class Test
def hello
'hello!'
end
end
test = Test.new
p test.hello # "hello!"
test = nil
# p test.hello # undefined method `hello' for nil:NilClass
if test # nilはfalse扱い
p test.hello # ここは通らないのでエラーとならない
else
p 'bye!' # bye!
end
# `&.`演算子や`||`演算子を使えば条件分岐を減らすことができる時もある
p test&.hello # nil ← エラーとならずにnilが返される
p test&.hello || 'bye!' # "bye!"
&.演算子を使用しても、nilではないものに対して存在しないメソッドを呼び出した場合はエラーとなる
now = Time.now
# p now&.hello # undefined method `hello' for ~:Time
tryメソッド
railsのtryメソッドを用いると、nilではないものに対して存在しないメソッドを呼び出した場合でもエラーとなりません。
# rails上でしか動きません
now = Time.now
p now.try(:hello)
変数が定義されているか調べる方法
変数が定義されているか確認する際はdefined?メソッドを用います、未定義であればnilを返します。
a = 10
p defined?(a) # local-variable
p defined?(b) # nil
可変長引数、展開
可変長引数
引数名の前に*を付けることで引数の個数を可変にすることができます。
渡された引数は配列となって可変長引数に渡されます。
def variable_arg(*args)
p args.class # Array
p args # [1, 2, 3]
end
variable_arg 1, 2, 3
def sum(*nums)
nums.sum
end
puts sum 1, 2 # 3
puts sum 1, 2, 3 # 6
通常の引数と可変長引数を組み合わせることもできます。
def name_sum(name, *points)
"#{name}さんの合計点は#{points.sum}点です"
end
puts name_sum 'suzuki', 10, 20, 30 # suzukiさんの合計点は60点です
展開
逆にメソッド呼び出し時の引数名の前に*を付けると配列を展開してメソッドに渡すことができます。
def five_avg(a, b, c, d, e)
(a + b + c + d + e) / 5
end
def avg(*nums)
nums.sum / nums.length
end
points = [10, 20, 30, 40, 55]
puts five_avg *points # 31
puts avg *points # 31
参考
- ドキュメント・リファレンスマニュアル
- 参考にさせて頂いたQiitaの記事