验证Rails中的参数

时间:2017-02-03 17:58:03

标签: ruby-on-rails ruby

在我的Rails应用中,我想验证filterpost_type参数。

两者都是可选的,但如果它们存在,则它们必须具有值,并且必须具有与有效值数组中的值匹配的值。

在我的控制器中,我有两种方法可以检查它们:

def validate_filter
  if params.has_key?(:filter)
    if params[:filter].present?
      if ['popular', 'following', 'picks', 'promoted', 'first-posts'].include?(params[:filter])
        return true
      else
        return false
      end
    else
      return false
    end
  else
    return true
  end
end

def validate_post_type
  if params.has_key?(:post_type)
    if params[:post_type].present?
      if ['discussions', 'snaps', 'code', 'links'].include?(params[:post_type])
        return true
      else
        return false
      end
    else
      return false
    end
  else
    return true
  end
end

然后在我的主控制器方法中:

def index
    raise ActionController::RoutingError.new('Not Found') unless validate_filter && validate_post_type
    ...

因此,这意味着post_type=post_type=cam将返回404,但post_type=snaps将返回true。

是否有更好的方法来验证传递的参数是否有效,但是如果密钥本身存在则为空。在这种情况下,仅使用blank?present?是不够的。

4 个答案:

答案 0 :(得分:1)

我可能会将此逻辑移至模型中,但如果您真的想在控制器中使用它,则可以简化它。

def validate_filer
  return true unless params.has_key?(:filter)
  ['popular', 'following', 'picks', 'promoted', 'first-posts'].include?(params[:filter])
end

答案 1 :(得分:0)

也许是一个小帮手方法:

def validate_filter
  params_include?(:filter, %w(popular following picks promoted first-posts))
end

def validate_filter
  params_include?(:post_type, %w(discussions snaps code links))
end

def params_include?(key, values)
  !params.key?(key) || values.include?(params[key])
end

如果它们是查询参数或路径的一部分,则从您的问题中不清楚这些参数的来源。如果他们是路径的一部分,您可以考虑在routes.rb

中使用routing constraints

答案 2 :(得分:0)

您可以在before_action: validate_params, only: [:index] def validate_params return false unless params[:filter].present? && params[:post_type].present? params_include?(:filter, %w(popular following picks promoted first-posts)) params_include?(:post_type, %w(discussions snaps code links)) end 中执行此操作以执行控制器操作。

Der

答案 3 :(得分:0)

在使用API​​的情况下,我会考虑让客户端知道存在验证错误,而不仅仅是说404。

如何使用ActiveModel::Validations

class MyParamsValidator
  include ActiveModel::Validations

  AVAILABLE_FILTERS    = %w(popular following picks promoted first-posts)
  # this might come from an enum like MyModel.post_types
  AVAILABLE_POST_TYPES = %w(discussions snaps code links)

  attr_reader :data

  validates :filter, inclusion: { in: AVAILABLE_FILTERS }, allow_blank: true
  validates :post_type, inclusion: { in: AVAILABLE_POST_TYPES }, allow_blank: true

  def initialize(data)
    @data = data
  end

  def read_attribute_for_validation(key)
    data[key]
  end
end

class MyController < ApplicationController
  before_action :validate_params, only: :index

  def validate_params
    validator = MyParamsValidator.new(params)

    return if validator.valid?

    render json: { errors: validator.errors }, status: 422
  end
end

您可以通过一些测试here找到有关嵌套案例的更多信息。