json-schematized 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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