在某些动作上需要某些参数

时间:2019-01-31 13:09:49

标签: ruby-on-rails ruby ruby-on-rails-5

在某些情况下,我需要验证某些参数的存在。这是一个例子:

在我的用户控制器中,为了执行更新操作,我需要验证这些参数的存在。汽车控制器的交易相同,更新操作也一样,您可以在此处看到重复的主题。参数为additional_info

我的基本控制器提供了additional_info_params,可从请求中提取正确的数据。

这是我到目前为止尝试过的。我创建了一个AR控制器问题并将其包含在控制器中,这是一些代码:

module ClassMethods
  def require_additional_info_for(*methods)
    binding.pry
    return unless methods.include?(action_name)
    if additional_info_params.empty?
      head 400
    end
  end
end

我的想法是能够在控制器文件的顶部定义需要这些参数的方法,就像来自rails的before_action或来自cancan的skip_authorization_check一样。像这样:

MyController < BaseController
  include Concerns::AdditionalInformation
  require_additional_info_for :update

  def update
    ...
  end
end

但是,上面的代码无法按我的预期工作,主要是因为这会在没有太多关于请求的知识的情况下在请求类上触发(我需要通过action_name来获取操作名称)。

那我该怎么做?

2 个答案:

答案 0 :(得分:2)

是的,可以,但是我建议您使用before_action回调!

在“抽象”控制器中,像这样注册您的方法:

 class SameController < ApplicationController
   ...
   protected
     def require_additional_params
       render status: :unprocessable_entity if additional_info_params.empty?
     end
 end

此后,将使用此方法的所有控制器必须扩展SameController,并运行before_action并将上述方法传递给所需的动作,例如:

class UserController < SameController
  before_action :require_additional_params, only: [:action1, :action2]
end

注意:您可以将require_additional_params放在模块中并包含在控制器中,也可以只将其放在ApplicationController

答案 1 :(得分:0)

您可能还会考虑在各自的控制器中制作这些常规的强参数。看起来像这样:

def update_params
  params.require(:car).permit(:engine, :wheels, :rims).tap do |car_params|
    car_params.require(:engine)
  end
end

这将需要顶级:car参数(剥离),并且需要:engine参数,但允许其他两个参数(:wheels:rims )。如果不存在:engine,它将引发ActionController::ParameterMissing(就像缺少:cars一样)

这是直接从action controller strong params docs(最后一个示例在底部)

有时,我会将它们放入相应控制器上的单独私有方法中,因此也可能会有一个具有不同要求的create_params方法。与使用自定义方法作为before_action相比,我更喜欢这种方法。