congo 0.1.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 +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
|