Rubyのチートシート / メソッドと例外処理

Shunsuke Sawada

メソッドの基本的な書き方と例外処理。Railsチュートリアルを初めて読んだ時にcurrent_user=()みたいなメソッドがあって、え?てなったのを覚えてる…。

Rubyで使われる特殊な記号(!とか?とか)は下記サイトがとても参考になります。

Rubyで使われる記号の意味
Ruby QuickRef

 

ruby
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

# ---------------------------------------------- #
# メソッド
# ---------------------------------------------- #

puts "\n\n############## Option Hash ##############\n\n"

# **BAD***
# 引数が何個必要なのか、どの場所にどの引数なのか混乱しやすい
# デフォルト値が設定されていない引数を渡し忘れるとエラーになる
def get_profile_bad(user_id, name, email, age = 0, gender = 'femal')
    puts user_id
    puts name
    puts email
    puts age
    puts gender
end

# **GOOD**
# 必須でない引数はハッシュで受け取るとスッキリ
# user_id以外の引数はオプションなので渡さなくてもエラーにはならない
def set_profile_good(user_id, options = {})
    puts "ID   : #{user_id}"
    puts "NAME : #{options[:name]}"
    puts "MAIL : #{options[:email]}"
    puts "AGE  : #{options[:age]}"
    puts "GEN  : #{options[:gender]}"
end


# 実行する時は改行して見やすく

puts "\n--- GOOD ---\n\n"

set_profile_good(14,
        name:   "my name here",
        email:  "[email protected]",
        age:    99,
        gender: "male"
)


# 結果は同じだけど読みづらい

puts "\n--- BAD ---\n\n"

set_profile_good(14, {name: "my name here", email: "[email protected]", age: 99, gender: "male"})


# optionsを渡さなくても実行可能

puts "\n--- options省略 ---\n\n"

set_profile_good(14)





puts "\n\n############## 特殊な記号 ##############\n\n"


# "*"がついた引数で、それ以降の引数を配列として受け取る
# ---------------------------------------------- #
puts "--- Splat Arguments ---\n\n"

def show_names(status, *names)
    puts "STATUS : #{status}\nNAME   : #{names.join(', ')}"
end

# "fine"以外はnamesに配列として格納される
show_names("fine", "sawada", "sakata", "suzuki", "saito")



# '!'や'?'と同じく,'='も特別な意味を持っているが強制するものではない
# '='は代入するという意味をもったメソッド
# ---------------------------------------------- #

puts "\n--- 'xx=' method  ---\n\n"

class User

    def initialize(name)
        @name = name
    end

    ### アクセサメソッドを自分で定義 ###
    def name=(name)
        @name = name
    end

    def name
        @name
    end

    # xx=は単にメソッドなので、
    # @testインスタンス変数がなくても定義はできる
    def test=(text)
        puts text
    end

    ### アクセサメソッドは簡単に書ける ###

    # attr_accessor :name とすればメソッドを用意しなくても
    # インスタンス変数の中身を読んだり、変更したりできるので
    # name=(name)とnameメソッドは不要

    #attr_accessor :name
    #attr_reader: :name
    #attr_writer: :name

end

user = User.new("sawada")


#nameメソッド / 単にインスタンス変数@nameを返すだけ
puts user.name

# name=()メソッド
# インスタンスメソッドだからuserから呼び出せるのは当然
user.name=("kato")
puts user.name

# ()は省略できるけど、普通はこんな書き方はしない
user.name="suzuki"
puts user.name

# xx=タイプの名前のメソッドを定義すると、同時に「=」演算子を定義することになるので
# 下のような定番の書き方で、値をインスタンス変数に代入することができる
user.name = "saito"
puts user.name

# まず書かないと思うけど
# こんな代入っぽい書き方でも普通のメソッドのように振る舞う…
user.test = "テストだよ"






puts "\n\n############## 例外処理 ##############\n\n"

# 外部のAPIがダウンしてたりとか予想できないことも起こりうるので
# そんな時にアプリの処理を止めないよう例外処理がかける
# ---------------------------------------------- #

def find_from_api(name)

    users = ["sawada", "sakata", "suzuki", "saito"]

    if users.find { |u| u == name }
        puts "We found #{name} in users!\n"
    else
        raise StandardError.new("Hey! We got an error.\n")
    end
end


puts "--- 基本 ---\n\n"

begin
    find_from_api("batman")
rescue => e
    puts "Not found. #{e.message}" #エラーオブジェクトを受け取って表示
ensure
    find_from_api("sawada") #例外が発生しても行う処理
end


puts "\n--- 数回トライ ---\n\n"

error_count = 0
begin
    finding_from_api("sawada") #存在しないメソッド
rescue => e
    error_count += 1
    if error_count < 4
        puts "#{error_count}回目のエラーだよ…"
        puts "#{e.message}"
        retry
    end
ensure
    puts "あきらめた!"
end

上のコードを実行するとこうなるはずです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
############## Option Hash ##############


--- GOOD ---

ID   : 14
NAME : my name here
MAIL : [email protected]
AGE  : 99
GEN  : male

--- BAD ---

ID   : 14
NAME : my name here
MAIL : [email protected]
AGE  : 99
GEN  : male

--- options省略 ---

ID   : 14
NAME : 
MAIL : 
AGE  : 
GEN  : 


############## 特殊な記号 ##############

--- Splat Arguments ---

STATUS : fine
NAME   : sawada, sakata, suzuki, saito

--- 'xx=' method  ---

sawada
kato
suzuki
saito
テストだよ


############## 例外処理 ##############

--- 基本 ---

Not found. Hey! We got an error.
We found sawada in users!

--- 数回トライ ---

1回目のエラーだよ…
undefined method `finding_from_api' for main:Object
2回目のエラーだよ…
undefined method `finding_from_api' for main:Object
3回目のエラーだよ…
undefined method `finding_from_api' for main:Object
あきらめた!

26
Shunsuke Sawada

おすすめの記事

acts-as-taggable-on タグを表示させる順番を決めたい
Railsを4.2にバージョンアップしたら、Vagrantのローカル開発環境にアクセスできなくなった問題
Railsのバリデーションエラー後にレイアウトが崩れるとき