6

質問のより長く、別の言い回しは、「任意のデータ構造(ハッシュ、配列、整数、浮動小数点数、文字列など)の形状をテストするためのRubyライブラリまたはアプローチは何ですか?」です。

まず、簡単な例を示します。

hash_1 = {
  k1: 1.0,
  k2: 42,
  k3: {
    k4: "100.00",
    k5: "dollars"
  }
}

次に、それを検証したいと思います。これは、次のような形状/スキーマ/テンプレートと比較することを意味します。

shape_a = {
  k1: Float,
  k2: Integer,
  k3: Hash
}

または、おそらく、より具体的な形状:

shape_b = {
  k1: Float,
  k2: Integer,
  k3: {
    k4: String,
    k5: String
  }
}

考えられるAPIの1つは次のようになります。

require '_____________'

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

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

これらは単なる例であり、私は他のアプローチを受け入れています。

約3年前、私は自分のかゆみを掻くためにschema_hashを作成しました。私はそれを更新する予定ですが、最初に私は代替案とより良いアプローチの感覚を得たいと思いました。

この質問の動機はMongoのユースケースにありますが、質問は必ずしもMongo固有のものではありません。

冒頭で述べたように、ハッシュ、配列、プリミティブなど、任意のデータ構造をネストされた組み合わせで検証する機能を確認または構築したいと思います。

「Mongoのスキーマは必要ないのに、なぜ気にするのですか?」

  • 上で述べたように、私はMongoのユースケースだけを考えているわけではありません
  • ただし、Mongoのコンテキストでも、特定の形状をとるためにデータ構造を必要としない場合でも、形状またはパターンに対してデータ構造をテストし、それに応じて動作することは有用です。

「カスタム検証を書いてみませんか?」

私が前のプロジェクトに取り組んだとき、これはまさに私が始めたところです。ネストされたハッシュの検証を繰り返し作成するのは面倒です。何が簡単になるかを考え始め、上で共有したものと同様の構文を思いつきました。

そこには何がありますか?何を試してみればいいですか?

とはいえ、他の人が何をしているのか気になります。「黄金の道」はありますか?たとえば、埋め込みドキュメントやMongoidに関連付けられたvalidates_associatedなど、さまざまなアプローチを試していますが、ハッシュが1レベル以上深くネストされている場合、これらのアプローチはやり過ぎのように見えます。

検証のためにRubyToolboxで検証を探しましたが(しゃれを意図したもの)、探しているものが見つかりませんでした。私がそこにいる間、私は「検証」と呼ばれる新しいカテゴリーを提案しました。

私が求めていることは、「検証」トピック領域にはあまり当てはまらず、「データ構造」や「トラバーサル」などの他の領域には当てはまる可能性があります。もしそうなら、私を正しい方向に向けてください。

4

7 に答える 7

7

編集:質問を読み直すと、私の答えは少し単純すぎるようです。削除するかどうかはあなた次第です。コメントでお知らせください。

非常に単純なアプローチは次のようになります。

class Hash
  def has_shape?(shape)
    all? { |k, v| shape[k] === v }
  end
end

次のように使用します。

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

これは、最初に説明したバージョンをかなりうまく処理しているようです。これをlibに分解するのは難しくないので、モンキーパッチはしません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
于 2012-06-19T18:51:23.740 に答える
2

これはあなたが探しているものかもしれません:

https://github.com/JamesBrooks/hash_validator

于 2013-04-15T07:01:41.287 に答える
1

データhttp://rubygems.org/gems/validates_simpleのようなハッシュを検証するための gem を作成しました。値がクラスのメンバーであるかどうかを確認する検証を簡単に追加できます。ネストされた値の検証に関しては、必要に応じてこれをサポートするように gem を更新する必要があります。ルールの追加は次のように簡単です

  module Validation
    module Rules
      def validates_is_a_member_of(field, class, message='')
         callback = lambda do |data|
           data[field].is_a? Class
         end
         validates(field, callback, message)
      end
    end
  end

その後、validator.validates_is_a_member_of('age', Integer, 'age must be an int') を実行して、validator.validate({'age': 232423}) を実行できます。

于 2013-12-31T19:12:27.457 に答える
1

これは、Michael Kohl の再帰的な has_shape? を微調整したものです。shape_a と shape_b の両方で機能するメソッド (形状に再帰するサブハッシュがあるかどうかを確認するテストを追加しました):

  def has_shape?(shape)
    all? do |k, v|
      (Hash === v && Hash === shape[k]) ? v.has_shape?(shape[k]) : shape[k] === v
    end
  end

また、FWIW is_a を見つけましたか? ===より読みやすい。例えば:

  def has_shape?(shape)
    all? do |k, v|
      (v.is_a?(Hash) && shape[k].is_a?(Hash)) ? v.has_shape?(shape[k]) : v.is_a?(shape[k])
    end
  end

ただし、形状が JSON 互換の場合は、Ruby JSON Schema Validatorを検討することをお勧めします。これはより重量があり冗長ですが、JSON と同様にハッシュを検証するために使用でき、より詳細な制御 (必須キー、オプション キーなど) を提供します。

于 2020-01-28T02:53:03.500 に答える