congo 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/config/locales/en.yml +18 -0
- data/config/locales/fr.yml +18 -0
- data/init.rb +2 -0
- data/lib/congo.rb +16 -0
- data/lib/congo/content_type.rb +107 -0
- data/lib/congo/grip/attachment.rb +22 -0
- data/lib/congo/grip/has_attachment.rb +99 -0
- data/lib/congo/list.rb +64 -0
- data/lib/congo/metadata/association.rb +24 -0
- data/lib/congo/metadata/key.rb +40 -0
- data/lib/congo/metadata/validation.rb +42 -0
- data/lib/congo/migration.rb +143 -0
- data/lib/congo/proxy_scoper.rb +18 -0
- data/lib/congo/scoper.rb +81 -0
- data/lib/congo/support.rb +19 -0
- data/lib/congo/types.rb +64 -0
- data/lib/congo/validation.rb +86 -0
- data/spec/assets/avatar.jpeg +0 -0
- data/spec/assets/dhh.jpg +0 -0
- data/spec/functional/content_type_spec.rb +152 -0
- data/spec/functional/functional_spec_helper.rb +11 -0
- data/spec/functional/grip_spec.rb +47 -0
- data/spec/functional/key_spec.rb +94 -0
- data/spec/functional/list_spec.rb +67 -0
- data/spec/functional/migration_spec.rb +167 -0
- data/spec/functional/scoper_spec.rb +128 -0
- data/spec/functional/validation_spec.rb +90 -0
- data/spec/models.rb +41 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/unit/key_spec.rb +63 -0
- data/spec/unit/scoper_spec.rb +19 -0
- data/spec/unit/unit_spec_helper.rb +3 -0
- metadata +142 -0
Binary file
|
data/spec/assets/dhh.jpg
ADDED
Binary file
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/functional_spec_helper')
|
2
|
+
|
3
|
+
describe 'ContentType' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Account.destroy_all
|
7
|
+
Congo::ProxyScoper.destroy_all
|
8
|
+
Congo::ContentType.destroy_all
|
9
|
+
|
10
|
+
@account = Account.create(:email => 'layne_stanley@acme.org')
|
11
|
+
@website = Website.new(42, 'My simple website')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should be valid' do
|
15
|
+
build_content_type.should be_valid
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should not be valid without a name' do
|
19
|
+
type = build_content_type(:name => nil)
|
20
|
+
type.should_not be_valid
|
21
|
+
type.errors.on(:name).should_not be_nil
|
22
|
+
type.errors.on(:collection_name).should_not be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
[' BlogPost ', ' My projects', 'active posts '].each do |name|
|
26
|
+
it "should be valid with name included leading or trailing spaces (#{name})" do
|
27
|
+
type = build_content_type(:name => name)
|
28
|
+
type.should be_valid
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
['42BlogPosts', ' !cool', 'Great!', 'Super-PRoject43'].each do |name|
|
33
|
+
it "should not be valid with an invalid name (#{name})" do
|
34
|
+
type = build_content_type(:name => name)
|
35
|
+
type.should_not be_valid
|
36
|
+
type.errors.on(:name).should_not be_nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should be valid without a name but with a provided collection name' do
|
41
|
+
type = build_content_type(:name => nil, :collection_name => 'My projects')
|
42
|
+
type.should be_valid
|
43
|
+
type.name.should == "MyProject"
|
44
|
+
type.slug.should == "my_projects"
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should not valid if another content type with the same name' do
|
48
|
+
type_1 = build_content_type
|
49
|
+
type_1.save.should be_true
|
50
|
+
|
51
|
+
type_2 = build_content_type
|
52
|
+
type_2.should_not be_valid
|
53
|
+
type_2.errors.on(:name).should_not be_nil
|
54
|
+
type_2.name = 'Team'
|
55
|
+
type_2.should be_valid
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should not valid if the scoper instance already has a method identical to its name' do
|
59
|
+
type = build_content_type(:name => 'Person')
|
60
|
+
type.should_not be_valid
|
61
|
+
type.errors.on(:name).should_not be_nil
|
62
|
+
|
63
|
+
type = @website.content_types.build(:name => 'Page', :metadata_keys => [{ :name => 'title' }])
|
64
|
+
type.should_not be_valid
|
65
|
+
type.errors.on(:name).should_not be_nil
|
66
|
+
|
67
|
+
type.name = nil
|
68
|
+
type.collection_name = 'pages'
|
69
|
+
type.should_not be_valid
|
70
|
+
type.errors.on(:collection_name).should_not be_nil
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should not valid if another content type with the same collection name' do
|
74
|
+
type_1 = build_content_type(:name => nil, :collection_name => 'My projects')
|
75
|
+
type_1.save.should be_true
|
76
|
+
|
77
|
+
type_2 = build_content_type(:name => nil, :collection_name => 'My projects')
|
78
|
+
type_2.should_not be_valid
|
79
|
+
type_2.errors.on(:name).should_not be_nil
|
80
|
+
type_2.errors.on(:collection_name).should_not be_nil
|
81
|
+
type_2.name = nil
|
82
|
+
type_2.collection_name = 'My team'
|
83
|
+
type_2.should be_valid
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should not valid without keys' do
|
87
|
+
type = build_content_type(:metadata_keys => [])
|
88
|
+
type.should_not be_valid
|
89
|
+
type.errors.on(:metadata_keys).should_not be_nil
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should not be valid without a scope' do
|
93
|
+
type = build_content_type
|
94
|
+
type.scope = nil
|
95
|
+
type.should_not be_valid
|
96
|
+
type.errors.on(:scope).should_not be_nil
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should not be valid with 2 identical keys (same name)' do
|
100
|
+
type = build_content_type(:metadata_keys => [ { :name => 'name' }, { :name => 'name' }, { :name => 'description' } ])
|
101
|
+
type.should_not be_valid
|
102
|
+
type.errors.on(:metadata_keys).should_not be_nil
|
103
|
+
type.metadata_keys.first.should be_valid
|
104
|
+
type.metadata_keys.last.should be_valid
|
105
|
+
type.metadata_keys[1].errors.on(:name).should_not be_nil
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should be retrieved once saved' do
|
109
|
+
type = build_content_type
|
110
|
+
type.metadata_keys.should_not be_empty
|
111
|
+
type.save!.should be_true
|
112
|
+
type.save
|
113
|
+
|
114
|
+
type = type.reload
|
115
|
+
type.metadata_keys.size.should == 2
|
116
|
+
Congo::ContentType.first.metadata_keys.size.should == 2
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should remove contents as well when removed' do
|
120
|
+
type = build_content_type
|
121
|
+
type.save!
|
122
|
+
@account.projects.create(:name => 'project #1', :description => 'bla bla')
|
123
|
+
collection_name = type.send(:mongodb_collection_name)
|
124
|
+
MongoMapper.database.collection(collection_name).count.should == 1
|
125
|
+
|
126
|
+
another_type = build_content_type(:name => 'Foo')
|
127
|
+
another_type.save
|
128
|
+
|
129
|
+
@account = @account.reload
|
130
|
+
@account.content_types.count.should == 2
|
131
|
+
|
132
|
+
type.destroy
|
133
|
+
|
134
|
+
@account = @account.reload
|
135
|
+
@account.content_types.count.should == 1
|
136
|
+
MongoMapper.database.collection(collection_name).count.should == 0
|
137
|
+
@account.foos.count.should == 0
|
138
|
+
end
|
139
|
+
|
140
|
+
def build_content_type(options = {})
|
141
|
+
default_options = {
|
142
|
+
:name => 'Project',
|
143
|
+
:embedded => false,
|
144
|
+
:metadata_keys => [
|
145
|
+
{ :name => 'name' },
|
146
|
+
{ :name => 'description' }
|
147
|
+
] }
|
148
|
+
|
149
|
+
@account.content_types.build(default_options.merge(options))
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017, {
|
4
|
+
:logger => Logger.new(TEST_DIR + '/test.log')
|
5
|
+
})
|
6
|
+
MongoMapper.database = 'congotest'
|
7
|
+
|
8
|
+
MongoMapper.database.collection_names.each do |collection|
|
9
|
+
next if collection == 'system.indexes'
|
10
|
+
MongoMapper.database.collection(collection).drop
|
11
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/functional_spec_helper')
|
2
|
+
|
3
|
+
describe 'Grip' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Account.destroy_all
|
7
|
+
Congo::ContentType.destroy_all
|
8
|
+
|
9
|
+
@account = Account.create(:email => 'layne_stanley@acme.org')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should attach a file to a content' do
|
13
|
+
create_content_type
|
14
|
+
developer = @account.developers.create({
|
15
|
+
:name => 'Layne Stanley',
|
16
|
+
:bio => 'foo bar',
|
17
|
+
:picture => open_file('avatar.jpeg')
|
18
|
+
})
|
19
|
+
developer.should be_valid
|
20
|
+
developer.picture_name.should == 'avatar.jpeg'
|
21
|
+
developer.picture_content_type.should == 'image/jpeg'
|
22
|
+
developer.picture_path.should == "developer/#{developer._id}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_content_type(options = {})
|
26
|
+
type = build_content_type
|
27
|
+
type.save!
|
28
|
+
type
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_content_type(options = {})
|
32
|
+
default_options = {
|
33
|
+
:name => 'Developer',
|
34
|
+
:embedded => false,
|
35
|
+
:metadata_keys => [
|
36
|
+
{ :name => 'name', :type => 'String' },
|
37
|
+
{ :name => 'bio', :type => 'Text' },
|
38
|
+
{ :name => 'picture', :type => 'File' }
|
39
|
+
] }
|
40
|
+
|
41
|
+
@account.content_types.build(default_options.merge(options))
|
42
|
+
end
|
43
|
+
|
44
|
+
def open_file(name)
|
45
|
+
File.open(File.join(File.dirname(__FILE__), '..', 'assets', name))
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/functional_spec_helper')
|
2
|
+
|
3
|
+
describe 'Key' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
I18n.locale = :en
|
7
|
+
|
8
|
+
Account.destroy_all
|
9
|
+
Congo::ContentType.destroy_all
|
10
|
+
|
11
|
+
@account = Account.create(:email => 'layne_stanley@acme.org')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should add items' do
|
15
|
+
create_content_type
|
16
|
+
|
17
|
+
person = build_person
|
18
|
+
person.valid?.should be_true
|
19
|
+
person.name.should == 'Layne Stanley'
|
20
|
+
person.bio.should == "That's great"
|
21
|
+
person.email.should == 'layne_stanley@acme.org'
|
22
|
+
person.save
|
23
|
+
|
24
|
+
@account = Account.first # hard reload
|
25
|
+
person = @account.developers.first
|
26
|
+
person.email.should == 'layne_stanley@acme.org'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should not add items with invalid data (incorrect e-mail)' do
|
30
|
+
create_content_type
|
31
|
+
|
32
|
+
person = build_person(:email => 'layne_stanley-acme.org')
|
33
|
+
person.valid?.should be_false
|
34
|
+
person.errors.on(:email).should_not be_nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should convert date into the locale' do
|
38
|
+
create_content_type
|
39
|
+
person = build_person
|
40
|
+
person.save
|
41
|
+
|
42
|
+
@account = Account.first # hard reload
|
43
|
+
person = @account.developers.first
|
44
|
+
person.birthday.strftime(I18n.t('congo.date.formats.default')).should == '06/28/1979'
|
45
|
+
|
46
|
+
I18n.locale = :fr
|
47
|
+
person.birthday.strftime(I18n.t('congo.date.formats.default')).should == '28/06/1979'
|
48
|
+
|
49
|
+
person.birthday = '16/09/1982'
|
50
|
+
person.save
|
51
|
+
|
52
|
+
@account = Account.first # hard reload
|
53
|
+
person = @account.developers.first
|
54
|
+
person.birthday.strftime(I18n.t('congo.date.formats.default')).should == '16/09/1982'
|
55
|
+
person.localized_birthday.should == '16/09/1982'
|
56
|
+
|
57
|
+
person.localized_birthday = '29/06/2007'
|
58
|
+
person.save
|
59
|
+
@account = Account.first # hard reload
|
60
|
+
person = @account.developers.first
|
61
|
+
person.localized_birthday.should == '29/06/2007'
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_content_type(options = {})
|
65
|
+
type = build_content_type
|
66
|
+
type.save!
|
67
|
+
type
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_content_type(options = {})
|
71
|
+
default_options = {
|
72
|
+
:name => 'Developer',
|
73
|
+
:embedded => false,
|
74
|
+
:metadata_keys => [
|
75
|
+
{ :name => 'name', :type => 'String' },
|
76
|
+
{ :name => 'bio', :type => 'Text' },
|
77
|
+
{ :name => 'email', :type => 'Email' },
|
78
|
+
{ :name => 'birthday', :type => 'Date' }
|
79
|
+
] }
|
80
|
+
|
81
|
+
@account.content_types.build(default_options.merge(options))
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_person(options = {})
|
85
|
+
attributes = {
|
86
|
+
:name => 'Layne Stanley',
|
87
|
+
:bio => "That's great",
|
88
|
+
:email => 'layne_stanley@acme.org',
|
89
|
+
:birthday => '06/28/1979'
|
90
|
+
}
|
91
|
+
@account.developers.build attributes.merge(options)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/functional_spec_helper')
|
2
|
+
|
3
|
+
describe 'List' do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
class Congo::ContentType
|
7
|
+
include Congo::List
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
Account.destroy_all
|
13
|
+
Congo::ContentType.destroy_all
|
14
|
+
|
15
|
+
@account = Account.create(:email => 'layne_stanley@acme.org')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should increment item position once saved' do
|
19
|
+
create_content_type
|
20
|
+
person = @account.developers.create :name => 'Layne Stanley', :bio => "That's great"
|
21
|
+
person._position.should == 1
|
22
|
+
person = @account.developers.create :name => 'Kurt Cobain', :bio => "Suicide #2"
|
23
|
+
person._position.should == 2
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should decrement item position once deleted' do
|
27
|
+
populate
|
28
|
+
@account.developers.first(:conditions => { :name => 'River Phoenix' }).destroy
|
29
|
+
@account.developers.first(:conditions => { :name => 'Layne Stanley' })._position.should == 1
|
30
|
+
@account.developers.first(:conditions => { :name => 'Kurt Cobain' })._position.should == 2
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should reorder all the items of a collection' do
|
34
|
+
populate
|
35
|
+
klass = @account.content_types.first.to_const
|
36
|
+
klass.reorder_all(@account.developers.all(:order => 'name ASC').collect(&:_id))
|
37
|
+
@account.developers.first(:conditions => { :name => 'River Phoenix' })._position.should == 3
|
38
|
+
@account.developers.first(:conditions => { :name => 'Layne Stanley' })._position.should == 2
|
39
|
+
@account.developers.first(:conditions => { :name => 'Kurt Cobain' })._position.should == 1
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_content_type(options = {})
|
43
|
+
type = build_content_type
|
44
|
+
type.save!
|
45
|
+
type
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_content_type(options = {})
|
49
|
+
default_options = {
|
50
|
+
:name => 'Developer',
|
51
|
+
:embedded => false,
|
52
|
+
:metadata_keys => [
|
53
|
+
{ :name => 'name', :type => 'String' },
|
54
|
+
{ :name => 'bio', :type => 'Text' }
|
55
|
+
] }
|
56
|
+
|
57
|
+
@account.content_types.build(default_options.merge(options))
|
58
|
+
end
|
59
|
+
|
60
|
+
def populate
|
61
|
+
create_content_type
|
62
|
+
@account.developers.create :name => 'River Phoenix', :bio => "Life is good"
|
63
|
+
@account.developers.create :name => 'Layne Stanley', :bio => "That's great"
|
64
|
+
@account.developers.create :name => 'Kurt Cobain', :bio => "Suicide #2"
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/functional_spec_helper')
|
2
|
+
|
3
|
+
describe 'ContentType' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Account.destroy_all
|
7
|
+
Congo::ProxyScoper.destroy_all
|
8
|
+
Congo::ContentType.destroy_all
|
9
|
+
|
10
|
+
@account = Account.create(:email => 'layne_stanley@acme.org')
|
11
|
+
@content_type = @account.content_types.create!({
|
12
|
+
:name => 'Project',
|
13
|
+
:embedded => false,
|
14
|
+
:metadata_keys => [
|
15
|
+
{ :name => 'name' },
|
16
|
+
{ :name => 'description' },
|
17
|
+
{ :name => 'date' }
|
18
|
+
]
|
19
|
+
})
|
20
|
+
@content_type = @content_type.reload
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should create new record' do
|
24
|
+
project = @account.projects.create(:name => 'Project #1', :description => 'bla bla')
|
25
|
+
@account.projects.count.should == 1
|
26
|
+
project.out_dated?.should be_false
|
27
|
+
project.migrate!.should be_false
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should not create incremented migration since there are no documents in the collection' do
|
31
|
+
(type = build_content_type).save
|
32
|
+
type.version.should == 0
|
33
|
+
type.migrations.should be_empty
|
34
|
+
|
35
|
+
type = Congo::ContentType.first
|
36
|
+
new_metadata_keys = [type.metadata_keys.pop, Congo::Metadata::Key.new({ :name => 'date' }), type.metadata_keys.pop]
|
37
|
+
new_metadata_keys.last.name = 'title'
|
38
|
+
type.metadata_keys = new_metadata_keys
|
39
|
+
type.save
|
40
|
+
type.version.should == 0
|
41
|
+
type.migrations.should be_empty
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should create incremented migration once it has been updated AND there is at least one document in the collection' do
|
45
|
+
(type = build_content_type).save
|
46
|
+
@account.tasks.create(:name => 'foo', :description => 'bla bla')
|
47
|
+
type.version.should == 0
|
48
|
+
type.migrations.should be_empty
|
49
|
+
|
50
|
+
type = @account.content_types.all[1]
|
51
|
+
new_metadata_keys = [type.metadata_keys.pop, Congo::Metadata::Key.new({ :name => 'date' })]
|
52
|
+
new_metadata_keys.first.name = 'a_description'
|
53
|
+
type.metadata_keys = new_metadata_keys
|
54
|
+
type.save
|
55
|
+
type.version.should == 1
|
56
|
+
type.migrations.size.should == 1
|
57
|
+
type.migrations.first.tasks.size.should == 2
|
58
|
+
|
59
|
+
type.migrations.first.tasks[0][:action].should == 'rename'
|
60
|
+
type.migrations.first.tasks[0][:previous].should == 'description'
|
61
|
+
type.migrations.first.tasks[0][:next].should == 'a_description'
|
62
|
+
type.migrations.first.tasks[1][:action].should == 'drop'
|
63
|
+
type.migrations.first.tasks[1][:previous].should == 'name'
|
64
|
+
|
65
|
+
type = @account.content_types.all[1]
|
66
|
+
new_metadata_keys = [type.metadata_keys.pop]
|
67
|
+
type.metadata_keys = new_metadata_keys
|
68
|
+
type.save
|
69
|
+
type.version.should == 2
|
70
|
+
type.migrations.size.should == 2
|
71
|
+
type.migrations.last.tasks.size.should == 1
|
72
|
+
type.migrations.last.tasks[0][:action].should == 'drop'
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should migrate smoothly (renaming and dropping columns)' do
|
76
|
+
project = @account.projects.create(:name => 'Project #1', :description => 'bla bla', :date => '10/09/2009')
|
77
|
+
|
78
|
+
# renaming and droppping keys
|
79
|
+
new_keys = [@content_type.metadata_keys.first, @content_type.metadata_keys[1]]
|
80
|
+
new_keys.first.name = 'title'
|
81
|
+
@content_type.metadata_keys = new_keys
|
82
|
+
@content_type.save
|
83
|
+
|
84
|
+
@content_type.reload
|
85
|
+
@account = Account.first # we need a hard refresh :-)
|
86
|
+
|
87
|
+
project = @account.projects.first
|
88
|
+
project.title.should == 'Project #1'
|
89
|
+
project._version.should == 1
|
90
|
+
lambda { project.name }.should_not raise_error
|
91
|
+
lambda { project.date }.should raise_error
|
92
|
+
|
93
|
+
@account = Account.first # we need a hard refresh :-)
|
94
|
+
@account.associations[:projects].instance_variable_set "@klass", @account.content_types.first.to_const
|
95
|
+
|
96
|
+
another_project = @account.projects.create!(:title => 'Project #2', :description => 'bla bla')
|
97
|
+
lambda { another_project.name }.should raise_error
|
98
|
+
lambda { another_project.date }.should raise_error
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should run 2 pending migrations' do
|
102
|
+
project = @account.projects.create(:name => 'Project #1', :description => 'bla bla', :date => '10/09/2009')
|
103
|
+
|
104
|
+
new_keys = [@content_type.metadata_keys.first, @content_type.metadata_keys[1]]
|
105
|
+
new_keys.first.name = 'title'
|
106
|
+
@content_type.metadata_keys = new_keys
|
107
|
+
@content_type.save
|
108
|
+
|
109
|
+
@content_type = @content_type.reload # necessary
|
110
|
+
|
111
|
+
new_keys = [@content_type.metadata_keys.first]
|
112
|
+
new_keys.first.name = 'name'
|
113
|
+
@content_type.metadata_keys = new_keys
|
114
|
+
@content_type.save
|
115
|
+
|
116
|
+
@account = Account.first # we need a hard refresh :-)
|
117
|
+
project = @account.projects.first # two pending migrations
|
118
|
+
|
119
|
+
project._version.should == 2
|
120
|
+
project.name.should == 'Project #1'
|
121
|
+
lambda { project.title }.should raise_error
|
122
|
+
lambda { project.description }.should raise_error
|
123
|
+
lambda { project.date }.should raise_error
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should update validation if key name changes' do
|
127
|
+
@account.projects.create(:name => 'Project #1', :description => 'bla bla', :date => '10/09/2009')
|
128
|
+
|
129
|
+
@content_type.metadata_validations = [{ :key => 'name', :type => 'presence_of' }]
|
130
|
+
@content_type.save
|
131
|
+
|
132
|
+
new_keys = [@content_type.metadata_keys.first, @content_type.metadata_keys.last]
|
133
|
+
new_keys.first.name = 'title'
|
134
|
+
@content_type.metadata_keys = new_keys
|
135
|
+
@content_type.save
|
136
|
+
|
137
|
+
@content_type = Congo::ContentType.first # hard refresh
|
138
|
+
@content_type.metadata_validations.first.key.should == 'title'
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should update validation if key is droppped' do
|
142
|
+
@account.projects.create(:name => 'Project #1', :description => 'bla bla', :date => '10/09/2009')
|
143
|
+
|
144
|
+
@content_type.metadata_validations = [{ :key => 'description', :type => 'presence_of' }]
|
145
|
+
@content_type.save
|
146
|
+
|
147
|
+
new_keys = [@content_type.metadata_keys.first, @content_type.metadata_keys.last]
|
148
|
+
@content_type.metadata_keys = new_keys
|
149
|
+
@content_type.save
|
150
|
+
|
151
|
+
@content_type = Congo::ContentType.first # hard refresh
|
152
|
+
@content_type.metadata_validations.should be_empty
|
153
|
+
end
|
154
|
+
|
155
|
+
def build_content_type(options = {})
|
156
|
+
default_options = {
|
157
|
+
:name => 'Task',
|
158
|
+
:embedded => false,
|
159
|
+
:metadata_keys => [
|
160
|
+
{ :name => 'name' },
|
161
|
+
{ :name => 'description' }
|
162
|
+
] }
|
163
|
+
|
164
|
+
@account.content_types.build(default_options.merge(options))
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|