Help us understand the problem. What is going on with this article?

Railsのas_jsonをもうちょっと便利に使うオプション

More than 5 years have passed since last update.

Railsにはas_jsonっていう便利なメソッドがある。

irb(main):033:0> user = User.first
=> #<User id: 1, first_name: ‘Tatsuro’, last_name: ‘Baba’, email: ‘harakirisoul@gmail.com’>
irb(main):034:0> user.as_json
=> {"email"=>"user_1@example.com", "first_name"=>"User1", "id"=>1, "last_name"=>"USER1"}

ところが、これだとちょっと使い勝手が悪かったりする場合がある。そんなパターンに遭遇した時の、2つの解決策を紹介する。

Userのインスタンスが特殊なメソッドを持っていたりする場合

例えば、User#full_nameなんてメソッドがあったとして、それを含むjsonを書き出したい、というときに、どうするだろうか。ひとつの解決案は以下の通りだ。

user.as_json.merge(full_name: user.full_name)

多少無理やりだが、まぁHashなのでこれでも出来る。
でもちょっとスマートじゃない。ちょっとどころかだいぶスマートじゃない。ので、メソッド側でちゃんと準備してくれている。以下のように書いてみよう。

irb(main):035:0> user.as_json(methods: 'full_name')
=> {"email"=>"user_1@example.com", "first_name"=>"User1", "id"=>1, "last_name"=>"USER1”, “full_name”=>”User1 USER1”}

なんと便利な。full_nameはattributeじゃないにもかかわらず、他のattributeと同じようにHashに取り込まれている。

必要ないattributeを削りたい場合

例えば、上のUserモデルのパターンで言うと、「emailは要らない!名前だけくれ!」というパターンがあるかもしれない。

そんなときは、以下のような書き方が出来る。

user.as_json.delete_if{|k, v| k == 'email' }

だが、ダサいしスマートじゃないしメンテコストが高い。そこで、やっぱり用意されているこのオプションを使おう。

user.as_json(except: 'email')
=> {"first_name"=>"User1", "id"=>1, "last_name"=>"USER1”}

あるいは、逆にホワイトリスト形式でも大丈夫。

user.as_json(only: ['id', 'first_name', 'last_name'])
=> {"first_name"=>"User1", "id"=>1, "last_name"=>"USER1”}

驚きの便利さである。

他にもincludesとかオプションがあるので、ぜひ遊んでみて欲しい。

tbaba
プログラマー。ウェブアプリケーションとか。元 https://forkwell.com の中の人。今はちょっと違う仕事。仕事道具はVimとGit。Gitは綺麗な歴史を作る派。
http://weblog.tbaba.jp
grooves
エンジニア向けサービス「Forkwell」や「Forkwell Jobs」を開発・運営しています。
https://forkwell.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away