web-dev-qa-db-ja.com

Ruby on Rails高度なJSONシリアル化

Railsアプリで、JSONを介してすべての記事のインデックスと完全な記事をレンダリングしようとしていますが、その方法を理解するのに少し問題があります。

これが私のコントローラーです。

if params[:id]
    @article = Article.find(params[:id])
else
    @article = Article.published.not_draft.by_recent.first
end

respond_to do |format|

format.js { render :json => @article.to_json(
:except => [ :created_at, :updated_at, :draft, :id, :publish ], 
:include => {
    :comments => {
        :only => [:body]
    }
}),
:callback => params[:callback]}
end

応答でやりたいのは、次のようにすべての記事のインデックスを追加することです。

@index = Article.find(:all, :select => 'id, title')

私がそれを行うことができた唯一の方法は、インデックスと記事の両方をハッシュまたは配列に入れてから、それをJSONに入れることです。

@response = { :item => @article, :index => @index }

両方を含む完全なコード:

@index = Article.find(:all, :select => 'id, title')

if params[:id]
    @article = Article.find(params[:id])
else
    @article = Article.published.not_draft.by_recent.first
end

@response = { :item => @article, :index => @index }

respond_to do |format|

format.js { render :json => @response.to_json(), :callback => params[:callback]}

end

:includeまたは:exceptを指定して、正しくレンダリングできない場合を除いて、これで問題ありません。

18
Brad

あなたはあなたの質問の解決策をほのめかします。 JSONにレンダリングするハッシュを作成することをお勧めします。現在これを行うための好ましい方法は、as_jsonメソッドの実装を提供することです。 as_jsonは、エンコードするデータを含むハッシュを構築することにより、to_json出力をカスタマイズする正式な手段を提供します。

As_jsonとto_jsonがどのように相互作用するかについてのより徹底的な扱いは、 Jonathan Julianのウェブログ にあります。

28
nirvdrum

明確にするために、上記のコードは:includeと:exceptで機能します。そして、作品とは、エラーをスローしないことを意味します。問題は、インデックス内のすべての記事に対するコメントが含まれていることです。インデックスにリストされている記事ではなく、:itemへのコメントのみを含めたいと思っています。

ネストをハッシュまたはOpenStructオブジェクトとして機能させることができませんでした。

:includeにネストするとエラーがスローされ、:exceptにネストしてもエラーはスローされませんが、何も除外されず、:created_atなどは引き続き表示されます。

...

@response = { :item => @article, :index => @index }

format.js { render :json => @response.to_json(
:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}, 
:include => { :item => {
        :comments => {
                :only => [:body]
        }
}}),
:callback => params[:callback]}
end
2
Brad

to_jsonには、名前を付けたメソッドの結果を含む:methodオプションがあります。そのモデルで、JSONに必要な追加データを返すメソッドを定義できます。

1
DavidNorth

(回答を受け入れてください)

Nirvdrumが与えたリンクがあなたの答えを保持していると思います。誰もencode_jsonについて言及していないので、私は答えるだけです。

あなたの場合、あなたはas_jsonだけを扱っているべきです。ハッシュを作成し(as_jsonをさまざまに呼び出して)、それをrender :json => ...に送信する(to_jsonを呼び出さない)か、モデルにas_jsonを実装してRailsすべての作業を行います。(ただし、前者が必要になると思います。)

レンダリングされた応答にいくつかの凝ったjsが本当に必要な場合は、クラスにencode_jsonを実装できます(ここでも、to_jsonではありません)。例えば:

class JsEmptyClosure
  def encode_json(*args)
    "jQuery[\"noop\"] || function(){}"
  end
  def as_json(*args) self end
end

これは、有効なjsでto_jsonに応答するようになります(ただし、実際にはjsonではないことに注意してください)。

1
Corin

:include:exceptなどを次のようにネストできるはずです。

:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}...

それが機能しない場合は、ハッシュではなくオブジェクト(OpenStructなど)にします。

-マーカス

1
MarkusQ

質問をありがとう、私はいくつかの関連付けを持つモデルのjson形式をカスタマイズすることができます。

jsonをレンダリングします:@ posts.to_json(

:except => [:created_at、:updated_at、:user_id]、

:include => {

:user => {:only => [:email、:phone]}、

:location => {:only => [:title、:lat、:lon、:street、:city、:state、:zipcode]}、

:uploads => {:only => [:image]}

}

0
Guoqiang Huang

To_json出力で自動的に使用される代替ハッシュを返すようにattributesメソッドをオーバーロードすることをお勧めします。

class Article
   def attributes
     { ... } # define your hash that you want to return at the '...'
   end
end

私には、これはto_jsonを直接いじくり回すよりもはるかに簡単に思えます。

0