dm-core 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CONTRIBUTING +51 -0
  2. data/FAQ +26 -8
  3. data/Manifest.txt +2 -0
  4. data/Rakefile +2 -1
  5. data/lib/dm-core.rb +8 -3
  6. data/lib/dm-core/adapters/abstract_adapter.rb +2 -2
  7. data/lib/dm-core/adapters/data_objects_adapter.rb +18 -4
  8. data/lib/dm-core/adapters/mysql_adapter.rb +8 -4
  9. data/lib/dm-core/adapters/postgres_adapter.rb +12 -3
  10. data/lib/dm-core/adapters/sqlite3_adapter.rb +1 -1
  11. data/lib/dm-core/associations.rb +1 -0
  12. data/lib/dm-core/associations/many_to_one.rb +7 -1
  13. data/lib/dm-core/associations/one_to_many.rb +1 -1
  14. data/lib/dm-core/associations/relationship.rb +14 -13
  15. data/lib/dm-core/auto_migrations.rb +57 -5
  16. data/lib/dm-core/collection.rb +2 -1
  17. data/lib/dm-core/logger.rb +5 -6
  18. data/lib/dm-core/model.rb +17 -2
  19. data/lib/dm-core/naming_conventions.rb +57 -25
  20. data/lib/dm-core/property.rb +6 -5
  21. data/lib/dm-core/query.rb +20 -16
  22. data/lib/dm-core/resource.rb +24 -7
  23. data/lib/dm-core/version.rb +1 -1
  24. data/script/performance.rb +2 -1
  25. data/script/profile.rb +1 -0
  26. data/spec/integration/association_spec.rb +131 -81
  27. data/spec/integration/association_through_spec.rb +87 -42
  28. data/spec/integration/associations/many_to_many_spec.rb +76 -16
  29. data/spec/integration/associations/many_to_one_spec.rb +6 -1
  30. data/spec/integration/associations/one_to_many_spec.rb +69 -0
  31. data/spec/integration/collection_spec.rb +7 -0
  32. data/spec/integration/query_spec.rb +24 -7
  33. data/spec/integration/resource_spec.rb +59 -10
  34. data/spec/integration/sti_spec.rb +23 -0
  35. data/spec/models/zoo.rb +2 -3
  36. data/spec/spec_helper.rb +9 -1
  37. data/spec/unit/adapters/postgres_adapter_spec.rb +9 -1
  38. data/spec/unit/associations/many_to_one_spec.rb +6 -0
  39. data/spec/unit/auto_migrations_spec.rb +2 -1
  40. data/spec/unit/naming_conventions_spec.rb +26 -18
  41. data/spec/unit/property_spec.rb +3 -4
  42. data/spec/unit/resource_spec.rb +19 -22
  43. data/tasks/gemspec.rb +23 -0
  44. data/tasks/hoe.rb +9 -1
  45. metadata +6 -14
@@ -7,15 +7,15 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
7
7
 
8
8
  if ADAPTER
9
9
  describe "DataMapper::Resource with #{ADAPTER}" do
10
-
10
+
11
11
  load_models_for_metaphor :zoo
12
-
12
+
13
13
  before(:each) do
14
14
  DataMapper.auto_migrate!(ADAPTER)
15
15
  @zoo = Zoo.new(:name => "San Francisco")
16
16
  repository(ADAPTER) { @zoo.save }
17
17
  end
18
-
18
+
19
19
  # --- Move somewhere ----
20
20
  it "should be able to destroy objects" do
21
21
  lambda { @zoo.destroy.should be_true }.should_not raise_error
@@ -47,7 +47,7 @@ if ADAPTER
47
47
  zoo.name = "San Francisco"
48
48
  end
49
49
  end
50
-
50
+
51
51
  describe '#eql?' do
52
52
  it "should return true if the objects are the same instances"
53
53
  it "should return false if the other object is not an instance of the same model"
@@ -56,19 +56,68 @@ if ADAPTER
56
56
  it "should return true if all the properties are the same"
57
57
  it "should return false if any of the properties are different"
58
58
  end
