Responding with Multiple JSON Renders. (Ruby/Rails)

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



Leave a reply



Submit