验证 Rails 中的参数

Cam*_*ron 3 ruby ruby-on-rails

在我的 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
Run Code Online (Sandbox Code Playgroud)

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

def index
    raise ActionController::RoutingError.new('Not Found') unless validate_filter && validate_post_type
    ...
Run Code Online (Sandbox Code Playgroud)

所以这意味着post_type=post_type=cam返回 404 但post_type=snaps会返回 true。

有没有更好的方法来验证传递的参数是否有效,但对于空参数和密钥本身是否存在。在这种情况下,仅使用blank?andpresent?是不够的。

use*_*195 5

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

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


Pet*_*oth 5

对于 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
Run Code Online (Sandbox Code Playgroud)

您可以在此处找到有关嵌套案例和一些测试的更多信息。