• アーカイブ
  • RSS

GMOメディア エンジニアブログ

Rails Jbuilderのあまり知られてないかもしれない?メソッド3選

こんにちは山田コーダーです。先日Rails Jbuilderのコードを読んでみたら存在自体を知らなかったメソッドを3つ発見しましたので、今日はそれらを紹介したいと思います。

■その1:merge!

Jbuilderテンプレート内ではextract!メソッドを利用して、ActiveRecordオブジェクトのattributesを簡単に列挙することができます。
※Scaffoldで自動生成されるJbuilderテンプレートも以下のような感じですね!

json.extract! @item, :id, :name, :number, :public, :created_at, :updated_at

でもこれ、カラム数が多いテーブル全体を表示したい時はちょっと面倒じゃないでしょうか?行が長くなってRuboCop等の規約チェックツールに怒られますし、カラムの追加・削除の度にテンプレートの修正が必要になります。

という訳で弊社では試行錯誤の結果、RubyのSplat演算子(*)を用いて以下のように記述していました。

json.extract! @item, *@item.attribute_names

が、これでもまだ冗長に感じ、extract_all!みたいなメソッドは無いのかな?とチームメンバーにたずねた所、彼がStack Overflowで質問してくれて、merge!というメソッドがあるよ!との回答を頂きました。
※この回答をしてくれたかた日本の方のようです。ありがとうございました!

なおこのメソッドを利用するにはJbuilder 2.0以上が必要になります。

Rails 4.0系のGemfileは

gem 'jbuilder', '~> 1.x'

となってることが多いと思いますので以下のように修正します。
※Rails 4.1系であれば、すでに以下のようになってると思います。

gem 'jbuilder', '~> 2.0'

これでめでたくmerge!メソッドを利用して、以下のようにスッキリ書けるようになりました。もちろんネストした要素内やpartial内でも利用できます。

json.merge! @item.attributes

※merge!メソッドはextract!メソッドと違い、「要素の摘出」ではなく「ハッシュをここにマージしてください」という意味合いのメソッドのようです。そのためハッシュ(.attributes)を渡してあげる必要があります。

Jbuilderから少し話しがそれますが、created_atやupdated_atを表示させたくない場合は(そもそもDBから取得しないのがベストですが)、ActiveSupportのHash拡張のexceptメソッドを利用すれば以下のように書くことも可能です。

json.merge! @item.attributes.except('created_at', 'updated_at')

ちなみに残念なことにここでシンボルが使えません…。シンボルを使いたい場合は、同じくActiveSupportのHash拡張のwith_indifferent_accessメソッドを利用して以下のように書くことも可能です。が、こんなのテンプレートに書いてられませんね…。こうなったら何か別の方法を探すか、大人しくexcept!で列挙する方がいいかもしれません。

json.merge! @item.attributes.with_indifferent_access.except(:created_at, :updated_at)

■その2:ignore_nil!

よく考えたら上記のような問題、わざわざStack Overflowで聞かなくてもコードを読めば分かることでしたね。反省。
という訳でコードを読んでみたらmerge!の他にもJbuilderのREADEME.mdで利用方法が紹介されてないメソッドがあと2つありましたので、それらを紹介したいと思います。

二つ目はignore_nil!です。例えば以下のコード、@item.numberがnilの場合はJSON上はnumber: nullと表示されます。

json.number @item.number

この時「値がnilの場合はそもそも要素自体を表示させたくない」という場合は以下のようにifやunlessでの制御が必要になります。

json.number @item.number unless @item.number.nil?

でもこのコードもちょっと汚いですよね。

このような場合、ignore_nil!を利用すれば値がnilの時は要素自体が表示されなくなります。なおこの設定は、ignore_nil!メソッドの記述直後に有効化され、元の「nilをignoreしない状態」に戻すには、ignore_nil! falseを記述します。

json.var1 nil

json.ignore_nil!
json.var2 nil

json.ignore_nil! false
json.var3 nil

結果(var2: nullは表示されていません):

{
  var1: null,
  var3: null
}

こちらはクラスメソッドも用意されていますので、設定ファイルに以下を記述しておけば、アプリケーション全体でこの設定を有効化できます。

Jbuilder.ignore_nil

■その3:child!

最後がchild!メソッドです。ブロックを引数に取り、現在の要素内に配列の子要素を追加します。

json.users do
  json.child! do
    json.name 'yamada'
    json.email 'yamada@example.com'
  end

  json.child! do
    json.name 'yamada2'
    json.email 'yamada2@example.com'
  end
end

結果:

users: [
  {
    name: "yamada",
    email: "yamada@example.com"
  },
  {
    name: "yamada2",
    email: "yamada2@example.com"
  }
]

しかしながら実際にはJbuilderテンプレートの中で配列を構築しなければいけないパターンはあまりなさそうで、このメソッドの有用な使い方はよく分かりませんでした。

ひょっとすると既存の配列の最初や最後に、そのテンプレート特有の要素を追加する場合等に利用できるかもしれません。

json.array!(@items) do |item|
  json.extract! item, :name, :number
end

json.child! do
  json.name 'DUMMY'
  json.number 9999
end

結果:

[
  {
    name: "yamada1",
    number: 1
  },
  {
    name: "yamada2",
    number: 2
  },
  {
    name: "DUMMY",
    number: 9999
  }
]

以上です。

他にもcache!やkey_format!等のメソッドもありますが、こちら利用法が紹介されていますので、是非確認してみてくださいませ!

    • #Rails
  • gmom-yamadan Avatar Posted by gmom-yamadan
  • 18時間前
  • 固定リンク
Share

ショートURL
このエントリーをはてなブックマークに追加

TwitterFacebookPinterestGoogle+
← 前へ • 次へ →

Logo

Webサービスの開発・運営に役立つ技術情報をお届けします。このブログはGMOメディア株式会社が運営しています。

GMOメディア採用ページ

gmom-yamadan Avatar
Posted by gmom-yamadan

TAGS

RECENT POSTS

    • RSS
    • ランダム
    • アーカイブ
    • 携帯電話

    Effector Theme by Pixel Union Tumblrによって提供されています