59
-
59
+
60
+ describe '#hash' do
61
+ it "should return the same hash values for unsaved objects that are equal" do
62
+ e1 = Employee.new(:name => "John")
63
+ e2 = Employee.new(:name => "John")
64
+ e1.hash.should == e2.hash
65
+ end
66
+
67
+ it "should return the same hash values for saved objects that are equal" do
68
+ # Make sure that the object_id's are not the same
69
+ e1 = e2 = nil
70
+ repository(ADAPTER) do
71
+ e1 = Employee.create(:name => "John")
72
+ end
73
+ repository(ADAPTER) do
74
+ e2 = Employee.get("John")
75
+ end
76
+ e1.hash.should == e2.hash
77
+ end
78
+
79
+ it "should return a different hash value for different objects of the same type" do
80
+ e1 = Employee.create(:name => "John")
81
+ e2 = Employee.create(:name => "Dan")
82
+ e1.hash.should_not == e2.hash
83
+ end
84
+
85
+ it "should return a different hash value for different types of objects with the same key"
86
+ end
87
+
60
88
  describe '#id' do
61
89
  it "should be awesome"
62
90
  end
63
-
91
+
64
92
  describe '#inspect' do
65
93
  it "should return a string representing the object"
66
94
  end
67
-
95
+
68
96
  describe '#key' do
69
- it "should be awesome"
97
+ describe "original_value[:key]" do
98
+ it "should be used when an existing resource's key changes" do
99
+ employee = Employee.create(:name => "John")
100
+ employee.name = "Jon"
101
+ employee.key.should == ["John"]
102
+ end
103
+
104
+ it "should be used when saving an existing resource" do
105
+ repository(ADAPTER) do
106
+ employee = Employee.create(:name => "John")
107
+ employee.name = "Jon"
108
+ employee.save.should == true
109
+ Employee.get("Jon").should == employee
110
+ end
111
+ end
112
+
113
+ it "should not be used when a new resource's key changes" do
114
+ employee = Employee.new(:name => "John")
115
+ employee.name = "Jon"
116
+ employee.key.should == ["Jon"]
117
+ end
118
+ end
70
119
  end
71
-
120
+
72
121
  describe '#pretty_print' do
73
122
  it "should display a pretty version of inspect"
74
123
  end
@@ -86,7 +135,7 @@ if ADAPTER
86
135
  end
87
136
 
88
137
  end
89
-
138
+
90
139
  describe '#repository' do
91
140
  it "should return the repository associated with the object if there is one"
92
141
  it "should return the repository associated with the model if the object doesn't have one"
@@ -38,6 +38,29 @@ if HAS_SQLITE3
38
38
  end
39
39
  end
40
40
 
41
+ describe "with the identity map" do
42
+ before :all do
43
+ Book.auto_migrate!(:sqlite3)
44
+ repository(:sqlite3) do
45
+ Propaganda.create(:title => "Something", :isbn => "129038")
46
+ end
47
+ end
48
+
49
+ it "should find the base model in the identity map" do
50
+ repository(:sqlite3) do
51
+ book = Book.first
52
+ book.object_id.should == Propaganda.first.object_id
53
+ end
54
+ end
55
+
56
+ it "should find the child model in the identity map" do
57
+ repository(:sqlite3) do
58
+ book = Propaganda.first
59
+ book.object_id.should == Book.first.object_id
60
+ end
61
+ end
62
+ end
63
+
41
64
  describe "with a parent class" do
42
65
  before :all do
43
66
  Book.auto_migrate!(:sqlite3).should be_true
data/spec/models/zoo.rb CHANGED
@@ -9,7 +9,7 @@ class Zoo
9
9
  property :size, Integer
10
10
 
11
11
  has n, :animals
12
-
12
+
13
13
  def to_s
14
14
  name
15
15
  end
@@ -39,8 +39,7 @@ end
39
39
  class Employee
40
40
  include DataMapper::Resource
41
41
 
42
- property :id, Serial
43
- property :name, String
42
+ property :name, String, :key => true
44
43
  end
45
44
 
46
45
  class Keeper < Employee
data/spec/spec_helper.rb CHANGED
@@ -16,6 +16,14 @@ end
16
16
  DataMapper.setup(repository_name, "mock://localhost/#{repository_name}")
17
17
  end
18
18
 
19
+ # These environment variables will override the default connection string:
20
+ # MYSQL_SPEC_URI
21
+ # POSTGRES_SPEC_URI
22
+ # SQLITE3_SPEC_URI
23
+ #
24
+ # For example, in the bash shell, you might use:
25
+ # export MYSQL_SPEC_URI="mysql://localhost/dm_core_test?socket=/opt/local/var/run/mysql5/mysqld.sock"
26
+ #
19
27
  def setup_adapter(name, default_uri)
