datamapper 0.1.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.
Files changed (85) hide show
  1. data/CHANGELOG +2 -0
  2. data/MIT-LICENSE +22 -0
  3. data/README +1 -0
  4. data/example.rb +25 -0
  5. data/lib/data_mapper.rb +30 -0
  6. data/lib/data_mapper/adapters/abstract_adapter.rb +229 -0
  7. data/lib/data_mapper/adapters/mysql_adapter.rb +171 -0
  8. data/lib/data_mapper/adapters/sqlite3_adapter.rb +189 -0
  9. data/lib/data_mapper/associations.rb +19 -0
  10. data/lib/data_mapper/associations/belongs_to_association.rb +111 -0
  11. data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +100 -0
  12. data/lib/data_mapper/associations/has_many_association.rb +101 -0
  13. data/lib/data_mapper/associations/has_one_association.rb +107 -0
  14. data/lib/data_mapper/base.rb +160 -0
  15. data/lib/data_mapper/callbacks.rb +47 -0
  16. data/lib/data_mapper/database.rb +134 -0
  17. data/lib/data_mapper/extensions/active_record_impersonation.rb +69 -0
  18. data/lib/data_mapper/extensions/callback_helpers.rb +35 -0
  19. data/lib/data_mapper/identity_map.rb +21 -0
  20. data/lib/data_mapper/loaded_set.rb +45 -0
  21. data/lib/data_mapper/mappings/column.rb +78 -0
  22. data/lib/data_mapper/mappings/schema.rb +28 -0
  23. data/lib/data_mapper/mappings/table.rb +99 -0
  24. data/lib/data_mapper/queries/conditions.rb +141 -0
  25. data/lib/data_mapper/queries/connection.rb +34 -0
  26. data/lib/data_mapper/queries/create_table_statement.rb +38 -0
  27. data/lib/data_mapper/queries/delete_statement.rb +17 -0
  28. data/lib/data_mapper/queries/drop_table_statement.rb +17 -0
  29. data/lib/data_mapper/queries/insert_statement.rb +29 -0
  30. data/lib/data_mapper/queries/reader.rb +42 -0
  31. data/lib/data_mapper/queries/result.rb +19 -0
  32. data/lib/data_mapper/queries/select_statement.rb +103 -0
  33. data/lib/data_mapper/queries/table_exists_statement.rb +17 -0
  34. data/lib/data_mapper/queries/truncate_table_statement.rb +17 -0
  35. data/lib/data_mapper/queries/update_statement.rb +25 -0
  36. data/lib/data_mapper/session.rb +240 -0
  37. data/lib/data_mapper/support/blank_slate.rb +3 -0
  38. data/lib/data_mapper/support/connection_pool.rb +117 -0
  39. data/lib/data_mapper/support/enumerable.rb +27 -0
  40. data/lib/data_mapper/support/inflector.rb +329 -0
  41. data/lib/data_mapper/support/proc.rb +69 -0
  42. data/lib/data_mapper/support/string.rb +23 -0
  43. data/lib/data_mapper/support/symbol.rb +91 -0
  44. data/lib/data_mapper/support/weak_hash.rb +46 -0
  45. data/lib/data_mapper/unit_of_work.rb +38 -0
  46. data/lib/data_mapper/validations/confirmation_validator.rb +55 -0
  47. data/lib/data_mapper/validations/contextual_validations.rb +50 -0
  48. data/lib/data_mapper/validations/format_validator.rb +85 -0
  49. data/lib/data_mapper/validations/formats/email.rb +78 -0
  50. data/lib/data_mapper/validations/generic_validator.rb +27 -0
  51. data/lib/data_mapper/validations/length_validator.rb +75 -0
  52. data/lib/data_mapper/validations/required_field_validator.rb +47 -0
  53. data/lib/data_mapper/validations/unique_validator.rb +65 -0
  54. data/lib/data_mapper/validations/validation_errors.rb +34 -0
  55. data/lib/data_mapper/validations/validation_helper.rb +60 -0
  56. data/performance.rb +156 -0
  57. data/profile_data_mapper.rb +18 -0
  58. data/rakefile.rb +80 -0
  59. data/spec/basic_finder.rb +67 -0
  60. data/spec/belongs_to.rb +47 -0
  61. data/spec/fixtures/animals.yaml +32 -0
  62. data/spec/fixtures/exhibits.yaml +90 -0
  63. data/spec/fixtures/fruit.yaml +6 -0
  64. data/spec/fixtures/people.yaml +15 -0
  65. data/spec/fixtures/zoos.yaml +20 -0
  66. data/spec/has_and_belongs_to_many.rb +25 -0
  67. data/spec/has_many.rb +34 -0
  68. data/spec/legacy.rb +14 -0
  69. data/spec/models/animal.rb +7 -0
  70. data/spec/models/exhibit.rb +6 -0
  71. data/spec/models/fruit.rb +6 -0
  72. data/spec/models/person.rb +7 -0
  73. data/spec/models/post.rb +4 -0
  74. data/spec/models/sales_person.rb +4 -0
  75. data/spec/models/zoo.rb +5 -0
  76. data/spec/new_record.rb +24 -0
  77. data/spec/spec_helper.rb +61 -0
  78. data/spec/sub_select.rb +16 -0
  79. data/spec/symbolic_operators.rb +21 -0
  80. data/spec/validates_confirmation_of.rb +36 -0
  81. data/spec/validates_format_of.rb +61 -0
  82. data/spec/validates_length_of.rb +101 -0
  83. data/spec/validates_uniqueness_of.rb +45 -0
  84. data/spec/validations.rb +63 -0
  85. metadata +134 -0
