[RUBY] Gibt es einen Ingenieur, der die Json-Spalte in Rails nicht validiert hat?

Dies ist ein Artikel über die Validierung von Json-Spalten mithilfe von json-schema in Rails.

Vorwort

Es ist lange her, dass die Json-Spalte zu MySQL hinzugefügt wurde.

** Rails scheint nicht die Standardeinstellung zu sein, aber ich möchte Json ordnungsgemäß validieren! ** ** ** Aber wenn ich versuche, es ehrlich mit einer benutzerdefinierten Methode zu schreiben ...

Dummes Beispiel für eine benutzerdefinierte Methode

some_model.rb


class SomeModel < ApplicationRecord
  validate :verify_timetable

  private

  def verify_timetable
    errors.add(:timetable, 'Kein Array') && return unless timetable.is_a?(Array)

    timetable.each do |el|
      errors.add(:timetable, 'Element ist kein Hash') && next unless el.is_a?(Hash)
      errors.add(:timetable, 'Hash-Schlüssel ist ungültig') && next unless el.keys.sort == %w[end_at start_at]

      %w[start_at end_at].each do |key|
        DateTime.parse(el[key])
      rescue ArgumentError
        errors.add(:timetable, "#{key}Der Wert von ist ungültig")
      end
    end
  end
end

――Es wird eine beträchtliche Menge sein ... ――Es ist schwierig, eine Feinabstimmung durchzuführen, z. B. "Erlauben Sie einen Über- oder Mangel an Tasten?"

Ich denke, es gibt viele solcher Kunden. Wenn Sie nicht darüber nachdenken, führen Sie die Validierung auf der Anwendungsseite durch?

Dieses Mal werde ich json-schema verwenden, um die coolste Json-Validierungsmethode vorzustellen, an die ich je gedacht habe.

Wie es aussehen wird

some_model.rb


class SomeModel < ApplicationRecord
  TIMETABLE_SCHEMA = {
    type: 'array',
    items: {
      type: 'object',
      properties: {
        start_at: { type: 'string', format: :datetime },
        end_at: { type: 'string', format: :datetime },
      },
    },
  }.freeze
  validates :timetable, json: { schema: TIMETABLE_SCHEMA }
end

Es ist ziemlich intuitiv, nicht wahr? Sie können das Schema an einer beliebigen Stelle platzieren. Ich möchte die Validierung in der Validierung zusammenstellen, daher definiere ich sie kurz vor der Validierung.

Wie benutzt man

Edelsteininstallation

Gemfile


gem 'json-schema'

Definition des benutzerdefinierten Validators

Es ist eine Einstellung, um mit validates: hoge, json: {schema: fuga} aufrufen zu können. Ich habe es in "App / Validatoren" eingefügt.

app/validators/json_validator.rb


class JsonValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    JSON::Validator.validate!(options[:schema], value, strict: true)
  rescue JSON::Schema::ValidationError => e
    record.errors[attribute] << (options[:message] || e.message)
  end
end

Zu diesem Zeitpunkt ist eine Validierung gemäß dem normalen Json-Schema (Mustervergleich durch regulären Ausdruck, Definition von minLength, maxLength usw.) möglich. Lesen Sie Gem Readme und probieren Sie verschiedene Dinge aus, während Sie die Spezifikationen von Json Schema googeln. (Zum Beispiel ist "strict: true" eine Einstellung, die den erforderlichen Inhalt ignoriert und keinen Über- oder Mangel an Schlüsseln zulässt.) Es ist einfach, weil Sie mit Ruby-Hash schreiben können.

Hinzufügen von Varidata für DateTime

In Jsons Typdefinition gibt es keinen Datumstyp. Derzeit gibt es jedoch Fälle, in denen Sie Datums- und Uhrzeitinformationen in Json einfügen möchten. Unter Bezugnahme auf dieses Problem wird der Validator für DateTime zu JSON :: Validator hinzugefügt.

config/initializers/json_validator.rb


datetime = -> value {
  begin
    DateTime.parse(value)
  rescue ArgumentError
    raise JSON::Schema::CustomFormatError.new('not datetime format')
  end
}
JSON::Validator.register_format_validator(:datetime, datetime)

Wenn Sie etwas wie "Ich möchte dieses benutzerdefinierte Format!" Haben, können Sie es hier hinzufügen.

Festziehen

Wie war es? Dies scheint Sie von persönlichen Validierungsbeschreibungen zu befreien. Ingenieure, die die Validierung von Json vernachlässigt haben, werden diese Gelegenheit nutzen, um die Validierung auf der Anwendungsseite zu verbessern und ein gesundes Rails-Leben zu führen!

Recommended Posts

Gibt es einen Ingenieur, der die Json-Spalte in Rails nicht validiert hat?
So geben Sie den Wert aus, wenn sich ein Array im Array befindet
Gibt es eine Instanz, auch wenn der Konstruktor ausfällt?
[Schienen] So zeigen Sie Bilder in der Ansicht an
Wirf eine Ausnahme und fange, wenn es keinen Handler gibt, der dem Pfad im Frühjahr entspricht
Was tun, wenn Cloud 9 im Rails-Lernprogramm voll ist?
Ich sehe keinen Fehler bei der Installation des Rails-Bundles ... der Lösung
Puma --Nignx ist ein Fluchtweg, wenn die Schienen in der Umgebung nicht funktionieren