Association data into json output in Rails - ruby-on-rails

I have a model where I can get my index action to return a list of objects back as json but I need each one to return a list of sub elements over an association.
I have tried the following but the coasters are not being output. Is there a way this can return each parks coasters?
format.json do
render json: Park.scoped(include: :coasters)
end

Try something like :
render json: Park.joins(:coasters).select("parks.*,coasters.*") # parks.*, coasters.* refers to actual table names

This could be achieved with active_model_serializers gem.

the code should looks like this
format.json do
render json: Park.scoped.to_json(include: :coasters)
end
more info can be find here https://github.com/rails/rails/pull/2200

Related

postgres_ext-serializer each_serializer Rails 5 adding custom JSON meta data

I'm using Rails 5.2.3, postgres_ext (3.0.0), active_model_serializers (0.8.4), I am trying to render JSON data in the format of
{
total: 500,
totalNotFiltered: 500,
rows: [
...
]
}
I am able to get close but I am not able to get the additional custom fields added.
So far I have
respond_to do |format|
format.json { render json: #people, each_serializer: PersonSerializer, root: :rows, meta{total: 500, totalNotFiltered: 500}}
end
This gives the correct root :rows, but the meta data isnt being added.
The postgres_ext gem does great in getting the JSON rows correctly, down from 190ms av to 25ms av, so I want to use this. I have tried FastJSON (Netflix) but that is far slower and again not easy to format the output generated.
It might be something simple here but I can fathom how to add the 2 elements missing. Ideas or suggestions please
in array_serializer.rb of the postgres_ext-serializers-0.0.3 gem, I can hack this JSON string by adding the options I need, then added it as a patch for a temp solution. If someone has a better idea or way, please advise.
in the controller (this is for bootstraptable btw)
render json: #people, each_serializer: PersonSerializer, root: :rows, total: #people_count, totalNotFiltered: Person.all.count}
then serializer.rb
module IncludeMethods
def to_json(*)
root = #options.fetch(:root, self.class.root)
total = #options[:total]
totalNotFiltered = #options[:totalNotFiltered]
if ActiveRecord::Relation === object && root != false
total = "{\"total\":\"#{total}\",\"totalNotFiltered\":\"#{totalNotFiltered}\","
_postgres_serializable_array.sub('{', total)
else
super
end
end
end
Its not the best but it works for now

rails select query creating alias for attribute name

With the goal of creating a JSON string, the requirement is to use an existing attribute and assign it, in the JSON output, with the attribute name id.
#valids = Destination.limit(10).select(:name, :long_name, :other_code).as_json(except: :id)
except: :id is being invoked to avoid confusion, as other_code attribute is intended to be the id in the generated JSON.
this will then be transformed into valid JSON via
#valids.to_json
how can other_code be output as id ?
You can do this like that with a simple string instead of symbols.
Destination
.limit(10)
.select('name, long_name, other_code as id')
.as_json
Honestly am new to Ruby on rails but very experience with json and frontend application responses
You can try this. if it work, you can now try it with your database responses. Ensure that column id exist in that your database
def your_definition_here
respond_to do |format|
#valids='999'
format.json do
render json: {id: #valids}.to_json
#render json: {id: #valids.id}.to_json
end
end
end

Returning JSON from Ruby on Rails api

I inherit a RoR api, that provides that to a angular app. I am new to RoR and I am having difficulties with the way the api returns data in json.
def getLocations
location = params[:name]
query = "select * from view_locations where lower(location_name) like lower('#{location}%') limit 4 "
propAll = Property.connection.select_all(query)
respond_to do |format|
if !propAll.blank?
format.json { render json: {status:"ok", data:propAll}}
else
format.json { render json: {status:"error"}}
end
end
end
This code returns this array:
[{"location_name":"Nuevo León","id":"19","quantity":"5988","type":"State"},{"location_name":"Naucalpan de Juárez, México","id":"09","quantity":"131","type":"City"},{"location_name":"Nayarit","id":"18","quantity":"91","type":"State"},{"location_name":"Nacajuca, Tabasco","id":"013","quantity":"20","type":"City"}]
Is there any way that I could return the JSON instead of an array?
If its not possible, how should I use the returned array in Angularjs, right now we are going through every array element and pushing it in another array .
Thanks, for any help provided
Alberto

Serialize an array of models using active_model_serializers

I am trying to send the serialized version of a model to a view as a param, using the gem active_model_serializers
#app/serializers/admin_serializer.rb
class AdminSerializer < ActiveModel::Serializer
attributes :id, :email, :access_locked?
end
#app/controllers/dashboard/admins_controller.rb
def index
#search = Admin.search(params[:q])
#admins = #search.result(:distinct => true).page(params[:page]).per(10)
#page_entries_info = view_context.page_entries_info #admins
# render json: #admins
respond_to do |format|
format.html
format.js
format.json {render json: #admins}
end
end
#app/views/dashboard/admins/index.html.erb
<%= debug (ActiveModel::Serializer::Adapter.adapter_class(:json_api).new(ActiveModel::Serializer.serializer_for(#admins.first).new(#admins.first),{}).to_json) %>
<%= debug (#admins.all.map{|admin| AdminSerializer.new(admin).to_json}) %>
Above debugs are yielding the below response:
--- '{"data":{"id":"1","type":"admins","attributes":{"email":"tech#bluesapling.com","access_locked?":false}}}' //returned by the first debug
---
- '{"object":{"id":36,"email":"aubrey_schmitt#feeneykoch.io","created_at":"2016-03-28T05:15:17.546Z","updated_at":"2016-03-28T05:15:17.546Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":20,"email":"alysa_johnston#thompson.io","created_at":"2016-03-28T05:15:16.304Z","updated_at":"2016-03-28T05:15:16.304Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":22,"email":"kristofer.langosh#kunzeluettgen.com","created_at":"2016-03-28T05:15:16.459Z","updated_at":"2016-03-28T05:15:16.459Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":37,"email":"beryl_keler#wiza.biz","created_at":"2016-03-28T05:15:17.624Z","updated_at":"2016-03-28T05:15:17.624Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":5,"email":"wilhelmine_buckridge#crona.io","created_at":"2016-03-28T05:15:15.139Z","updated_at":"2016-03-28T05:15:15.139Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":14,"email":"edward_wisoky#corkery.net","created_at":"2016-03-28T05:15:15.838Z","updated_at":"2016-03-28T05:15:15.838Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":27,"email":"leonor#jerde.biz","created_at":"2016-03-28T05:15:16.848Z","updated_at":"2016-03-28T05:15:16.848Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":2,"email":"carley#wyman.net","created_at":"2016-03-28T05:15:14.873Z","updated_at":"2016-03-28T05:15:14.873Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":10,"email":"ervin.gleichner#cremin.org","created_at":"2016-03-28T05:15:15.527Z","updated_at":"2016-03-28T05:15:15.527Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":15,"email":"lonzo.dickens#johnscole.name","created_at":"2016-03-28T05:15:15.916Z","updated_at":"2016-03-28T05:15:15.916Z"},"instance_options":{},"root":null,"scope":null}'
In the first debug I am serializing only one object, while in the second one I am trying to do it for an array of objects.
The first debug is correctly returning the serialized version of the object(in json_api format) while second debug is not.
Tried ArraySerializer as well, with no success: ActiveModel::Serializer::ArraySerializer.new(#admins, each_serializer: AdminSerializer).as_json
how do I achieve the desired serialization. Moreover, if achieved, can I used some other simplified version of this? As this debug statement is way too verbose.
Tried all the solutions mentioned here - How do you initialize an ActiveModel::Serializer class with an ActiveRecord::Relation array?
The basic problem which I am trying to solve is, in the index method of the Admin controller, the Admin object is passed as a PORO to the index.html file. But I want the serialized json version of this object so that I can pass it to my react components as a prop
index method is rendering proper json on firing http://dashboard.localhost.com:3000/admins.json
UPDATE#1 for the index method
def index
#search = Admin.search(params[:q])
#admins_array = #search.result(:distinct => true).to_a
if params[:page]
#admins = #search.result(:distinct => true).page(params[:page][:number]).per(10)
#admins_json_array = Kaminari.paginate_array(#admins_array).page(params[:page][:number]).per(10)
else
#admins = #search.result(:distinct => true).page(1).per(10)
#admins_json_array = Kaminari.paginate_array(#admins_array).page(1).per(10)
end
#admins_json = ActiveModel::SerializableResource.new(#admins_json_array.to_a)
...
...
...
end
I have a controller that I need to specify the serializer in, due to wanting different attributes from the default serializer.
In Controller:
def index
search = User.ransack(search_params)
render json: search.result, each_serializer: MembershipRenewalSerializer::MemberSerializer
end
So, just to get things working, what happens if you specify the each_serializer option?
Edits:
Outside Controller:
ActiveModel::SerializableResource.new(
User.first(2),
each_serializer: MembershipRenewalSerializer::MemberSerializer
).to_json
Note, that without specifying each_serializer, SerializableResource would use the UserSerializer.
Edit #2,
It looks like there is something weird happening with the #admins data.
Try converting to an array:
ActiveModel::SerializableResource.new(#admins.to_a).to_json
Edit #3
To paginate your array, try the following:
#search = Admin.search(params[:q])
#results = #search.result(:distinct => true).to_a
#admins = Kaminari.paginate_array(#results).page(params[:page]).per(10)
Follow the guide: Serializing before controller render
You could use ActiveModel::SerializableResource.new(#admins, adapter: :json_api).to_json
in index.html.erb
<%= debug (ActiveModel::SerializableResource.new(#posts, adapter: :json_api).to_json) %>
below is the output(using posts)
'{"data":[{"id":"1","type":"posts","attributes":{"title":"first post","body":null}},{"id":"2","type":"posts","attributes":{"title":"second post","body":null}}],"links":{}}
I create a concern with some API helper methods and there you can check if its a collection pass find the appropiate serializer and pass it to the collection serializer.
def api_response(data)
render json: wrap_answer(data)
end
def wrap_answer(data)
if data.respond_to?(:each)
ActiveModel::Serializer::CollectionSerializer.new(data, each_serializer: ActiveModel::Serializer.serializer_for(data.first))
else
data
end
end
should have made that into string and use json.stringify to make that as a string and make your life easy

Not adding data to associated table

With the code below and entry is created in the venuetypes table with the correct *venue_id* and time stamps however, the type column remains as null
def new
#new1 = "gfdsgfd"
#venue = Venue.new
#venue.save
#venuetype = #venue.venuetypes.create(:type => "test")
#venuetype.save
respond_to do |format|
format.html # new.html.erb
format.json { render json: #venue }
end
end
Unless you've specified otherwise, rails expects a type column to be used for single table inheritance which is probably causing problems.
Also, venuetypes.create will only save the venue type if it is created successfully, as will the .save call afterwards. You have almost certainly got an error on the venue type which is causing it not to be saved. Try using .save! which will throw an error or by lookins at #venuetype.errors which will contain any error messages that have caused it not to be saved.

Resources