json-schematized 0.1.0 → 0.2.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.
data/Gemfile CHANGED
@@ -1,3 +1,10 @@
1
1
  source :rubygems
2
2
 
3
3
  gemspec
4
+
5
+ # RUBY_VERSION ~> "1.9.0"
6
+ # gem "debugger"
7
+
8
+ # RUBY_VERSION ~> "1.8.0"
9
+ # gem "ruby-debug"
10
+ # gem "linecache", "0.43"
data/Gemfile.lock CHANGED
@@ -2,22 +2,33 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  json-schematized (0.1.0)
5
+ activesupport
5
6
  multi_json (~> 1.0)
7
+ virtus
6
8
 
7
9
  GEM
8
10
  remote: http://rubygems.org/
9
11
  specs:
12
+ activesupport (3.2.7)
13
+ i18n (~> 0.6)
14
+ multi_json (~> 1.0)
15
+ backports (2.6.7)
16
+ descendants_tracker (0.0.1)
10
17
  diff-lcs (1.1.3)
11
- json (1.7.5)
18
+ i18n (0.6.1)
19
+ json (1.7.6)
12
20
  multi_json (1.5.0)
13
- rspec (2.10.0)
14
- rspec-core (~> 2.10.0)
15
- rspec-expectations (~> 2.10.0)
16
- rspec-mocks (~> 2.10.0)
17
- rspec-core (2.10.1)
18
- rspec-expectations (2.10.0)
21
+ rspec (2.12.0)
22
+ rspec-core (~> 2.12.0)
23
+ rspec-expectations (~> 2.12.0)
24
+ rspec-mocks (~> 2.12.0)
25
+ rspec-core (2.12.2)
26
+ rspec-expectations (2.12.1)
19
27
  diff-lcs (~> 1.1.3)
20
- rspec-mocks (2.10.1)
28
+ rspec-mocks (2.12.1)
29
+ virtus (0.5.4)
30
+ backports (~> 2.6.1)
31
+ descendants_tracker (~> 0.0.1)
21
32
 
22
33
  PLATFORMS
23
34
  ruby
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # JSON::Schematized
2
2
 
