Permalink
Browse files

add KlassFactory to create classes from schemata with their properites

  • Loading branch information...
1 parent 5f5ad19 commit bff187e3fb544f941a7a53fb3a87ebd6c0c39ca7 @schorsch schorsch committed Jan 1, 2013
Showing with 125 additions and 1 deletion.
  1. +32 −0 README.md
  2. +1 −0 lib/schema_tools.rb
  3. +35 −0 lib/schema_tools/klass_factory.rb
  4. +1 −1 lib/schema_tools/version.rb
  5. +56 −0 spec/schema_tools/klass_factory_spec.rb
View
@@ -111,6 +111,38 @@ methods to you local classes .. like people NOT using JSON schema
# raw access
contact.schema_attrs
+## Objects from Schema - KlassFactory
+
+Use the KlassFactory to directly create classes, with all attributes from a
+schema. The classes are named after each schema[name] found in from global path.
+So lets assume you have a 'client.json' schema with a name attribute in it, for
+the following examples:
+
+ SchemaTools::KlassFactory.build
+ client = Client.new
+ client.name = 'Mändy'
+
+
+Rather like a namespace? Good idea, but the class or module must be defined.
+
+ module SalesKing; end
+ SchemaTools::KlassFactory.build namespace: SalesKing
+ client = SalesKing::Client.new
+
+Add a custom schema reader
+
+ reader = SchemaTools::Reader.new
+ reader.path = HappyPdf::Schema.path
+ SchemaTools::KlassFactory.build reader: reader
+
+
+
+## Real world examples
+
+* [HappyPdf json schema](https://github.com/happyPDF/happypdf_json_schema) .. api gem will follow
+* [DocTag ruby gem](https://github.com/docTag/doctag_rb) and [DocTag json-schema](https://github.com/docTag/doctag_json_schema)
+* [SalesKing json schema](https://github.com/salesking/sk_api_schema)
+
## Test
Only runs on Ruby 1.9
View
@@ -6,6 +6,7 @@
require 'schema_tools/reader'
require 'schema_tools/cleaner'
require 'schema_tools/hash'
+require 'schema_tools/klass_factory'
module SchemaTools
@@ -0,0 +1,35 @@
+# encoding: utf-8
+require 'active_support/core_ext/string/inflections'
+module SchemaTools
+ class KlassFactory
+
+ class << self
+
+ # Build classes from schema inside the given namespace. Uses all classes
+ # found in schema path
+ #
+ # @param [String|Symbol|Module] namespace of the new classes e.g. MyCustomNamespace::MySchemaClass
+ # @param [Hash] opts
+ # @options opts [SchemaTools::Reader] :reader to use instead of global one
+ def build(opts={})
+ reader = opts[:reader] || SchemaTools::Reader
+ schemata = reader.read_all( opts[:path] || SchemaTools.schema_path )
+ namespace = opts[:namespace] || Object
+ if namespace.is_a?(String) || namespace.is_a?(Symbol)
+ namespace = "#{namespace}".constantize
+ end
+
+ schemata.each do |schema|
+ klass_name = schema['name'].classify
+ next if namespace.const_defined?(klass_name, false)
+ klass = namespace.const_set(klass_name, Class.new)
+ klass.class_eval do
+ include SchemaTools::Modules::Attributes
+ has_schema_attrs schema['name'], reader: reader
+ end
+ end
+ end
+
+ end
+ end
+end
@@ -1,3 +1,3 @@
module SchemaTools
- VERSION = '0.0.6'
+ VERSION = '0.0.7'
end
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+class TestNamespaceKlass
+ # for schema classes
+end
+
+module TestNamespaceModule
+
+end
+
+describe SchemaTools::KlassFactory do
+
+ after :each do
+ SchemaTools::Reader.registry_reset
+
+ # try cleaning objs
+ Object.send :remove_const, 'Client' if Object.const_defined? 'Client'
+ TestNamespaceKlass.send :remove_const, 'Client' if TestNamespaceKlass.const_defined? 'Client'
+ TestNamespaceModule.send :remove_const, 'Client' if TestNamespaceModule.const_defined? 'Client'
+ end
+
+ context 'class building' do
+ it 'should build from class name' do
+ SchemaTools::KlassFactory.build
+ expect { Client.new }.to_not raise_error
+ expect { Lead.new }.to_not raise_error
+ end
+
+ end
+
+ context 'class building with namespace' do
+
+ after :each do
+ end
+
+ it 'should build from class name' do
+ SchemaTools::KlassFactory.build(namespace: TestNamespaceKlass)
+ expect { TestNamespaceKlass::Client.new }.to_not raise_error
+ end
+
+ it 'should build from class as string' do
+ SchemaTools::KlassFactory.build(namespace: 'TestNamespaceKlass')
+ expect { TestNamespaceKlass::Client.new }.to_not raise_error
+ end
+ it 'should build from module name' do
+ SchemaTools::KlassFactory.build(namespace: TestNamespaceModule)
+ expect { TestNamespaceModule::Client.new }.to_not raise_error
+ end
+
+ it 'should build from module name as string' do
+ SchemaTools::KlassFactory.build(namespace: 'TestNamespaceModule')
+ expect { TestNamespaceModule::Client.new }.to_not raise_error
+ end
+
+ end
+end

0 comments on commit bff187e

Please sign in to comment.