data_bindings 0.0.1
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/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +167 -0
- data/Rakefile +13 -0
- data/data_bindings.gemspec +35 -0
- data/lib/data_bindings/adapters/bson.rb +32 -0
- data/lib/data_bindings/adapters/json.rb +32 -0
- data/lib/data_bindings/adapters/native.rb +50 -0
- data/lib/data_bindings/adapters/params.rb +91 -0
- data/lib/data_bindings/adapters/ruby.rb +44 -0
- data/lib/data_bindings/adapters/tnetstring.rb +32 -0
- data/lib/data_bindings/adapters/xml.rb +74 -0
- data/lib/data_bindings/adapters/yaml.rb +26 -0
- data/lib/data_bindings/adapters.rb +12 -0
- data/lib/data_bindings/bound.rb +331 -0
- data/lib/data_bindings/converters.rb +83 -0
- data/lib/data_bindings/generator.rb +140 -0
- data/lib/data_bindings/unbound.rb +76 -0
- data/lib/data_bindings/util.rb +78 -0
- data/lib/data_bindings/version.rb +3 -0
- data/lib/data_bindings.rb +52 -0
- data/test/array_test.rb +55 -0
- data/test/bson_test.rb +23 -0
- data/test/converter_test.rb +36 -0
- data/test/data_bindings_test.rb +67 -0
- data/test/fixtures/1.json +1 -0
- data/test/json_test.rb +40 -0
- data/test/native_test.rb +64 -0
- data/test/params_test.rb +60 -0
- data/test/test_helper.rb +17 -0
- data/test/tnetstring_test.rb +23 -0
- data/test/validation_test.rb +217 -0
- data/test/xml_test.rb +20 -0
- data/test/yaml_test.rb +19 -0
- metadata +282 -0
data/test/bson_test.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Data Bindings bson" do
|
|
4
|
+
describe "bson parsing" do
|
|
5
|
+
it "should parse bson" do
|
|
6
|
+
a = DataBindings.from_bson(BSON.serialize(:author => 'siggy', :title => 'bible')).bind { property :author; property :title }
|
|
7
|
+
assert a.valid?
|
|
8
|
+
assert_equal "siggy", a[:author]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "bson generation" do
|
|
13
|
+
it "should generate bson" do
|
|
14
|
+
a = DataBindings.from_ruby('author' => 'siggy',"title" => 'koran').bind { property :author; property :title }
|
|
15
|
+
assert a.valid?
|
|
16
|
+
valid_bson_representations = [
|
|
17
|
+
"(\x00\x00\x00\x02author\x00\x06\x00\x00\x00siggy\x00\x02title\x00\x06\x00\x00\x00koran\x00\x00",
|
|
18
|
+
"(\x00\x00\x00\x02title\x00\x06\x00\x00\x00koran\x00\x02author\x00\x06\x00\x00\x00siggy\x00\x00"
|
|
19
|
+
]
|
|
20
|
+
assert valid_bson_representations.include?( a.convert_to_bson )
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Data Bindings" do
|
|
4
|
+
before do
|
|
5
|
+
DataBindings.reset!
|
|
6
|
+
DataBindings.type(:person) do
|
|
7
|
+
property :name, String
|
|
8
|
+
property :age, Integer
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "custom readers" do
|
|
13
|
+
it "should allow adding a custom converter" do
|
|
14
|
+
DataBindings.reader(:kolob) { '{"name":"god","age":123}' }
|
|
15
|
+
a = DataBindings.from_json_kolob.bind(:person)
|
|
16
|
+
assert_equal "god", a[:name]
|
|
17
|
+
assert a.valid?
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe "custom writers" do
|
|
22
|
+
it "should allow adding a custom converter" do
|
|
23
|
+
data = ''
|
|
24
|
+
DataBindings.writer(:kolob) { |o| data = o }
|
|
25
|
+
a = DataBindings.from_json('{"author":"siggy","title":"bible"}').convert_to_json_kolob
|
|
26
|
+
assert_equal MultiJson.decode('{"author":"siggy","title":"bible"}'), MultiJson.decode(data)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should allow adding a custom converter for a bound object" do
|
|
30
|
+
data = ''
|
|
31
|
+
DataBindings.writer(:kolob) { |o| data = o }
|
|
32
|
+
a = DataBindings.from_json('{"name":"siggy","age":32}').bind(:person).convert_to_json_kolob
|
|
33
|
+
assert_equal MultiJson.decode('{"name":"siggy","age":32}'), MultiJson.decode(data)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Data Bindings" do
|
|
4
|
+
before do
|
|
5
|
+
DataBindings.reset!
|
|
6
|
+
DataBindings.type(:person) do
|
|
7
|
+
property :name, String
|
|
8
|
+
property :age, Integer
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should raise a validation error if neither the key or alias key exist on an object" do
|
|
13
|
+
DataBindings.type(:file) do
|
|
14
|
+
property :size, Integer
|
|
15
|
+
property :filename, String, :alias => [:filenames, :file_name]
|
|
16
|
+
end
|
|
17
|
+
a = DataBindings.from_json('{"size":925, "fn":"foo.txt"}').bind(:file)
|
|
18
|
+
assert_equal({'filename' => "not found"}, a.errors)
|
|
19
|
+
refute a.errors.empty?
|
|
20
|
+
refute a.valid?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "from_*_file" do
|
|
24
|
+
it "should load from a file" do
|
|
25
|
+
a = DataBindings.from_json_file(File.expand_path("../fixtures/1.json", __FILE__)).bind_array {
|
|
26
|
+
all_elements :person
|
|
27
|
+
}
|
|
28
|
+
assert a.valid?
|
|
29
|
+
assert_equal "josh", a[1][:name]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "from_*_net" do
|
|
34
|
+
it "should load from the net" do
|
|
35
|
+
a = DataBindings.from_json_http("http://localhost/1.json").bind_array {
|
|
36
|
+
all_elements :person
|
|
37
|
+
}
|
|
38
|
+
assert a.valid?
|
|
39
|
+
assert_equal "josh", a[1][:name]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should fail to load without auth" do
|
|
43
|
+
assert_raises DataBindings::HttpError do
|
|
44
|
+
a = DataBindings.from_json_http("http://secret/1.json").bind_array {
|
|
45
|
+
all_elements :person
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should load with the right auth" do
|
|
51
|
+
a = DataBindings.from_json_http("http://secret/1.json", :basic_auth => {:username => 'test', :password => 'user'}).bind_array {
|
|
52
|
+
all_elements :person
|
|
53
|
+
}
|
|
54
|
+
assert a.valid?
|
|
55
|
+
assert_equal "josh", a[1][:name]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "strictness via the generator's default" do
|
|
60
|
+
it "should reject extra properties" do
|
|
61
|
+
DataBindings.strict = true
|
|
62
|
+
a = DataBindings.from_json('{"author":"siggy","title":"bible"}').bind { property :author }
|
|
63
|
+
assert_equal "siggy", a[:author]
|
|
64
|
+
refute a.valid?
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"name":"andrew","age":32},{"name":"josh","age":12}]
|
data/test/json_test.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Data Bindings json" do
|
|
4
|
+
before do
|
|
5
|
+
DataBindings.reset!
|
|
6
|
+
DataBindings.type(:person) do
|
|
7
|
+
property :name, String
|
|
8
|
+
property :age, Integer
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should create a JSON object" do
|
|
13
|
+
a = DataBindings.from_json('{"name":"Andrew","age":32}').bind(:person)
|
|
14
|
+
assert a.errors.empty?
|
|
15
|
+
assert a.valid?
|
|
16
|
+
assert_equal "Andrew", a[:name]
|
|
17
|
+
assert_equal MultiJson.decode("{\"name\":\"Andrew\",\"age\":32}"), MultiJson.decode(a.convert_to_json)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should refuse to create a JSON object when the data is invalid" do
|
|
21
|
+
a = DataBindings.from_json('{"name":"Andrew","age":"asd"}').bind(:person)
|
|
22
|
+
refute a.errors.empty?
|
|
23
|
+
refute a.valid?
|
|
24
|
+
assert_raises(DataBindings::FailedValidation) { a.convert_to_json }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should create a JSON object when the data is invalid and is forced" do
|
|
28
|
+
a = DataBindings.from_json('{"name":"Andrew","age":"asd"}').bind(:person)
|
|
29
|
+
refute a.errors.empty?
|
|
30
|
+
refute a.valid?
|
|
31
|
+
assert_equal MultiJson.decode("{\"name\":\"Andrew\",\"age\":\"asd\"}"), MultiJson.decode(a.force_convert_to_json)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should parse JSON" do
|
|
35
|
+
a = DataBindings.from_json("[1,2,3]").bind([Integer])
|
|
36
|
+
assert a.valid?
|
|
37
|
+
assert a.errors.empty?
|
|
38
|
+
assert_equal [1, 2, 3], [a[0], a[1], a[2]]
|
|
39
|
+
end
|
|
40
|
+
end
|
data/test/native_test.rb
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Data Bindings native" do
|
|
4
|
+
before do
|
|
5
|
+
DataBindings.reset!
|
|
6
|
+
DataBindings.type(:person) do
|
|
7
|
+
property :name, String
|
|
8
|
+
property :age, Integer
|
|
9
|
+
end
|
|
10
|
+
@person = Class.new { attr_accessor :name, :age; def initialize(name, age); @name, @age = name, age; end }
|
|
11
|
+
DataBindings.for_native(:person) { |props| @person.new(props[:name], props[:age]) }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should parse a Native object" do
|
|
15
|
+
p = @person.new("ben", 23)
|
|
16
|
+
a = DataBindings.from_native(p)
|
|
17
|
+
assert_equal "ben", a['name']
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should transform into json without a binding (roughly)" do
|
|
21
|
+
p = @person.new("ben", 23)
|
|
22
|
+
assert_raises(DataBindings::UnboundError) { DataBindings.from_native(p).convert_to_json }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should not transform into json without a binding" do
|
|
26
|
+
p = @person.new("ben", 23)
|
|
27
|
+
a = DataBindings.from_native(p).bind(:person).convert_to_json
|
|
28
|
+
assert_equal({"name" => "ben", "age" => 23}, MultiJson.decode(a))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should transform into a native object" do
|
|
32
|
+
a = DataBindings.from_json('{"name":"Andrew","age":32}').bind(:person)
|
|
33
|
+
assert a.errors.empty?
|
|
34
|
+
assert a.valid?
|
|
35
|
+
assert_equal "Andrew", a[:name]
|
|
36
|
+
assert_equal "Andrew", a.to_native.name
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should create a hash when there is no binding" do
|
|
40
|
+
a = DataBindings.from_json('{"name":"Andrew","age":32}').to_native
|
|
41
|
+
assert_equal "Andrew", a.name
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should be able to create nested objets" do
|
|
45
|
+
DataBindings.type(:address_book) do
|
|
46
|
+
property :owner, :person
|
|
47
|
+
property :friends, [:person]
|
|
48
|
+
end
|
|
49
|
+
address_book = Class.new {
|
|
50
|
+
attr_accessor :owner, :friends
|
|
51
|
+
def initialize(owner, friends)
|
|
52
|
+
@owner, @friends = owner, friends
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def find(name)
|
|
56
|
+
idx = @friends.find_index{|f| f.name == name }
|
|
57
|
+
idx && @friends[idx]
|
|
58
|
+
end
|
|
59
|
+
}
|
|
60
|
+
DataBindings.for_native(:address_book) { |props| address_book.new(props[:owner], props[:friends]) }
|
|
61
|
+
book = DataBindings.from_json('{"owner":{"name":"josh","age":34},"friends":[{"name":"grinch","age":123},{"name":"steve","age":23}]}').bind(:address_book).to_native
|
|
62
|
+
assert_equal 'steve', book.find('steve').name
|
|
63
|
+
end
|
|
64
|
+
end
|
data/test/params_test.rb
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Data Bindings params" do
|
|
4
|
+
|
|
5
|
+
describe "params parsing" do
|
|
6
|
+
it "should parse params" do
|
|
7
|
+
a = DataBindings.from_params("author=josh&title=great+expectations").bind { property :author; property :title }
|
|
8
|
+
assert a.valid?
|
|
9
|
+
assert_equal "josh", a[:author]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should parse a nested hash" do
|
|
13
|
+
a = DataBindings.from_params("name[first_name][short]=ben&name[first_name][long]=benjamin&name[last_name]=coe").bind { property :name }
|
|
14
|
+
assert a.valid?
|
|
15
|
+
assert_equal "ben", a[:name][:first_name][:short]
|
|
16
|
+
assert_equal "benjamin", a[:name][:first_name][:long]
|
|
17
|
+
assert_equal "coe", a[:name][:last_name]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should parse an array" do
|
|
21
|
+
a = DataBindings.from_params("name[0][last_name]=coe&name[0][first_name]=ben&name[1][first_name]=josh").bind { property :name }
|
|
22
|
+
assert a.valid?
|
|
23
|
+
assert_equal "ben", a[:name][0][:first_name]
|
|
24
|
+
assert_equal "coe", a[:name][0][:last_name]
|
|
25
|
+
assert_equal "josh", a[:name][1][:first_name]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "params generation" do
|
|
30
|
+
|
|
31
|
+
it "should generate params" do
|
|
32
|
+
a = DataBindings.from_ruby('author' => 'siggy',"title" => 'koran').bind { property :author; property :title }
|
|
33
|
+
assert a.valid?
|
|
34
|
+
assert_match "author=siggy", a.convert_to_params
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should generate params for nested hash" do
|
|
38
|
+
a = DataBindings.from_ruby('author' => {'name' => {'first_name' => 'bill'}}, 'title' => 'koran', 'meta' => {'isbn' => 9999} ).bind do
|
|
39
|
+
property :author
|
|
40
|
+
property :title
|
|
41
|
+
property :meta
|
|
42
|
+
end
|
|
43
|
+
assert a.valid?
|
|
44
|
+
assert_match "author[name][first_name]=bill", a.convert_to_params
|
|
45
|
+
assert_match "meta[isbn]=9999", a.convert_to_params
|
|
46
|
+
assert_match "title=koran", a.convert_to_params
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should generate params for nested array" do
|
|
50
|
+
a = DataBindings.from_ruby('authors' => ['josh', 'ben'], 'title' => 'koran' ).bind do
|
|
51
|
+
property :authors
|
|
52
|
+
property :title
|
|
53
|
+
end
|
|
54
|
+
assert a.valid?
|
|
55
|
+
assert_match "authors[0]=josh", a.convert_to_params
|
|
56
|
+
assert_match "title=koran", a.convert_to_params
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'minitest/spec'
|
|
2
|
+
require 'minitest/autorun'
|
|
3
|
+
|
|
4
|
+
$: << File.expand_path("../../lib", __FILE__)
|
|
5
|
+
require 'data_bindings'
|
|
6
|
+
require 'fakeweb'
|
|
7
|
+
|
|
8
|
+
FakeWeb.allow_net_connect = false
|
|
9
|
+
|
|
10
|
+
Dir[File.expand_path("../fixtures/*", __FILE__)].each do |f|
|
|
11
|
+
FakeWeb.register_uri(:get, "http://localhost/#{File.basename(f)}", :body => File.read(f))
|
|
12
|
+
FakeWeb.register_uri(:get, "http://secret/#{File.basename(f)}", :body => "Unauthorized", :status => ["401", "Unauthorized"])
|
|
13
|
+
FakeWeb.register_uri(:get, "http://test:user@secret/#{File.basename(f)}", :body => File.read(f))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
require 'bson'
|
|
17
|
+
require 'tnetstring'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Data Bindings tnetstring" do
|
|
4
|
+
describe "tnetstring parsing" do
|
|
5
|
+
it "should parse tnetstring" do
|
|
6
|
+
a = DataBindings.from_tnetstring(TNetstring.dump('author' => 'siggy', 'title' => 'bible')).bind { property :author; property :title }
|
|
7
|
+
assert a.valid?
|
|
8
|
+
assert_equal "siggy", a[:author]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "tnetstring generation" do
|
|
13
|
+
it "should generate tnetstring" do
|
|
14
|
+
a = DataBindings.from_ruby('author' => 'siggy',"title" => 'koran').bind { property :author; property :title }
|
|
15
|
+
assert a.valid?
|
|
16
|
+
valid_tnetstring_representations = [
|
|
17
|
+
"33:6:author,5:siggy,5:title,5:koran,}",
|
|
18
|
+
"33:5:title,5:koran,6:author,5:siggy,}"
|
|
19
|
+
]
|
|
20
|
+
assert valid_tnetstring_representations.include?( a.convert_to_tnetstring )
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
describe "Data Bindings validation" do
|
|
2
|
+
before do
|
|
3
|
+
DataBindings.reset!
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
it "should revalidate" do
|
|
7
|
+
a = DataBindings.from_json("[1,2,3]").bind([Integer])
|
|
8
|
+
assert a.valid?
|
|
9
|
+
assert a.errors.empty?
|
|
10
|
+
assert_equal [1, 2, 3], [a[0], a[1], a[2]]
|
|
11
|
+
a.unshift 'asd'
|
|
12
|
+
refute a.valid?
|
|
13
|
+
refute a.errors.empty?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should allow for a property to have a Boolean type" do
|
|
17
|
+
DataBindings.type(:person) do
|
|
18
|
+
property :name, String
|
|
19
|
+
property :awesome, :boolean
|
|
20
|
+
end
|
|
21
|
+
a = DataBindings.from_json('{"name":"Andrew","awesome":"true"}').bind(:person)
|
|
22
|
+
assert a.errors.empty?
|
|
23
|
+
assert a.valid?
|
|
24
|
+
assert_equal true, a[:awesome]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should allow for a property to have a default value set" do
|
|
28
|
+
DataBindings.type(:person) do
|
|
29
|
+
property :name, String
|
|
30
|
+
property :age, Integer, :default => 25
|
|
31
|
+
end
|
|
32
|
+
a = DataBindings.from_json('{"name":"Andrew"}').bind(:person)
|
|
33
|
+
assert a.errors.empty?
|
|
34
|
+
assert a.valid?
|
|
35
|
+
assert_equal 25, a[:age]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should allow the default value to be overridden with another value." do
|
|
39
|
+
DataBindings.type(:person) do
|
|
40
|
+
property :name, String
|
|
41
|
+
property :age, Integer, :default => 25
|
|
42
|
+
end
|
|
43
|
+
a = DataBindings.from_json('{"name":"Andrew", "age":26}').bind(:person)
|
|
44
|
+
assert a.errors.empty?
|
|
45
|
+
assert a.valid?
|
|
46
|
+
assert_equal 26, a[:age]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should allow for an alias property name to be set for a property" do
|
|
50
|
+
DataBindings.type(:file) do
|
|
51
|
+
property :size, Integer
|
|
52
|
+
property :filename, String, :alias => :file_name
|
|
53
|
+
end
|
|
54
|
+
a = DataBindings.from_json('{"size":925, "file_name":"foo.txt"}').bind(:file)
|
|
55
|
+
assert a.errors.empty?
|
|
56
|
+
assert a.valid?
|
|
57
|
+
assert_equal "foo.txt", a[:filename]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should allow an array of aliases to be provided for a property" do
|
|
61
|
+
DataBindings.type(:file) do
|
|
62
|
+
property :size, Integer
|
|
63
|
+
property :filename, String, :alias => [:filenames, :file_name]
|
|
64
|
+
end
|
|
65
|
+
a = DataBindings.from_json('{"size":925, "file_name":"foo.txt"}').bind(:file)
|
|
66
|
+
assert a.errors.empty?
|
|
67
|
+
assert a.valid?
|
|
68
|
+
assert_equal "foo.txt", a[:filename]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "should raise when using bind! with invalid data" do
|
|
72
|
+
DataBindings.type(:person) do
|
|
73
|
+
property :name, String
|
|
74
|
+
property :age, Integer
|
|
75
|
+
end
|
|
76
|
+
assert_raises DataBindings::FailedValidation do
|
|
77
|
+
DataBindings.from_json('{"name":"Andrew","age":"asd"}').bind!(:person)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should give back the original object with errors with invalid data" do
|
|
82
|
+
DataBindings.type(:person) do
|
|
83
|
+
property :name, String
|
|
84
|
+
property :age, Integer
|
|
85
|
+
end
|
|
86
|
+
a = DataBindings.from_json('{"name":"Andrew","age":"asd"}').bind(:person)
|
|
87
|
+
assert_equal "Andrew", a[:name]
|
|
88
|
+
assert_equal "asd", a[:age]
|
|
89
|
+
refute a.valid?
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe "nested DataBindings::FailedValidation" do
|
|
93
|
+
before do
|
|
94
|
+
DataBindings.for_native(:person) { |obj| person.new(obj[:name], obj[:age]) }
|
|
95
|
+
DataBindings.type(:person) do
|
|
96
|
+
property :name, String
|
|
97
|
+
property :age, Integer
|
|
98
|
+
property :books, Array(:book)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
DataBindings.type(:book) do
|
|
102
|
+
property :author, String
|
|
103
|
+
property :title, String
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "should bind to ruby" do
|
|
108
|
+
a = DataBindings.from_json('{"name":"Andrew","age":32,"books":[{"author":"Siggy","title":"Help Me"},{"author":"Samsum","title":"SC2 and you"}]}').bind(:person)
|
|
109
|
+
assert a.valid?
|
|
110
|
+
assert a.errors.empty?
|
|
111
|
+
assert_equal "Andrew", a[:name]
|
|
112
|
+
assert_equal "Help Me", a[:books][0][:title]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "should be invalid if a nested object is invalid" do
|
|
116
|
+
a = DataBindings.from_json('{"name":"Andrew","age":32,"books":[{"author":"Siggy"},{"author":"Samsum","title":"SC2 and you"}]}').bind(:person)
|
|
117
|
+
refute a.valid?
|
|
118
|
+
refute a.errors.empty?
|
|
119
|
+
assert_equal "Andrew", a[:name]
|
|
120
|
+
assert_equal nil, a[:books][0][:title]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
describe "nested validation" do
|
|
125
|
+
it "should bind to ruby" do
|
|
126
|
+
a = DataBindings.from_json('{"name":"Andrew","age":32,"book":{"author":"Siggy","title":"Help Me"}}').to_native
|
|
127
|
+
assert_equal OpenStruct, a.class
|
|
128
|
+
assert_equal "Siggy", a.book.author
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
describe "in clause" do
|
|
133
|
+
before do
|
|
134
|
+
DataBindings.type(:person) do
|
|
135
|
+
property :name, String, :in => %w(Steve John Andrew)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should have vaild data" do
|
|
140
|
+
a = DataBindings.from_json('{"name":"Andrew"}').bind(:person)
|
|
141
|
+
assert_equal "Andrew", a[:name]
|
|
142
|
+
assert a.valid?
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "should handle invaild data" do
|
|
146
|
+
a = DataBindings.from_json('{"name":"Josh"}').bind(:person)
|
|
147
|
+
assert_equal "Josh", a[:name]
|
|
148
|
+
refute a.valid?
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
describe "inline data type" do
|
|
153
|
+
before do
|
|
154
|
+
DataBindings.type(:person) do
|
|
155
|
+
property :books, [] do
|
|
156
|
+
property :author
|
|
157
|
+
property :title
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "should have vaild data" do
|
|
163
|
+
a = DataBindings.from_json('{"books":[{"author":"siggy","title":"bible"},{"author":"josh","title":"koran"}]}').bind(:person)
|
|
164
|
+
assert_equal "josh", a[:books][1][:author]
|
|
165
|
+
assert a.valid?
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "should handle invaild data" do
|
|
169
|
+
a = DataBindings.from_json('{"books":[{"author":"siggy"},{"author":"josh","title":"koran"}]}').bind(:person)
|
|
170
|
+
assert_equal "josh", a[:books][1][:author]
|
|
171
|
+
refute a.valid?
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "should allow binding to the data in a non-named way" do
|
|
175
|
+
a = DataBindings.from_json('{"books":[{"author":"siggy","title":"bible"},{"author":"josh","title":"koran"}]}').bind {
|
|
176
|
+
property :books, [] do
|
|
177
|
+
property :author
|
|
178
|
+
property :title
|
|
179
|
+
end
|
|
180
|
+
}
|
|
181
|
+
assert_equal "josh", a[:books][1][:author]
|
|
182
|
+
assert a.valid?
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
describe "ad-hoc data type" do
|
|
187
|
+
it "should allow binding to the data in a non-named way" do
|
|
188
|
+
a = DataBindings.from_json('{"books":[{"author":"siggy","title":"bible"},{"author":"josh","title":"koran"}]}').bind {
|
|
189
|
+
property :books, [] do
|
|
190
|
+
property :author
|
|
191
|
+
property :title
|
|
192
|
+
end
|
|
193
|
+
}
|
|
194
|
+
assert_equal "josh", a[:books][1][:author]
|
|
195
|
+
assert a.valid?
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "should handle invaild data" do
|
|
199
|
+
a = DataBindings.from_json('{"books":[{"author":"siggy"},{"author":"josh","title":"koran"}]}').bind {
|
|
200
|
+
property :books, [] do
|
|
201
|
+
property :author
|
|
202
|
+
property :title
|
|
203
|
+
end
|
|
204
|
+
}
|
|
205
|
+
assert_equal "josh", a[:books][1][:author]
|
|
206
|
+
refute a.valid?
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
describe "strictness" do
|
|
210
|
+
it "should reject extra properties" do
|
|
211
|
+
a = DataBindings.from_json('{"author":"siggy","title":"bible"}').bind(:strict => true) { property :author }
|
|
212
|
+
assert_equal "siggy", a[:author]
|
|
213
|
+
refute a.valid?
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|