20
28
  begin
21
29
  DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
@@ -66,7 +74,7 @@ end
66
74
 
67
75
  class Comment
68
76
  include DataMapper::Resource
69
-
77
+
70
78
  property :id, Serial # blah
71
79
  end
72
80
 
@@ -115,9 +115,17 @@ if HAS_POSTGRES
115
115
  end
116
116
  end
117
117
 
118
- it 'should execute the superclass destroy_model_storage' do
118
+ it 'should not execute the superclass destroy_model_storage if the storage does not exist' do
119
119
  rv = mock('inside super')
120
120
  @adapter.class.superclass.send(:define_method, :destroy_model_storage) { rv }
121
+ @adapter.destroy_model_storage(@repository, @model).should_not == rv
122
+ end
123
+
124
+ it 'should execute the superclass destroy_model_storage if the storage exists' do
125
+ rv = mock('inside super')
126
+ @adapter.class.superclass.send(:define_method, :destroy_model_storage) { rv }
127
+ @adapter.stub!(:storage_exists?).and_return(true)
128
+
121
129
  @adapter.destroy_model_storage(@repository, @model).should == rv
122
130
  end
123
131
  end
@@ -101,7 +101,13 @@ describe DataMapper::Associations::ManyToOne::Proxy do
101
101
  end
102
102
 
103
103
  it 'should return the result of the save' do
104
+ child_key = mock("child_key")
105
+ child_key.should_receive(:set).and_return(true)
106
+ parent_key = mock("parent_key")
107
+ parent_key.should_receive(:get).and_return(1)
104
108
  @relationship.should_receive(:with_repository).and_yield(@repository)
109
+ @relationship.should_receive(:child_key).and_return(child_key)
110
+ @relationship.should_receive(:parent_key).and_return(parent_key)
105
111
  save_results = mock('save results')
106
112
  @parent.should_receive(:save).with(no_args).and_return(save_results)
107
113
  @association.save.object_id.should == save_results.object_id
@@ -85,7 +85,8 @@ describe DataMapper::AutoMigrations do
85
85
 
86
86
  models.each do |model|
87
87
  DataMapper::Resource.descendants << model
88
- model.should_receive(:auto_migrate!).with(@repository_name)
88
+ model.should_receive(:auto_migrate_down!).with(@repository_name)
89
+ model.should_receive(:auto_migrate_up!).with(@repository_name)
89
90
  end
90
91
 
91
92
  DataMapper::AutoMigrator.auto_migrate(@repository_name)
@@ -1,28 +1,36 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
2
 
3
3
  describe "DataMapper::NamingConventions" do
4
- it "should coerce a string into the Underscored convention" do
5
- DataMapper::NamingConventions::Underscored.call('User').should == 'user'
6
- DataMapper::NamingConventions::Underscored.call('UserAccountSetting').should == 'user_account_setting'
7
- end
4
+ describe "Resource" do
5
+ it "should coerce a string into the Underscored convention" do
6
+ DataMapper::NamingConventions::Resource::Underscored.call('User').should == 'user'
7
+ DataMapper::NamingConventions::Resource::Underscored.call('UserAccountSetting').should == 'user_account_setting'
8
+ end
8
9
 
9
- it "should coerce a string into the UnderscoredAndPluralized convention" do
10
- DataMapper::NamingConventions::UnderscoredAndPluralized.call('User').should == 'users'
11
- DataMapper::NamingConventions::UnderscoredAndPluralized.call('UserAccountSetting').should == 'user_account_settings'
12
- end
10
+ it "should coerce a string into the UnderscoredAndPluralized convention" do
11
+ DataMapper::NamingConventions::Resource::UnderscoredAndPluralized.call('User').should == 'users'
12
+ DataMapper::NamingConventions::Resource::UnderscoredAndPluralized.call('UserAccountSetting').should == 'user_account_settings'
13
+ end
13
14
 
