LoginSignup
1
0

More than 1 year has passed since last update.

Ruby を書き始めてハマったこと

Last updated at Posted at 2022-04-15

String なのか Symbol なのか

Ruby には Symbol という、文字列の皮を被った数値があり、少メモリで高速なことから、Hash のキーとかでよく見かけます。

自分で作った Hash であれば誤解はないですが、メソッドから生成された Hash のキーが String だったりすると、キーを指定しても nil が返ってきて、「俺が入れたデータが無くなっとる!」と焦ります。

JSON.parsesymbolize_names: true をつけると Symbol

JSON.parse でそのままだと、キーは String になる。

JSON.parse('{"name":"tanaka","age":19}')
=> {"name"=>"tanaka", "age"=>19}

symbolize_names: true をつけるとキーが Symbol になります。

SON.parse('{"name":"tanaka","age":19}', symbolize_names: true)
=> {:name=>"tanaka", :age=>19}

ActionController::ParametersSymbolString 両方で参照可能だが

Rails の parameter は SymbolString 両方で参照できます。

params[:email]
=> "sample@example.com"
params['email']
=> "sample@example.com"

ただし、他の Hash に merge しようとすると String しか残らないので、SymbolString で値が違うなんてことに。。。

new_params = { email: 'test@test.com' }.merge(params)
new_params[:email]
=> "test@test.com"
new_params['email']
=> "sample@example.com"

with_indifferent_access を付けることで、同じ動きを維持できます。

new_params = { email: 'test@test.com' }.with_indifferent_access.merge(params)
new_params[:email]
=> "test@test.com"
new_params['email']
=> "test@test.com"

Exception なのか nil なのか

Ruby ではエラーになった場合、Exception を出すパターンと nil を返すパターンがあり、メソッドによって異なります。
特に、似たようなメソッドなのに違う動きをする場合もあるので、注意が必要です。

Time.parse, Time.zone.parse の引数エラー

Time.parse('hoge')
ArgumentError: no time information in "hoge"
Time.zone.parse('hoge')
=> nil

TimeTime.zone 同じメソッドが用意されているので、使い勝手も同じかと思いきや、違うことがあるので、注意が必要ですね。

Integerto_i の引数エラー

Integer('hoge')
ArgumentError: invalid value for Integer(): "hoge"
'hoge'.to_i
=> 0

正直、to_i0 が返ってくるのは、使いにくくないかい ?

"!" が付いてないのに破壊的なやつがいる

Ruby では破壊的メソッドの後には "!" が付いてるよ、と習いませんでしたか ?
map! とか sort! とか
自分でメソッド作る時も、"!" つけることで、使うときは注意してね、って分かりやすい。

ですが、全てに "!" がついているわけではないんですよ。。。

keep_if, delete_if は破壊的

ArrayHash にある keep_if, delete_if メソッドは呼び出したオブジェクト自身が変更されます。

num_list = [1, 2, 3, 4, 5]                    #=> [1, 2, 3, 4, 5]
odd = num_list.keep_if {|num| num.odd?}       #=> [1, 3, 5]
even = num_list.delete_if {|num| num.odd?}    #=> []
num_list                                      #=> []

まー、名前から見ても、分かりそうですし、
delete_if = reject!keep_if = filter! なんですけど。

結論

何となくで実装せず、ちゃんと仕様を確認しよう。

参考にしたもの

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0