Rails Controller Display a of List of Resources/Objects? - ruby-on-rails

For my app I have three models: Quotes, Images, Videos, all of them I consider content. I want to call the index action of my ContententController to display a mix of these objects in JSON format. For example, I get something like this back.
[
{ ...image json... },
{ ...image json... },
{ ...video json... },
{ ...quote json... },
{ ...image json... }
]
How would I approach this? I feel like this has something to do with an SQL UNION? Thank you!

If you consider all three "content", then you really should use a single table inheritance strategy where they all inherit from the Content model. That way you can call
#Contents = Content.all.whatever
Instead of having to call each and then mix them together, or getting more complex then you need with the query. Turning them into JSON would then be easy considering each object would have its normal to_json method called on it, when doing something like this
format.json {render :json => #Contents}

def index
#quotes = Quotes.all
#images = Image.all
#videos = Video.all
#contents = #quotes + #images + #videos
format.json {render :json => #contents}
end
I think you can just append each object, but I wont recommend you to do that.

Related

Problem with selecting elements with the same params

What i do wrong? I want to return every products which pass condition:
def show
products = Product.select{|x| x[:category_id] == params[:id]}
render json: products
end
When i write
def show
products = Product.select{|x| x[:category_id] == 1}
render json: products
end
it works why the first example doesn't work?
I am pretty sure that there is mismatch in data type.
1=='1' #will be always false
1==1 #will be true
'1'=='1' #will be true as well
And also check for nil value from params[:id]
Please make sure to change as follows
def show
products = Product.select{|x| x.category_id == params[:id].to_i}
render json: products
end
OR
The best solution as suggested by #Eyeslandic is to use .where as it will not check for mismatch in data type. And also you don't have to take care of nil value from params[:id].
You should really be using a where to stop sql from loading all your products.
#products = Product.where('category_is = ?', params[:id])
The being said, if you are sticking to rails restful conventions, the fact you have a param called :id that is the category_id suggests you are on the category controller. So maybe consider changing your logic to:
#category = Category.includes(:products).find(params[:id])
you can then access products via
#category.products
or if your not interested in the category too much maybe
#products = Category.includes(:products).find(params[:id])&.products

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

Make root node in Active Model Serializer

I have an array of JSON in my Rails App in this format using Active Model Serializer:
[
{
"contact" : {}
},
{
"contact" : {}
}
]
How do I make it so that I remove one level of node above the contact USING active model serializer like this:
[
{
},
{
}
]
I also want to remove the node name "contact".
This was covered in RailsCast #409 Active Model Serializers.
In order to remove the root node, you add root: false in the call to render in your controller. Assuming your contacts in JSON come from a contacts#index method, your code may look something like:
def index
#contacts = Contacts.all
respond_to do |format|
format.html
format.json { render json: #contacts, root: false }
end
end
Or, if you don't want any root nodes in any of your JSON, in your ApplicationController, add the following method:
def default_serializer_options
{root: false}
end
For people using ActiveModel::Serializer v0.10.x, you will need to create an initializer and include the following:
# config/initializers/serializer.rb
ActiveModelSerializers.config.adapter = :json
ActiveModelSerializers.config.json_include_toplevel_object = true
Then, just restart your app and you should get the root objects you desire.
This works in Rails 5.1.x. YMMV. HTH.
Usually the root node has the name of your controller by default if I am not wrong.
format.json { render json: #contacts}
Of course you need to remove root false, it removes the node's name.
If you want contact as root object use this:
format.json { render json :#contacts, :root => 'contact' }
/config/initializers/serializer.rb
ActiveModelSerializers.config.adapter = :json_api # Default: `:attributes`
By default ActiveModelSerializers will use the Attributes Adapter (no
JSON root). But we strongly advise you to use JsonApi Adapter, which
follows 1.0 of the format specified in jsonapi.org/format.

Sending a query string to rails respond_to

I am rather new to ruby and rails development.
for the past little while, I have been trying to figure out how I can pass params/query string to a rails respond_to block. I am focusing on the json response.
Say I have the following
def index
#employees = Employee.all
respond_to do |format|
format.html
format.json { render json: #employees }
end
end
and I am looking to only get a json response containing employees who have an id that is greater than 500. What would be the best way to go about this.
I have been trying to make the json request using jQuery.ajax() and I know you can pass data to the server that is formatted to a query, but not sure how to make it work.
The above example is only hypothetical. I am only looking for a way to be able to use a query sting when wanting a json response.
Thanks for the help!
Whatever parameters are sent with the request (in the query string) should be available in your controller (check the params variable). Here's one way to get the Employees with id's at & above 500:
Replace
#employees = Employee.all
with
#employees = Employee.find(:all, conditions: ["id >= ?", 500])
Please note that you don't need to pass anything besides the format to that respond_to block.

Array of ActiveRecords to JSON

I am aware that ActiveRecord provides a to_json method which allows fields to be filtered out of the JSON output using :only and :except.
At present I am using the following to format an array from a find as JSON:
#customers = Customer.find(:all)
...
format.js { render :json => #customers}
How would I be able to select the fields to be output in the objects in the array? Is there a shortcut or do I need to do this by hand?
Cheers,
Adam
I think you answered your own question. With Rails 2.3.x you could use the following:
#customers = Customer.all #Shortcut for to Customer.find(:all)
respond_to do |format|
format.js { render :json => #customers.to_json(:only=>[:column_one, :column_two]}
end
You can overwrite the to_json method of the model class if you want to globally apply the change for the model.
For example, to exclude null values from the rendered JSON you could overwrite the original ActiveRecord method to_json
def to_json(options)
hash = Serializer.new(self, options).serializable_record
hash = { self.class.model_name => hash } if include_root_in_json
ActiveSupport::JSON.encode(hash)
end
with this in your model class:
def to_json(options)
hash = Serializer.new(self, options).serializable_record.reject {|key, value| value.nil? }
hash = { self.class.model_name => hash } if include_root_in_json
ActiveSupport::JSON.encode(hash)
end
If you peep into the ActionController::Base class, you'll see that it calls to_json on your collection immediately (no extra options used), so you've got to have it already prepared. So if in your action you don't use the attributes that are not rendered to json, you can replace your find with
#customers = Customer.find(:all, :select => ["id", ...])
to select only the ones that you need.

Resources