如何破坏 Rails 应用程序和 return 404 为 JSON
How to break Rails application and return 404 as JSON
Rails 应用程序作为 API 服务工作。我使用 mongoid
在我现在写的控制器中:
class UsersController < ApplicationController
def show
@user = User.find params[:user_id]
unless @user
render json: { error: I18n.t('user.messages.not_found') }, status: :not_found
return
end
# ... some actions with @user object
end
end
我需要使代码更简洁并将此代码移动到模块中。我假设控制器中的代码可能如下所示:
class UsersController < ApplicationController
def show
@user = User.find params[:user_id]
not_found? @user
# ... some actions with @user object
end
end
或者像这样
class UsersController < ApplicationController
def show
@user = found? User, params[:user_id]
# ... some actions with @user object
end
end
Pundit gem (https://github.com/elabs/pundit) 就是一个例子。在我的控制器中我写:
...
def index
authorize User, :index?
@users = User.all
end
...
如果用户无法访问此页面,则 Pundit 会引发异常并 return 向带有 401 http 代码的客户端错误消息。
重构我的代码以使控制器更简洁的更好方法是什么?
我的解决方案:
lib/myapp/exceptions.rb
module MyApp
module Exceptions
class Error < StandardError; end
class ModelNotFound < Error
def initialize(model)
# api_error - helper for create standart JSON-response
@json = api_error("#{ model.model_name.plural }.#{ model.model_name.singular }_not_found")
message = @json
super(message)
end
def json
@json
end
end
def self.included(base)
base.rescue_from MyApp::Exceptions::ModelNotFound do |e|
render json: e.json, status: :not_found
end
end
end
end
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
...
include MyApp::Exceptions
def found?(model, id)
@model = model.find id
return @model if @model
raise MyApp::Exceptions::ModelNotFound.new model
end
使用示例:
app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = found? User, params[:user_id]
# ... some actions with @user object
end
end
当我执行 GET 请求时 /users/77777 应用程序 returns:
{
'code': 'users_user_not_found',
'error': 'User not found'
}
Rails 应用程序作为 API 服务工作。我使用 mongoid
在我现在写的控制器中:
class UsersController < ApplicationController
def show
@user = User.find params[:user_id]
unless @user
render json: { error: I18n.t('user.messages.not_found') }, status: :not_found
return
end
# ... some actions with @user object
end
end
我需要使代码更简洁并将此代码移动到模块中。我假设控制器中的代码可能如下所示:
class UsersController < ApplicationController
def show
@user = User.find params[:user_id]
not_found? @user
# ... some actions with @user object
end
end
或者像这样
class UsersController < ApplicationController
def show
@user = found? User, params[:user_id]
# ... some actions with @user object
end
end
Pundit gem (https://github.com/elabs/pundit) 就是一个例子。在我的控制器中我写:
...
def index
authorize User, :index?
@users = User.all
end
...
如果用户无法访问此页面,则 Pundit 会引发异常并 return 向带有 401 http 代码的客户端错误消息。
重构我的代码以使控制器更简洁的更好方法是什么?
我的解决方案:
lib/myapp/exceptions.rb
module MyApp
module Exceptions
class Error < StandardError; end
class ModelNotFound < Error
def initialize(model)
# api_error - helper for create standart JSON-response
@json = api_error("#{ model.model_name.plural }.#{ model.model_name.singular }_not_found")
message = @json
super(message)
end
def json
@json
end
end
def self.included(base)
base.rescue_from MyApp::Exceptions::ModelNotFound do |e|
render json: e.json, status: :not_found
end
end
end
end
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
...
include MyApp::Exceptions
def found?(model, id)
@model = model.find id
return @model if @model
raise MyApp::Exceptions::ModelNotFound.new model
end
使用示例:
app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = found? User, params[:user_id]
# ... some actions with @user object
end
end
当我执行 GET 请求时 /users/77777 应用程序 returns:
{
'code': 'users_user_not_found',
'error': 'User not found'
}