I am rendering one record with with association like below
render :json => Scheme.where("id=?", params[:id]).first
.to_json(:include => { :navs => { :only => [:schemeCode,:navDate,:navValue] }})
Associations
Scheme has_many navs
Nav belongs_to scheme
I need to render only last record in Nav , but above will print all the navs since its one to many. I tried :limit => 1 and ordering it in desc , buts limit itself not working.Any help will be appreciated.
render :json => Scheme.where("id=?", params[:id]).first
.to_json(:include => { :navs => { :only => [:schemeCode,:navDate,:navValue], :limit => 1 }})
If you're creating a complicated json format, try gem 'jbuilder' introduced in RailsCast to leave the structure to view.
In your show.json.jbuilder view, make it something like:
#scheme = Scheme.find(params[:id])
json.scheme #scheme.as_json
json.extract! #scheme.navs.last, :schemeCode, :navDate, :navValue
which will render the data in json format as well as keep your controller clean & neat.
The use of Scheme.where("id=?", params[:id]).first in your code can be shortened as Scheme.find(params[:id]) if your id is unique.
Related
How can I expand associations more than one level deep? Right now I can expand reviews but am not sure how to also expand the patient_profile_id?
class Review
belongs_to :patient_profile
end
render json: doctors.to_json(
:include => {:reviews => {:include => :patient_profile_id }}
)
I'd highly suggest you check out the jbuilder gem. There's a great railscast that explains it's usage.
Basically, you will have to add a jbuilder file into your views, that gives you allot more control over your json.
For your specific use case you'd use something like this:
doctors/index.json.jbuilder
json.doctors #doctors do |json, doctor|
json.(doctor, :id, :name)
json.reviews doctor.reviews do |json, review|
json.(review, :id, :rating, :patient_profile_id)
json.patient_profile review.patient_profile do |json, profile|
json.(profile, :id, :name, ... ) # attributes of the profile
end
end
end
Try to use something like this:
render json: doctors.to_json(
:include => {:reviews => {:include => :patient_profile }}
)
Here you can find detail information how to serialize nested objects.
Check for overriding as_json method
I have the followin Ruby + Rails code
render :json => enterprise.to_json(:include => { :v3_passengers => { :include => [:cost_center, :restrictions]}})
And I need to apply a WHERE filter using one of the fields of the v3_passengers model before rendering it as json (for example "where v3_passenger.id = 2345")
I have tried this
render :json => enterprise.includes(:v3_passengers).where(enterprise_country: Thread.current['CurrentBehaviour'].COUNTRY).includes(:cost_center, :restrictions).to_json
But is not working, I have looked arround whitout any look in how to achieve this.
UPDATE
This are how the models are related
class Enterprise < ActiveRecord::Base
has_many :v3_passengers
class V3Passenger < GlobalDB
has_many :restrictions
belongs_to :cost_center
1. First you need to filter by joins or includes:
foo = enterprise.joins(:v3_passengers).where(v3_passengers: {enterprise_country: Thread.current['CurrentBehaviour'].COUNTRY})
or (prefered includes, since you are going to need v3_passengers )
foo = enterprise.includes(:v3_passengers).where(v3_passengers: {enterprise_country: Thread.current['CurrentBehaviour'].COUNTRY})
2. Then include the other nodes you need in the to_json:
foo.to_json(include: [v3_passengers: { include: [:cost_center, :restrictions] } ])
Final Result:
render :json => enterprise.joins(:v3_passengers).where(v3_passengers: {enterprise_country: Thread.current['CurrentBehaviour'].COUNTRY}).to_json(include: [v3_passengers: { include: [:cost_center, :restrictions] } ])
The problem is that:
model.includes(:other_model).to_json
Isn't the same as:
model.to_json(include: :other_model)
So your first attempt is giving you all the fields of Enterprise, V3Passenger, Restriction and CostCenter in the output. Your second attempt is just giving you fields of Enterprise.
One potential fix is:
enterprise.joins(:v3_passengers).where("v3_passengers.id=?",2345).to_json(include: :v3_passengers)
(Including the other tables of course.)
This will give you JSON for all the Enterprises with v3_passengers.id=2345, including JSON for all their V3Passengers (even the V3Passengers who don't have id 2345).
If you only want to include V3Passengers who match the where clause then you need to add a scoped association to the model:
has_many :v3_passengers_where_id_2345, -> { where id: 2345 }
And then use that association when doing the JSON conversion:
enterprise.joins(:v3_passengers).where("v3_passengers.id=?",2345).to_json(include: :v3_passengers_where_id_2345)
This will give you JSON for enterprises who have v3_passengers.id=2345, including only their V3Passengers who have id 2345.
The second shot is close to working variant.
render :json => enterprise.v3_passengers.where(enterprise_country: Thread.current['CurrentBehaviour'].COUNTRY).includes(:cost_center, :restrictions).to_json
Try to use some relation.
For more clear answer add your key models listings, Enterprice and passengers models.
if you need the enterprise attributes in the resulting json:
render :json => enterprise.joins(:v3_passengers).where("v3_passengers.enterprise_country = ?", Thread.current['CurrentBehaviour'].COUNTRY).to_json(include: [v3_passengers: { include: [:cost_center, :restrictions] } ])
if you just need the passengers:
render :json => enterprise.v3_passengers.where(enterprise_country: Thread.current['CurrentBehaviour'].COUNTRY).includes(:cost_center, :restrictions).to_json( include: [:cost_center, :restrictions])
In a rails app I have an action that returns a json representation of a collection of different models. It looks something like this:
respond_to :json
def index
#cars = Car.all
#vans = Van.all
respond_with({
:cars => #cars,
:vans => #vans
})
end
However, I want to customise the attributes and methods that are passed to the json object. A bit like:
respond_with({
:cars => #cars.to_json(:only => [:make, :model], :methods => [:full_name]),
:vans => #vans
})
Doing the above, causes the json representation of the "cars" to be escaped as one big string, like:
{
"cars":"[{\"car\":{\"make\":\"Ford\" ... etc
"vans": [{"van":{"make":"Citreon" ... vans not escaped
}
Obviously I'm approaching this the wrong way. Can anyone point me in the right direction?
Since you're nesting the to_json in another Hash, I think you need to use as_json (which returns a Hash instead of a String) instead:
respond_with({
:cars => #cars.as_json(:only => [:make, :model], :methods => [:full_name]),
:vans => #vans
})
I have problems to restrict an as_json include by a dynamic attribute:
#pirates_ships = #current_account.pirates.as_json(:include => {:ships => {:only => [:id, :name]}}, :only => [:id, :last_name])
This for sure gives me all pirates with or without their ships.
But I also need to restrict the ships by e.g. ships.ocean_id
I tried resolving it by includes with conditions:
pirates.includes(:ships).where("ships.ocean_id = ?", #ocean.id).as_json(...)
The restriction works, but now all pirates without a ship are lost.
Also no luck with my own JOIN Syntax.
Any ideas?
Ahoy
UPDATE
My solution so far is to manually eager load. This way I can have my dynamic conditions:
#pirates = #current_account.pirates
#ships = #current_account.ships.where({:pirate_id.in => #pirates, :ocean_id => #ocean.id})
render :json => { :pirates => #pirates.as_json(...), :ships => #ships.as_json(...) }
My Ajax callback can now iterate over :pirates and add for each pirate his ships if any.
(I use a JS template engine clientside to generate the view from the JSON response)
Not very elegant, but performance is important in my case.
I'am still open for better ideas.
I tried dynamic has_many :ships, :conditions => ...
but that's a bit fiddly.
I think your best bet would be altering the #pirates_ships hash after generating it from as_json (I tried multiple variations of includes, etc. and couldn't get anything to work).
#pirates_ships = #current_account.pirates.as_json(:include => :ships)
#pirates_ships.each do |pirate|
pirate[:ships].delete_if{ |ship| ship.ocean_id != #ocean.id }
end
# Now, #pirates_ships should contain ALL pirates, as well as ships for #ocean
i am changing from WebORB to Warhammerkids Rails3-amf - great choice, even tehre are some open issues. One those issues is, how can I get records from an association to the array, which is sent back to the Flex-Application.
In WebORB the method of the controller looks like:
def getClients(clientFilter,myMandant)
clients = Client.find(:all, :conditions => {:account_id => myMandant}, :include => [:addresses, :contacts, :proofs])
end
in Rails3-amf I have a similar construction:
def getClients()
#clients = Client.find(:all, :conditions => {:account_id => params[1]}, :include => [:addresses, :contacts, :proofs])
respond_with(#clients) do |format|
format.amf { render :amf => #clients}
end
With this code I get back all correctly typed Client Objects as an Array, but without the records from the ":include" argument.
How can I handle this ??
I also tried another way with:
....
respond_with(#clients) do |format|
format.amf { render :amf => #clients.to_amf(:include => [:addresses, :contacts, :proofs])}
....
With this try I got an error message" undefined method to_amf for #.
Thanks for any help.
I don't know about rail3-amf, but you might find it worthwhile having a look at restfulx - https://github.com/dima/restfulx/tree/rails3
It consists of a library for rails, and a library for flex. It supports data transfer through json, xml, or amf.
The actionscript api for working with models is very nice too:
var user:User = new User();
user.first_name = "Ed";
user.create();
It can also keep track of rails associations etc.:
trace(user.account.title);
See more usage here - https://github.com/dima/restfulx_framework/wiki/Working-with-RestfulX-Models