JSON.parse() メソッドの型変換よりrailsのblank?メソッドを使った方が簡単だった

Mon Oct 22, 2018 - rails
Sat Jan 18, 2020

JavaScriptの型をどうやって変更しようか悩んだあげく、結局、railsのblank?メソッドを使って解決したという話。

悩んだのでメモしておきます。

とあるアプリのバクの原因

ユーザーがセレクトボックスで選択したものをJavaScriptで処理し、値をrubyの三項演算子で処理するという簡単な処理を書いていましたが、フロントエンジニアがちょっとJavaScriptの処理を変更したため、動かなくなりました。

原因は、JavaScriptのJSON.parse() メソッドを使ったこと。

これまでは、ユーザーがセレクトボックスで未選択だったらJavaScriptで、

1
2
3
<!-- JSON.stringify() メソッドはJavaScript オブジェクトをJSON 文字列に変換します -->

string  ''

を返していましたが、JSON.parse() メソッドを使うと、これがnullで返ります。

1
2
<!-- JSON.parse() メソッドは文字列をオブジェクトに変換します -->
object  null

んで、これらの処理をrails側でどう処理していたのかというと。

1
name = params[:name] == '' ? nil : User.find(params[:name]).name

rubyの三項演算子は単純でnameがfalseだとnilを返して、値があればfindメソッドが動くというもの。

この処理がJSON.parse() メソッドのせいでエラーになった。

なぜかというとJSON.parse() メソッドの返値がObjectでnullを返すから。

公式サイトでnullの詳細をみると。

1
2
3
4
5
6
// foo が存在せず、定義も初期化もされていない場合:
> foo
"ReferenceError: foo is not defined"
// foo が存在しているが、型も値も持たない場合:
> var foo = null; foo;
"null"

javascriptのnullがクセモノで、foo が存在しているが、型も値も持たないというなんとも厄介なやつ。

先ほどの、rubyの三項演算子のはfalseの場合はnilが返るという処理にしていましたが、nullが返るせいで、存在はしているがないという意味なので、trueになってfindの処理が動いてエラーになる。

1
email = params[:email] == '' ? nil : User.find(params[:name]).email

railsのblank?メソッドを使う

解決したい問題は、中身が空か、または入れモノそのものが存在しないときの判定がしたい。

それを解決するのがblank?メソッド

変数.blank? nil? + empty? のようなメソッド。nilまたは空のオブジェクトをチェックできる。 nil, “”, " “(半角スペースのみ), , {}(空のハッシュ) のときにfalseを返します。 Railsで拡張されたメソッドで、Rubyのみでは使えないのでご注意ください。 Railsドキュメント

blank?メソッドを使ってさっきのやつを修正するとこうなる。

1
email = params[:email].blank? ? nil : User.find(params[:name]).email

これで、jsでnullが返ってこようがundefinedが返ってこうようが大丈夫になった。

最初はjsでnullをundefinedにどう変更しようかなとずいぶん悩んだが、railsのblank?メソッドで解決できるという悲しい結末になりました。

Tags: JavaScript
See Also