json-schematized 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +2 -0
- data/Gemfile +2 -0
- data/README.md +24 -2
- data/json-schematized.gemspec +21 -0
- data/lib/json/schematized/basic_wrapper.rb +31 -26
- data/lib/json/schematized/dsl.rb +1 -3
- data/lib/json/schematized/virtus_wrapper.rb +7 -0
- data/lib/json/schematized/wrapper.rb +14 -10
- data/script/console +36 -0
- data/spec/fixtures/person.yml +38 -0
- data/spec/lib/json/schematized/base_spec.rb +14 -0
- data/spec/lib/json/schematized/basic_wrapper_spec.rb +25 -0
- data/spec/lib/json/schematized/virtus_wrapper_spec.rb +20 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/general_shared_excamples.rb +151 -0
- metadata +115 -63
- data/Gemfile.lock +0 -39
data/.rspec
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -30,7 +30,7 @@ person:
|
|
30
30
|
type: string
|
31
31
|
```
|
32
32
|
|
33
|
-
### Basic Wrapper Usage
|
33
|
+
### Basic Wrapper Usage
|
34
34
|
|
35
35
|
```ruby
|
36
36
|
require "json-schematized"
|
@@ -49,7 +49,18 @@ person.children.first.class # => Person::Child
|
|
49
49
|
person.children.first.name # => "William"
|
50
50
|
```
|
51
51
|
|
52
|
-
|
52
|
+
Another way to use Basic Wrapper is as follows:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
class Person < Hash
|
56
|
+
include JSON::Schematized
|
57
|
+
json_schema wrapper: :basic do # block called for each new instance
|
58
|
+
YAML.load(File.read(File.expand_path("../person.yml", __FILE__)))["person"]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
### Virtus Wrapper Usage
|
53
64
|
|
54
65
|
```ruby
|
55
66
|
require "json-schematized"
|
@@ -68,3 +79,14 @@ person.children.class # => Person::ChildrenCollection
|
|
68
79
|
person.children.first.class # => Person::Child
|
69
80
|
person.children.first.name # => "William"
|
70
81
|
```
|
82
|
+
|
83
|
+
### Object with Basic Wrapper usage
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
person = Hash.new
|
87
|
+
json_schema = YAML.load(File.read(File.expand_path("../person.yml", __FILE__)))["person"]
|
88
|
+
person.extend JSON::Schematized::BasicWrapper.modularize(json_schema)
|
89
|
+
|
90
|
+
person.children << {}
|
91
|
+
# ...
|
92
|
+
```
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "json-schematized"
|
3
|
+
s.version = "0.2.1"
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.summary = "Object builder based on JSON-Schema"
|
6
|
+
s.require_paths = ["lib"]
|
7
|
+
s.files = `git ls-files -- Gemfile README.md lib/ script/ *.gemspec`.split("\n")
|
8
|
+
s.test_files = `git ls-files -- .rspec Gemfile spec/`.split("\n")
|
9
|
+
|
10
|
+
s.description = ""
|
11
|
+
s.authors = ["Marcelo Manzan"]
|
12
|
+
s.email = "manzan@gmail.com"
|
13
|
+
s.homepage = "http://github.com/abril"
|
14
|
+
|
15
|
+
s.add_runtime_dependency "multi_json", "~> 1.0"
|
16
|
+
s.add_runtime_dependency "activesupport"
|
17
|
+
s.add_runtime_dependency "virtus"
|
18
|
+
|
19
|
+
s.add_development_dependency "json", "~> 1.4"
|
20
|
+
s.add_development_dependency "rspec", ">= 2.6"
|
21
|
+
end
|
@@ -16,21 +16,23 @@ module JSON
|
|
16
16
|
|
17
17
|
module ClassMethods
|
18
18
|
def attribute_set
|
19
|
-
|
19
|
+
json_schema_module.attribute_set
|
20
|
+
end
|
21
|
+
|
22
|
+
def json_schema_module
|
23
|
+
BasicWrapper.modularize(json_schema)
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
23
27
|
def initialize(attrs = nil)
|
24
28
|
self.json_schema = self.class.json_schema
|
25
|
-
|
29
|
+
self.attributes = attrs
|
26
30
|
end
|
27
31
|
|
28
32
|
def self.modularize(json_schema)
|
29
33
|
super(json_schema) do
|
30
34
|
include BasicWrapper::SchematizedHash
|
31
35
|
|
32
|
-
def json_schema=(*args); end
|
33
|
-
|
34
36
|
def self.attribute_set
|
35
37
|
unless defined?(@attribute_set)
|
36
38
|
set = []
|
@@ -46,20 +48,17 @@ module JSON
|
|
46
48
|
super
|
47
49
|
return if base.class.include? BasicWrapper::Models
|
48
50
|
class_name = :ComplexTypes
|
49
|
-
|
50
|
-
const_get(class_name)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
define_method :subclasses_namespace do
|
57
|
-
klass
|
58
|
-
end
|
59
|
-
end
|
51
|
+
if const_defined?(class_name)
|
52
|
+
klass = const_get(class_name)
|
53
|
+
else
|
54
|
+
klass = const_set(class_name, Module.new)
|
55
|
+
_mod = self
|
56
|
+
klass.module_eval do
|
57
|
+
define_method(:submodels_scope){ _mod }
|
60
58
|
end
|
61
|
-
base.extend klass
|
62
59
|
end
|
60
|
+
base.extend klass
|
61
|
+
BasicWrapper::SchematizedHash.ensure_structure!(base, base.json_schema)
|
63
62
|
end
|
64
63
|
end
|
65
64
|
end
|
@@ -82,10 +81,6 @@ module JSON
|
|
82
81
|
end
|
83
82
|
|
84
83
|
module Models
|
85
|
-
def attributes
|
86
|
-
self
|
87
|
-
end
|
88
|
-
|
89
84
|
def json_schema=(json_schema)
|
90
85
|
extend BasicWrapper.modularize(json_schema)
|
91
86
|
end
|
@@ -109,7 +104,7 @@ module JSON
|
|
109
104
|
if members_module.json_schema[:type] == "object"
|
110
105
|
new_value = members_type.new
|
111
106
|
new_value.extend members_module
|
112
|
-
new_value.
|
107
|
+
new_value.attributes = value if value.is_a?(Hash)
|
113
108
|
super(new_value)
|
114
109
|
else
|
115
110
|
super
|
@@ -138,11 +133,17 @@ module JSON
|
|
138
133
|
end
|
139
134
|
end
|
140
135
|
|
136
|
+
def attributes
|
137
|
+
self
|
138
|
+
end
|
139
|
+
|
140
|
+
def json_schema=(*args); end
|
141
|
+
|
141
142
|
def respond_to?(method_name)
|
142
143
|
json_schema[:properties].has_key?(method_name.to_sym) || super
|
143
144
|
end
|
144
145
|
|
145
|
-
def
|
146
|
+
def submodels_scope
|
146
147
|
self.class
|
147
148
|
end
|
148
149
|
|
@@ -150,23 +151,27 @@ module JSON
|
|
150
151
|
if meta = json_schema[:properties][key.to_sym]
|
151
152
|
case meta[:type]
|
152
153
|
when "array"
|
153
|
-
collection = BasicWrapper.build_collection(
|
154
|
+
collection = BasicWrapper.build_collection(submodels_scope, key, meta[:items])
|
154
155
|
new_value = collection.class.new
|
155
156
|
new_value.coerce_members_to(collection.first, meta[:items])
|
156
157
|
new_value.mass_assign!(value) if value.is_a?(Array)
|
157
158
|
value = new_value
|
158
159
|
when "object"
|
159
|
-
model_class = BasicWrapper.build_model(
|
160
|
+
model_class = BasicWrapper.build_model(submodels_scope, key, meta)
|
160
161
|
new_value = model_class.new
|
161
162
|
new_value.json_schema = meta
|
162
|
-
new_value.
|
163
|
+
new_value.attributes = value if value.is_a?(Hash)
|
163
164
|
value = new_value
|
165
|
+
else
|
166
|
+
attribute = submodels_scope.attribute_set[key.to_sym]
|
167
|
+
attribute = attribute.writer if attribute.respond_to?(:writer)
|
168
|
+
value = attribute.coerce(value)
|
164
169
|
end
|
165
170
|
end
|
166
171
|
super(key.to_s, value)
|
167
172
|
end
|
168
173
|
|
169
|
-
def
|
174
|
+
def attributes=(hash)
|
170
175
|
return unless hash.is_a?(Hash)
|
171
176
|
hash.each_pair do |key, value|
|
172
177
|
self[key] = value
|
data/lib/json/schematized/dsl.rb
CHANGED
@@ -11,15 +11,13 @@ module JSON
|
|
11
11
|
schema = MultiJson.dump(schema) unless schema.is_a?(String)
|
12
12
|
MultiJson.load(schema, :symbolize_keys => true)
|
13
13
|
else
|
14
|
-
return if self === Base
|
15
14
|
opts = args.last.is_a?(Hash) ? args.pop : {}
|
16
15
|
json = args.first
|
17
16
|
raise ArgumentError, "JSON or block expected" if block_given? ^ json.nil?
|
18
17
|
block = Proc.new{ json } unless block_given?
|
19
18
|
@json_schema_loader = block
|
20
19
|
wrapper = "#{opts.fetch(:wrapper, :basic)}_wrapper".gsub(/(?:\A_*|_)([^_])/){ $1.upcase }.to_sym
|
21
|
-
|
22
|
-
send(:include, wrapper) if wrapper
|
20
|
+
include Schematized.const_get(wrapper) if Schematized.const_defined?(wrapper)
|
23
21
|
self
|
24
22
|
end
|
25
23
|
end
|
@@ -15,6 +15,13 @@ module JSON
|
|
15
15
|
|
16
16
|
def self.included(base)
|
17
17
|
base.send(:include, modularize(base.json_schema))
|
18
|
+
base.extend ClassMethods
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def json_schema_module
|
23
|
+
VirtusWrapper.modularize(json_schema)
|
24
|
+
end
|
18
25
|
end
|
19
26
|
|
20
27
|
def self.modularize(json_schema)
|
@@ -16,13 +16,11 @@ module JSON
|
|
16
16
|
const_get(module_name)
|
17
17
|
else
|
18
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
19
|
m.send(:include, self::Models)
|
20
|
+
def m.json_schema; @json_schema end
|
22
21
|
m.module_eval do
|
23
|
-
|
24
|
-
|
25
|
-
end
|
22
|
+
@json_schema = json_schema.freeze
|
23
|
+
define_method(:json_schema){ m.json_schema }
|
26
24
|
end
|
27
25
|
m.module_eval(&block) if block_given?
|
28
26
|
end
|
@@ -62,19 +60,25 @@ module JSON
|
|
62
60
|
|
63
61
|
def meta_type(ref, field_name, meta, singularize = false)
|
64
62
|
case meta[:type]
|
65
|
-
when "string"
|
66
|
-
String
|
67
63
|
when "array"
|
68
64
|
build_collection(ref, field_name, meta[:items])
|
69
65
|
when "object"
|
70
66
|
build_model(ref, field_name, meta, singularize)
|
67
|
+
when "boolean"
|
68
|
+
TrueClass
|
69
|
+
when "integer"
|
70
|
+
Integer
|
71
71
|
else
|
72
|
-
parse_json_schema_type meta[:type]
|
72
|
+
parse_json_schema_type ref, field_name, meta[:type]
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
-
def parse_json_schema_type(type)
|
77
|
-
|
76
|
+
def parse_json_schema_type(ref, field_name, type)
|
77
|
+
case type
|
78
|
+
when "string" then String
|
79
|
+
when "number" then Numeric
|
80
|
+
else Object
|
81
|
+
end
|
78
82
|
end
|
79
83
|
|
80
84
|
def build_class_name(field_name)
|
data/script/console
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "rubygems"
|
5
|
+
require "bundler"
|
6
|
+
rescue LoadError
|
7
|
+
raise "Could not load the bundler gem. Install it with `gem install bundler`."
|
8
|
+
end
|
9
|
+
|
10
|
+
begin
|
11
|
+
# Set up load paths for all bundled gems
|
12
|
+
ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
|
13
|
+
Bundler.setup
|
14
|
+
rescue Bundler::GemNotFound
|
15
|
+
raise RuntimeError, "Bundler couldn't find some gems." +
|
16
|
+
"Did you run `bundle install`?"
|
17
|
+
end
|
18
|
+
|
19
|
+
require "json-schematized"
|
20
|
+
require "json"
|
21
|
+
|
22
|
+
class Person < JSON::Schematized::Base
|
23
|
+
json_schema do
|
24
|
+
YAML.load(File.read(File.expand_path("../../spec/fixtures/person.yml", __FILE__)))["person"]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class VPerson
|
29
|
+
include JSON::Schematized
|
30
|
+
json_schema :wrapper => :virtus do
|
31
|
+
YAML.load(File.read(File.expand_path("../../spec/fixtures/person.yml", __FILE__)))["person"]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require "irb"
|
36
|
+
IRB.start(__FILE__)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
person:
|
2
|
+
type: object
|
3
|
+
properties:
|
4
|
+
email:
|
5
|
+
type: string
|
6
|
+
age:
|
7
|
+
type: integer
|
8
|
+
phones:
|
9
|
+
type: array
|
10
|
+
required: true
|
11
|
+
items:
|
12
|
+
type: string
|
13
|
+
address:
|
14
|
+
type: object
|
15
|
+
required: true
|
16
|
+
properties:
|
17
|
+
street_name:
|
18
|
+
type: string
|
19
|
+
number:
|
20
|
+
type: number
|
21
|
+
children:
|
22
|
+
type: array
|
23
|
+
items:
|
24
|
+
type: object
|
25
|
+
properties:
|
26
|
+
name:
|
27
|
+
type: string
|
28
|
+
age:
|
29
|
+
type: integer
|
30
|
+
born_location:
|
31
|
+
type: object
|
32
|
+
properties:
|
33
|
+
country:
|
34
|
+
type: string
|
35
|
+
state:
|
36
|
+
type: string
|
37
|
+
city:
|
38
|
+
type: string
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class SimplePerson < JSON::Schematized::Base
|
4
|
+
json_schema do
|
5
|
+
YAML.load(File.read(File.expand_path("../../../../fixtures/person.yml", __FILE__)))["person"]
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe JSON::Schematized::Base do
|
10
|
+
let(:described_class){ JSON::Schematized::BasicWrapper }
|
11
|
+
it_should_behave_like "a JSON::Schematized::Wrapper" do
|
12
|
+
let(:model_class){ SimplePerson }
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class BPerson < Hash
|
4
|
+
include JSON::Schematized
|
5
|
+
json_schema :wrapper => :basic do
|
6
|
+
YAML.load(File.read(File.expand_path("../../../../fixtures/person.yml", __FILE__)))["person"]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ::JSON::Schematized::BasicWrapper do
|
11
|
+
it_should_behave_like "a JSON::Schematized::Wrapper" do
|
12
|
+
let(:model_class){ ::BPerson }
|
13
|
+
context "model instances" do
|
14
|
+
subject { model_class.new }
|
15
|
+
its(:attributes){ should == {"phones" => [], "address" => {}} }
|
16
|
+
its(:children){ should be_instance_of model_class::ChildrenCollection }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "object" do
|
20
|
+
let(:object_model){ Hash.new.extend(modularized_schema) }
|
21
|
+
subject { object_model }
|
22
|
+
it { should == {"phones" => [], "address" => {}} }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class VPerson
|
4
|
+
include JSON::Schematized
|
5
|
+
json_schema :wrapper => :virtus do
|
6
|
+
YAML.load(File.read(File.expand_path("../../../../fixtures/person.yml", __FILE__)))["person"]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ::JSON::Schematized::VirtusWrapper do
|
11
|
+
it_should_behave_like "a JSON::Schematized::Wrapper" do
|
12
|
+
let(:model_class){ ::VPerson }
|
13
|
+
let(:object_model_module) { modularized_schema::ComplexTypes }
|
14
|
+
|
15
|
+
context "model classes" do
|
16
|
+
subject { model_class }
|
17
|
+
it { should be_include described_class.modularize(schema) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
gemlib = File.expand_path("../../lib", __FILE__)
|
3
|
+
$:.unshift(gemlib) unless $:.include?(gemlib)
|
4
|
+
|
5
|
+
require "json-schematized"
|
6
|
+
require "json"
|
7
|
+
require "yaml"
|
8
|
+
|
9
|
+
|
10
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
11
|
+
# in spec/support/ and its subdirectories.
|
12
|
+
Dir[File.expand_path("../support/**/*.rb", __FILE__)].each{ |f| require f }
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
shared_examples "a model with submodel types" do
|
4
|
+
subject { model_scope } # model_scope must be defined inside `it_should_behave_like` block
|
5
|
+
it { should be_const_defined :Address }
|
6
|
+
it { should be_const_defined :ChildrenCollection }
|
7
|
+
it { should be_const_defined :Child }
|
8
|
+
it { should be_const_defined :PhonesCollection }
|
9
|
+
it { should_not be_const_defined :BornLocation }
|
10
|
+
|
11
|
+
context "submodel Child types" do
|
12
|
+
subject { model_scope::Child }
|
13
|
+
it { should be_const_defined :BornLocation }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "submodel Address attribute set names" do
|
17
|
+
subject { model_scope::Address.attribute_set.map(&:name) }
|
18
|
+
it { should be_include :street_name }
|
19
|
+
it { should be_include :number }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "submodel Child attribute set names" do
|
23
|
+
subject { model_scope::Child.attribute_set.map(&:name) }
|
24
|
+
it { should be_include :name }
|
25
|
+
it { should be_include :age }
|
26
|
+
it { should be_include :born_location }
|
27
|
+
end
|
28
|
+
|
29
|
+
context "submodel Child::BornLocation attribute set names" do
|
30
|
+
subject { model_scope::Child::BornLocation.attribute_set.map(&:name) }
|
31
|
+
it { should be_include :country }
|
32
|
+
it { should be_include :state }
|
33
|
+
it { should be_include :city }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
shared_examples "a JSON::Schematized::Wrapper" do
|
38
|
+
let(:schema_fixture_file){ File.expand_path("../../fixtures/person.yml", __FILE__) }
|
39
|
+
let(:schema_str){ MultiJson.dump(YAML.load(File.read(schema_fixture_file))["person"]) }
|
40
|
+
|
41
|
+
let(:schema){ MultiJson.load(schema_str, :symbolize_keys => true) }
|
42
|
+
let(:modularized_schema){ described_class.modularize(schema) }
|
43
|
+
let(:object_model_module){ modularized_schema }
|
44
|
+
|
45
|
+
context "wrapper module" do
|
46
|
+
subject { modularized_schema }
|
47
|
+
it { should be_kind_of Module }
|
48
|
+
it { should be_include JSON::Schematized::Models }
|
49
|
+
it { should be_include described_class::Models }
|
50
|
+
its(:name){ should =~ /\A#{described_class}::JSD/ }
|
51
|
+
its(:json_schema){ should == schema }
|
52
|
+
end
|
53
|
+
|
54
|
+
it_should_behave_like "a model with submodel types" do
|
55
|
+
let(:model_scope){ model_class }
|
56
|
+
end
|
57
|
+
|
58
|
+
context "model classes" do
|
59
|
+
subject { model_class } # model_class must be defined inside `it_should_behave_like` block
|
60
|
+
it { should be_include described_class }
|
61
|
+
it { should be_include JSON::Schematized::Models }
|
62
|
+
it { should be_include described_class::Models }
|
63
|
+
its(:json_schema){ should == schema }
|
64
|
+
its(:json_schema_module){ should be modularized_schema }
|
65
|
+
|
66
|
+
context "attribute set names" do
|
67
|
+
subject { model_class.attribute_set.map(&:name) }
|
68
|
+
it { should be_include :address }
|
69
|
+
it { should be_include :children }
|
70
|
+
it { should be_include :email }
|
71
|
+
it { should be_include :phones }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "model instances" do
|
76
|
+
subject { model_class.new }
|
77
|
+
its(:address){ should be_instance_of model_class::Address }
|
78
|
+
its(:phones){ should be_instance_of model_class::PhonesCollection }
|
79
|
+
its(:children){ should be_instance_of model_class::ChildrenCollection }
|
80
|
+
its(:children){ should be_kind_of ::Array }
|
81
|
+
|
82
|
+
context "with mass assignment" do
|
83
|
+
let(:phones){ ["555-1234"] }
|
84
|
+
let(:address){ {:street_name => "Wall Street", :number => 1000} }
|
85
|
+
let(:born_location){ {} }
|
86
|
+
let(:child){ {:name => "John", :age => "10", :born_location => born_location} }
|
87
|
+
let :attrs do
|
88
|
+
{
|
89
|
+
:email => "me@email.com", :phones => phones,
|
90
|
+
:age => "45",
|
91
|
+
:address => address, :children => [child]
|
92
|
+
}
|
93
|
+
end
|
94
|
+
subject { model_class.new attrs }
|
95
|
+
its(:email){ should == "me@email.com" }
|
96
|
+
its(:age){ should be 45 }
|
97
|
+
its(:phones){ should be_instance_of model_class::PhonesCollection }
|
98
|
+
its(:"phones.size"){ should be 1 }
|
99
|
+
its(:"phones.first"){ should == "555-1234" }
|
100
|
+
its(:address){ should be_instance_of model_class::Address }
|
101
|
+
its(:"address.street_name"){ should == address[:street_name] }
|
102
|
+
its(:"address.number"){ should == address[:number] }
|
103
|
+
its(:children){ should be_instance_of model_class::ChildrenCollection }
|
104
|
+
its(:"children.size"){ should be 1 }
|
105
|
+
its(:"children.first"){ should be_instance_of model_class::Child }
|
106
|
+
its(:"children.first.name"){ should == child[:name] }
|
107
|
+
its(:"children.first.age"){ should == child[:age].to_i }
|
108
|
+
its(:"children.first.born_location"){ should be_instance_of model_class::Child::BornLocation }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "collection classes" do
|
113
|
+
subject { model_class::ChildrenCollection }
|
114
|
+
it { should be_include JSON::Schematized::Collections }
|
115
|
+
it { should be_include described_class::Collections }
|
116
|
+
end
|
117
|
+
|
118
|
+
context "extended object" do
|
119
|
+
let(:object_model){ Hash.new.extend(modularized_schema) }
|
120
|
+
subject { object_model }
|
121
|
+
before do
|
122
|
+
object_model.age = "45"
|
123
|
+
object_model.children = [{:age => "10", :born_location => {}}]
|
124
|
+
end
|
125
|
+
|
126
|
+
its(:class){ should_not be_const_defined :Address }
|
127
|
+
its(:class){ should_not be_const_defined :ChildrenCollection }
|
128
|
+
its(:class){ should_not be_const_defined :Child }
|
129
|
+
its(:class){ should_not be_const_defined :PhonesCollection }
|
130
|
+
its(:class){ should_not be_const_defined :BornLocation }
|
131
|
+
it { should be_kind_of object_model_module }
|
132
|
+
it { should be_respond_to :age }
|
133
|
+
it { should be_respond_to :email }
|
134
|
+
it { should be_respond_to :address }
|
135
|
+
it { should be_respond_to :children }
|
136
|
+
it { should be_respond_to :phones }
|
137
|
+
its(:age){ should be 45 }
|
138
|
+
its(:address){ subject.should be_instance_of object_model_module::Address } # adapted to ruby-1.8.x
|
139
|
+
its(:phones){ subject.should be_instance_of object_model_module::PhonesCollection } # adapted to ruby-1.8.x
|
140
|
+
its(:children){ should be_instance_of object_model_module::ChildrenCollection }
|
141
|
+
its(:children){ should be_kind_of ::Array }
|
142
|
+
its(:"children.size"){ should be 1 }
|
143
|
+
its(:"children.first"){ should be_instance_of object_model_module::Child }
|
144
|
+
its(:"children.first.age"){ should be 10 }
|
145
|
+
its(:"children.first.born_location"){ should be_instance_of object_model_module::Child::BornLocation }
|
146
|
+
|
147
|
+
it_should_behave_like "a model with submodel types" do
|
148
|
+
let(:model_scope){ object_model_module }
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
metadata
CHANGED
@@ -1,108 +1,160 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: json-schematized
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 1
|
10
|
+
version: 0.2.1
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Marcelo Manzan
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2013-02-14 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: multi_json
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
25
|
+
requirements:
|
19
26
|
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 15
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 0
|
32
|
+
version: "1.0"
|
22
33
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
26
36
|
name: activesupport
|
27
|
-
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
39
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
33
47
|
type: :runtime
|
34
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
37
50
|
name: virtus
|
38
|
-
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
53
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
44
61
|
type: :runtime
|
45
|
-
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
48
64
|
name: json
|
49
|
-
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
67
|
none: false
|
51
|
-
requirements:
|
68
|
+
requirements:
|
52
69
|
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 7
|
72
|
+
segments:
|
73
|
+
- 1
|
74
|
+
- 4
|
75
|
+
version: "1.4"
|
55
76
|
type: :development
|
56
|
-
|
57
|
-
|
58
|
-
- !ruby/object:Gem::Dependency
|
77
|
+
version_requirements: *id004
|
78
|
+
- !ruby/object:Gem::Dependency
|
59
79
|
name: rspec
|
60
|
-
|
80
|
+
prerelease: false
|
81
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
61
82
|
none: false
|
62
|
-
requirements:
|
63
|
-
- -
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
hash: 15
|
87
|
+
segments:
|
88
|
+
- 2
|
89
|
+
- 6
|
90
|
+
version: "2.6"
|
66
91
|
type: :development
|
67
|
-
|
68
|
-
|
69
|
-
description: ''
|
92
|
+
version_requirements: *id005
|
93
|
+
description: ""
|
70
94
|
email: manzan@gmail.com
|
71
95
|
executables: []
|
96
|
+
|
72
97
|
extensions: []
|
98
|
+
|
73
99
|
extra_rdoc_files: []
|
74
|
-
|
100
|
+
|
101
|
+
files:
|
102
|
+
- Gemfile
|
103
|
+
- README.md
|
104
|
+
- json-schematized.gemspec
|
105
|
+
- lib/json-schematized.rb
|
75
106
|
- lib/json/schematized/base.rb
|
76
107
|
- lib/json/schematized/basic_wrapper.rb
|
77
108
|
- lib/json/schematized/dsl.rb
|
78
109
|
- lib/json/schematized/virtus_wrapper.rb
|
79
110
|
- lib/json/schematized/wrapper.rb
|
80
|
-
-
|
81
|
-
-
|
82
|
-
-
|
83
|
-
-
|
111
|
+
- script/console
|
112
|
+
- .rspec
|
113
|
+
- spec/fixtures/person.yml
|
114
|
+
- spec/lib/json/schematized/base_spec.rb
|
115
|
+
- spec/lib/json/schematized/basic_wrapper_spec.rb
|
116
|
+
- spec/lib/json/schematized/virtus_wrapper_spec.rb
|
117
|
+
- spec/spec_helper.rb
|
118
|
+
- spec/support/general_shared_excamples.rb
|
84
119
|
homepage: http://github.com/abril
|
85
120
|
licenses: []
|
121
|
+
|
86
122
|
post_install_message:
|
87
123
|
rdoc_options: []
|
88
|
-
|
124
|
+
|
125
|
+
require_paths:
|
89
126
|
- lib
|
90
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
128
|
none: false
|
92
|
-
requirements:
|
93
|
-
- -
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
|
96
|
-
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
hash: 3
|
133
|
+
segments:
|
134
|
+
- 0
|
135
|
+
version: "0"
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
137
|
none: false
|
98
|
-
requirements:
|
99
|
-
- -
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
hash: 3
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
version: "0"
|
102
145
|
requirements: []
|
146
|
+
|
103
147
|
rubyforge_project:
|
104
148
|
rubygems_version: 1.8.15
|
105
149
|
signing_key:
|
106
150
|
specification_version: 3
|
107
|
-
summary:
|
108
|
-
test_files:
|
151
|
+
summary: Object builder based on JSON-Schema
|
152
|
+
test_files:
|
153
|
+
- .rspec
|
154
|
+
- Gemfile
|
155
|
+
- spec/fixtures/person.yml
|
156
|
+
- spec/lib/json/schematized/base_spec.rb
|
157
|
+
- spec/lib/json/schematized/basic_wrapper_spec.rb
|
158
|
+
- spec/lib/json/schematized/virtus_wrapper_spec.rb
|
159
|
+
- spec/spec_helper.rb
|
160
|
+
- spec/support/general_shared_excamples.rb
|
data/Gemfile.lock
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
json-schematized (0.1.0)
|
5
|
-
activesupport
|
6
|
-
multi_json (~> 1.0)
|
7
|
-
virtus
|
8
|
-
|
9
|
-
GEM
|
10
|
-
remote: http://rubygems.org/
|
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)
|
17
|
-
diff-lcs (1.1.3)
|
18
|
-
i18n (0.6.1)
|
19
|
-
json (1.7.6)
|
20
|
-
multi_json (1.5.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)
|
27
|
-
diff-lcs (~> 1.1.3)
|
28
|
-
rspec-mocks (2.12.1)
|
29
|
-
virtus (0.5.4)
|
30
|
-
backports (~> 2.6.1)
|
31
|
-
descendants_tracker (~> 0.0.1)
|
32
|
-
|
33
|
-
PLATFORMS
|
34
|
-
ruby
|
35
|
-
|
36
|
-
DEPENDENCIES
|
37
|
-
json (~> 1.4)
|
38
|
-
json-schematized!
|
39
|
-
rspec (>= 2.6)
|