エラーメモ【TypeError】
エラーの解決過程を記録しておきます。
記事投稿アプリで記事内容を未入力で投稿しようとすると以下のようなエラーが発生しました。
TypeError - no implicit conversion of nil into String:
TypeErrorとは
メソッドの引数に期待される型ではないオブジェクトや、期待される振る舞いを持たないオブジェクトが渡された時に発生します。
エラー文を翻訳
no implicit conversion of nil into String
を翻訳すると
nilからStringへの暗黙の変換がない
となりました。
string型に変換する必要がありそうです。
該当箇所を確認
現在の該当箇所のコードは
def build_body(controller) result = '' article_blocks.each do |article_block| result << if article_block.sentence? sentence = article_block.blockable sentence.body end end result end
こんな感じです。
簡単に言うとコンテンツがあれば<<
でresultに追加する、というコードです。
コンテンツが存在すれば正常に処理され画面が表示されますが、コンテンツがないままだとエラーが発生する状態です。
string型のオブジェクトを取得したいのにnil型だから受け取れない、とのことなのでまずは実際に何型のオブジェクトか見てみます。
sentence.body.class
でsentence.body
がnil型だと分かりました。
これをstring型にできれば解決するはずです。
どうやって型を変えるか
初めに思いついたのはto_s
メソッドでstring型に変換するやり方です。
想定通り、string型になりました。
このやり方でもエラーは解決しましたが、||=
を使って空文字を明示する書き方の方が良いそうです。
def build_body(controller) result = '' article_blocks.each do |article_block| result << if article_block.sentence? sentence = article_block.blockable sentence.body ||= '' end end result end
このようにしてエラー解決できました。
||= は何をしているか
||=
は自己代入やnilガード
と呼ばれるそうです。
左辺がnilまたはfalseの場合は右辺が代入され、それ以外の場合は代入はされません。
sentence.bodyに「テスト」と入力して確認してみます。
入力されているのでnilにはならないはずです。
nil?メソッドでfalseが返ってきたのでsentence.bodyはnilではないことがわかります。
nilではないので右辺の''(空の文字列)は代入されず「テスト」となっていますね。
書籍などで||=この書き方を見たり、nilガードという言葉自体は見たことありましたが、実際に検証して理解が深まりました。
最後に
||= これだけ見ると記号か暗号のようですが、hoge = 1
のような変数に代入するコードに||
という関所があって、hogeが空っぽの時は1さんに「うむ、入れてやろう」、hogeに何か入ってる時は「今hogeは満員だ。帰れ」と言ってるイメージで覚えました。知らんけど。
今回は以上です。ありがとうございました。
参考サイト
class TypeError (Ruby 3.0.0 リファレンスマニュアル)
Rubyで使われる記号の意味(正規表現の複雑な記号は除く) (Ruby 3.0.0 リファレンスマニュアル)
【Ruby】使いこなせると便利。||演算子のいろんな使い方 - Qiita
Rubyの自己代入(||=)とはこんな仕組みです - Qiita
【Ruby入門】nilのポイントまとめ(nil? empty? blank? present?) | 侍エンジニアブログ