Reputation: 623
Given two models and a controller:
Apples
class Apples < ActiveRecord::Base
belongs_to :not_oranges
...
def as_json(options={})
opts = {:include => [:not_oranges]}
super(options.reverse_merge! opts)
end
end
Oranges
class Oranges < ActiveRecord::Base
belongs_to :not_apples
...
def as_json(options={})
opts = {:include => [:not_apples]}
super(options.reverse_merge! opts)
end
end
Search Controller
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
As you can see, the two models are completely unrelated and both have different :include
options in their as_json
definitions.
All works as expected if the search query only hits apples or only hits oranges, but once both objects aren't empty I get:
undefined method `not_apples' for #<Oranges:0x00000004af8cd8>
Seems either the two as_json
definitions are being merged, or Oranges.as_json
is being overriden by Apples.as_json
.
Is this expected behaviour? Is there any clean way around it without using something like RABL? I feel it would be overkill for my needs.
Upvotes: 0
Views: 250
Reputation: 84134
In pseudo code the code for hash as_json
method looks like
def as_json(options={})
Hash[collect {|key,element| [key.to_s,element.as_json(options)]}]
end
But your element is modifying the options argument you pass to it. Hash is unaware of this and so passes the modified options hash to as json
.
It's usually a good idea not to modify in place the arguments passed to you, except when it is very clear this is ok. I'd rewrite your method as
def as_json(options={})
defaults = {:include => :not_apples}
super(defaults.merge(options))
end
Upvotes: 1