14
- it "should coerce a string into the UnderscoredAndPluralized convention joining namespace with underscore" do
15
- DataMapper::NamingConventions::UnderscoredAndPluralized.call('Model::User').should == 'model_users'
16
- DataMapper::NamingConventions::UnderscoredAndPluralized.call('Model::UserAccountSetting').should == 'model_user_account_settings'
17
- end
15
+ it "should coerce a string into the UnderscoredAndPluralized convention joining namespace with underscore" do
16
+ DataMapper::NamingConventions::Resource::UnderscoredAndPluralized.call('Model::User').should == 'model_users'
17
+ DataMapper::NamingConventions::Resource::UnderscoredAndPluralized.call('Model::UserAccountSetting').should == 'model_user_account_settings'
18
+ end
19
+
20
+ it "should coerce a string into the UnderscoredAndPluralizedWithoutModule convention" do
21
+ DataMapper::NamingConventions::Resource::UnderscoredAndPluralizedWithoutModule.call('Model::User').should == 'users'
22
+ DataMapper::NamingConventions::Resource::UnderscoredAndPluralizedWithoutModule.call('Model::UserAccountSetting').should == 'user_account_settings'
23
+ end
18
24
 
19
- it "should coerce a string into the UnderscoredAndPluralizedWithoutModule convention" do
20
- DataMapper::NamingConventions::UnderscoredAndPluralizedWithoutModule.call('Model::User').should == 'users'
21
- DataMapper::NamingConventions::UnderscoredAndPluralizedWithoutModule.call('Model::UserAccountSetting').should == 'user_account_settings'
25
+ it "should coerce a string into the Yaml convention" do
26
+ DataMapper::NamingConventions::Resource::Yaml.call('UserSetting').should == 'user_settings.yaml'
27
+ DataMapper::NamingConventions::Resource::Yaml.call('User').should == 'users.yaml'
28
+ end
22
29
  end
23
30
 
24
- it "should coerce a string into the Yaml convention" do
25
- DataMapper::NamingConventions::Yaml.call('UserSetting').should == 'user_settings.yaml'
26
- DataMapper::NamingConventions::Yaml.call('User').should == 'users.yaml'
31
+ describe "Field" do
32
+ it "should accept a property as input" do
33
+ DataMapper::NamingConventions::Field::Underscored.call(Article.blog_id).should == 'blog_id'
34
+ end
27
35
  end
28
36
  end
@@ -292,10 +292,9 @@ describe DataMapper::Property do
292
292
  Potato.new().should respond_to(:public?)
293
293
  end
294
294
 
295
- it "should raise an ArgumentError when created with an invalid option" do
296
- lambda{
297
- DataMapper::Property.new(Tomato,:botanical_name,String,{:foo=>:bar})
298
- }.should raise_error(ArgumentError)
295
+ it "should move unknown options into Property#extra_options" do
296
+ d = DataMapper::Property.new(Tomato,:botanical_name,String,{:foo=>:bar})
297
+ d.extra_options.should == {:foo => :bar}
299
298
  end
300
299
 
301
300
  it 'should return the attribute value from a given instance' do
@@ -1,9 +1,6 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
2
 
3
- # rSpec completely FUBARs everything if you give it a Module here.
4
- # So we give it a String of the module name instead.
5
- # DO NOT CHANGE THIS!
6
- describe "DataMapper::Resource" do
3
+ describe DataMapper::Resource do
7
4
 
8
5
  load_models_for_metaphor :zoo
9
6
 
@@ -72,20 +69,6 @@ class Planet
72
69
  end
73
70
  end
74
71
 
75
- class BlackHole
76
- include DataMapper::Resource
77
-
78
- property :id, Integer, :key => true
79
- property :data, Object, :reader => :private
80
- end
81
-
82
- class LegacyStar
83
- include DataMapper::Resource
84
- def self.default_repository_name
85
- :legacy
86
- end
87
- end
88
-
89
72
  class Phone
90
73
  include DataMapper::Resource
91
74
 
@@ -124,10 +107,7 @@ class Cyclist
124
107
  property :victories, Integer
125
108
  end
126
109
 
127
- # rSpec completely FUBARs everything if you give it a Module here.
128
- # So we give it a String of the module name instead.
129
- # DO NOT CHANGE THIS!
130
- describe "DataMapper::Resource" do
110
+ describe DataMapper::Resource do
131
111
 
132
112
  it 'should provide #save' do
133
113
  Planet.new.should respond_to(:save)
@@ -328,6 +308,23 @@ describe "DataMapper::Resource" do
328
308
  jupiter.attributes.should == attributes.merge(new_age)
329
309
  end
330
310
 
