Ruby on Rails - Render JSON for multiple models
One way you could do this is to create a hash with the objects you want to render, and then pass that to the render method. Like so:
respond_to do |format|
format.json { render :json => {:moulding => @moulding,
:material_costs => @material_costs }}
end
If the models aren't associated through active record, that's probably your best solution.
If an association does exist, you can pass an :include
argument to the render call, like so:
respond_to do |format|
format.json { render :json => @moulding.to_json(:include => [:material_costs])}
end
Note that you wouldn't have to retrieve the @material_costs
variable in the section above if you take this approach, Rails will automatically load it from the @moulding
variable.
responding with multiple JSON renders. (Ruby/Rails)
you could actually do it like so:
format.json {
render :json => {
:websites => @allWebsites,
:pages => @allPages,
:element_types => @AllElementTypes,
:element_data => @AllElementData
}
}
in case you use jquery you will need to do something like:
data = $.parseJSON( xhr.responseText );
data.websites #=> @allWebsites data from your controller
data.pages #=> @allPages data from your controller
and so on
EDIT:
answering your question, you don't necessarily have to parse the response, it's just what I usually do. There's a number of functions that do it for you right away, for example:
$.getJSON('/info', function(data) {
var websites = data.websites,
pages = data.pages,
...
});
How to render two json objects as response on a rails controller
An easy way to do this is to build a hash with your objects
complex = Complex.find(params[:id])
search_params = {complex_id: complex._id}
fields = Field.where(search_params)
render json: { complex: complex, fields: fields, search_params: search_params }, status: :ok
Another way would be to user a view such as some_view.json.erb
where you render the objects as you are expecting it in your angular view. Also you can use can use ActiveModelSerializers, read on https://github.com/rails-api/active_model_serializers
Ideally what you will want to do is encapsulate this response into its object and make a single call in your controller that returns you the results
Without going into too much details something like this
results = MyComplexFieldsObj.response(params[:id])
render son: results, status: :ok
Multiple response with render :json
You need to call render json:
just one time.
One way to work around this is to build a single JSON that would contain both objects you want to return.
render json: {:errors => @user.errors.full_messages,
:other_element => other_element }
Rails Render Multiple in controller Using Json API
What I understand is that you want to return a multipart JSON containing more than 1 type of resources, articles, news and users in your case. And if I understand it right, here's a piece of code which might help you.
Let's say you have a controller called manage_content.rb
, write a function inside it.
def return_content
@articles = Article.where(:is_published => true).order('created_at DESC').page(params[:page]).per(6)
@news = Article.where(:news => true)
@users = User.all
# This is will create a single object with embedded arrays of your resource objects inside.
@content = {
articles: @articles,
news: @news,
users: @users
}
render json: { :data => @content, :status => 200 }
end
And in your config/routes.rb, add the corresponding route
get 'render_content' => "manage_content#return_content"
Test it by firing localhost:3000/render_content
from your broswer. This should render you a JSON like,
{
data:
{
articles: [
{.....},
{.....}
],
news: [
{.....},
{.....}
],
users: [
{.....},
{.....}
]
},
status: 200
}
Remember that articles, users and news are JSON arrays. Mind the arrays and objects while parsing the json response at your front-end.
Regards.
Rails 4 render json with multiple objects and includes
Without adding any gems:
def index
boats = Boat.includes(:year)
render json: {
boats: boats.as_json(include: { year: { only: :name } }),
numTotalBoats: boats.count
}
end
At some point though, I believe you should use stand-alone serializers:
Note: Depending on whether you're using pagination gem or not, you might need to change .count
calls below to .total_count
(for Kaminari) or something else that will read the count correctly from paginated collection.
I recommend using ActiveModel Serializers and this is how it would be accomplished for your case.
Start by adding the gem to Gemfile:
gem 'active_model_serializers', '~-> 0.10'
Overwrite the adapter in config/initializers/active_model_serializer.rb:
ActiveModelSerializers.config.adapter = :json
Define serializers for your models,
# app/serializers/boat_serializer.rb
class BoatSerializer < ActiveModel::Serializer
attributes :name
has_one :year
end
# app/serializers/year_serializer.rb
class YearSerializer < ActiveModel::Serializer
attributes :name
end
And finally, in your controller:
boats = Boat.includes(:year)
render json: boats, meta: boats.count, meta_key: "numTotalBoats"
And you will achieve:
{
"boats": [
{
"name": "Boaty McBoatFace",
"year": {
"name": "2018"
}
},
{
"name": "Titanic",
"year": {
"name": "1911"
}
}
],
"numTotalBoats": 2
}
Adding that count in each index controller is a bit tedious, so I usually end up defining my own adapters or collection serializers in order to take care of that automatically (Tested with Rails 5, not 4).
# lib/active_model_serializers/adapter/json_extended.rb
module ActiveModelSerializers
module Adapter
class JsonExtended < Json
def meta
if serializer.object.is_a?(ActiveRecord::Relation)
{ total_count: serializer.object.count }
end.to_h.merge(instance_options.fetch(:meta, {})).presence
end
end
end
end
# config/initializers/active_model_serializer.rb
ActiveModelSerializers.config.adapter = ActiveModelSerializers::Adapter::JsonExtended
# make sure to add lib to eager load paths
# config/application.rb
config.eager_load_paths << Rails.root.join("lib")
And now your index action can look like this
def index
boats = Boat.includes(:year)
render json: boats
end
And output:
{
"boats": [
{
"name": "Boaty McBoatFace",
"year": {
"name": "2018"
}
},
{
"name": "Titanic",
"year": {
"name": "1911"
}
}
],
"meta": {
"total_count": 2
}
}
I think it's a little easier to parse this count for different endpoints and you will get it automatically while responding with a collection, so your controllers will be a little simpler.
Using multiple arguments for a json response controller action
This is how you would solve the problem with ActiveModelSerializers.
# Gemfile
# ...
gem 'active_model_serializers'
# app/controllers/games_controller.rb
# ...
def autocomplete
@games = Game.search(params[:query], fields: [{ title: :word_start }], limit: 10)
render json: @games
end
# app/serializers/game_serializer.rb
class GameSerializer < ActiveModel::Serializer
attributes :title, :box_art_url
end
In case you want to use a different serializer for the search results representation of games vs the normal representation you can specify the serializer:
# app/controllers/games_controller.rb
# ...
def autocomplete
@games = Game.search(params[:query], fields: [{ title: :word_start }], limit: 10)
render json: @games, each_serializer: GameSearchResultSerializer
end
Rails 4 - Simple include multiple JSON inside another JSON
I am not sure that I understand your question. If product_details
doesn't work, try this:
def update_quantity
@product = Product.by_id(params[:product_id])
respond_to do |format|
format.json {
render :json => @product.to_json(
{
:include => [ :current_price ],
:methods => [ :product_details ]
}
)
}
end
end
In your Product
model add:
def product_details
ProductDetail.availables.by_id(self.id)
end
If you want only some fields of product_details
:
respond_to do |format|
format.json {
render :json => @product.to_json(
{
:include => [
:current_price,
product_details: {
only: [
:field1,
:field2
]
}
]
}
)
}
end
Rails: rendering json with multiple objects
hope to help you
def index
@beers = Beer.all
@micros = Micros.all
render json: {
beers: ActiveModel::Serializer::CollectionSerializer.new(@beers, each_serializer: BeerSerializer),
micros: ActiveModel::Serializer::CollectionSerializer.new(@micros, each_serializer: MicroSerializer),
}
end
Related Topics
How to Sort a Ruby Hash Alphabetically by Keys
Require Lib in Rspec with Ruby 1.9.2 Brings "No Such File to Load"
How to Remove All Elements That Satisfy a Condition in Array in Ruby
What Is the Point of Object#Presence in Rails
Ruby: How to Calculate a Path Relative to Another One
Add_Foreign_Key VS Add_Reference in Rails
How to Find a Memory Leak on Heroku
Rails: Difference Between Env.Fetch() and Env[]
Decoding Facebook's Signed Request in Ruby/Sinatra
How to Tell If I'm Running from Jruby VS. Ruby
Carrierwave How to Get the File Extension
How to Select Array Elements in a Given Range in Ruby
Ruby: How to Send a JSON Post Request Using Curb
Create Hash from Array and Frequency
Rails Nested With_Option :If Used in Validation
How to Resolve Deprecation Warnings for Openssl::Cipher::Cipher#Encrypt