Module: JSI::SchemaClasses

Extended by:
Memoize
Defined in:
lib/jsi/schema_classes.rb

Overview

this module is just a namespace for schema classes.

Class Method Summary collapse

Methods included from Memoize

clear_memo, memoize

Class Method Details

.[](schema_id) ⇒ Class subclassing JSI::Base

JSI::SchemaClasses[schema_id] returns a class for the schema with the given id, the same class as returned from JSI.class_for_schema.

Parameters:

Returns:

  • (Class subclassing JSI::Base)

    the class for that schema



9
10
11
# File 'lib/jsi/schema_classes.rb', line 9

def self.[](schema_id)
  @classes_by_id[schema_id]
end

.class_for_schema(schema_object) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/jsi/schema_classes.rb', line 18

def class_for_schema(schema_object)
  memoize(:class_for_schema, JSI::Schema.from_object(schema_object)) do |schema_|
    Class.new(Base).instance_exec(schema_) do |schema|
      define_singleton_method(:schema) { schema }
      define_method(:schema) { schema }
      include(JSI::SchemaClasses.module_for_schema(schema, conflicting_modules: [Base, BaseArray, BaseHash]))

      jsi_class = self
      define_method(:jsi_class) { jsi_class }

      SchemaClasses.instance_exec(self) { |klass| @classes_by_id[klass.schema_id] = klass }

      self
    end
  end
end

.module_for_schema(schema_object, conflicting_modules: []) ⇒ Object

a module for the given schema, with accessor methods for any object property names the schema identifies. also has a singleton method called #schema to access the JSI::Schema this module represents.

accessor methods are defined on these modules so that methods can be defined on JSI.class_for_schema classes without method redefinition warnings. additionally, these overriding instance methods can call super to invoke the normal accessor behavior.

no property names that are the same as existing method names on the JSI class will be defined. users should use #[] and #[]= to access properties whose names conflict with existing methods.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/jsi/schema_classes.rb', line 47

def SchemaClasses.module_for_schema(schema_object, conflicting_modules: [])
  schema__ = JSI::Schema.from_object(schema_object)
  memoize(:module_for_schema, schema__, conflicting_modules) do |schema_, conflicting_modules_|
    Module.new.tap do |m|
      m.instance_exec(schema_) do |schema|
        define_singleton_method(:schema) { schema }
        define_singleton_method(:schema_id) do
          schema.schema_id
        end
        define_singleton_method(:inspect) do
          %Q(#<Module for Schema: #{schema_id}>)
        end

        conflicting_instance_methods = (conflicting_modules_ + [m]).map do |mod|
          mod.instance_methods + mod.private_instance_methods
        end.inject(Set.new, &:|)
        accessors_to_define = schema.described_object_property_names.map(&:to_s) - conflicting_instance_methods.map(&:to_s)
        accessors_to_define.each do |property_name|
          define_method(property_name) do
            if respond_to?(:[])
              self[property_name]
            else
              raise(NoMethodError, "schema instance of class #{self.class} does not respond to []; cannot call reader '#{property_name}'. instance is #{instance.pretty_inspect.chomp}")
            end
          end
          define_method("#{property_name}=") do |value|
            if respond_to?(:[]=)
              self[property_name] = value
            else
              raise(NoMethodError, "schema instance of class #{self.class} does not respond to []=; cannot call writer '#{property_name}='. instance is #{instance.pretty_inspect.chomp}")
            end
          end
        end
      end
    end
  end
end