验证 Ruby 哈希的形状?

Dav*_* J. 6 ruby mongodb

这个问题的一个更长的替代措辞是:“有哪些 Ruby 库或方法可以测试任意数据结构(散列、数组、整数、浮点数、字符串等)的形状?”

首先,让我展示一个简单的例子:

hash_1 = {
  k1: 1.0,
  k2: 42,
  k3: {
    k4: "100.00",
    k5: "dollars"
  }
}
Run Code Online (Sandbox Code Playgroud)

接下来,我想验证它——我的意思是与形状/模式/模板进行比较,例如:

shape_a = {
  k1: Float,
  k2: Integer,
  k3: Hash
}
Run Code Online (Sandbox Code Playgroud)

或者,也许,更具体的形状:

shape_b = {
  k1: Float,
  k2: Integer,
  k3: {
    k4: String,
    k5: String
  }
}
Run Code Online (Sandbox Code Playgroud)

一种可能的 API 可能如下所示:

require '_____________'

hash_1.schema = shape_a
hash_1.valid? # => true

hash_1.schema = shape_b
hash_1.valid? # => true
Run Code Online (Sandbox Code Playgroud)

这些只是示例,我对其他方法持开放态度。

大约 3 年前,我写了schema_hash来解决我自己的问题。我计划更新它,但首先我想了解替代方案和更好的方法。

这个问题的动机来自一个 Mongo 用例,但这个问题不一定是 Mongo 特定的。

就像我在顶部提到的那样,我希望看到或构建验证任意数据结构的能力:散列、数组、基元等,以任何嵌套组合进行。

“你不需要 Mongo 的模式,所以你为什么要关心?”

  • 就像我上面提到的,我并不是专门考虑 Mongo 用例
  • 但即使在 Mongo 的上下文中,即使您不想要求数据结构采用某种形状,根据形状或模式测试数据结构并相应地采取行动仍然很有用。

“为什么不直接编写自定义验证?”

当我从事上一个项目时,这正是我开始的地方。为嵌套散列重复编写验证是很痛苦的。我开始考虑什么能让它更容易,我想出了一个类似于我上面分享的语法。

外面有什么?我应该尝试什么?

综上所述,我很好奇其他人在做什么。有没有“黄金之路”?我正在尝试不同的方法,包括嵌入的文档和与Mongoid 相关的validates_related ……但是当哈希嵌套超过一个级别或那么深时,这些方法似乎有点矫枉过正。

我四处寻找Ruby Toolbox 上Validation 以进行验证(双关语),但没有找到我要找的东西。当我在那里时,我建议了一个名为“验证”的新类别。

我所问的问题很可能不太适合“验证”主题领域,而更适合其他主题领域,例如“数据结构”和“遍历”。如果是这样,请指出我正确的方向。

Mic*_*ohl 6

编辑:重读你的问题,我的回答似乎有点过于简单了。我将把它留给你我是否应该删除它,只需通过评论让我知道。

一个非常简单的方法是这样的:

class Hash
  def has_shape?(shape)
    all? { |k, v| shape[k] === v }
  end
end
Run Code Online (Sandbox Code Playgroud)

像这样使用:

hash_1.has_shape?(shape_a) #=> true
shape_b = { k1: Float, k2: Integer, k3: Integer }
hash_1.has_shape?(shape_b) #=> false
Run Code Online (Sandbox Code Playgroud)

这似乎已经很好地处理了您描述的第一个版本。将其分解为 lib 并不难,因此它不会是monkey-patch Hash。向该has_shape?方法添加递归将处理您更复杂的情况。

更新:这是一个带有递归的版本:

class Hash
  def has_shape?(shape)
    all? do |k, v|
      Hash === v ? v.has_shape?(shape[k]) : shape[k] === v
    end
  end
end
Run Code Online (Sandbox Code Playgroud)