有没有更好的方法来检查子参数?

Is there a better way to check child params?

是否有比以下代码更好的检查 items_attributes 的方法?我必须先检查 params[:order],因为有时它可能不存在,但我讨厌长条件语句的外观。

if params[:order] and params[:order][:items_attributes]

UPDATE for ruby 2.3,现在你可以使用挖掘方法

params.dig(:order, :item_attributes)

如果您使用 andand gem:

if params[:order].andand[:items_attributes]

您也可以使用 try

您可以使用 try,像这样:

params[:order].try(:[], :items_attributes)

try 方法 returns nil 如果接收方没有响应它,而不是引发异常。

希望对您有所帮助!

如果我有这样的问题,我会考虑用这样的东西扩展基本的 ruby class Hash(这只是一个想法)

class Hash

  def has_nested_values?(*args)
    current_value = self.dup
    args.each do |arg|
      current_value = current_value[arg]
      break unless current_value
    end
    !!current_value
  end

end

结果是

h[:a] = {b: {c: {d: 1}}}

h.has_nested_values?(:a, :b, :c)
=> true

h.has_nested_values?(:a, :b, :cc)
=> false

PS 我不喜欢 dup 的实现,但它有效

您可以创建辅助方法以更轻松地处理嵌套哈希。在您的 lib 文件夹中创建 ruby_ext.rb 文件,并编写此函数:

module RubyExt
  module SafeHashChain
    def safe(*args)
      if args.size == 0 then self # Called without args ...
      elsif args.size == 1 then self[args[0]] # Reached end
      elsif self[args[0]].is_a?(Hash) then self[args[0]].safe(*args[1..-1])
      else nil end # Reached end-value too soon
    end
  end
end

class Hash; include RubyExt::SafeHashChain; end

在此之后,您可以像这样在嵌套哈希上调用安全方法:

params.safe(:order,:items_attributes)

它会 return 来自 items_attributes 的值。如果订单或 items_attributes 不存在,它将 return nil。

Params 实际上是ActionController::Parameters 的一个实例,并内置了白名单过滤功能。

这使得做这样的事情成为可能:

# White list for Order params
def order_params
    params.require(:order).permit(:items_attributes)
end

// If :order is missing exception, and then filter only permitted.
valid_params = order_params()

// Also make these calls safe without risk for unwanted params
order = Order.new(order_params())
order.save!    

您可能喜欢使用默认值获取?

order = params.fetch(:order, {})

if order[:item_attributes]
  # ...
end