311
+ # Illustrates a possible controller situation, where an expected params
312
+ # key does not exist.
313
+ it "update_attributes(nil) should raise an exception" do
314
+ hincapie = Cyclist.new
315
+ params = {}
316
+ lambda {
317
+ hincapie.update_attributes(params[:does_not_exist])
318
+ }.should raise_error(ArgumentError)
319
+ end
320
+
321
+ it "update_attributes(:not_a_hash) should raise an exception" do
322
+ hincapie = Cyclist.new
323
+ lambda {
324
+ hincapie.update_attributes(:not_a_hash).should be_false
325
+ }.should raise_error(ArgumentError)
326
+ end
327
+
331
328
  # :core is a private accessor so Ruby should raise NameError
332
329
  it "should not be able to set private attributes" do
333
330
  lambda {
data/tasks/gemspec.rb ADDED
@@ -0,0 +1,23 @@
1
+ desc "Generate gemspec"
2
+ task :gemspec do |x|
3
+ # Clean up extraneous files before checking manifest
4
+ %x[rake clean]
5
+
6
+ # Check the manifest before generating the gemspec
7
+ manifest = %x[rake check_manifest]
8
+ manifest.gsub!("(in /usr/local/projects/dm/dm-core)\n", "")
9
+
10
+ unless manifest.empty?
11
+ print "\n", "#"*68, "\n"
12
+ print <<-EOS
13
+ Manifest.txt is not up-to-date. Please review the changes below.
14
+ If the changes are correct, run 'rake check_manifest | patch'
15
+ and then run this command again.
16
+ EOS
17
+ print "#"*68, "\n\n"
18
+ puts manifest
19
+ else
20
+ %x[rake debug_gem > #{GEM_NAME}.gemspec]
21
+ puts "Successfully created gemspec for #{GEM_NAME}!"
22
+ end
23
+ end
data/tasks/hoe.rb CHANGED
@@ -19,6 +19,14 @@ Run 'rubyforge setup' to prepare your env for access to Rubyforge
19
19
  RUBYFORGE_USERNAME.replace @config["username"]
20
20
  end
21
21
 
22
+ # Remove hoe dependency
23
+ class Hoe
24
+ def extra_dev_deps
25
+ @extra_dev_deps.reject! { |dep| dep[0] == "hoe" }
26
+ @extra_dev_deps
27
+ end
28
+ end
29
+
22
30
  hoe = Hoe.new(GEM_NAME, GEM_VERSION) do |p|
23
31
 
24
32
  p.developer(AUTHOR, EMAIL)
@@ -29,7 +37,7 @@ hoe = Hoe.new(GEM_NAME, GEM_VERSION) do |p|
29
37
 
30
38
  p.rubyforge_name = PROJECT_NAME if PROJECT_NAME
31
39
 
32
- p.clean_globs |= ["{coverage,doc,log}/", "**/*.db", "profile_results.*", "**/.*.sw?", "*.gem", ".config", "**/.DS_Store"]
40
+ p.clean_globs |= ["{coverage,doc,log,tmp}", "**/*.{log,db}", "profile_results.*", "**/.DS_Store"]
33
41
 
34
42
  GEM_DEPENDENCIES.each do |dep|
35
43
  p.extra_deps << dep
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Smoot
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-07-24 00:00:00 -05:00
12
+ date: 2008-08-21 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - "="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.9.3
23
+ version: 0.9.4
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: extlib
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - "="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.9.3
33
+ version: 0.9.4
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rspec
@@ -52,16 +52,6 @@ dependencies:
52
52
  - !ruby/object:Gem::Version
53
53
  version: 1.0.4
54
54
  version:
55
- - !ruby/object:Gem::Dependency
56
- name: hoe
57
- type: :development
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- version: 1.7.0
64
- version:
65
55
  description: Faster, Better, Simpler.
66
56
  email:
67
57
  - ssmoot@gmail.com
@@ -75,6 +65,7 @@ extra_rdoc_files:
75
65
  - README.txt
76
66
  files:
77
67
  - .autotest
68
+ - CONTRIBUTING
78
69
  - FAQ
79
70
  - History.txt
80
71
  - MIT-LICENSE
@@ -195,6 +186,7 @@ files:
195
186
  - tasks/ci.rb
196
187
  - tasks/dm.rb
197
188
  - tasks/doc.rb
189
+ - tasks/gemspec.rb
198
190
  - tasks/hoe.rb
199
191
  - tasks/install.rb
200
192
  has_rdoc: true