lib/wcc/contentful/model_validators.rb in wcc-contentful-0.1.0 vs lib/wcc/contentful/model_validators.rb in wcc-contentful-0.2.0
- old
+ new
@@ -4,46 +4,97 @@
require_relative 'model_validators/dsl'
module WCC::Contentful::ModelValidators
def schema
- return if @field_validations.nil? || @field_validations.empty?
- field_validations = @field_validations
+ return if validations.nil? || validations.empty?
- # "page": {
- # "sys": { ... }
- # "fields": {
- # "title": { ... },
- # "sections": { ... },
- # ...
- # }
- # }
+ all_field_validations =
+ validations.each_with_object({}) do |(content_type, procs), h|
+ next if procs.empty?
- fields_schema =
- Dry::Validation.Schema do
- # Had to dig through the internals of Dry::Validation to find
- # this magic incantation
- field_validations.each { |dsl| instance_eval(&dsl.to_proc) }
+ # "page": {
+ # "sys": { ... }
+ # "fields": {
+ # "title": { ... },
+ # "sections": { ... },
+ # ...
+ # }
+ # }
+ h[content_type] =
+ Dry::Validation.Schema do
+ # Had to dig through the internals of Dry::Validation to find
+ # this magic incantation
+ procs.each { |dsl| instance_eval(&dsl.to_proc) }
+ end
end
Dry::Validation.Schema do
- required('fields').schema(fields_schema)
+ all_field_validations.each do |content_type, fields_schema|
+ required(content_type).schema do
+ required('fields').schema(fields_schema)
+ end
+ end
end
end
+ def validations
+ # This needs to be a class variable so that subclasses defined in application
+ # code can add to the total package of model validations
+ # rubocop:disable Style/ClassVars
+ @@validations ||= {}
+ # rubocop:enable Style/ClassVars
+ end
+
+ ##
+ # Accepts a block which uses the {dry-validation DSL}[http://dry-rb.org/gems/dry-validation/]
+ # to validate the 'fields' object of a content type.
def validate_fields(&block)
raise ArgumentError, 'validate_fields requires a block' unless block_given?
dsl = ProcDsl.new(Proc.new(&block))
- (@field_validations ||= []) << dsl
+ ct = try(:content_type) || name.demodulize.camelize(:lower)
+ (validations[ct] ||= []) << dsl
end
+ ##
+ # Validates a single field is of the expected type.
+ # Type expectations are one of:
+ #
+ # [:String] the field type must be `Symbol` or `Text`
+ # [:Int] the field type must be `Integer`
+ # [:Float] the field type must be `Number`
+ # [:DateTime] the field type must be 'Date'
+ # [:Asset] the field must be a link and the `linkType` must be `Asset`
+ # [:Link] the field must be a link and the `linkType` must be `Entry`.
+ # [:Location] the field type must be `Location`
+ # [:Boolean] the field type must be `Boolean`
+ # [:Json] the field type must be `Json` - a json blob.
+ # [:Array] the field must be a List.
+ #
+ # Additional validation options can be enforced:
+ #
+ # [:required] the 'Required Field' checkbox must be checked
+ # [:optional] the 'Required Field' checkbox must not be checked
+ # [:link_to] (only `:Link` or `:Array` type) the given content type(s) must be
+ # checked in the 'Accept only specified entry type' validations
+ # Example:
+ # validate_field :button, :Link, link_to: ['button', 'altButton']
+ #
+ # [:items] (only `:Array` type) the items of the list must be of the given type.
+ # Example:
+ # validate_field :my_strings, :Array, items: :String
+ #
+ # Examples:
+ # see WCC::Contentful::Model::Menu and WCC::Contentful::Model::MenuButton
def validate_field(field, type, *options)
dsl = FieldDsl.new(field, type, options)
- (@field_validations ||= []) << dsl
+ ct = try(:content_type) || name.demodulize.camelize(:lower)
+ (validations[ct] ||= []) << dsl
end
+ ##
# Accepts a content types response from the API and transforms it
# to be acceptible for the validator.
def self.transform_content_types_for_validation(content_types)
if !content_types.is_a?(Array) && items = content_types.try(:[], 'items')
content_types = items