3
- Template builder based on JSON-Schema.
3
+ [![Build Status](https://travis-ci.org/abril/json-schematized.png?branch=master)](https://travis-ci.org/abril/json-schematized)
4
+
5
+ Object builder based on JSON-Schema.
4
6
 
5
7
  ## Sample usage
6
8
 
@@ -9,24 +11,26 @@ Consider the following JSON-Schema (escaped as YAML, for better viewing):
9
11
  ```yaml
10
12
  # person.yml
11
13
  person:
12
- name:
13
- type: string
14
- birth:
15
- type: object
16
- properties:
17
- name:
18
- type: string
19
- children:
20
- type: array
21
- required: true
22
- items:
14
+ type: object
15
+ properties:
16
+ name:
17
+ type: string
18
+ birth:
23
19
  type: object
24
20
  properties:
25
21
  name:
26
22
  type: string
23
+ children:
24
+ type: array
25
+ required: true
26
+ items:
27
+ type: object
28
+ properties:
29
+ name:
30
+ type: string
27
31
  ```
28
32
 
29
- Usage:
33
+ ### Basic Wrapper Usage:
30
34
 
31
35
  ```ruby
32
36
  require "json-schematized"
@@ -37,8 +41,30 @@ class Person < JSON::Schematized::Base
37
41
  end
38
42
  end
39
43
 
40
- person = Person.new name: "John", birth: {name: "John Smith"}
41
- person.children # => []
42
- person.name # => "John"
43
- person.birth.name # => "John Smith"
44
+ person = Person.new name: "John", children: [{name: "William"}]
45
+ person.name # => "John"
46
+ person.children # => [{"name" => "William"}]
47
+ person.children.class # => Person::ChildrenCollection
48
+ person.children.first.class # => Person::Child
49
+ person.children.first.name # => "William"
50
+ ```
51
+
52
+ ### Virtus Wrapper Usage:
53
+
54
+ ```ruby
55
+ require "json-schematized"
56
+
57
+ class Person
58
+ include JSON::Schematized
59
+ json_schema wrapper: :virtus do # block called only once
60
+ YAML.load(File.read(File.expand_path("../person.yml", __FILE__)))["person"]
61
+ end
62
+ end
63
+
64
+ person = Person.new name: "John", children: [{name: "William"}]
65
+ person.name # => "John"
66
+ person.children # => [#<Person::Child:0x007fc990906fd0 @name="William">]
67
+ person.children.class # => Person::ChildrenCollection
68
+ person.children.first.class # => Person::Child
69
+ person.children.first.name # => "William"
44
70
  ```
@@ -1,17 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  module JSON
3
3
  module Schematized
4
- class Base
5
- extend DSL
6
- include SchematizedObject
7
-
8
- attr_reader :__json__
9
-
10
- def initialize(attrs = nil)
11
- @__json__ = {}
12
- @__schema__ = Builder.new(self.class.json_schema)
13
- __schema__.copy_to(__json__, attrs)
14
- end
4
+ class Base < BasicWrapper.model_superclass
5
+ include Schematized
15
6
  end
16
7
  end
17
8
  end
@@ -0,0 +1,209 @@
1
+ # encoding: UTF-8
2
+
3
+ require "virtus"
4
+
5
+ module JSON
6
+ module Schematized
7
+ module BasicWrapper
8
+ extend Wrapper
9
+
10
+ def self.included(base)
11
+ raise TypeError, "#{base.inspect} should inherits #{model_superclass}" unless base < model_superclass
12
+ base.send(:include, Models)
13
+ base.extend ClassMethods
14
+ prepare_schema!(base, base.json_schema, :complex_types)
15
+ end
16
+
17
+ module ClassMethods
18
+ def attribute_set
19
+ BasicWrapper.modularize(json_schema).attribute_set
20
+ end
21
+ end
22
+
23
+ def initialize(attrs = nil)
24
+ self.json_schema = self.class.json_schema
25
+ mass_assign!(attrs)
26
+ end
27
+
28
+ def self.modularize(json_schema)
29
+ super(json_schema) do
30
+ include BasicWrapper::SchematizedHash
31
+
32
+ def json_schema=(*args); end
33
+
34
+ def self.attribute_set
35
+ unless defined?(@attribute_set)
36
+ set = []
37
+ json_schema[:properties].each_pair do |field_name, meta|
38
+ set << Virtus::Attribute.build(field_name, BasicWrapper.meta_type(self, field_name, meta))
39
+ end
40
+ @attribute_set = Virtus::AttributeSet.new(nil, set)
41
+ end
42
+ @attribute_set
43
+ end
44
+
45
+ def self.extend_object(base)
46
+ super
47
+ return if base.class.include? BasicWrapper::Models
48
+ class_name = :ComplexTypes
49
+ (const_defined?(class_name) ?
50
+ const_get(class_name) :
51
+ const_set(class_name, Module.new)
52
+ ).tap do |klass|
53
+ unless klass.include?(self)
54
+ klass.send(:include, self)
55
+ klass.module_eval do
56
+ define_method :subclasses_namespace do
57
+ klass
58
+ end
59
+ end
60
+ end
61
+ base.extend klass
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def self.prepare_model(ref, field_name, model_class, json_schema)
68
+ model_class.extend BasicWrapper::ClassMethods
69
+ parent_namespace = {:ref => ref, :field => field_name.to_sym}
70
+ model_class.instance_variable_set(:@parent_namespace, parent_namespace)
71
+ def model_class.json_schema
72
+ json_schema = @parent_namespace[:ref].json_schema
73
+ meta = json_schema[:properties][@parent_namespace[:field]] || {}
74
+ meta = meta[:items] if meta[:type] == "array"
75
+ meta
76
+ end
77
+ prepare_schema!(model_class, json_schema, :complex_types)
78
+ end
79
+
80
+ def self.model_superclass
81
+ ::Hash
82
+ end
83
+
84
+ module Models
85
+ def attributes
86
+ self
87
+ end
88
+
89
+ def json_schema=(json_schema)
90
+ extend BasicWrapper.modularize(json_schema)
91
+ end
92
+ end
93
+
94
+ module Collections
95
+ def coerce_members_to(member_type, json_schema)
96
+ extend BasicWrapper::SchematizedArray
97
+ self.members_type = member_type
98
+ self.members_module = BasicWrapper.modularize(json_schema)
99
+ end
100
+ end
101
+
102
+ module SchematizedArray
103
+ attr_accessor :members_type
104
+ attr_accessor :members_module
105
+
106
+ def coerce_members_to(*args); end
107
+
108
+ def <<(value)
109
+ if members_module.json_schema[:type] == "object"
110
+ new_value = members_type.new
111
+ new_value.extend members_module
112
+ new_value.mass_assign!(value) if value.is_a?(Hash)
113
+ super(new_value)
114
+ else
115
+ super
116
+ end
117
+ end
118
+
119
+ def mass_assign!(array)
120
+ array.each do |value|
121
+ self << value
122
+ end
123
+ end
124
+ end
125
+
126
+ module SchematizedHash
127
+ def method_missing(name, *args)
128
+ key = name.to_s
129
+ if key =~ /=\z/
130
+ key = $`.to_sym
131
+ if json_schema[:properties][key]
132
+ self[key] = args.first
133
+ else
134
+ super
135
+ end
136
+ else
137
+ read_attribute key
138
+ end
139
+ end
140
+
141
+ def respond_to?(method_name)
142
+ json_schema[:properties].has_key?(method_name.to_sym) || super
143
+ end
144
+
145
+ def subclasses_namespace
146
+ self.class
147
+ end
148
+
149
+ def []=(key, value)
150
+ if meta = json_schema[:properties][key.to_sym]
151
+ case meta[:type]
152
+ when "array"
153
+ collection = BasicWrapper.build_collection(subclasses_namespace, key, meta[:items])
154
+ new_value = collection.class.new
155
+ new_value.coerce_members_to(collection.first, meta[:items])
156
+ new_value.mass_assign!(value) if value.is_a?(Array)
157
+ value = new_value
158
+ when "object"
159
+ model_class = BasicWrapper.build_model(subclasses_namespace, key, meta)
160
+ new_value = model_class.new
161
+ new_value.json_schema = meta
162
+ new_value.mass_assign!(value) if value.is_a?(Hash)
163
+ value = new_value
164
+ end
165
+ end
166
+ super(key.to_s, value)
167
+ end
168
+
169
+ def mass_assign!(hash)
170
+ return unless hash.is_a?(Hash)
171
+ hash.each_pair do |key, value|
172
+ self[key] = value
173
+ end
174
+ ensure
175
+ SchematizedHash.ensure_structure!(self, json_schema)
176
+ end
177
+
178
+ def read_attribute(name)
179
+ name = name.to_s
180
+ value = self[name]
181
+ if !has_key?(name) && (meta = json_schema[:properties][name.to_sym])
182
+ case meta[:type]
183
+ when "array"
184
+ self[name] = []
185
+ value = self[name]
186
+ when "object"
187
+ self[name] = {}
188
+ value = self[name]
189
+ end
190
+ end
191
+ value
192
+ end
193
+
194
+ def self.ensure_structure!(json, schema)
195
+ meta = schema[:properties]
196
+ meta.each_pair do |key, schema|
197
+ if !json.has_key?(key.to_s) && schema[:required]
198
+ json[key.to_s] = case schema[:type]
199
+ when "object" then {}
200
+ when "array" then []
201
+ else nil
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
@@ -5,16 +5,22 @@ require "multi_json"
5
5
  module JSON
6
6
  module Schematized
7
7
  module DSL
8
- def json_schema(json = nil, &block)
9
- if instance_variable_defined?(:"@json_schema")
10
- schema = @json_schema[:loader].call
8
+ def json_schema(*args, &block)
9
+ if instance_variable_defined?(:"@json_schema_loader")
10
+ schema = @json_schema_loader.call
11
11
  schema = MultiJson.dump(schema) unless schema.is_a?(String)
12
12
  MultiJson.load(schema, :symbolize_keys => true)
13
13
  else
14
14
  return if self === Base
15
+ opts = args.last.is_a?(Hash) ? args.pop : {}
16
+ json = args.first
15
17
  raise ArgumentError, "JSON or block expected" if block_given? ^ json.nil?
16
18
  block = Proc.new{ json } unless block_given?
17
- @json_schema = {:loader => block}
19
+ @json_schema_loader = block
20
+ wrapper = "#{opts.fetch(:wrapper, :basic)}_wrapper".gsub(/(?:\A_*|_)([^_])/){ $1.upcase }.to_sym
21
+ wrapper = Schematized.const_defined?(wrapper) ? Schematized.const_get(wrapper) : nil
22
+ send(:include, wrapper) if wrapper
23
+ self
18
24
  end
19
25
  end
20
26
  end
@@ -0,0 +1,83 @@
1
+ # encoding: UTF-8
2
+
3
+ require "virtus"
4
+
5
+ module JSON
6
+ module Schematized
7
+ module DSL
8
+ def virtus_module
9
+ VirtusWrapper.modularize(json_schema)
10
+ end
11
+ end
12
+
13
+ module VirtusWrapper
14
+ extend Wrapper
15
+
16
+ def self.included(base)
17
+ base.send(:include, modularize(base.json_schema))
18
+ end
19
+
20
+ def self.modularize(json_schema)
21
+ super(json_schema) do
22
+ include ::Virtus
23
+
24
+ VirtusWrapper.prepare_schema!(self, self.json_schema, :simple_types)
25
+ def self.included(base)
26
+ super
27
+ VirtusWrapper.prepare_schema!(base, json_schema, :complex_types)
28
+ end
29
+
30
+ def self.extend_object(base)
31
+ class_name = :ComplexTypes
32
+ (const_defined?(class_name) ?
33
+ const_get(class_name) :
34
+ const_set(class_name, Module.new)
35
+ ).tap do |klass|
36
+ klass.send(:include, self) unless klass.include?(self)
37
+ base.extend klass
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def self.prepare_model(ref, field_name, model_class, json_schema)
44
+ model_class.send(:include, modularize(json_schema))
45
+ end
46
+
47
+ def self.add_attribute!(ref, field_name, meta, kind)
48
+ opts = {}
49
+ klass = (kind.is_a?(Class) ? kind : kind.class)
50
+ if kind.is_a?(Class)
51
+ opts[:default] = klass.new if meta[:required] && kind.include?(::Virtus)
52
+ else
53
+ opts[:default] = kind.class.new
54
+ end
55
+ ref.attribute field_name, kind, opts
56
+ end
57
+
58
+ def self.collection_superclass
59
+ Array
60
+ end
61
+
62
+ class Array < ::Array
63
+ end
64
+
65
+ module Attribute
66
+ class Array < ::Virtus::Attribute::Array
67
+ primitive VirtusWrapper::Array
68
+ default primitive.new
69
+
70
+ def new_collection
71
+ (@primitive || self.class.primitive).new
72
+ end
73
+
74
+ def self.merge_options(type, options)
75
+ merged_options = super
76
+ klass = type.is_a?(Class) ? type : type.class
77
+ merged_options.merge(:primitive => klass)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,122 @@
1
+ # encoding: UTF-8
2
+
3
+ module JSON
4
+ module Schematized
5
+ module Wrapper
6
+ def self.extended(base)
7
+ base.const_set(:Models, Module.new).send(:include, Schematized::Models)
8
+ base.const_set(:Collections, Module.new).send(:include, Schematized::Collections)
9
+ end
10
+
11
+ def modularize(json_schema, &block)
12
+ json_schema = MultiJson.dump(json_schema) unless json_schema.is_a?(String)
13
+ json_schema = MultiJson.load(json_schema, :symbolize_keys => true)
14
+ module_name = "JSD#{json_schema.hash}".gsub(/\-/, "_").to_sym # JSON-Schema Definition
15
+ if const_defined?(module_name)
16
+ const_get(module_name)
17
+ else
18
+ const_set(module_name, Module.new).tap do |m|
19
+ m.instance_variable_set(:@json_schema, json_schema)
20
+ def m.json_schema; @json_schema; end
21
+ m.send(:include, self::Models)
22
+ m.module_eval do
23
+ define_method :json_schema do
24
+ m.json_schema
25
+ end
26
+ end
27
+ m.module_eval(&block) if block_given?
28
+ end
29
+ end
30
+ end
31
+
32
+ def prepare_schema!(ref, json_schema, mode)
33
+ modes = {
34
+ :complex_types => 1,
35
+ :simple_types => 2,
36
+ :all_types => 3
37
+ }
38
+ mode = [modes[mode].to_i, 0].max
39
+ accept_complex_types = (modes[:complex_types] & mode) > 0
40
+ accept_simple_types = (modes[:simple_types] & mode) > 0
41
+ json_schema[:properties].each_pair do |field_name, meta|
42
+ kind = nil
43
+ case meta[:type]
44
+ when "array"
45
+ next unless accept_complex_types
46
+ collection = build_collection(ref, field_name, meta[:items])
47
+ kind = collection
48
+ when "object"
49
+ next unless accept_complex_types
50
+ model = build_model(ref, field_name, meta)
51
+ kind = model
52
+ else
53
+ next unless accept_simple_types
54
+ kind = meta_type(ref, field_name, meta)
55
+ end
56
+ add_attribute! ref, field_name, meta, kind
57
+ end
58
+ end
59
+
60
+ def add_attribute!(ref, field_name, meta, kind)
61
+ end
62
+
63
+ def meta_type(ref, field_name, meta, singularize = false)
64
+ case meta[:type]
65
+ when "string"
66
+ String
67
+ when "array"
68
+ build_collection(ref, field_name, meta[:items])
69
+ when "object"
70
+ build_model(ref, field_name, meta, singularize)
71
+ else
72
+ parse_json_schema_type meta[:type]
73
+ end
74
+ end
75
+
76
+ def parse_json_schema_type(type)
77
+ Object
78
+ end
79
+
80
+ def build_class_name(field_name)
81
+ field_name.to_s.gsub(/(?:\A_*|_)([^_])/){ $1.upcase }
82
+ end
83
+
84
+ def collection_superclass
85
+ Array
86
+ end
87
+
88
+ def build_collection(ref, field_name, meta)
89
+ class_name = [build_class_name(field_name), "Collection"].join.to_sym
90
+ (ref.const_defined?(class_name) ?
91
+ ref.const_get(class_name) :
92
+ ref.const_set(class_name, Class.new(collection_superclass))
93
+ ).tap do |klass|
94
+ unless klass.include?(Schematized::Collections)
95
+ klass.send(:include, self::Collections)
96
+ end
97
+ end[meta_type(ref, field_name, meta, true)]
98
+ end
99
+
100
+ def model_superclass
101
+ end
102
+
103
+ def build_model(ref, field_name, json_schema, singularize = false)
104
+ name = field_name
105
+ name = ::ActiveSupport::Inflector.singularize(field_name.to_s).to_sym if singularize
106
+ class_name = build_class_name(name).to_sym
107
+ (ref.const_defined?(class_name) ?
108
+ ref.const_get(class_name) :
109
+ ref.const_set(class_name, Class.new(*[model_superclass].compact))
110
+ ).tap do |klass|
111
+ unless klass.include?(Schematized::Models)
112
+ klass.send(:include, self::Models)
113
+ prepare_model(ref, field_name, klass, json_schema)
114
+ end
115
+ end
116
+ end
117
+
118
+ def prepare_model(ref, field_name, model_class, json_schema)
119
+ end
120
+ end
121
+ end
122
+ end
@@ -2,13 +2,21 @@
2
2
  $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__))
3
3
 
4
4
  require "rubygems"
5
+ require "active_support"
5
6
 
6
7
  module JSON
7
8
  module Schematized
8
9
  autoload :Base, "json/schematized/base"
9
- autoload :Builder, "json/schematized/builder"
10
10
  autoload :DSL, "json/schematized/dsl"
11
+ autoload :Wrapper, "json/schematized/wrapper"
12
+ autoload :BasicWrapper, "json/schematized/basic_wrapper"
13
+ autoload :VirtusWrapper, "json/schematized/virtus_wrapper"
14
+
15
+ def self.included(base)
16
+ base.extend DSL
17
+ end
18
+
19
+ module Models; end
20
+ module Collections; end
11
21
  end
12
22
  end
13
-
14
- require "json/schematized_objects"
metadata CHANGED
@@ -1,116 +1,108 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: json-schematized
3
- version: !ruby/object:Gem::Version
4
- hash: 27
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Marcelo Manzan
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2013-01-15 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2013-01-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: multi_json
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70120517130240 !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
18
+ requirements:
26
19
  - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 15
29
- segments:
30
- - 1
31
- - 0
32
- version: "1.0"
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70120517130240
25
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ requirement: &70120517129800 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70120517129800
36
+ - !ruby/object:Gem::Dependency
37
+ name: virtus
38
+ requirement: &70120517129340 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
33
44
  type: :runtime
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: json
37
45
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
46
+ version_requirements: *70120517129340
47
+ - !ruby/object:Gem::Dependency
48
+ name: json
49
+ requirement: &70120517128840 !ruby/object:Gem::Requirement
39
50
  none: false
40
- requirements:
51
+ requirements:
41
52
  - - ~>
42
- - !ruby/object:Gem::Version
43
- hash: 7
44
- segments:
45
- - 1
46
- - 4
47
- version: "1.4"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.4'
48
55
  type: :development
49
- version_requirements: *id002
50
- - !ruby/object:Gem::Dependency
51
- name: rspec
52
56
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
57
+ version_requirements: *70120517128840
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &70120517128340 !ruby/object:Gem::Requirement
54
61
  none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 15
59
- segments:
60
- - 2
61
- - 6
62
- version: "2.6"
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '2.6'
63
66
  type: :development
64
- version_requirements: *id003
65
- description: ""
67
+ prerelease: false
68
+ version_requirements: *70120517128340
69
+ description: ''
66
70
  email: manzan@gmail.com
67
71
  executables: []
68
-
69
72
  extensions: []
70
-
71
73
  extra_rdoc_files: []
72
-
73
- files:
74
+ files:
74
75
  - lib/json/schematized/base.rb
75
- - lib/json/schematized/builder.rb
76
+ - lib/json/schematized/basic_wrapper.rb
76
77
  - lib/json/schematized/dsl.rb
77
- - lib/json/schematized_objects.rb
78
+ - lib/json/schematized/virtus_wrapper.rb
79
+ - lib/json/schematized/wrapper.rb
78
80
  - lib/json-schematized.rb
79
81
  - README.md
80
82
  - Gemfile
81
83
  - Gemfile.lock
82
84
  homepage: http://github.com/abril
83
85
  licenses: []
84
-
85
86
  post_install_message:
86
87
  rdoc_options: []
87
-
88
- require_paths:
88
+ require_paths:
89
89
  - lib
90
- required_ruby_version: !ruby/object:Gem::Requirement
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
91
  none: false
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- hash: 3
96
- segments:
97
- - 0
98
- version: "0"
99
- required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
97
  none: false
101
- requirements:
102
- - - ">="
103
- - !ruby/object:Gem::Version
104
- hash: 3
105
- segments:
106
- - 0
107
- version: "0"
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
108
102
  requirements: []
109
-
110
103
  rubyforge_project:
111
104
  rubygems_version: 1.8.15
112
105
  signing_key:
113
106
  specification_version: 3
114
107
  summary: Template builder based on JSON-Schema
115
108
  test_files: []
116
-
@@ -1,77 +0,0 @@
1
- # encoding: UTF-8
2
- module JSON
3
- module Schematized
4
- class Builder
5
- attr_reader :schema
6
-
7
- def initialize(schema)
8
- @schema = schema
9
- end
10
-
11
- def member?(key)
12
- schema[:properties][key.to_sym]
13
- end
14
-
15
- def copy_to(json, attrs)
16
- if json.is_a?(Array)
17
- return unless attrs.is_a?(Array)
18
- attrs.each{ |value| assign!(json, nil, schema, value) }
19
- else
20
- return unless attrs.is_a?(Hash)
21
- attrs.each_pair do |key, value|
22
- meta = member?(key)
23
- assign!(json, key, meta, value) if meta
24
- end
25
- end
26
- ensure_structure(json, schema)
27
- json
28
- end
29
-
30
- def ensure_structure(json, schema)
31
- case json
32
- when Array
33
- meta = schema[:items]
34
- case meta && meta[:type]
35
- when "object", "array"
36
- json.each do |value|
37
- ensure_structure(value, meta)
38
- end
39
- end
40
- when Hash
41
- meta = schema[:properties]
42
- meta.each_pair do |key, schema|
43
- case value = json[key.to_s]
44
- when Hash
45
- ensure_structure(value, schema) if schema[:type] == "object"
46
- when Array
47
- ensure_structure(value, schema) if schema[:type] == "array"
48
- when nil
49
- if schema[:required]
50
- case schema[:type]
51
- when "object"
52
- ensure_structure(json[key.to_s] = {}, schema)
53
- when "array"
54
- ensure_structure(json[key.to_s] = [], schema)
55
- end
56
- end
57
- end
58
- end
59
- end
60
- end
61
-
62
- def assign!(json, key, meta, value)
63
- case meta[:type]
64
- when "object"
65
- value = self.class.new(meta).copy_to({}, value)
66
- when "array"
67
- value = self.class.new(meta[:items]).copy_to([], value)
68
- end
69
- if json.is_a?(Array)
70
- json << value
71
- else
72
- json[key.to_s] = value
73
- end
74
- end
75
- end
76
- end
77
- end
@@ -1,51 +0,0 @@
1
- # encoding: UTF-8
2
- module JSON
3
- module SchematizedObject
4
- attr_accessor :__schema__
5
-
6
- def __json__
7
- self
8
- end
9
-
10
- protected
11
-
12
- def method_missing(name, *args)
13
- key = name.to_s
14
- if key =~ /=\z/
15
- key = $`.to_sym
16
- meta = __schema__.member?(key)
17
- meta ? __schema__.assign!(__json__, key, meta, args.first) : super
18
- else
19
- read_attribute key
20
- end
21
- end
22
-
23
- def read_attribute(name)
24
- name = name.to_s
25
- value = __json__[name]
26
- if !__json__.has_key?(name) && (meta = __schema__.member?(name))
27
- case meta[:type]
28
- when "array"
29
- value = __json__[name] = [].tap do |array|
30
- array.extend SchematizedArray
31
- array.__schema__ = __schema__.class.new(meta[:items])
32
- end
33
- when "object"
34
- value = __json__[name] = {}.tap do |hash|
35
- hash.extend SchematizedObject
36
- hash.__schema__ = __schema__.class.new(meta)
37
- end
38
- end
39
- end
40
- value
41
- end
42
- end
43
-
44
- module SchematizedArray
45
- attr_accessor :__schema__
46
-
47
- def __json__
48
- self
49
- end
50
- end
51
- end