动态设置current_object并避免使用before_filter

时间:2015-09-12 16:47:41

标签: ruby-on-rails ruby

假设我们有 rails API 。在许多控制器方法中,我需要设置我的current_object,这要归功于请求中的params。然后我可以设置 before_action ,如:

def set_current_object
  if My_object.exists? params[:id]
    @current_object = My_object.find params[:id]
  else
    render json: {error: 'Object not found'}.to_json, status:404
  end
end

这没关系。但我想在我的控制器方法中动态设置current_object 。想象一下,我在一个控制器中有一个show方法,我需要使用我的current_object:

def show
  render json: {object_name: current_object.name}.to_json, status: 200
end

current_object将是一个辅助方法,如:

def current_object
  if My_object.exists? params[:id]
    return My_object.find params[:id]
  else
    render json: {error: 'Object not found'}.to_json, status:404
  end
end

然后,如果My_object.exists? params [:id]为false我想发送404并停止我的控制器方法。就像这里写的一样,它显然不起作用。有什么建议吗?

2 个答案:

答案 0 :(得分:2)

你走在正确的轨道上。通常你会实现这种"延迟加载"作为memoizes使用||= idiom返回值的方法。

您只需修改current_object帮助程序,以便在无法返回有效值时触发404错误。通常,您可以通过引发可识别的异常(例如ActiveRecord::RecordNotFound)并使用rescue_from子句在控制器中处理此异常来执行此操作。

class ApplicationController
  def current_object
    if My_object.exists? params[:id]
      # memozie the value so subsequent calls don't hit the database
      @current_object ||= My_object.find params[:id]
    else
      raise ActiveRecord::RecordNotFound  
    end
  end


  rescue_from ActiveRecord::RecordNotFound with: :show_404

  def show_404
    render json: {error: 'Object not found'}.to_json, status:404
  end
end

现在,因为您在控制器层次结构的顶层遵循处理ActiveRecord::RecordNotFound的非常标准的Rails约定,所以现在可以大大清理current_object方法。而不是检查是否存在记录,只是尝试按ID查找记录。如果它不存在,ActiveRecord将自动为您引发异常。实际上,您的整个current_object方法应该是一行代码:

class ApplicationController
  def current_object
    @current_object ||= My_object.find(params[:id])
  end

  rescue_from ActiveRecord::RecordNotFound with: :show_404

  def show_404
    render json: {error: 'Object not found'}.to_json, status:404
  end
end

答案 1 :(得分:0)

假设My_object是一个模型,如果您只使用find,那么数据库中不存在的params[:id]将引发ActiveRecord::RecordNotFound错误,和Rails' ActionController::Base将捕获异常并默认呈现404:

def current_object
  My_object.find params[:id]
end