Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement type systems #149

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Implement type systems #149

wants to merge 1 commit into from

Conversation

akxcv
Copy link
Contributor

@akxcv akxcv commented Oct 17, 2019

Closes #148.

Now, Surrealist has two type systems out of the box: Surrealist::TypeSystems::Builtin and Surrealist::TypeSystems::DryTypes.

Every type system has its own type-checking strategy, error reporting strategy, and coercion strategy. Error reporting is done during the type-checking via result objects.

Configuration

To set the type system to use across all serializers:

Surrealist.configure do |config|
  config.type_system = :builtin # the default
  config.type_system = :dry_types # use Dry::Types
  config.type_system = MyTypeSystem # use a custom type system
end

To set the type system for a given serializer:

class MySerializer < Surrealist::Serializer
  type_system :dry_types

  json_schema do
    # ...
  end

  # ...
end

Defining a custom type system

To define a custom type system, create a module that conforms to Surrealist's type system interface. For example, you could support Thy like this:

module ThyTypeSystem
  class << self
    include Surrealist::Result::DSL

    # Returns a Result.
    def check_type(value, type_class)
      thy_result = type_class.check(value)
      # If everything is okay, return a successful result.
      return success if result.success?
      # If the type check failed, return a Failure with a message.
      failure(result.message)
    end

    # Thy does not support type coercion.
    def coerce(value, _type_class)
      value
    end
  end
end

I've also taken this chance to remove Surrealist::Carrier in favour of Surrealist::Config. Carrier was a confusing class with unclear responsibilities and Configuration is your standard configuration object.

And, the grammatically wrong namespaces_nesting_level is changed to namespace_nesting_level. I've introduced aliases for backward compatibility. And deprecation warnings for them.


# Alias for backward compatibility.
if overrides.key?(:namespaces_nesting_level)
overrides.merge!(namespace_nesting_level: overrides.delete(:namespaces_nesting_level))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance/RedundantMerge: Use overrides[:namespace_nesting_level] = overrides.delete(:namespaces_nesting_level) instead of overrides.merge!(namespace_nesting_level: overrides.delete(:namespaces_nesting_level)).

@akxcv
Copy link
Contributor Author

akxcv commented Oct 17, 2019

Please take a look at this initial implementation. Some questions I have:

  1. How do we document the type system interface (besides the README)? Right now, documentation comments are kind of duplicated between Builtin and DryTypes.
  2. Currently, this is a breaking change, because Surrealist now forces you to use a single type system per serializer, but before it used to guess whether a type is builtin or from dry-types. I think that this is fine, it should be rather rare that someone uses two different type systems per serializer in their code. But we might want to create a separate "guessing" type system for backward compatibility (it would ship deprecated from the start).

@0exp
Copy link

0exp commented Oct 17, 2019

approved

Repository owner deleted a comment from houndci-bot Jun 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pluggable type systems
3 participants