datamapper 0.2.5 → 0.3.0
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/CHANGELOG +5 -1
- data/FAQ +96 -0
- data/QUICKLINKS +12 -0
- data/README +57 -155
- data/environment.rb +61 -43
- data/example.rb +30 -12
- data/lib/data_mapper.rb +6 -1
- data/lib/data_mapper/adapters/abstract_adapter.rb +0 -57
- data/lib/data_mapper/adapters/data_object_adapter.rb +203 -97
- data/lib/data_mapper/adapters/mysql_adapter.rb +4 -0
- data/lib/data_mapper/adapters/postgresql_adapter.rb +7 -1
- data/lib/data_mapper/adapters/sql/coersion.rb +3 -2
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +29 -10
- data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +4 -0
- data/lib/data_mapper/adapters/sql/mappings/column.rb +13 -9
- data/lib/data_mapper/adapters/sql/mappings/conditions.rb +172 -0
- data/lib/data_mapper/adapters/sql/mappings/table.rb +43 -17
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +9 -2
- data/lib/data_mapper/associations.rb +75 -3
- data/lib/data_mapper/associations/belongs_to_association.rb +70 -36
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +195 -86
- data/lib/data_mapper/associations/has_many_association.rb +168 -61
- data/lib/data_mapper/associations/has_n_association.rb +23 -3
- data/lib/data_mapper/attributes.rb +73 -0
- data/lib/data_mapper/auto_migrations.rb +2 -6
- data/lib/data_mapper/base.rb +5 -9
- data/lib/data_mapper/database.rb +4 -3
- data/lib/data_mapper/embedded_value.rb +66 -30
- data/lib/data_mapper/identity_map.rb +1 -3
- data/lib/data_mapper/is/tree.rb +121 -0
- data/lib/data_mapper/migration.rb +155 -0
- data/lib/data_mapper/persistence.rb +532 -218
- data/lib/data_mapper/property.rb +306 -0
- data/lib/data_mapper/query.rb +164 -0
- data/lib/data_mapper/support/blank.rb +2 -2
- data/lib/data_mapper/support/connection_pool.rb +5 -6
- data/lib/data_mapper/support/enumerable.rb +3 -3
- data/lib/data_mapper/support/errors.rb +10 -1
- data/lib/data_mapper/support/inflector.rb +174 -238
- data/lib/data_mapper/support/object.rb +54 -0
- data/lib/data_mapper/support/serialization.rb +19 -1
- data/lib/data_mapper/support/string.rb +7 -16
- data/lib/data_mapper/support/symbol.rb +3 -15
- data/lib/data_mapper/support/typed_set.rb +68 -0
- data/lib/data_mapper/types/base.rb +44 -0
- data/lib/data_mapper/types/string.rb +34 -0
- data/lib/data_mapper/validations/number_validator.rb +40 -0
- data/lib/data_mapper/validations/string_validator.rb +20 -0
- data/lib/data_mapper/validations/validator.rb +13 -0
- data/performance.rb +26 -1
- data/profile_data_mapper.rb +1 -1
- data/rakefile.rb +42 -2
- data/spec/acts_as_tree_spec.rb +11 -3
- data/spec/adapters/data_object_adapter_spec.rb +31 -0
- data/spec/associations/belongs_to_association_spec.rb +98 -0
- data/spec/associations/has_and_belongs_to_many_association_spec.rb +377 -0
- data/spec/associations/has_many_association_spec.rb +337 -0
- data/spec/attributes_spec.rb +23 -1
- data/spec/auto_migrations_spec.rb +86 -29
- data/spec/callbacks_spec.rb +107 -0
- data/spec/column_spec.rb +5 -2
- data/spec/count_command_spec.rb +33 -1
- data/spec/database_spec.rb +18 -0
- data/spec/dependency_spec.rb +4 -2
- data/spec/embedded_value_spec.rb +8 -8
- data/spec/fixtures/people.yaml +1 -1
- data/spec/fixtures/projects.yaml +10 -1
- data/spec/fixtures/tasks.yaml +6 -0
- data/spec/fixtures/tasks_tasks.yaml +2 -0
- data/spec/fixtures/tomatoes.yaml +1 -0
- data/spec/is_a_tree_spec.rb +149 -0
- data/spec/load_command_spec.rb +71 -9
- data/spec/magic_columns_spec.rb +17 -2
- data/spec/migration_spec.rb +267 -0
- data/spec/models/animal.rb +1 -1
- data/spec/models/candidate.rb +8 -0
- data/spec/models/career.rb +1 -1
- data/spec/models/chain.rb +8 -0
- data/spec/models/comment.rb +1 -1
- data/spec/models/exhibit.rb +1 -1
- data/spec/models/fence.rb +7 -0
- data/spec/models/fruit.rb +2 -2
- data/spec/models/job.rb +8 -0
- data/spec/models/person.rb +2 -3
- data/spec/models/post.rb +1 -1
- data/spec/models/project.rb +21 -1
- data/spec/models/section.rb +1 -1
- data/spec/models/serializer.rb +1 -1
- data/spec/models/task.rb +9 -0
- data/spec/models/tomato.rb +27 -0
- data/spec/models/user.rb +8 -2
- data/spec/models/zoo.rb +2 -7
- data/spec/paranoia_spec.rb +1 -1
- data/spec/{base_spec.rb → persistence_spec.rb} +207 -18
- data/spec/postgres_spec.rb +48 -6
- data/spec/property_spec.rb +90 -9
- data/spec/query_spec.rb +71 -5
- data/spec/save_command_spec.rb +11 -0
- data/spec/spec_helper.rb +14 -11
- data/spec/support/blank_spec.rb +8 -0
- data/spec/support/inflector_spec.rb +41 -0
- data/spec/support/object_spec.rb +9 -0
- data/spec/{serialization_spec.rb → support/serialization_spec.rb} +1 -1
- data/spec/support/silence_spec.rb +15 -0
- data/spec/{support_spec.rb → support/string_spec.rb} +3 -3
- data/spec/support/struct_spec.rb +12 -0
- data/spec/support/typed_set_spec.rb +66 -0
- data/spec/table_spec.rb +3 -3
- data/spec/types/string.rb +81 -0
- data/spec/validates_uniqueness_of_spec.rb +17 -0
- data/spec/validations/number_validator.rb +59 -0
- data/spec/validations/string_validator.rb +14 -0
- metadata +59 -17
- data/do_performance.rb +0 -153
- data/lib/data_mapper/support/active_record_impersonation.rb +0 -103
- data/lib/data_mapper/support/weak_hash.rb +0 -46
- data/spec/active_record_impersonation_spec.rb +0 -129
- data/spec/associations_spec.rb +0 -232
- data/spec/conditions_spec.rb +0 -49
- data/spec/has_many_association_spec.rb +0 -173
- data/spec/models/animals_exhibit.rb +0 -8
data/do_performance.rb
DELETED
@@ -1,153 +0,0 @@
|
|
1
|
-
require 'benchmark'
|
2
|
-
require 'lib/data_mapper'
|
3
|
-
|
4
|
-
DataMapper::Database.setup({
|
5
|
-
:adapter => 'do_mysql',
|
6
|
-
:database => 'data_mapper_1',
|
7
|
-
:username => 'root'
|
8
|
-
})
|
9
|
-
|
10
|
-
class DMAnimal < DataMapper::Base
|
11
|
-
set_table_name 'animals'
|
12
|
-
property :name, :string
|
13
|
-
property :notes, :string
|
14
|
-
end
|
15
|
-
|
16
|
-
class DMPerson < DataMapper::Base
|
17
|
-
set_table_name 'people'
|
18
|
-
property :name, :string
|
19
|
-
property :age, :integer
|
20
|
-
property :occupation, :string
|
21
|
-
property :notes, :text
|
22
|
-
property :street, :string
|
23
|
-
property :city, :string
|
24
|
-
property :state, :string, :size => 2
|
25
|
-
property :zip_code, :string, :size => 10
|
26
|
-
end
|
27
|
-
|
28
|
-
class Exhibit < DataMapper::Base
|
29
|
-
property :name, :string
|
30
|
-
belongs_to :zoo
|
31
|
-
end
|
32
|
-
|
33
|
-
class Zoo < DataMapper::Base
|
34
|
-
property :name, :string
|
35
|
-
has_many :exhibits
|
36
|
-
end
|
37
|
-
|
38
|
-
N = (ENV['N'] || 1000).to_i
|
39
|
-
|
40
|
-
# 4.times do
|
41
|
-
# [DMAnimal, Zoo, Exhibit].each do |klass|
|
42
|
-
# klass.all.each do |instance|
|
43
|
-
# klass.create(instance.attributes.reject { |k,v| k == :id })
|
44
|
-
# end
|
45
|
-
# end
|
46
|
-
# end
|
47
|
-
|
48
|
-
Benchmark::send(ENV['BM'] || :bmbm, 40) do |x|
|
49
|
-
|
50
|
-
x.report('DataMapper:id') do
|
51
|
-
N.times { DMAnimal[1] }
|
52
|
-
end
|
53
|
-
|
54
|
-
x.report('DataMapper:id:in-session') do
|
55
|
-
database do
|
56
|
-
N.times { DMAnimal[1] }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
x.report('DataMapper:all') do
|
61
|
-
N.times { DMAnimal.all }
|
62
|
-
end
|
63
|
-
|
64
|
-
x.report('DataMapper:all:in-session') do
|
65
|
-
database do
|
66
|
-
N.times { DMAnimal.all }
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
x.report('DataMapper:conditions:short') do
|
71
|
-
N.times { Zoo[:name => 'Galveston'] }
|
72
|
-
end
|
73
|
-
|
74
|
-
x.report('DataMapper:conditions:short:in-session') do
|
75
|
-
database do
|
76
|
-
N.times { Zoo[:name => 'Galveston'] }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
x.report('DataMapper:conditions:long') do
|
81
|
-
N.times { Zoo.find(:first, :conditions => ['name = ?', 'Galveston']) }
|
82
|
-
end
|
83
|
-
|
84
|
-
x.report('DataMapper:conditions:long:in-session') do
|
85
|
-
database do
|
86
|
-
N.times { Zoo.find(:first, :conditions => ['name = ?', 'Galveston']) }
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
people = [
|
91
|
-
['Sam', 29, 'Programmer', 'A slow text field'],
|
92
|
-
['Amy', 28, 'Business Analyst Manager', 'A slow text field'],
|
93
|
-
['Scott', 25, 'Programmer', 'A slow text field'],
|
94
|
-
['Josh', 23, 'Supervisor', 'A slow text field'],
|
95
|
-
['Bob', 40, 'Peon', 'A slow text field']
|
96
|
-
]
|
97
|
-
|
98
|
-
DMPerson.truncate!
|
99
|
-
|
100
|
-
x.report('DataMapper:insert') do
|
101
|
-
N.times do
|
102
|
-
people.each do |a|
|
103
|
-
DMPerson::create(:name => a[0], :age => a[1], :occupation => a[2], :notes => a[3])
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
x.report('DataMapper:update') do
|
109
|
-
N.times do
|
110
|
-
bob = DMAnimal.first(:name => 'Elephant')
|
111
|
-
bob.notes = 'Updated by DataMapper'
|
112
|
-
bob.save
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
x.report('DataMapper:associations') do
|
117
|
-
N.times do
|
118
|
-
Zoo.all.each { |zoo| zoo.exhibits.entries }
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
x.report('DataMapper:associations:in-session') do
|
123
|
-
database do
|
124
|
-
N.times do
|
125
|
-
Zoo.all.each { |zoo| zoo.exhibits.entries }
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
x.report('DataMapper:find_by_sql') do
|
131
|
-
N.times do
|
132
|
-
database.query("SELECT * FROM zoos")
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
x.report('DataMapper:accessors') do
|
137
|
-
person = DMPerson.first
|
138
|
-
|
139
|
-
N.times do
|
140
|
-
<<-VCARD
|
141
|
-
#{person.name} (#{person.age})
|
142
|
-
#{person.occupation}
|
143
|
-
|
144
|
-
#{person.street}
|
145
|
-
#{person.city}, #{person.state} #{person.zip_code}
|
146
|
-
|
147
|
-
#{person.notes}
|
148
|
-
VCARD
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
|
153
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Support
|
3
|
-
|
4
|
-
module ActiveRecordImpersonation
|
5
|
-
|
6
|
-
def self.included(base)
|
7
|
-
base.extend(ClassMethods)
|
8
|
-
end
|
9
|
-
|
10
|
-
def save
|
11
|
-
database_context.save(self)
|
12
|
-
end
|
13
|
-
|
14
|
-
def reload!
|
15
|
-
database_context.first(self.class, key, :select => original_values.keys, :reload => true)
|
16
|
-
self.loaded_associations.each { |association| association.reload! }
|
17
|
-
self
|
18
|
-
end
|
19
|
-
|
20
|
-
def reload
|
21
|
-
reload!
|
22
|
-
end
|
23
|
-
|
24
|
-
def destroy!
|
25
|
-
database_context.destroy(self)
|
26
|
-
end
|
27
|
-
|
28
|
-
module ClassMethods
|
29
|
-
|
30
|
-
def find_or_create(search_attributes, create_attributes = {})
|
31
|
-
first(search_attributes) || create(search_attributes.merge(create_attributes))
|
32
|
-
end
|
33
|
-
|
34
|
-
def all(options = {})
|
35
|
-
database.all(self, options)
|
36
|
-
end
|
37
|
-
|
38
|
-
def each(options = {}, &b)
|
39
|
-
raise ArgumentError.new(":offset is not supported with the #each method") if options.has_key?(:offset)
|
40
|
-
|
41
|
-
offset = 0
|
42
|
-
limit = options[:limit] || (self::const_defined?('DEFAULT_LIMIT') ? self::DEFAULT_LIMIT : 500)
|
43
|
-
|
44
|
-
until (results = all(options.merge(:limit => limit, :offset => offset))).empty?
|
45
|
-
results.each(&b)
|
46
|
-
offset += limit
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def first(*args)
|
51
|
-
database.first(self, *args)
|
52
|
-
end
|
53
|
-
|
54
|
-
def count(*args)
|
55
|
-
database.count(self, *args)
|
56
|
-
end
|
57
|
-
|
58
|
-
def delete_all
|
59
|
-
database.delete_all(self)
|
60
|
-
end
|
61
|
-
|
62
|
-
def truncate!
|
63
|
-
database.truncate(self)
|
64
|
-
end
|
65
|
-
|
66
|
-
def find(type_or_id, options = {})
|
67
|
-
case type_or_id
|
68
|
-
when :first then first(options)
|
69
|
-
when :all then all(options)
|
70
|
-
else first(type_or_id, options)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def find_by_sql(*args)
|
75
|
-
DataMapper::database.query(*args)
|
76
|
-
end
|
77
|
-
|
78
|
-
def get(*keys)
|
79
|
-
database.get(self, keys)
|
80
|
-
end
|
81
|
-
|
82
|
-
def [](*keys)
|
83
|
-
raise ArgumentError.new('Hash is not a valid key') if keys.size == 1 && keys.first.is_a?(Hash)
|
84
|
-
database.get(self, keys)
|
85
|
-
end
|
86
|
-
|
87
|
-
def create(attributes)
|
88
|
-
instance = self.new(attributes)
|
89
|
-
instance.save
|
90
|
-
instance
|
91
|
-
end
|
92
|
-
|
93
|
-
def create!(attributes)
|
94
|
-
instance = self.new(attributes)
|
95
|
-
instance.save
|
96
|
-
raise InvalidRecord.new(instance) if instance.new_record?
|
97
|
-
instance
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|
103
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Support
|
3
|
-
class WeakHash
|
4
|
-
attr_reader :cache
|
5
|
-
def initialize( cache = Hash.new )
|
6
|
-
@cache = cache
|
7
|
-
@key_map = {}
|
8
|
-
@rev_cache = Hash.new{|h,k| h[k] = {}}
|
9
|
-
@reclaim_value = lambda do |value_id|
|
10
|
-
if @rev_cache.has_key? value_id
|
11
|
-
@rev_cache[value_id].each_key{|key| @cache.delete key}
|
12
|
-
@rev_cache.delete value_id
|
13
|
-
end
|
14
|
-
end
|
15
|
-
@reclaim_key = lambda do |key_id|
|
16
|
-
if @key_map.has_key? key_id
|
17
|
-
@cache.delete @key_map[key_id]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def []( key )
|
23
|
-
value_id = @cache[key]
|
24
|
-
return ObjectSpace._id2ref(value_id) unless value_id.nil?
|
25
|
-
nil
|
26
|
-
rescue RangeError
|
27
|
-
nil
|
28
|
-
end
|
29
|
-
|
30
|
-
def []=( key, value )
|
31
|
-
case key
|
32
|
-
when Fixnum, Symbol, true, false
|
33
|
-
key2 = key
|
34
|
-
else
|
35
|
-
key2 = key.dup
|
36
|
-
end
|
37
|
-
@rev_cache[value.object_id][key2] = true
|
38
|
-
@cache[key2] = value.object_id
|
39
|
-
@key_map[key.object_id] = key2
|
40
|
-
|
41
|
-
ObjectSpace.define_finalizer(value, @reclaim_value)
|
42
|
-
ObjectSpace.define_finalizer(key, @reclaim_key)
|
43
|
-
end
|
44
|
-
end # class WeakHash
|
45
|
-
end # module Support
|
46
|
-
end # module DataMapper
|
@@ -1,129 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + "/spec_helper"
|
2
|
-
|
3
|
-
describe DataMapper::Support::ActiveRecordImpersonation do
|
4
|
-
|
5
|
-
before(:all) do
|
6
|
-
fixtures(:animals)
|
7
|
-
fixtures(:exhibits)
|
8
|
-
end
|
9
|
-
|
10
|
-
describe 'A record' do
|
11
|
-
it 'should save and return true if validations pass' do
|
12
|
-
count = Exhibit.count
|
13
|
-
bugs_and_more_bugs = Exhibit.new(:name => 'Bugs And More Bugs')
|
14
|
-
bugs_and_more_bugs.save.should be_true
|
15
|
-
Exhibit.count.should == count + 1
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'should return false on save if validations fail' do
|
19
|
-
count = Exhibit.count
|
20
|
-
bugs_and_more_bugs = Exhibit.new
|
21
|
-
bugs_and_more_bugs.save.should be_false
|
22
|
-
Exhibit.count.should == count
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'should reload its attributes' do
|
26
|
-
frog = Animal.first(:name => 'Frog')
|
27
|
-
frog.name = 'MegaFrog'
|
28
|
-
frog.name.should == 'MegaFrog'
|
29
|
-
frog.reload!
|
30
|
-
frog.name.should == 'Frog'
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should prepare it's associations for reload" do
|
34
|
-
chippy = Animal.first(:name => 'Cup')
|
35
|
-
amazonia = Exhibit.first(:name => 'Amazonia')
|
36
|
-
amazonia.animals << chippy
|
37
|
-
amazonia.animals.should include(chippy)
|
38
|
-
amazonia.reload!
|
39
|
-
amazonia.animals.should_not include(chippy)
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should be destroyed!' do
|
43
|
-
capybara = Animal.create(:name => 'Capybara')
|
44
|
-
count = Animal.count
|
45
|
-
capybara.destroy!
|
46
|
-
Animal.first(:name => 'Capybara').should be_nil
|
47
|
-
Animal.count.should == count - 1
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'should return the first match using find_or_create' do
|
52
|
-
count = Animal.count
|
53
|
-
frog = Animal.find_or_create(:name => 'Frog')
|
54
|
-
frog.name.should == 'Frog'
|
55
|
-
Animal.count.should == count
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'should create a record if a match is not found with find_or_create' do
|
59
|
-
count = Animal.count
|
60
|
-
capybara = Animal.find_or_create(:name => 'Capybara')
|
61
|
-
capybara.name.should == 'Capybara'
|
62
|
-
Animal.count.should == count + 1
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'should return all records' do
|
66
|
-
all_animals = Animal.all
|
67
|
-
all_animals.length.should == Animal.count
|
68
|
-
all_animals.each do |animal|
|
69
|
-
animal.class.should == Animal
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'should return the first record' do
|
74
|
-
Animal.first.should == Animal.find(:first)
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'should return a count of the records' do
|
78
|
-
Animal.count.should == Animal.find_by_sql("SELECT COUNT(*) FROM animals")[0]
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'should delete all records' do
|
82
|
-
Animal.delete_all
|
83
|
-
Animal.count.should == 0
|
84
|
-
|
85
|
-
fixtures(:animals)
|
86
|
-
end
|
87
|
-
|
88
|
-
#it 'should be truncated' do
|
89
|
-
# Animal.truncate!
|
90
|
-
# Animal.count.should == 0
|
91
|
-
#
|
92
|
-
# fixtures(:animals)
|
93
|
-
#end
|
94
|
-
|
95
|
-
it 'should find a matching record given an id' do
|
96
|
-
Animal.find(1).name.should == 'Frog'
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'should find all records' do
|
100
|
-
Animal.find(:all).length.should == Animal.count
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'should find all matching records given some condition' do
|
104
|
-
Animal.find(:all, :conditions => ["name = ?", "Frog"])[0].name.should == 'Frog'
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'should find the first matching record' do
|
108
|
-
Animal.find(:first).name.should == 'Frog'
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'should find the first matching record given some condition' do
|
112
|
-
Animal.find(:first, :conditions => ["name = ?", "Frog"]).name.should == 'Frog'
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'should select records using the supplied sql fragment' do
|
116
|
-
Animal.find_by_sql("SELECT name FROM animals WHERE name='Frog'")[0].should == 'Frog'
|
117
|
-
end
|
118
|
-
|
119
|
-
it 'should retrieve the indexed element' do
|
120
|
-
Animal[1].id.should == 1
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'should create a new record' do
|
124
|
-
count = Animal.count
|
125
|
-
capybara = Animal.create(:name => 'Capybara')
|
126
|
-
capybara.name.should == 'Capybara'
|
127
|
-
Animal.count.should == count + 1
|
128
|
-
end
|
129
|
-
end
|
data/spec/associations_spec.rb
DELETED
@@ -1,232 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + "/spec_helper"
|
2
|
-
|
3
|
-
describe DataMapper::Associations::BelongsToAssociation do
|
4
|
-
before(:all) do
|
5
|
-
fixtures(:zoos)
|
6
|
-
end
|
7
|
-
|
8
|
-
before(:each) do
|
9
|
-
@aviary = Exhibit.first(:name => 'Monkey Mayhem')
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'has a zoo association' do
|
13
|
-
@aviary.zoo.class.should == Zoo
|
14
|
-
Exhibit.new.zoo.should == nil
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'belongs to a zoo' do
|
18
|
-
@aviary.zoo.should == @aviary.database_context.first(Zoo, :name => 'San Diego')
|
19
|
-
end
|
20
|
-
|
21
|
-
it "is assigned a zoo_id" do
|
22
|
-
zoo = Zoo.first
|
23
|
-
exhibit = Exhibit.new(:name => 'bob')
|
24
|
-
exhibit.zoo = zoo
|
25
|
-
exhibit.instance_variable_get("@zoo_id").should == zoo.id
|
26
|
-
|
27
|
-
exhibit.save.should eql(true)
|
28
|
-
|
29
|
-
zoo2 = Zoo.first
|
30
|
-
zoo2.exhibits.should include(exhibit)
|
31
|
-
|
32
|
-
exhibit.destroy!
|
33
|
-
|
34
|
-
zoo = Zoo.new(:name => 'bob')
|
35
|
-
bob = Exhibit.new(:name => 'bob')
|
36
|
-
zoo.exhibits << bob
|
37
|
-
zoo.save.should eql(true)
|
38
|
-
|
39
|
-
zoo.exhibits.first.should_not be_a_new_record
|
40
|
-
|
41
|
-
bob.destroy!
|
42
|
-
zoo.destroy!
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'can build its zoo' do
|
46
|
-
database do |db|
|
47
|
-
e = Exhibit.new({:name => 'Super Extra Crazy Monkey Cage'})
|
48
|
-
e.zoo.should == nil
|
49
|
-
e.build_zoo({:name => 'Monkey Zoo'})
|
50
|
-
e.zoo.class == Zoo
|
51
|
-
e.zoo.new_record?.should == true
|
52
|
-
|
53
|
-
e.save
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'can build its zoo' do
|
58
|
-
database do |db|
|
59
|
-
e = Exhibit.new({:name => 'Super Extra Crazy Monkey Cage'})
|
60
|
-
e.zoo.should == nil
|
61
|
-
e.create_zoo({:name => 'Monkey Zoo'})
|
62
|
-
e.zoo.class == Zoo
|
63
|
-
e.zoo.new_record?.should == false
|
64
|
-
e.save
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
after(:all) do
|
69
|
-
fixtures('zoos')
|
70
|
-
fixtures('exhibits')
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe DataMapper::Associations::HasAndBelongsToManyAssociation do
|
75
|
-
|
76
|
-
before(:all) do
|
77
|
-
fixtures(:animals)
|
78
|
-
fixtures(:exhibits)
|
79
|
-
end
|
80
|
-
|
81
|
-
before(:each) do
|
82
|
-
@amazonia = Exhibit.first :name => 'Amazonia'
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should generate the SQL for a join statement" do
|
86
|
-
animals_association = database(:mock).schema[Exhibit].associations.find { |a| a.name == :animals }
|
87
|
-
|
88
|
-
animals_association.to_sql.should == <<-EOS.compress_lines
|
89
|
-
JOIN `animals_exhibits` ON `animals_exhibits`.`exhibit_id` = `exhibits`.`id`
|
90
|
-
JOIN `animals` ON `animals`.`id` = `animals_exhibits`.`animal_id`
|
91
|
-
EOS
|
92
|
-
end
|
93
|
-
|
94
|
-
it "should load associations" do
|
95
|
-
database do
|
96
|
-
froggy = Animal.first(:name => 'Frog')
|
97
|
-
froggy.exhibits.size.should == 1
|
98
|
-
froggy.exhibits.entries.first.should == Exhibit.first(:name => 'Amazonia')
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'has an animals association' do
|
103
|
-
[@amazonia, Exhibit.new].each do |exhibit|
|
104
|
-
exhibit.animals.class.should == DataMapper::Associations::HasAndBelongsToManyAssociation::Set
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'has many animals' do
|
109
|
-
@amazonia.animals.size.should == 1
|
110
|
-
end
|
111
|
-
|
112
|
-
it 'should load associations magically' do
|
113
|
-
Exhibit.all.each do |exhibit|
|
114
|
-
exhibit.animals.each do |animal|
|
115
|
-
animal.exhibits.should include(exhibit)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
it 'should allow association of additional objects' do
|
121
|
-
@amazonia.animals << Animal.new(:name => "Buffalo")
|
122
|
-
@amazonia.animals.size.should == 2
|
123
|
-
@amazonia.reload
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should allow association of additional objects (CLEAN)" do
|
127
|
-
pending "http://wm.lighthouseapp.com/projects/4819-datamapper/tickets/92"
|
128
|
-
@amazonia.should_not be_dirty
|
129
|
-
|
130
|
-
animal = Animal[2]
|
131
|
-
animal.should_not be_dirty
|
132
|
-
|
133
|
-
@amazonia.animals << animal
|
134
|
-
@amazonia.animals.size.should == 2
|
135
|
-
@amazonia.reload
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'should allow you to fill and clear an association' do
|
139
|
-
marcy = Exhibit.create(:name => 'marcy')
|
140
|
-
|
141
|
-
Animal.all.each do |animal|
|
142
|
-
marcy.animals << animal
|
143
|
-
end
|
144
|
-
|
145
|
-
marcy.save.should eql(true)
|
146
|
-
marcy.should have(Animal.count).animals
|
147
|
-
|
148
|
-
marcy.animals.clear
|
149
|
-
marcy.should have(0).animals
|
150
|
-
|
151
|
-
marcy.save.should eql(true)
|
152
|
-
|
153
|
-
marcys_stand_in = Exhibit[marcy.id]
|
154
|
-
marcys_stand_in.should have(0).animals
|
155
|
-
|
156
|
-
marcy.destroy!
|
157
|
-
end
|
158
|
-
|
159
|
-
it 'should allow you to delete a specific association member' do
|
160
|
-
walter = Exhibit.create(:name => 'walter')
|
161
|
-
|
162
|
-
Animal.all.each do |animal|
|
163
|
-
walter.animals << animal
|
164
|
-
end
|
165
|
-
|
166
|
-
walter.save.should eql(true)
|
167
|
-
walter.should have(Animal.count).animals
|
168
|
-
|
169
|
-
delete_me = walter.animals.entries.first
|
170
|
-
walter.animals.delete(delete_me).should eql(delete_me)
|
171
|
-
walter.animals.delete(delete_me).should eql(nil)
|
172
|
-
|
173
|
-
walter.should have(Animal.count - 1).animals
|
174
|
-
walter.save.should eql(true)
|
175
|
-
|
176
|
-
walters_stand_in = Exhibit[walter.id]
|
177
|
-
walters_stand_in.animals.size.should eql(walter.animals.size)
|
178
|
-
|
179
|
-
walter.destroy!
|
180
|
-
end
|
181
|
-
|
182
|
-
it "should allow updates to associations using association_ids[]" do
|
183
|
-
pending "Awaiting implementation of association_ids[]"
|
184
|
-
meerkat = Animal.new(:name => "Meerkat")
|
185
|
-
@amazonia.animals.size.should == 1
|
186
|
-
|
187
|
-
@amazonia.animal_ids << meerkat.id
|
188
|
-
@amazonia.save
|
189
|
-
|
190
|
-
@amazonia.animals.size.should == 2
|
191
|
-
@amazonia.animals.should include?(meerkat)
|
192
|
-
end
|
193
|
-
|
194
|
-
it "Should handle setting complementary associations" do
|
195
|
-
pending("some borkage here")
|
196
|
-
u1 = User.create(:name => "u1")
|
197
|
-
u1.comments.should be_empty
|
198
|
-
|
199
|
-
c1 = Comment.create(:comment => "c", :author => u1)
|
200
|
-
# p u1
|
201
|
-
# p c1
|
202
|
-
|
203
|
-
u1.comments.should_not be_empty
|
204
|
-
u1.comments.should include(c1)
|
205
|
-
|
206
|
-
u1.reload!
|
207
|
-
u1.comments.should_not be_empty
|
208
|
-
u1.comments.should include(c1)
|
209
|
-
end
|
210
|
-
|
211
|
-
it "should raise an error when attempting to associate an object not of the correct type (assuming added model doesn't inherit from the correct type)" do
|
212
|
-
pending("see: http://wm.lighthouseapp.com/projects/4819-datamapper/tickets/91")
|
213
|
-
@amazonia.animals.should_not be_empty
|
214
|
-
chuck = Person.new(:name => "Chuck")
|
215
|
-
|
216
|
-
## InvalidRecord isn't the error we should use here....needs to be changed
|
217
|
-
lambda { @amazonia.animals << chuck }.should raise_error(WrongType)
|
218
|
-
|
219
|
-
end
|
220
|
-
|
221
|
-
it "should associate an object which has inherited from the correct type into an association" do
|
222
|
-
pending("see: http://wm.lighthouseapp.com/projects/4819-datamapper/tickets/91")
|
223
|
-
programmer = Career.first(:name => 'Programmer')
|
224
|
-
programmer.followers.should_not be_empty
|
225
|
-
|
226
|
-
sales_person = SalesPerson.new(:name => 'Chuck')
|
227
|
-
|
228
|
-
lambda { programmer.followers << sales_person }.should_not raise_error(WrongType)
|
229
|
-
|
230
|
-
end
|
231
|
-
|
232
|
-
end
|