ruby-on-rails - from - render rails
Rails 4: responda solo a JSON y no a HTML (9)
respond_to :json
crear una API en los rieles 4, y tengo un problema donde Rails devuelve un error de 500 en lugar de un 406 al usar respond_to :json
e intentar acceder a la versión html.
Aquí hay un controlador de ejemplo que demuestra el problema:
class PostsController < ApplicationController
respond_to :json
def index
@posts = Post.all
end
end
También tengo una vista de jbuilder para el index
que funciona al acceder a través de JSON. Si intento acceder a la ruta sin la extensión JSON, intenta cargar la plantilla HTML (que no existe) y devuelve un error 500, en lugar de simplemente renderizar JSON o devolver un error 406.
¿Qué podría estar causando esto? Saludos por cualquier ayuda.
Como está utilizando un before_filter, tendrá un 406 No aceptable si se realiza una solicitud para un formato que no está definido.
Ejemplo:
class SomeController < ApplicationController
respond_to :json
def show
@record = Record.find params[:id]
respond_with @record
end
end
La otra forma sería agregar un before_filter para verificar el formato y reaccionar en consecuencia.
Ejemplo:
class ApplicationController < ActionController::Base
before_filter :check_format
def check_format
render :nothing => true, :status => 406 unless params[:format] == ''json''
end
end
Pero creo que puedes hacerlo:
respond_to do |format|
format.json { render :json => @posts }
end
Más información: http://guides.rubyonrails.org/layouts_and_rendering.html
Creo que hay 2 partes aquí:
1) Json solo solicita en rieles
2) json solo respuestas en rieles
1) Configure su controlador de aplicaciones para garantizar solo las solicitudes json
# app/controller/application_controller.rb
before_action :ensure_json_request
def ensure_json_request
return if request.format == :json
render :nothing => true, :status => 406
end
2) Configure las rutas de la API de Rails para garantizar solo las respuestas json
# config/routes.rb
MyApp::Application.routes.draw do
namespace :api, constraints: { format: ''json'' } do
namespace :v1 do
resources :posts
end
end
end
En Rails 4, debe pasar una lambda para aplicar la restricción en una ruta.
Desafortunadamente, esto NO funcionará porque todavía intentará servir (o intentar servir) una plantilla html ya que el formato es un parámetro opcional:
resources :posts, constraints: { format: ''json'' }
Esto SÍ funciona (usa la lambda):
resources :posts, constraints: lambda { |req| req.format == :json }
Vea la segunda nota (final) en edgeguides.rubyonrails.org/… .
Para evitar cargar la plantilla HTML inexistente, configure el tipo de recurso predeterminado como JSON en config / routes.rb:
resources :posts, :defaults => { :format => :json }
Puede establecerlo teniendo un filtro anterior que establece la solicitud a JSON explícitamente.
request.format = :json
Puedes probar esto, ya que yo también estaba enfrentando este problema y ahora se soluciona al usar esta solución.
class PostsController < ApplicationController
respond_to :json
def index
@posts = Post.all
render json: @posts
end
end
Sugeriría que gem ''active_model_serializers''
. Es realmente increíble y se mantiene limpio.
ApplicationController:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception, if: Proc.new { |c| c.request.format != ''application/json'' }
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == ''application/json'' }
end
Rutas:
namespace :api, defaults: { format: :json } do
resource :posts
end
Controlador de publicaciones:
def index
render json: Post.all
end
cuando intentes una respuesta en json es porque solo necesitas algunas propiedades. He usado esto
@my_model=Model.select(:attributeN, :attributeN......, attributeN)
respond_to do |format|
format.json {
render json: @my_model
}
end
constraints
no funcionaban para las solicitudes POST y luego probé los defaults
para todos.
namespace :api, :defaults => { :format => ''json'' } do
namespace :v1 do
resources :users do
collection do
get ''profile''
end
end
post ''signup'' => ''users#create''
post ''login'' => ''user_sessions#create''
end
end