【问题标题】:How to deduplicate the code getting parameters and checking nil in Ruby如何在 Ruby 中对获取参数和检查 nil 的代码进行重复数据删除
【发布时间】:2012-11-19 09:06:44
【问题描述】:
token = params[:token]
email = params[:email]
phone_number = params[:phone_number]
iso_code = params[:iso_code]

if token.nil? or email.nil? or phone_number.nil? or iso_code.nil?
  raise InvalidParameterException
end

token.strip!
email.strip!
phone_number.strip!
iso_code.strip!

#use the variables

我的 rails 项目中有很多这样的代码。 您如何在 Ruby on Rails 中推广这种模式?
反射和元编程有可能吗?

【问题讨论】:

  • 这里需要更清楚一点。您是在检查哈希中是否缺少值,还是检查该值是否实际上是 nil
  • 好点,我正在检查变量是否缺失。我会更新的

标签: ruby-on-rails ruby design-patterns reflection metaprogramming


【解决方案1】:
unless [:token, :email, :phone_number, :iso_code].-(params.keys).empty?
  raise InvalidParameterException
end
params.each{|_, v| v.strip!}

然后,每次都像params[:token]一样使用它。也许您可以为params 使用更短的变量名,例如p

【讨论】:

  • 嗯?有用。你用了什么魔法?我需要一些解释,请
  • .-(params.keys)
  • params.keys 是散列中的键列表。当您从[:token, ...] 中减去它时,那么任何不在param 中的键都将保留。您希望这是empty?。接下来,您只需遍历params,并将strip! 应用于它的每个值。
【解决方案2】:

我认为在这种情况下不需要元编程或模式,只是常识:

[:token, :email, :phone_number, :iso_code].each do |k|
  raise InvalidParameterException if params[k].nil?    
  params[k] = params[k].strip
end

我一直不明白这种反模式的流行程度:

par_1 = params[:par_1]
...
par_n = params[:par_n]

为什么不改用params[:par_x]?使用在散列中分组的 params 变量通常比将它们存储到一堆局部变量中更方便。

【讨论】:

    【解决方案3】:

    你可以定义下面的方法:

    def verify_presence_define_var_and_strip(params, symbol_list)
      symbol_list.each do |s|
        raise InvalidParameterException if params[s].nil?
        define_method s, params[s].strip
      end
    end
    

    使用此方法,您的代码可以替换为:

    verify_presence_define_var_and_strip(params, [:token, :email, :phone_number, :iso_code])
    

    请注意,它将定义方法,而不仅仅是设置局部变量,但如果您的类中还没有具有此名称的方法,您应该会得到相同的结果。

    您可能更喜欢使用instance_variable_set 方法,但您必须在变量名前加上@

    [更新]

    如果你真的想定义局部变量而不是方法/实例变量,我不知道使用 eval 的其他解决方案:

    eval "#{s} = #{params[:s].strip}"
    

    但是,如果您搜索eval,您会发现,这被认为是不好的做法,而且在这种情况下,您将评估来自 URL / POST 参数的值!

    【讨论】:

    • 酷。但是,instance_variable_set 仅在 Class 中有效?是不是可以动态创建局部变量?
    • 我已将我的答案更新为instance_variable_set 需要变量名以@ 开头。我现在也会针对您的问题进行更新。
    【解决方案4】:

    创建一个辅助方法来访问 params 哈希并遍历元素并检查 nil 并自行引发异常或将值返回给可能引发异常的调用方法。

    你可以像这样迭代任何哈希,

    hash.each do |key,value|
     #example nil check
      if value.nil?
        #do what you want
      end
    end
    

    【讨论】:

      【解决方案5】:

      如果你想在你的参数散列中提高 nil,你可以这样做

      raise InvalidParameterException if params.values.include? nil
      

      如果您只想提高某些特定参数,您必须首先选择与这些键关联的值:

      required_keys = [:key1, :key2, :key3]
      raise invalidParameterException if required_keys.map{|k| params[k]}.include? nil
      

      编辑:由于缺少分数而无法回答,但我相信其中一个答案不起作用:

      [:some_key] - {some_key: nil}.keys   # => []
      

      如果参数哈希包含一个用值 nil 初始化的键(由于解析失败或用户输入无效),则数组减法不起作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-23
        • 2021-01-11
        • 2019-01-08
        • 2012-11-12
        相关资源
        最近更新 更多