@@ -0,0 +1,18 @@
1
+ require 'example'
2
+ require 'ruby-prof'
3
+
4
+ # RubyProf, making profiling Ruby pretty since 1899!
5
+ def profile(&b)
6
+ result = RubyProf.profile &b
7
+
8
+ printer = RubyProf::GraphHtmlPrinter.new(result)
9
+ File::open('profile_results.html', 'w+') do |file|
10
+ printer.print(file, 0)
11
+ end
12
+ end
13
+
14
+ profile do
15
+ 1000.times do
16
+ Zoo[:name => 'Galveston']
17
+ end
18
+ end
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rake'
4
+ require 'spec/rake/spectask'
5
+ require 'rake/rdoctask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+
9
+ task :default => 'test'
10
+
11
+ desc "Run specifications"
12
+ Spec::Rake::SpecTask.new('test') do |t|
13
+ t.spec_opts = [ '-rspec/spec_helper' ]
14
+ t.spec_files = FileList[ENV['FILES'] || 'spec/*.rb']
15
+ end
16
+
17
+ desc "Run comparison with ActiveRecord"
18
+ task :perf do
19
+ load 'performance.rb'
20
+ end
21
+
22
+ desc "Profile DataMapper"
23
+ task :profile do
24
+ load 'profile_data_mapper.rb'
25
+ end
26
+
27
+ PACKAGE_VERSION = '0.1.0'
28
+
29
+ PACKAGE_FILES = FileList[
30
+ 'README',
31
+ 'CHANGELOG',
32
+ 'MIT-LICENSE',
33
+ '*.rb',
34
+ 'lib/**/*.rb',
35
+ 'spec/**/*.{rb,yaml}'
36
+ ].to_a
37
+
38
+ PROJECT = 'datamapper'
39
+
40
+ desc "Generate Documentation"
41
+ rd = Rake::RDocTask.new do |rdoc|
42
+ rdoc.rdoc_dir = 'doc'
43
+ rdoc.title = "DataMapper -- An Object/Relational Mapper for Ruby"
44
+ rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
45
+ rdoc.rdoc_files.include(PACKAGE_FILES.reject { |path| path =~ /^(spec|\w+\.rb)/ })
46
+ end
47
+
48
+ gem_spec = Gem::Specification.new do |s|
49
+ s.platform = Gem::Platform::RUBY
50
+ s.name = PROJECT
51
+ s.summary = "An Object/Relational Mapper for Ruby"
52
+ s.description = "It's ActiveRecord, but Faster, Better, Simpler."
53
+ s.version = PACKAGE_VERSION
54
+
55
+ s.authors = 'Sam Smoot'
56
+ s.email = 'ssmoot@gmail.com'
57
+ s.rubyforge_project = PROJECT
58
+ s.homepage = 'http://datamapper.org'
59
+
60
+ s.files = PACKAGE_FILES
61
+
62
+ s.require_path = 'lib'
63
+ s.requirements << 'none'
64
+ s.autorequire = 'data_mapper'
65
+
66
+ s.has_rdoc = true
67
+ s.rdoc_options << '--line-numbers' << '--inline-source' << '--main' << 'README'
68
+ s.extra_rdoc_files = rd.rdoc_files.reject { |path| path =~ /\.rb$/ }.to_a
69
+ end
70
+
71
+ Rake::GemPackageTask.new(gem_spec) do |p|
72
+ p.gem_spec = gem_spec
73
+ p.need_tar = true
74
+ p.need_zip = true
75
+ end
76
+
77
+ desc "Publish to RubyForge"
78
+ task :rubyforge => [ :rdoc, :gem ] do
79
+ Rake::SshDirPublisher.new(ENV['RUBYFORGE_USER'], "/var/www/gforge-projects/#{PROJECT}", 'doc').upload
80
+ end
@@ -0,0 +1,67 @@
1
+ context 'Finder' do
2
+
3
+ specify 'database-specific load should not fail' do
4
+
5
+ DataMapper::database do |db|
6
+ froggy = db.find(Animal, :first, :conditions => ['name = ?', 'Frog'])
7
+ froggy.name.should == 'Frog'
8
+ end
9
+
10
+ end
11
+
12
+ specify 'current-database load should not fail' do
13
+ froggy = DataMapper::database.find(Animal, :first).name.should == 'Frog'
14
+ end
15
+
16
+ specify 'load through ActiveRecord impersonation should not fail' do
17
+ Animal.find(:all).size.should == 16
18
+ end
19
+
20
+ specify 'load through Og impersonation should not fail' do
21
+ Animal.all.size.should == 16
22
+ end
23
+
24
+ specify ':conditions option should accept a hash' do
25
+ Animal.all(:conditions => { :name => 'Frog' }).size.should == 1
26
+ end
27
+
28
+ specify 'non-standard options should be considered part of the conditions' do
29
+ database.log.debug('non-standard options should be considered part of the conditions')
30
+ zebra = Animal.first(:name => 'Zebra')
31
+ zebra.name.should == 'Zebra'
32
+
33
+ elephant = Animal[:name => 'Elephant']
34
+ elephant.name.should == 'Elephant'
35
+
36
+ aged = Person.all(:age => 29)
37
+ aged.size.should == 2
38
+ aged.first.name.should == 'Sam'
39
+ aged.last.name.should == 'Bob'
40
+
41
+ fixtures(:animals)
42
+ end
43
+
44
+ specify 'should not find deleted objects' do
45
+ database do
46
+ wally = Animal[:name => 'Whale']
47
+ wally.destroy!.should == true
48
+
49
+ wallys_evil_twin = Animal[:name => 'Whale']
50
+ wallys_evil_twin.should == nil
51
+
52
+ wally.new_record?.should == true
53
+ wally.save
54
+
55
+ Animal[:name => 'Whale'].should == wally
56
+ end
57
+ end
58
+
59
+ specify 'lazy-loads should issue for whole sets' do
60
+ people = Person.all
61
+
62
+ people.each do |person|
63
+ person.notes
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,47 @@
1
+ context 'An Exhibit' do
2
+
3
+ setup do
4
+ @aviary = Exhibit[:name => 'Monkey Mayhem']
5
+ end
6
+
7
+ specify 'has a zoo association' do
8
+ @aviary.zoo.class.should == Zoo
9
+ Exhibit.new.zoo.should == nil
10
+ end
11
+
12
+ specify 'belongs to a zoo' do
13
+ database do |db|
14
+ @aviary.zoo.should == @aviary.session.find(Zoo, :first, :name => 'San Diego')
15
+ end
16
+ end
17
+
18
+ specify 'can build its zoo' do
19
+ database do |db|
20
+ e = Exhibit.new({:name => 'Super Extra Crazy Monkey Cage'})
21
+ e.zoo.should == nil
22
+ e.build_zoo({:name => 'Monkey Zoo'})
23
+ e.zoo.class == Zoo
24
+ e.zoo.new_record?.should == true
25
+
26
+ # Need to get associations working properly before this works ....
27
+ e.save
28
+ end
29
+ end
30
+
31
+ specify 'can build its zoo' do
32
+ database do |db|
33
+ e = Exhibit.new({:name => 'Super Extra Crazy Monkey Cage'})
34
+ e.zoo.should == nil
35
+ e.create_zoo({:name => 'Monkey Zoo'})
36
+ e.zoo.class == Zoo
37
+ e.zoo.new_record?.should == false
38
+ e.save
39
+ end
40
+ end
41
+
42
+ teardown do
43
+ fixtures('zoos')
44
+ fixtures('exhibits')
45
+ end
46
+
47
+ end
@@ -0,0 +1,32 @@
1
+ - name: Frog
2
+ notes: I am a Frog!
3
+ - name: Bear
4
+ notes: I am a Bear!
5
+ - name: Giraffe
6
+ notes: I am a Giraffe!
7
+ - name: Zebra
8
+ notes: I am a Zebra!
9
+ - name: Cow
10
+ notes: I am a Cow!
11
+ - name: Pig
12
+ notes: I am a Pig!
13
+ - name: Cup
14
+ notes: I am a Cup!
15
+ - name: Cat
16
+ notes: I am a Cat!
17
+ - name: Dog
18
+ notes: I am a Dog!
19
+ - name: Elephant
20
+ notes: I am a Elephant!
21
+ - name: Whale
22
+ notes: I am a Whale!
23
+ - name: Dolphin
24
+ notes: I am a Dolphin!
25
+ - name: Mouse
26
+ notes: I am a Mouse!
27
+ - name: Rat
28
+ notes: I am a Rat!
29
+ - name: Camel
30
+ notes: I am a Camel!
31
+ - name: Fox
32
+ notes: I am a Fox!
@@ -0,0 +1,90 @@
1
+ - name: Horses & Courses
2
+ zoo_id: 1
3
+ - name: Aviary
4
+ zoo_id: 1
5
+ - name: Polar Planet
6
+ zoo_id: 2
7
+ - name: Monkey Mayhem
8
+ zoo_id: 2
9
+ - name: Amazonia
10
+ zoo_id: 3
11
+ - name: Deep Blue Ocean
12
+ zoo_id: 3
13
+ - name: Fish Fight!
14
+ zoo_id: 3
15
+ - name: The Dolphin Show
16
+ zoo_id: 3
17
+ - name: Canal Life
18
+ zoo_id: 4
19
+ - name: The Reptile Pit
20
+ zoo_id: 4
21
+ - name: Kangaroo Exhibit
22
+ zoo_id: 4
23
+ - name: A Million Years Ago...
24
+ zoo_id: 5
25
+ - name: The Wild West
26
+ zoo_id: 5
27
+ - name: Tumble Weeds
28
+ zoo_id: 5
29
+ - name: Missisipi Mud
30
+ zoo_id: 6
31
+ - name: Craw-Daddy's of the Deep!
32
+ zoo_id: 6
33
+ - name: The Littlest Big City
34
+ zoo_id: 7
35
+ - name: Jellyfish On Parade
36
+ zoo_id: 8
37
+ - name: Sea-Life Among the Rigs
38
+ zoo_id: 8
39
+ - name: Monsters of the Rainforest
40
+ zoo_id: 8
41
+ - name: So You Wanna Be A Street-Kid?
42
+ zoo_id: 9
43
+ - name: Don't Feed the Hippies!
44
+ zoo_id: 9
45
+ - name: At the Equator
46
+ zoo_id: 10
47
+ - name: River Habitats
48
+ zoo_id: 10
49
+ - name: A Fiesta of Plant-life
50
+ zoo_id: 10
51
+ - name: Smog World!
52
+ zoo_id: 11
53
+ - name: Where Are They Now? Extinct Species Edition
54
+ zoo_id: 11
55
+ - name: The Fragile Eco-System of the Cheese-Steak
56
+ zoo_id: 12
57
+ - name: Rats!
58
+ zoo_id: 13
59
+ - name: Penguins on Wall St.
60
+ zoo_id: 13
61
+ - name: King of the Jungle
62
+ zoo_id: 13
63
+ - name: The World's Fish-Market
64
+ zoo_id: 14
65
+ - name: Water-World
66
+ zoo_id: 14
67
+ - name: Micro-sized Soft-shelled Crabs
68
+ zoo_id: 14
69
+ - name: Do Animals Like Coffee?
70
+ zoo_id: 14
71
+ - name: On A Clear Day...
72
+ zoo_id: 15
73
+ - name: Twenty Thousand Leagues Under the Sky
74
+ zoo_id: 15
75
+ - name: Closed for Renovation
76
+ zoo_id: 16
77
+ - name: Ducks!
78
+ zoo_id: 17
79
+ - name: Retired Animal Life
80
+ zoo_id: 18
81
+ - name: The Clean Side of the Gulf
82
+ zoo_id: 18
83
+ - name: The Complete History of Rice
84
+ zoo_id: 19
85
+ - name: Safari World
86
+ zoo_id: 19
87
+ - name: Of Mice & Men
88
+ zoo_id: 20
89
+ - name: Snakes!
90
+ zoo_id: 20
@@ -0,0 +1,6 @@
1
+ - name: Kiwi
2
+ devourer_id: 5
3
+ - name: Pear
4
+ devourer_id: 11
5
+ - name: Watermelon
6
+ devourer_id: 7
@@ -0,0 +1,15 @@
1
+ - name: Sam
2
+ age: 29
3
+ occupation: Programmer
4
+ - name: Amy
5
+ age: 28
6
+ occupation: Business Analyst Manager
7
+ - name: Scott
8
+ age: 25
9
+ occupation: Programmer
10
+ - name: Josh
11
+ age: 23
12
+ occupation: Supervisor
13
+ - name: Bob
14
+ age: 29
15
+ occupation: Peon
@@ -0,0 +1,20 @@
1
+ - name: Dallas
2
+ - name: San Diego
3
+ - name: Miami
4
+ - name: Ft. Lauderdale
5
+ - name: Ft. Worth
6
+ - name: New Orleans
7
+ - name: San Antonio
8
+ - name: Galveston
9
+ - name: Austin
10
+ - name: Brownsville
11
+ - name: Los Angeles
12
+ - name: Phillidelphia
13
+ - name: New York
14
+ - name: Seattle
15
+ - name: Houston
16
+ - name: Corpus Christi
17
+ - name: Sacramento
18
+ - name: Pensacola
19
+ - name: Santa Francisco
20
+ - name: Orlando
@@ -0,0 +1,25 @@
1
+ # context 'An Exhibit' do
2
+ #
3
+ # setup do
4
+ # @amazonia = Exhibit[:name => 'Amazonia']
5
+ # end
6
+ #
7
+ # specify 'has an animals association' do
8
+ # [@amazonia, Exhibit.new].each do |exhibit|
9
+ # exhibit.animals.class.should == DataMapper::Associations::HasAndBelongsToManyAssociation
10
+ # end
11
+ # end
12
+ #
13
+ # specify 'has many animals' do
14
+ # @amazonia.animals.size.should == 2
15
+ # end
16
+ #
17
+ # specify 'should load associations magically' do
18
+ # Exhibit.all.each do |exhibit|
19
+ # exhibit.animals.each do |animal|
20
+ # animal.exhibits.should.include?(exhibit)
21
+ # end
22
+ # end
23
+ # end
24
+ #
25
+ # end
@@ -0,0 +1,34 @@
1
+ describe DataMapper::Associations::HasManyAssociation do
2
+
3
+ before(:all) do
4
+ fixtures(:zoos)
5
+ fixtures(:exhibits)
6
+
7
+ @san_diego = Zoo[:name => 'San Diego']
8
+ @dallas = Zoo[:name => 'Dallas']
9
+ @miami = Zoo[:name => 'Miami']
10
+ end
11
+
12
+ it 'should expose a proxy for the accessor' do
13
+ [@miami, Zoo.new].each do |z|
14
+ z.exhibits.class.should == DataMapper::Associations::HasManyAssociation
15
+ end
16
+ end
17
+
18
+ it 'should lazily-load the association when Enumerable methods are called' do
19
+ database do |db|
20
+ @san_diego.exhibits.size.should == 2
21
+ @san_diego.exhibits.should include(@san_diego.session.find(Exhibit, :first, :name => 'Monkey Mayhem'))
22
+ end
23
+ end
24
+
25
+ it 'should eager-load associations for an entire set' do
26
+ zoos = Zoo.all
27
+ zoos.each do |zoo|
28
+ zoo.exhibits.each do |exhibit|
29
+ exhibit.zoo.should == zoo
30
+ end
31
+ end
32
+ end
33
+
34
+ end