Rails 6 jbuilder not rendering array properly - ruby-on-rails

I have a problem with rendering array properly with JBuilder on Rails 6 (API only mode).
I basically have a list of registration plates, which I want to fetch via API request
My index view looks like this:
# frozen_string_literal: true
json.array! #registration_plates,
partial: 'registration_plates/registration_plate',
as: :registration_plate
My show view looks like:
# frozen_string_literal: true
json.partial! 'registration_plates/registration_plate',
registration_plate: #registration_plate
And finally partial _registration_plate.json.jbuilder is very simple:
# frozen_string_literal: true
json.id registration_plate.id
json.plate registration_plate.plate.to_s
I do get a normal response from server:
But instead of an array, I get the series of JSON objects
Did anyone have similar problem, or do you have any idea how to solve it?
Than you in advance.
EDIT
Also my controller is configured to render the jbuilder rather than json
# GET /registration_plates
def index
#registration_plates = RegistrationPlate.all
render #registration_plates
end
# GET /registration_plates/1
def show
render #registration_plate
end
And if I change the index action to look like
def index
#registration_plates = RegistrationPlate.all
render json: #registration_plates.to_json(only: %i[id plate])
end
i do get correct output, but then, I defy the sole purpose of jbuilder

update your index to remove render #registration_plates
# GET /registration_plates
def index
#registration_plates = RegistrationPlate.all
end
render #registration_plates renders _registration_plate.json.jbuilder directly without going into index.json.jbuilder

Related

Rails respond with paperclip image.url multiple URLs

I'm building a simple rails application where users can upload some images. Now I need a simple controller that returns the image's URLs of related record which have the same id_attivita. To do so I create a function in the controller and enable it in the routes.rb file.
My question is about how to respond to the http request with the attribute value of image.url provided from paperclip?
def getattached
#photo_attivitum = PhotoAttivitum.where(id_attivita: params[:id_attivita])
respond_to do |format|
#photo_attivitum.each do |p|
format.html { render :json => p.image.url}
end
end
end
it works but it returns only the URLs of the first record not the other four record's URLs...
How can I do this?
Add the following gem to your Gemfile
gem 'active_model_serializers'
Then install it using bundle
bundle install
You can generate a serializer as follows
rails g serializer photo_attivitum
it will create Serializer class file in
# app/serializers/photo_attivitum_serializer.rb
class PhotoAttivitumSerializer < ActiveModel::Serializer
attributes :id, :image_url
def image_url
object.image.url
end
end
And in controller
def getattached
#photo_attivitum = PhotoAttivitum.where(id_attivita:
params[:id_attivita])
render json: #photo_attivitum
end
Not sure what u want to do? Show all image urls in json?
urls = #photo_attivitum.pluck('image_url')
format.html { render :json => urls}

Rails 4 - How to render JSON regardless of requested format?

I'd like a Rails controller (all of them, actually, it's an API) to render JSON always always.
I don't want Rails to return "route not found", or try and fail to find an HTML template, or return 406. I just want it to automatically and always render JSON, e.g. from a RABL or JBuilder view.
Is this possible? Related questions seem to have answers that have the aforementioned downsides.
You can add a before_filter in your controller to set the request format to json:
# app/controllers/foos_controller.rb
before_action :set_default_response_format
protected
def set_default_response_format
request.format = :json
end
This will set all response format to json. If you want to allow other formats, you could check for the presence of format parameter when setting request.format, for e.g:
def set_default_response_format
request.format = :json unless params[:format]
end
You can use format.any:
def action
respond_to do |format|
format.any { render json: your_json, content_type: 'application/json' }
end
end
It's just:
render formats: :json
I had similar issue but with '.js' extension. To solve I did the following in the view:
<%= params.except!(:format) %>
<%= will_paginate #posts %>
I tried the above solutions and it didn't solve my use case.
In some of the controllers of my Rails 4.2 app, there was no explicit render called. For example, a service object was called and nothing was returned. Since they are json api controllers, rails was complaining with a missing template error. To resolve I added this to our base controller.
def render(*args)
options = args.first
options.present? ? super : super(json: {}, status: :ok)
end
It's a large app I'm converting to Rails 5, so this is just a safety measure as I removed the RocketPants gem that seemed to do this automatically.
As a note, my controllers inherit from ActionController::Base
Of course:
before_filter :always_json
protected
def always_json
params[:format] = "json"
end
You should probably put this in a root controller for your API.

Rails 4 json return on API

I'm creating an API on my application. I currently overrided the as_json method in my model in order to be able to get attached files as well as logo from Paperclip :
def as_json( options = {} )
super.merge(logo_small: self.logo.url(:small), logo_large: self.logo.url(:large), taxe: self.taxe, attachments: self.attachments)
end
Then within my controller, I'm doing :
def index
#products = current_user.products
respond_with #products
end
def show
respond_with #product
end
The problem is that on the index, I don't want get all the attachments. I only need it on the show method. So I tried it :
def index
#products = current_user.products
respond_with #products, except: [:attachments]
end
But unfortunately it's only working on default product attributes (everyting that I merged seems not to be consider). How can I do to not send :attachments?
Thanks
I'd recommend you have a look at active_model_serializers. It will provide a nice and OOP way of handling the kind of object decoration you need - selectively excluding attributes - and much more. There's even a Railscast!

How to send JSON data using rails

Hi I am trying to create a custom controller that return a method as json.
Here my controller
respond_to :json
def rates
#event = Event.find(params[:id])
respond_with #event.avg_rating
end
Now I have my model with the following method
# returns the average rating for that event
def avg_rating
#avg = self.ratings.average(:stars)
#avg ? #avg : 0
end
However when i get the respond I get this:
3.75
What I would like is a standard json respond either {"event": "3.75"}
But I am not sure what to use to simply transform it to make an answer like that
You will need an actual object to be rendered to json. A hash is usually easiest. And you will want to use render instead of respond_with
render json: {:event => #event.avg_rating}

Rails : render and exit immediately

Using the omniauth gem, I am forced to define a single route callback for succesful logins, regardless of the provider :
def auth_callback
auth_data = request.env['omniauth.auth']
if auth_data.has_key('something')
process_one(auth_data)
else
process_two(auth_data)
end
# No view is available here
end
def process_one
# do something then render view for process_one
return
end
def process_two
# do something then render view for process_two
return
end
How can I prevent the controller from returning to the auth_callback method and try to display the corresponding view (which does not exist) ? Treatment should be considered as complete once the process_one or process_two methods have returned.
Why not specifically call render in those methods?
def process_one
# do something then render view for process_one
render :process_one and return
end
Rails should detect that you've already run it and not try to render again.
If you want to return from the chain of methods, e.g.
def a
...
b
...
render "smth"
end
...
def b
...
# render from some conditional from here
...
end
will cause AbstractController::DoubleRenderError, which means that you call render twice.
You can read this article to find out 4 ways to manage such situation.

Resources