arunthampi-supermodel 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README +23 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/lib/supermodel.rb +9 -0
- data/lib/supermodel/base.rb +284 -0
- data/lib/supermodel/errors.rb +6 -0
- data/lib/supermodel/support.rb +2 -0
- data/lib/supermodel/support/extensions.rb +80 -0
- data/lib/supermodel/support/inflections.rb +52 -0
- data/lib/supermodel/support/inflector.rb +277 -0
- data/spec/base/from_json_spec.rb +70 -0
- data/spec/base/has_many_spec.rb +89 -0
- data/spec/base/has_one_spec.rb +80 -0
- data/spec/base/has_spec.rb +88 -0
- data/spec/base/initialize_spec.rb +64 -0
- data/spec/base/marshal_dump_spec.rb +64 -0
- data/spec/base/marshal_load_spec.rb +58 -0
- data/spec/base/module_spec.rb +15 -0
- data/spec/base/nested_class_spec.rb +16 -0
- data/spec/base/to_json_spec.rb +73 -0
- data/spec/spec_helper.rb +9 -0
- data/supermodel.gemspec +15 -0
- metadata +83 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe "A class which is a subclass of SuperModel::Base with a has_one association" do
|
4
|
+
before(:each) do
|
5
|
+
class PhoneNumber < SuperModel::Base
|
6
|
+
has :mobile_number, :which_is => :text
|
7
|
+
end
|
8
|
+
|
9
|
+
class Contact < SuperModel::Base
|
10
|
+
has_one :phone_number
|
11
|
+
end
|
12
|
+
|
13
|
+
@c = Contact.new
|
14
|
+
@p1 = PhoneNumber.new(:mobile_number => '(666) 666-6666')
|
15
|
+
end
|
16
|
+
|
17
|
+
after(:each) do
|
18
|
+
Object.send(:remove_const, :PhoneNumber)
|
19
|
+
Object.send(:remove_const, :Contact)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have an instance variable called associations which is a Hash with the key being :phone_number" do
|
23
|
+
Contact.has_one_associations.class.should == Hash
|
24
|
+
Contact.has_one_associations.keys.should == [:phone_number]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have methods called phone_number and phone_number=" do
|
28
|
+
@c.should respond_to(:phone_number)
|
29
|
+
@c.should respond_to(:phone_number=)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have a method called people which returns an empty array" do
|
33
|
+
@c.phone_number.should == nil
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be able to set a Person object to the association, and over-ride any previous settings" do
|
37
|
+
@c.phone_number = @p1
|
38
|
+
@c.phone_number.should == @p1
|
39
|
+
|
40
|
+
p2 = PhoneNumber.new
|
41
|
+
|
42
|
+
@c.phone_number = p2
|
43
|
+
@c.phone_number.should == p2
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "An object instantiated from class which is a subclass of SuperModel::Base" do
|
49
|
+
before(:each) do
|
50
|
+
class Pet < SuperModel::Base
|
51
|
+
has :name
|
52
|
+
end
|
53
|
+
|
54
|
+
class Person < SuperModel::Base
|
55
|
+
has :name
|
56
|
+
has_one :pet
|
57
|
+
end
|
58
|
+
|
59
|
+
@pet = Pet.new(:name => "Tom")
|
60
|
+
@person1 = Person.new(:name => 'McLovin', :pet => @pet)
|
61
|
+
@person2 = Person.new(:name => 'Seth', :pet => {:name => 'Jerry'})
|
62
|
+
end
|
63
|
+
|
64
|
+
after(:each) do
|
65
|
+
Object.send(:remove_const, :Person)
|
66
|
+
Object.send(:remove_const, :Pet)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should be able to initialize with a hash which contains descendents of SuperModel::Base" do
|
70
|
+
@pet.name.should == "Tom"
|
71
|
+
|
72
|
+
@person1.name.should == 'McLovin'
|
73
|
+
@person1.pet.should == @pet
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should be able to initialize from a hash which contains only Strings" do
|
77
|
+
@person2.name.should == 'Seth'
|
78
|
+
@person2.pet.name.should == 'Jerry'
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe "A class which is a subclass of SuperModel::Base" do
|
4
|
+
before(:each) do
|
5
|
+
class Person < SuperModel::Base
|
6
|
+
has :name, :which_is => :text
|
7
|
+
end
|
8
|
+
# Initialize a new Person object
|
9
|
+
@p = Person.new
|
10
|
+
end
|
11
|
+
|
12
|
+
after(:each) do
|
13
|
+
Object.send(:remove_const, :Person)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have a method called name which returns the value of the variable name" do
|
17
|
+
@p.should respond_to(:name)
|
18
|
+
@p.name.should == ""
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should have a method called name= which should let you set the instance variable name" do
|
22
|
+
@p.should respond_to(:name=)
|
23
|
+
@p.name = "McLovin"
|
24
|
+
@p.name.should == "McLovin"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "A class which is a subclass of SuperModel::Base with a default value specified" do
|
29
|
+
before(:each) do
|
30
|
+
class NamedPerson < SuperModel::Base
|
31
|
+
has :name, :which_is => :text, :with_default_value => "McLovin"
|
32
|
+
end
|
33
|
+
|
34
|
+
@n = NamedPerson.new
|
35
|
+
end
|
36
|
+
|
37
|
+
after(:each) do
|
38
|
+
Object.send(:remove_const, :NamedPerson)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have a method called name which returns the value of the variable name" do
|
42
|
+
@n.should respond_to(:name)
|
43
|
+
@n.name.should == "McLovin"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should have a method called name= which should let you set the instance variable name" do
|
47
|
+
@n.should respond_to(:name=)
|
48
|
+
@n.name = "Seth"
|
49
|
+
@n.name.should == "Seth"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "A class which is a subclass of SuperModel::Base with a default numerical value specified" do
|
54
|
+
before(:each) do
|
55
|
+
class AgedPerson < SuperModel::Base
|
56
|
+
has :name
|
57
|
+
has :age, :which_is => :number, :with_default_value => 10
|
58
|
+
end
|
59
|
+
|
60
|
+
@a = AgedPerson.new
|
61
|
+
end
|
62
|
+
|
63
|
+
after(:each) do
|
64
|
+
Object.send(:remove_const, :AgedPerson)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should have an instance variable called attributes which is a Hash with the keys being :name, :age" do
|
68
|
+
AgedPerson.attributes.class.should == Hash
|
69
|
+
AgedPerson.attributes.keys.index(:name).should_not == nil
|
70
|
+
AgedPerson.attributes.keys.index(:age).should_not == nil
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should have methods called name and age which return the values of the variables name and age respectively" do
|
74
|
+
@a.should respond_to(:name)
|
75
|
+
@a.should respond_to(:age)
|
76
|
+
|
77
|
+
@a.name.should == ""
|
78
|
+
@a.age.should == 10
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should have a method called name= which should let you set the instance variable name" do
|
82
|
+
@a.should respond_to(:name=)
|
83
|
+
@a.should respond_to(:age=)
|
84
|
+
|
85
|
+
@a.age = 15
|
86
|
+
@a.age.should == 15
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe "SuperModel::Base #new method with a hash containing one key-value pair" do
|
4
|
+
before(:all) do
|
5
|
+
class Person < SuperModel::Base
|
6
|
+
has :name
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:all) do
|
11
|
+
Object.send(:remove_const, :Person)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should be able to initialize attributes correctly from a hash" do
|
15
|
+
p = Person.new(:name => 'McLovin')
|
16
|
+
p.name.should == 'McLovin'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "SuperModel::Base #new method with a hash containing more than one key-value pair" do
|
21
|
+
before(:all) do
|
22
|
+
class Person < SuperModel::Base
|
23
|
+
has :name
|
24
|
+
has :age, :which_is => :number, :with_default_value => 25
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
after(:all) do
|
29
|
+
Object.send(:remove_const, :Person)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be able to initialize attributes correctly from the hash" do
|
33
|
+
p = Person.new(:name => 'McLovin', :age => 12)
|
34
|
+
p.name.should == 'McLovin'
|
35
|
+
p.age.should == 12
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "SuperModel::Base #new method with a block (and self being passed to the block)" do
|
40
|
+
before(:all) do
|
41
|
+
class Dog < SuperModel::Base
|
42
|
+
has :name
|
43
|
+
has :age, :which_is => :number
|
44
|
+
has :collar
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
after(:all) do
|
49
|
+
Object.send(:remove_const, :Dog)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should be able to initialize all the attributes correctly" do
|
53
|
+
dog = Dog.new do |d|
|
54
|
+
d.name = "Buster"
|
55
|
+
d.age = 2
|
56
|
+
d.collar = "Stray"
|
57
|
+
end
|
58
|
+
|
59
|
+
dog.name.should == "Buster"
|
60
|
+
dog.age.should == 2
|
61
|
+
dog.collar.should == "Stray"
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe "SuperModel::Base #marshal_dump method with just simple attributes" do
|
4
|
+
before(:each) do
|
5
|
+
class Hotel < SuperModel::Base
|
6
|
+
has :name, :which_is => :text, :with_default_value => "Swissotel The Stamford"
|
7
|
+
has :star_rating, :which_is => :decimal, :with_default_value => 5.0
|
8
|
+
has :rooms, :which_is => :number, :with_default_value => 100
|
9
|
+
end
|
10
|
+
|
11
|
+
@h = Hotel.new
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
Object.send(:remove_const, :Hotel)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should have to the marshal_dump method" do
|
19
|
+
@h.should respond_to(:marshal_dump)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should produce valid JSON output when sent the marshal_dump method" do
|
23
|
+
@h.stub!(:to_json).and_return("Deflated JSON")
|
24
|
+
@h.marshal_dump.should == 'Deflated JSON'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should produce valid JSON output when an attribute has been changed and the marshal_dump method is sent" do
|
28
|
+
@h.rooms = 200
|
29
|
+
@h.stub!(:to_json).and_return("Deflated JSON, Part deux")
|
30
|
+
@h.marshal_dump.should == 'Deflated JSON, Part deux'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "SuperModel::Base #marshal_dump with associations" do
|
35
|
+
before(:each) do
|
36
|
+
class Hospital < SuperModel::Base
|
37
|
+
has :name
|
38
|
+
end
|
39
|
+
|
40
|
+
class CrazyPerson < SuperModel::Base
|
41
|
+
has :name, :which_is => :text, :with_default_value => "Crazed McLovin"
|
42
|
+
has_many :hospitals
|
43
|
+
end
|
44
|
+
|
45
|
+
@c = CrazyPerson.new
|
46
|
+
|
47
|
+
@h1 = Hospital.new(:name => "Crazy Hospital 1")
|
48
|
+
@h2 = Hospital.new(:name => "Crazy Hospital 2")
|
49
|
+
|
50
|
+
@c.add_hospital(@h1)
|
51
|
+
@c.add_hospital(@h2)
|
52
|
+
end
|
53
|
+
|
54
|
+
after(:each) do
|
55
|
+
Object.send(:remove_const, :Hospital)
|
56
|
+
Object.send(:remove_const, :CrazyPerson)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should produce valid JSON when sent the marshal_dump method" do
|
60
|
+
# Stub the deflate method, which will basically give us the gzip'd JSON
|
61
|
+
@c.stub!(:to_json).and_return("Deflated JSON, Part three")
|
62
|
+
@c.marshal_dump.should == 'Deflated JSON, Part three'
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe "SuperModel::Base #marshal_load method, with many attributes" do
|
4
|
+
before(:all) do
|
5
|
+
class Hotel < SuperModel::Base
|
6
|
+
has :name, :which_is => :text, :with_default_value => "Swissotel The Stamford"
|
7
|
+
has :star_rating, :which_is => :decimal, :with_default_value => 5.0
|
8
|
+
has :rooms, :which_is => :number, :with_default_value => 100
|
9
|
+
end
|
10
|
+
|
11
|
+
class Hospital < SuperModel::Base
|
12
|
+
has :name
|
13
|
+
end
|
14
|
+
|
15
|
+
class CrazyPerson < SuperModel::Base
|
16
|
+
has :name, :which_is => :text, :with_default_value => "Crazed McLovin"
|
17
|
+
has_many :hospitals
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
after(:all) do
|
22
|
+
Object.send(:remove_const, :Hotel)
|
23
|
+
Object.send(:remove_const, :Hospital)
|
24
|
+
Object.send(:remove_const, :CrazyPerson)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have the marshal_load method" do
|
28
|
+
Hotel.new.should respond_to(:marshal_load)
|
29
|
+
Hospital.new.should respond_to(:marshal_load)
|
30
|
+
CrazyPerson.new.should respond_to(:marshal_load)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should instantiate an object when sent the marshal_load method with valid json as a parameter" do
|
34
|
+
h = Hotel.new
|
35
|
+
|
36
|
+
h = h.marshal_load("{\"name\":\"Swissotel The Stamford\",\"rooms\":200,\"star_rating\":4.0}")
|
37
|
+
h.class.should == Hotel
|
38
|
+
# Check whether all attributes are set correctly
|
39
|
+
h.name.should == "Swissotel The Stamford"
|
40
|
+
h.rooms.should == 200
|
41
|
+
h.star_rating.should == 4.0
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should instantiate an object when sent the marshal_load method with valid JSON (containing associations) as a parameter" do
|
45
|
+
|
46
|
+
crazy = CrazyPerson.new.marshal_load('{"name":"Crazed McLovin","hospitals":[{"name":"Crazy Hospital 1"},{"name":"Crazy Hospital 2"}]}')
|
47
|
+
crazy.class.should == CrazyPerson
|
48
|
+
|
49
|
+
crazy.name == "Crazed McLovin"
|
50
|
+
crazy.hospitals.size.should == 2
|
51
|
+
|
52
|
+
hospitals = crazy.hospitals.collect{|h| h.name }
|
53
|
+
hospitals.sort!
|
54
|
+
|
55
|
+
hospitals.first.should == 'Crazy Hospital 1'
|
56
|
+
hospitals.last.should == 'Crazy Hospital 2'
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe "A Cheezburger subclass of SuperModel::Base defined in the Burgers module" do
|
4
|
+
before(:all) do
|
5
|
+
module Burgers
|
6
|
+
class Cheezburger < SuperModel::Base
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have a base_class of Burgers::Cheezburger" do
|
12
|
+
Burgers::Cheezburger.base_class.should == Burgers::Cheezburger
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe "A Cheezburger subclass of SuperModel::Base nested in a Lolcat subclass of SuperModel::Base" do
|
4
|
+
before(:all) do
|
5
|
+
class Lolcat < SuperModel::Base
|
6
|
+
class Cheezburger < SuperModel::Base
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have a base_class of Lolcat::Cheezburger" do
|
12
|
+
Lolcat.base_class.should == Lolcat
|
13
|
+
Lolcat::Cheezburger.base_class.should == Lolcat::Cheezburger
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe "SuperModel::Base #to_json method with just simple attributes" do
|
4
|
+
before(:each) do
|
5
|
+
class Hotel < SuperModel::Base
|
6
|
+
has :name, :which_is => :text, :with_default_value => "Swissotel The Stamford"
|
7
|
+
has :star_rating, :which_is => :decimal, :with_default_value => 5.0
|
8
|
+
has :rooms, :which_is => :number, :with_default_value => 100
|
9
|
+
end
|
10
|
+
|
11
|
+
@h = Hotel.new
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
Object.send(:remove_const, :Hotel)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should have to the to_json method" do
|
19
|
+
@h.should respond_to(:to_json)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should produce valid JSON output when sent the to_json method" do
|
23
|
+
json_output = @h.to_json
|
24
|
+
# Check for JSON regex, since attributes can appear in any order
|
25
|
+
(json_output =~ /"name":"Swissotel The Stamford"/).should_not == nil
|
26
|
+
(json_output =~ /"rooms":100/).should_not == nil
|
27
|
+
(json_output =~ /"star_rating":5.0/).should_not == nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should produce valid JSON output when an attribute has been changed and the to_json method is sent" do
|
31
|
+
@h.rooms = 200
|
32
|
+
json_output = @h.to_json
|
33
|
+
# Check for JSON regex, since attributes can appear in any order
|
34
|
+
(json_output =~ /"name":"Swissotel The Stamford"/).should_not == nil
|
35
|
+
(json_output =~ /"rooms":200/).should_not == nil
|
36
|
+
(json_output =~ /"star_rating":5.0/).should_not == nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "SuperModel::Base #to_json with associations" do
|
41
|
+
before(:each) do
|
42
|
+
class Hospital < SuperModel::Base
|
43
|
+
has :name
|
44
|
+
end
|
45
|
+
|
46
|
+
class CrazyPerson < SuperModel::Base
|
47
|
+
has :name, :which_is => :text, :with_default_value => "Crazed McLovin"
|
48
|
+
has_many :hospitals
|
49
|
+
end
|
50
|
+
|
51
|
+
@c = CrazyPerson.new
|
52
|
+
|
53
|
+
@h1 = Hospital.new(:name => "Crazy Hospital 1")
|
54
|
+
@h2 = Hospital.new(:name => "Crazy Hospital 2")
|
55
|
+
|
56
|
+
@c.add_hospital(@h1)
|
57
|
+
@c.add_hospital(@h2)
|
58
|
+
end
|
59
|
+
|
60
|
+
after(:each) do
|
61
|
+
Object.send(:remove_const, :Hospital)
|
62
|
+
Object.send(:remove_const, :CrazyPerson)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should produce valid JSON when sent the to_json method" do
|
66
|
+
json_output = @c.to_json
|
67
|
+
# Check for JSON regex, since attributes can appear in any order
|
68
|
+
(json_output =~ /"name":"Crazed McLovin"/).should_not == nil
|
69
|
+
(json_output =~ /"hospitals":\[.*?\]/).should_not == nil
|
70
|
+
(json_output =~ /\{.*?"name":"Crazy Hospital 1".*?\}/).should_not == nil
|
71
|
+
(json_output =~ /\{.*?"name":"Crazy Hospital 2".*?\}/).should_not == nil
|
72
|
+
end
|
73
|
+
end
|