0

2 つのモデルとコントローラーが与えられた場合:

りんご

class Apples < ActiveRecord::Base
  belongs_to :not_oranges
  ...
  def as_json(options={})
    opts = {:include => [:not_oranges]}
    super(options.reverse_merge! opts)
  end
end

オレンジ

class Oranges < ActiveRecord::Base
  belongs_to :not_apples
  ...
  def as_json(options={})
    opts = {:include => [:not_apples]}
    super(options.reverse_merge! opts)
  end
end

検索コントローラー

class SearchController < ApplicationController
  a = Apples.search params[:q]
  o - Oranges.search params[:q]

  @results = {
    :apples => a,
    :oranges => o
  }

  respond_to do |format|
    format.json { render :json => @results }
end

ご覧のとおり、2 つのモデルはまったく無関係であり、両方:includeの定義に異なるオプションがありますas_json

検索クエリがリンゴのみにヒットするか、オレンジのみにヒットする場合、すべてが期待どおりに機能しますが、両方のオブジェクトが空でない場合は、次のようになります。

undefined method `not_apples' for #<Oranges:0x00000004af8cd8>

2 つのas_json定義がマージされているか、Oranges.as_jsonによってオーバーライドされているようApples.as_jsonです。

これは予想される動作ですか?RABL のようなものを使用せずに、それを回避するクリーンな方法はありますか? 私のニーズにはやり過ぎだと思います。

4

1 に答える 1

1

擬似コードでは、ハッシュas_jsonメソッドのコードは次のようになります。

def as_json(options={})
  Hash[collect {|key,element| [key.to_s,element.as_json(options)]}]
end

しかし、あなたの要素は、あなたが渡した options 引数を変更しています。Hash はこれを認識しないため、変更されたオプション ハッシュを に渡しますas json

通常は、渡された引数をその場で変更しないことをお勧めします。ただし、問題がないことが非常に明確な場合を除きます。私はあなたの方法を次のように書き直します

def as_json(options={})
  defaults = {:include => :not_apples}
  super(defaults.merge(options))
end
于 2012-07-12T07:17:50.940 に答える