json_schema_view 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +58 -0
  4. data/.yardopts +1 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +84 -0
  7. data/Gemfile +18 -0
  8. data/LICENSE.md +202 -0
  9. data/README.md +117 -0
  10. data/Rakefile +12 -0
  11. data/json_schema_view.gemspec +42 -0
  12. data/lib/json_schema_view/base_component.rb +82 -0
  13. data/lib/json_schema_view/base_props.rb +32 -0
  14. data/lib/json_schema_view/configuration/schema_set_dictionary.rb +51 -0
  15. data/lib/json_schema_view/configuration.rb +44 -0
  16. data/lib/json_schema_view/json_schema_definable.rb +22 -0
  17. data/lib/json_schema_view/json_world_extensions/additional_properties.rb +58 -0
  18. data/lib/json_schema_view/json_world_extensions/any_of.rb +41 -0
  19. data/lib/json_schema_view/json_world_extensions/camelizable.rb +36 -0
  20. data/lib/json_schema_view/json_world_extensions/compact_optional_properties.rb +20 -0
  21. data/lib/json_schema_view/json_world_extensions/constant_property.rb +39 -0
  22. data/lib/json_schema_view/json_world_extensions/declarable.rb +55 -0
  23. data/lib/json_schema_view/json_world_extensions/enum_type.rb +45 -0
  24. data/lib/json_schema_view/json_world_extensions/map_type.rb +47 -0
  25. data/lib/json_schema_view/json_world_extensions/validatable.rb +17 -0
  26. data/lib/json_schema_view/json_world_extensions.rb +31 -0
  27. data/lib/json_schema_view/rails/generators/install/USAGE +5 -0
  28. data/lib/json_schema_view/rails/generators/install/install_generator.rb +50 -0
  29. data/lib/json_schema_view/rails/generators/install/templates/base_component.rb.tt +17 -0
  30. data/lib/json_schema_view/rails/generators/install/templates/base_props.rb.tt +7 -0
  31. data/lib/json_schema_view/rails/generators/install/templates/component_schema_set.rb.tt +25 -0
  32. data/lib/json_schema_view/rails/generators/install/templates/example/todo_item_resource.rb +52 -0
  33. data/lib/json_schema_view/rails/generators/install/templates/example/todo_list_component.rb +67 -0
  34. data/lib/json_schema_view/rails/generators/install/templates/initializer.rb.tt +15 -0
  35. data/lib/json_schema_view/rails/generators.rb +8 -0
  36. data/lib/json_schema_view/rails/rails_engine.rb +20 -0
  37. data/lib/json_schema_view/rails/tasks/json_schema_component.rake +9 -0
  38. data/lib/json_schema_view/rails.rb +8 -0
  39. data/lib/json_schema_view/renderers/base.rb +27 -0
  40. data/lib/json_schema_view/renderers/json.rb +28 -0
  41. data/lib/json_schema_view/renderers/react_on_rails.rb +17 -0
  42. data/lib/json_schema_view/renderers.rb +22 -0
  43. data/lib/json_schema_view/schema_set/constant_search_helper.rb +114 -0
  44. data/lib/json_schema_view/schema_set.rb +58 -0
  45. data/lib/json_schema_view/version.rb +5 -0
  46. data/lib/json_schema_view.rb +29 -0
  47. data/sig/json_schema_view.rbs +4 -0
  48. metadata +134 -0
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "delegate"
4
+
5
+ module JsonSchemaView
6
+ class Configuration
7
+ # :nodoc:
8
+ class SchemaSetDictionary < Delegator
9
+ attr_reader :hash
10
+
11
+ # @param contents [Hash, nil]
12
+ def initialize(contents = nil)
13
+ @hash = ActiveSupport::HashWithIndifferentAccess.new(contents)
14
+ super
15
+ end
16
+
17
+ # @overload {Delegator#__getobj__}
18
+ # @return [HashWithIndifferentAccess{Symbol => Symbol}]
19
+ def __getobj__
20
+ hash
21
+ end
22
+
23
+ # @overload {Delegator#__setobj__}
24
+ def __setobj__(_)
25
+ # noop
26
+ end
27
+
28
+ # @param key [#to_sym] The alias name of SchemaSet
29
+ # @param value [String, Symbol] The name of SchemaSet class
30
+ def []=(key, value)
31
+ raise TypeError, "key (#{key}) cannot be converted to a symbol" unless key.respond_to?(:to_sym)
32
+
33
+ if !value.is_a?(String) && !value.is_a?(Symbol)
34
+ raise TypeError,
35
+ "value (#{value}) must be the name of SchemaSet class"
36
+ end
37
+
38
+ hash[key.to_sym] = value.to_sym
39
+ end
40
+
41
+ # @return [SchemaSet]
42
+ def fetch_instance(key)
43
+ klass = fetch(key).constantize
44
+
45
+ raise TypeError, "#{klass} is not the name of SchemaSet class" unless klass < JsonSchemaView::SchemaSet
46
+
47
+ klass.new
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonSchemaView
4
+ # The singleton holds the configuration for the gem.
5
+ # it can be accessed by both its class methods and Rails's configuration.
6
+ class Configuration
7
+ require_relative "configuration/schema_set_dictionary"
8
+
9
+ class << self
10
+ # @return [JsonSchemaView::Configuration]
11
+ def instance
12
+ @instance ||= new
13
+ end
14
+
15
+ # @yield [configuration]
16
+ # @yieldparam configuration [JsonSchemaView::Configuration]
17
+ def configure(&block)
18
+ instance.configure(&block)
19
+ end
20
+ end
21
+
22
+ def initialize
23
+ @schema_sets = SchemaSetDictionary.new
24
+ @validate_by_default = false
25
+ end
26
+
27
+ # @return [SchemaSetDictionary{Symbol => Symbol}] The renderers.
28
+ attr_reader :schema_sets
29
+
30
+ # @return [Boolean] Whether if validate components with its schema on render by default.
31
+ attr_accessor :validate_by_default
32
+
33
+ # @param new_sets [Hash{String, Symbol => String, Symbol}]
34
+ def schema_sets=(new_sets)
35
+ @schema_sets = SchemaSetDictionary.new(new_sets)
36
+ end
37
+
38
+ # @yield [configuration]
39
+ # @yieldparam configuration [JsonSchemaView::Configuration]
40
+ def configure
41
+ yield self
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_world"
4
+
5
+ require_relative "json_world_extensions"
6
+
7
+ module JsonSchemaView
8
+ # @abstract
9
+ module JsonSchemaDefinable
10
+ extend ActiveSupport::Concern
11
+
12
+ include ::JsonWorld::DSL
13
+ include JsonWorldExtensions::Schema202012
14
+ include JsonWorldExtensions::CompactOptionalProperties
15
+ include JsonWorldExtensions::Camelizable
16
+ include JsonWorldExtensions::Validatable
17
+
18
+ included do
19
+ additional_properties(false)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+
5
+ module JsonSchemaView
6
+ module JsonWorldExtensions
7
+ # Define JSON Schema's additionalProperties property.
8
+ # @see https://json-schema.org/understanding-json-schema/reference/object.html#additional-properties
9
+ #
10
+ # @example
11
+ # class Zoo
12
+ # include JsonWorld::DSL
13
+ # include JsonSchemaView::JsonWorldExtensions::MapType::DSL
14
+ #
15
+ # additional_properties(false)
16
+ # property(
17
+ # :dogMap,
18
+ # type: map_type(Dog),
19
+ # )
20
+ # end
21
+ module AdditionalProperties
22
+ extend ActiveSupport::Concern
23
+
24
+ class_methods do
25
+ # @override {Class.override}
26
+ def inherited(child)
27
+ super
28
+ child.additional_properties(additional_properties)
29
+ end
30
+
31
+ # Return the additionalProperties property.
32
+ # Set the additionalProperties property if arguments are given.
33
+ # @see https://json-schema.org/draft/2020-12/json-schema-core.html#additionalProperties
34
+ # @see https://json-schema.org/understanding-json-schema/reference/object.html#id5
35
+ #
36
+ # @param value [false, Hash]
37
+ # @param value_keywords [Hash]
38
+ def additional_properties(value = nil, **value_keywords)
39
+ return @additional_properties = value unless value.nil?
40
+ return @additional_properties = value_keywords unless value_keywords.empty?
41
+
42
+ @additional_properties
43
+ end
44
+
45
+ # @override {JsonWorld::DSL::ClassMethods#as_json_schema}
46
+ def as_json_schema
47
+ # Do not allow undefined properities.
48
+ # @see https://json-schema.org/understanding-json-schema/reference/object.html#additionalproperties
49
+ if @additional_properties.nil?
50
+ super
51
+ else
52
+ super.merge("additionalProperties": @additional_properties)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonSchemaView
4
+ module JsonWorldExtensions
5
+ # This class implements `anyOf` schema composition.
6
+ # Instances of this class acts as an json world compatible object and prints the schema for anyOf combination.
7
+ # @see https://json-schema.org/understanding-json-schema/reference/combining.html#id6
8
+ # @example
9
+ # class Zoo
10
+ # include JsonWorld::DSL
11
+ # include JsonSchemaView::JsonWorldExtensions::MapType::DSL
12
+ # property(
13
+ # :animal,
14
+ # type: any_of.new(Dog, Cat),
15
+ # )
16
+ # end
17
+ class AnyOf
18
+ module DSL
19
+ extend ActiveSupport::Concern
20
+
21
+ class_methods do
22
+ def any_of(*types)
23
+ JsonWorldExtensions::AnyOf.new(*types)
24
+ end
25
+ end
26
+ end
27
+
28
+ attr_reader :types
29
+
30
+ def initialize(*types)
31
+ @types = types
32
+ end
33
+
34
+ def as_json_schema
35
+ { "anyOf" => types.map(&:as_json_schema) }
36
+ end
37
+
38
+ alias as_json_schema_without_links as_json_schema
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+
5
+ module JsonSchemaView
6
+ module JsonWorldExtensions
7
+ # Make the object to be serialized with camelized properties.
8
+ module Camelizable
9
+ extend ActiveSupport::Concern
10
+
11
+ class_methods do
12
+ # @param (see JsonWorld::DSL::ClassMethods#property)
13
+ # @param camelize [Boolean] if true, camelize the property name on json format.
14
+ def property(raw_property_name, camelize: true, **options)
15
+ raw_property_name = raw_property_name.to_sym
16
+ property_name = camelize ? camelize_name(raw_property_name) : raw_property_name
17
+
18
+ super(property_name, **options)
19
+
20
+ # Define a method with camelized name as an alias of the method with raw name.
21
+ if camelize && property_name != raw_property_name
22
+ define_method(property_name) do
23
+ public_send(raw_property_name)
24
+ end
25
+ end
26
+ end
27
+
28
+ # @param name [String, Symbol]
29
+ # @return [Symbol]
30
+ def camelize_name(name)
31
+ ActiveSupport::Inflector.camelize(name.to_s, false).to_sym
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonSchemaView
4
+ module JsonWorldExtensions
5
+ # This module automatically removes properties with null value from encoded json if the property is optional.
6
+ #
7
+ # JSON Schema distinguishs a optional property and a nullable property.
8
+ # If the value of a optional property is empty, you should remove the property from the encoded json.
9
+ # This module make safe such the optional properties.
10
+ # @see https://json-schema.org/understanding-json-schema/reference/object.html#required-properties
11
+ module CompactOptionalProperties
12
+ # @note Overrides {JsonWorld::JsonEncodable#properties}
13
+ def properties(options)
14
+ optional_property_names = self.class.property_definitions.select(&:optional?).map(&:property_name)
15
+
16
+ super(options).reject { |key, value| value.nil? && optional_property_names.include?(key) }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonSchemaView
4
+ module JsonWorldExtensions
5
+ # This module allows {JsonWorld::DSL::ClassMethods#property} to define constant values.
6
+ # Defined constant values are reflect to JSON Schema.
7
+ # @see https://json-schema.org/understanding-json-schema/reference/generic.html#constant-values
8
+ module ConstantProperty
9
+ extend ActiveSupport::Concern
10
+
11
+ class_methods do
12
+ # If property is defined with `const` parameter, define an instance method to return the value.
13
+ # @note Overrides {JsonWorld::DSL::ClassMethods#property}
14
+ def property(name, **options)
15
+ if options[:const]
16
+ const = options[:const].freeze
17
+ define_method(name) { const }
18
+ end
19
+
20
+ super(name, **options)
21
+ end
22
+
23
+ # Add constant values informations JSON Schema
24
+ # @note Overrides {JsonWorld::DSL::ClassMethods#as_json_schema}
25
+ def as_json_schema
26
+ property_hash = property_definitions.map do |property|
27
+ if (const = property.raw_options[:const])
28
+ # For now, use enumerated values instead of constant values.
29
+ [property.property_name, { const: const }]
30
+ else
31
+ nil
32
+ end
33
+ end.compact.to_h
34
+ super.deep_merge(properties: property_hash)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonSchemaView
4
+ module JsonWorldExtensions
5
+ # Add methods to declare a common schema. Declared schema are exported as `$defs` property.
6
+ #
7
+ # @see: https://json-schema.org/understanding-json-schema/structuring.html#defs
8
+ module Declarable
9
+ extend ::ActiveSupport::Concern
10
+
11
+ class_methods do
12
+ attr_writer :declarations
13
+
14
+ # @override {Class.inherited}
15
+ def inherited(child)
16
+ super
17
+ child.declarations = declarations.clone
18
+ end
19
+
20
+ # @param type_or_name [Class<JsonWorld::DSL>, Symbol]
21
+ # @param (see JsonWorld::DSL::ClassMethods#property)
22
+ def declare(type_or_name, **options)
23
+ property_type = options[:type] || type_or_name
24
+ property_name = type_or_name.is_a?(Module) ? type_or_name.name.demodulize.to_sym : type_or_name.to_sym
25
+
26
+ declaration = JsonWorld::PropertyDefinition.new(property_name: property_name, type: property_type, **options)
27
+ declarations << declaration
28
+ end
29
+
30
+ # @override {JsonWorld::DSL::ClassMethods#as_json_schema}
31
+ def as_json_schema
32
+ decls = declarations_as_json_schema
33
+ if decls.present?
34
+ super.merge("$defs": decls)
35
+ else
36
+ super
37
+ end
38
+ end
39
+
40
+ def declarations_as_json_schema
41
+ declarations.inject({}) do |result, declaration|
42
+ result.merge(
43
+ declaration.property_name => declaration.as_json_schema,
44
+ )
45
+ end
46
+ end
47
+
48
+ # @return [Array<PropertyDefinition>]
49
+ def declarations
50
+ @declarations ||= []
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonSchemaView
4
+ module JsonWorldExtensions
5
+ # This module allows {JsonWorld::DSL::ClassMethods#property} to define enum values.
6
+ # Defined constant values are reflect to JSON Schema.
7
+ # @see https://json-schema.org/understanding-json-schema/reference/generic.html#enumerated-values
8
+ # @example
9
+ # class Zoo
10
+ # include JsonWorld::DSL
11
+ # include JsonSchemaView::JsonWorldExtensions::EnumType::DSL
12
+ # property(
13
+ # :animal,
14
+ # type: enum_type("Dog", "Cat"),
15
+ # )
16
+ # end
17
+ class EnumType
18
+ module DSL
19
+ extend ActiveSupport::Concern
20
+
21
+ class_methods do
22
+ def enum_type(*args)
23
+ JsonWorldExtensions::EnumType.new(*args)
24
+ end
25
+ end
26
+ end
27
+
28
+ attr_reader :candidates
29
+
30
+ # @param type [String, Symbol, #as_json_schema]
31
+ # @param candidates [Array<Object>]
32
+ def initialize(*candidates)
33
+ @candidates = candidates
34
+ end
35
+
36
+ def as_json_schema
37
+ {
38
+ enum: candidates
39
+ }
40
+ end
41
+
42
+ alias as_json_schema_without_links as_json_schema
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonSchemaView
4
+ module JsonWorldExtensions
5
+ # This class implements map type (string keys to values with the given type) in JSON Schema.
6
+ # You can specify the type of values but you cannot specify the type of keys,
7
+ # because JSON and JSON Schema only support String keys in objects.
8
+ #
9
+ # @see https://json-schema.org/understanding-json-schema/reference/object.html#additional-properties
10
+ #
11
+ # @example
12
+ # class Zoo
13
+ # include JsonWorld::DSL
14
+ # include JsonSchemaView::JsonWorldExtensions::MapType::DSL
15
+ # property(
16
+ # :dogMap,
17
+ # type: map_type(Dog),
18
+ # )
19
+ # end
20
+ class MapType
21
+ module DSL
22
+ extend ActiveSupport::Concern
23
+
24
+ class_methods do
25
+ def map_type(type)
26
+ JsonWorldExtensions::MapType.new(type)
27
+ end
28
+ end
29
+ end
30
+
31
+ attr_reader :type
32
+
33
+ def initialize(type)
34
+ @type = type
35
+ end
36
+
37
+ def as_json_schema
38
+ {
39
+ type: "object",
40
+ additionalProperties: JsonWorld::PropertyDefinition.new(type: type).as_json_schema
41
+ }
42
+ end
43
+
44
+ alias as_json_schema_without_links as_json_schema
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "json-schema"
5
+
6
+ module JsonSchemaView
7
+ module JsonWorldExtensions
8
+ # Add method to validate self properties with {JSON::Validator}.
9
+ module Validatable
10
+ # @raise [JSON::Schema::ValidationError] if self is not valid.
11
+ # @return [void]
12
+ def validate_json!
13
+ JSON::Validator.validate!(self.class.as_json_schema, as_json)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+
5
+ module JsonSchemaView
6
+ # A collection of extensions for {JsonWorld::DSL} to support recent JSON Schema.
7
+ # @private
8
+ module JsonWorldExtensions
9
+ require_relative "json_world_extensions/additional_properties"
10
+ require_relative "json_world_extensions/any_of"
11
+ require_relative "json_world_extensions/camelizable"
12
+ require_relative "json_world_extensions/compact_optional_properties"
13
+ require_relative "json_world_extensions/constant_property"
14
+ require_relative "json_world_extensions/declarable"
15
+ require_relative "json_world_extensions/enum_type"
16
+ require_relative "json_world_extensions/map_type"
17
+ require_relative "json_world_extensions/validatable"
18
+
19
+ # @see https://json-schema.org/specification.html
20
+ module Schema202012
21
+ extend ActiveSupport::Concern
22
+
23
+ include AdditionalProperties
24
+ include AnyOf::DSL
25
+ include ConstantProperty
26
+ include Declarable
27
+ include EnumType::DSL
28
+ include MapType::DSL
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Generates the configuration file (config/initializers/json_schema_view.rb) and setup components dir (app/components).:
3
+
4
+ Example:
5
+ `bin/rails generate json_schema_view:install`
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module JsonSchemaView
6
+ module Generators
7
+ # Install files to setup json_schema_view gem.
8
+ class InstallGenerator < Rails::Generators::Base
9
+ source_root File.expand_path("templates", __dir__)
10
+
11
+ class_option :components_path, type: :string, default: "app/components"
12
+ class_option :export_path, type: :string, default: "json_schema"
13
+ class_option :renderer_type, type: :string, default: "react_on_rails"
14
+
15
+ def create_initializer
16
+ template "initializer.rb", "config/initializers/json_schema_view.rb"
17
+ end
18
+
19
+ def create_base_classes
20
+ template "base_component.rb", File.join(components_path, "base_component.rb")
21
+ template "base_props.rb", File.join(components_path, "base_props.rb")
22
+ template "component_schema_set.rb", File.join(components_path, "component_schema_set.rb")
23
+ end
24
+
25
+ def create_exmaples
26
+ template "example/todo_list_component.rb", File.join(components_path, "example_todo_list_component.rb")
27
+ template "example/todo_item_resource.rb",
28
+ File.join(components_path, "example_todo_list_component", "todo_item_resource.rb")
29
+ end
30
+
31
+ private
32
+
33
+ def components_path
34
+ options[:components_path]
35
+ end
36
+
37
+ def export_path
38
+ options[:export_path]
39
+ end
40
+
41
+ def renderer_type
42
+ options[:renderer_type]
43
+ end
44
+
45
+ def schema_set_class_name
46
+ "ComponentSchemaSet"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_schema_view"
4
+
5
+ # @abstract
6
+ class BaseComponent < ::JsonSchemaView::BaseComponent
7
+ # You can configure how this components is rendered.
8
+ #
9
+ # There are some preset renderers:
10
+ # * `:json` - serialize the component as json text.
11
+ # * `:react_on_rails` - render the component by using react_on_rails gem.
12
+ renderer_class(:<%= renderer_type %>)
13
+
14
+ def base_props_class
15
+ BaseProps
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_schema_view"
4
+
5
+ # @abstract
6
+ class BaseProps < ::JsonSchemaView::BaseProps
7
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_schema_view"
4
+
5
+ # Configure what resource to export its JSON Schema and where directory to export.
6
+ class <%= schema_set_class_name %> < ::JsonSchemaView::SchemaSet
7
+ # <%= schema_set_class_name %> looks up component classses in this directory.
8
+ def root_path
9
+ __dir__
10
+ end
11
+
12
+ # <%= schema_set_class_name %> exports JSON Schema of these component classes.
13
+ def resource_classes_to_export
14
+ [
15
+ # Export all component classes (except for BaseComopnent) in `root_path`.
16
+ *search_component_classes.excluding(BaseComponent),
17
+ # You can add extra classes including {JsonSchemaDefinable} here to export their JSON Schemas.
18
+ ]
19
+ end
20
+
21
+ # <%= schema_set_class_name %> exports JSON Schema to this directory.
22
+ def export_path
23
+ Rails.root.join("<%= export_path %>")
24
+ end
25
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_schema_view"
4
+
5
+ class ExampleTodoListComponent
6
+ # This is an example definition of a resource.
7
+ #
8
+ # A class that includes {JsonSchemaView::JsonSchemaDefinable} can generate its JSON Schema
9
+ # and it can be used as a type in another resource's property.
10
+ class TodoItemResource
11
+ include JsonSchemaView::JsonSchemaDefinable
12
+
13
+ property(
14
+ :name,
15
+ description: "The title of TODO item.",
16
+ type: String,
17
+ )
18
+
19
+ property(
20
+ :done,
21
+ description: "Whether the TODO item is done or not.",
22
+ type: [TrueClass, FalseClass],
23
+ )
24
+
25
+ property(
26
+ :note,
27
+ description: "The additional description of TODO item.",
28
+ type: String,
29
+ optional: true,
30
+ )
31
+
32
+ # @param todo_item [Hash] A todo item ({ name: String, done: Boolean, note: String or nil }).
33
+ def initialize(todo_item)
34
+ @todo_item = todo_item
35
+ end
36
+
37
+ # @return [String] The title of TODO item.
38
+ def title
39
+ @todo_item[:title]
40
+ end
41
+
42
+ # @return [Boolean] Whether the TODO item is done or not.
43
+ def done
44
+ @todo_item[:done]
45
+ end
46
+
47
+ # @param note [String, nil] The additional description of TODO item.
48
+ def note
49
+ @todo_item[:note]
50
+ end
51
+ end
52
+ end