Rails routes: json endpoint naming convention - ruby-on-rails

I have an endpoint that renders json:
def controller_method
render json: json_response
end
However, I am curious about the naming convention of the route. The following naming leads to ActionController::UnknownFormat Controller#controller_method is missing a template for this request format and variant.:
get '/controller/controller_method.json', to: 'controller#controller_method'
However, I successfully get the json when the route is named:
get '/controller/controller_method_data', to: 'controller#controller_method'
Am I not allowed to put .json in the url routes? Any way that I can allow .json be the name of the route?

There is a much easier way to respond to different formats - just use ActionController::MimeResponds
get '/controller/controller_method', to: 'controller#controller_method'
class Controller < ApplicationController
def controller_method
respond_to do |format|
format.json { render json: { hello: 'world' } }
format.html # renders the view implicitly
format.txt { render plain: 'Hello world'}
end
end
end

Related

can I use rabl without using .json in the url?

I have rabl up and running.
I have this in routes:
get 'biblios/collection/:biblio_urn' => 'biblios#biblio_rabl', as: 'collection_biblio'
in the controller:
def biblio_rabl
biblio = Biblio.where(biblio_urn: params[:biblio_urn]).take
end
This url points to the correct result :
http://localhost:3000/dts/biblios/collection/urn:cts:froLit:ed_desmarez:1900
I would like that url to always respond using rabl and showing the the template dts/biblios/biblio_rabl.json.rabl
I mean without adding .json at the end of the url.
I have tried this in the routes.rb, but it doesn't redirect :
get 'biblios/collection/:biblio_urn' => 'biblios#biblio_rabl', as: 'collection_biblio', to: redirect('biblios/collection/%{biblio_urn}.json')
Is that possible at all?
You can force the response to be json by changing the request format in the controller:
request.format = :json
Then make sure you have a respond_to block like this because it's always better to be explicit about your responses:
def biblio_rabl
respond_to do |format|
format.json { json: Biblio.where(biblio_urn: params[:biblio_urn]).take }
end
end

Render different controller methods as JSON in Rails 5.2

I have a resource that renders as JSON perfectly fine at localhost:3000/gins.json from #gins = Gin.order(name: :desc).
Which will return ALL gins. However, I'd like to have a JSON response that only returns the last 4 gins, to use elsewhere. In the controller I also have:
#latestgins = Gin.order("created_at DESC").first(4)
The above would work in an index.html.erb view with <%= #latestgins.name %>, but how do I get the JSON for this? I have tried render json: #latestgins but navigating to localhost:3000/latestings.json, of course, gives a routing error.
I suspect I'm attacking this in completely the wrong way, but only just starting out with Rails API.
you can add respond to format json in your index method:
def index
#gins = Gin.order(name: :desc)
#latestgins = Gin.order("created_at DESC").first(4)
respond_to do |format|
format.html
format.json { render json: #latestgins }
end
end
your #latestgins is now available here : localhost:3000/gins.json
Edit
If you want a custom route to display your data, just add it in your routes:
defaults format: :json do
get 'last4gins', to: "gins#index"
end
Your data for the last 4 entries is available at http://localhost:3000/last4gins.json, at http://localhost:3000/last4gins but also at localhost:3000/gins.json
If you want to keep the gins index route clean, you can also create a custom method and remove the #latestgins from your index:
# routes
get 'last4gins', to: "gins#last4gins"
#controller
def index
#gins = Gin.order(name: :desc)
end
def last4gins
#latestgins = Gin.order("created_at DESC").first(4)
render json: #latestgins
end
Now the data is no more available at /gins.json

what is (.:format) appended to url path during rake routes?

When I run rake routes, I get something like this:
signin /signin(.:format) application#signin
What is the (.:format) in the middle?
It's an optional format. It matches URLs like:
/signin
/signin.html
/signin.json
This format can then be used in the controller. For example:
class UsersController < ApplicationController
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render xml: #users}
format.json { render json: #users}
end
end
end
This code snippet is from Action Controller Overview. See more details in the routing guide.

Rails Test post Request with firefox plugin results in bad request

I m trying to test the create method of my rails App , I cant figure out what is wrong and why constantly having "bad request".
The routing goes line this:
namespace :api do
namespace :v1 do
resources :routes
resources :line_items
end
end
My controller is like this:
def create
#route = Route.new(permitted_params)
respond_to do |format|
if #route.save
format.json { render json: #route, status: :created }
else
format.json { render json: #route.errors, status: :unprocessable_entity }
end
end
end
My permitted params are these:
def permitted_params
params.require(:route).permit(:comment)
end
I use the firefox plugin OpenHttpRequester and this is what I get when I click to POST button, when I insert submit my json = route:{comment:"bla"}
Any ideas what of what the request should be ?
I have changed the json part to {"route":{"comment":"bla"} and get a nice 422 response.. still no luck
I was missing the following line in the controller:
skip_before_filter :verify_authenticity_token

Rails render template with status

What is the simplest/shortest way to respond in an API controller. Currently the following works:
respond_to do |format|
format.json { render 'client', status: :ok }
end
however this controller will only ever respond to json (respond_to :json) so the whole respond_to do |format| thing seems like unnecessary code.
Ideally I would just like to do something simple like:
render 'client', status: :ok
Update:
I neglected to mention that: 'client' is a jbuilder template that does not match my action name.
You can use render directly
render json: 'client', status: :ok
According to #hassasin, you can indicate your controller to render json: format on each action of your controller.
Other option is to take advantage of your config.routes.rb to set the entire response format of your controller, e.g. contacts_controller:
resources :contacts, defaults: {format: :json}
If you want to indicate the status, add this to your actions:
def index
render status: :ok # 200, 400, 500, what ever you want
end
I tested the code above with Rails 3.2.16
I hope it helps you.
Since you are using json views (assume you are using jbuilder), you dont need that render statement if your action name matches the view name.

Resources