Rails – サービス層でURL.encodeがNoMethodErrorになる

背景

Rails で日本語が含まれるURLを扱う場合、日本語部分をエンコードする必要があります。

通常、URI.encode (url) で事足りるはずですが、サービス層で利用した時に次のエラーが出ました。


class ServiceObject
  def execute
    url = 'https://example.com/日本語'
    URI.encode(url)
    # ここでエラー!
    # 以下、処理が続く
  end
end
NoMethodError: private method `open' called for #\u003cURI::Generic:0x00007ff5600923f8\u003e

URI::Generic の open メソッドが定義されていないというエラー内容。

Ruby のバーションは2.4.4 なので、 URI モジュール自体は含まれているはずなのですが。

解決策

(その1)require ‘uri’

まず、サービス層(app/services)にパスが通っていない可能性が考えられます。

そのため、該当ファイル内で「require ‘uri’」を明示することで解決してみます。


# 明示する
require 'uri'

class ServiceObject
  def execute
    url = 'https://example.com/日本語'
    URI.encode(url)
    # 以下、処理が続く
  end
end

(その2)gem ‘addressable’

Addressable という日本語URLのパースするための gem でも解決できます。

まず Gemfile の編集。


gem 'addressable'

gem をインストール。

$ bundle install

そして 「URI.encode」でなく「Addressable::URI.escape」という書き方に変更します。


class ServiceObject
  def execute
    url = 'https://example.com/日本語'
    Addressable::URI.escape.escape(url)
    # 以下、処理が続く
  end
end

その2の方が確実なので、今回はそっちを使って解決しました。

Sources

兵庫県西宮市生まれのフリーランスRailsエンジニア。案件によってWordPressの作業も請け負ったりしてます。2014年から2016年にかけてオーストラリアで生活。 現在は東京を拠点に活動。/ 前職・資格:公認会計士 / プログラミング言語:Ruby, JavaScript, HTML, CSS / 日本語・英語
コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です