dm-core 0.9.8 → 0.9.9

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.
@@ -1,3 +1,14 @@
1
+ === 0.9.9 / 2009-01-04
2
+
3
+ * 1 minor enhancement:
4
+
5
+ * Updated Resource and Collection to be serializable with Marshal
6
+
7
+ * 1 bug fix:
8
+
9
+ * Fixed Model#copy to copy properties that are the same in both
10
+ repositories.
11
+
1
12
  === 0.9.8 / 2008-12-07
2
13
 
3
14
  * 3 minor enhancements:
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ AUTHOR = "Sam Smoot"
13
13
  EMAIL = "ssmoot@gmail.com"
14
14
  GEM_NAME = "dm-core"
15
15
  GEM_VERSION = DataMapper::VERSION
16
- GEM_DEPENDENCIES = ["data_objects", "~>0.9.9"],
16
+ GEM_DEPENDENCIES = ["data_objects", "~>0.9.10"],
17
17
  ["extlib", "~>0.9.9"],
18
18
  ["addressable", "~>2.0.1"]
19
19
 
@@ -1,12 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{dm-core}
3
- s.version = '0.9.8'
3
+ s.version = '0.9.9'
4
4
 
5
5
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
- s.authors = ["Sam Smoot"]
7
- s.date = %q{2008-07-24}
6
+ s.authors = ["Dan Kubb"]
7
+ s.date = %q{2009-01-04}
8
8
  s.description = %q{Faster, Better, Simpler!}
9
- s.email = ["ssmoot@gmail.com"]
9
+ s.email = ["dan.kubb@gmail.com"]
10
10
  s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
11
11
  s.files = [".autotest", "CONTRIBUTING", "FAQ", "History.txt", "MIT-LICENSE", "Manifest.txt", "QUICKLINKS", "README.txt", "Rakefile", "SPECS", "TODO", "lib/dm-core.rb", "lib/dm-core/adapters.rb", "lib/dm-core/adapters/abstract_adapter.rb", "lib/dm-core/adapters/data_objects_adapter.rb", "lib/dm-core/adapters/mysql_adapter.rb", "lib/dm-core/adapters/postgres_adapter.rb", "lib/dm-core/adapters/sqlite3_adapter.rb", "lib/dm-core/associations.rb", "lib/dm-core/associations/many_to_many.rb", "lib/dm-core/associations/many_to_one.rb", "lib/dm-core/associations/one_to_many.rb", "lib/dm-core/associations/one_to_one.rb", "lib/dm-core/associations/relationship.rb", "lib/dm-core/associations/relationship_chain.rb", "lib/dm-core/auto_migrations.rb", "lib/dm-core/collection.rb", "lib/dm-core/dependency_queue.rb", "lib/dm-core/hook.rb", "lib/dm-core/identity_map.rb", "lib/dm-core/is.rb", "lib/dm-core/logger.rb", "lib/dm-core/migrations/destructive_migrations.rb", "lib/dm-core/migrator.rb", "lib/dm-core/model.rb", "lib/dm-core/naming_conventions.rb", "lib/dm-core/property.rb", "lib/dm-core/property_set.rb", "lib/dm-core/query.rb", "lib/dm-core/repository.rb", "lib/dm-core/resource.rb", "lib/dm-core/scope.rb", "lib/dm-core/support.rb", "lib/dm-core/support/array.rb", "lib/dm-core/support/assertions.rb", "lib/dm-core/support/errors.rb", "lib/dm-core/support/kernel.rb", "lib/dm-core/support/symbol.rb", "lib/dm-core/transaction.rb", "lib/dm-core/type.rb", "lib/dm-core/type_map.rb", "lib/dm-core/types.rb", "lib/dm-core/types/boolean.rb", "lib/dm-core/types/discriminator.rb", "lib/dm-core/types/object.rb", "lib/dm-core/types/paranoid_boolean.rb", "lib/dm-core/types/paranoid_datetime.rb", "lib/dm-core/types/serial.rb", "lib/dm-core/types/text.rb", "lib/dm-core/version.rb", "script/all", "script/performance.rb", "script/profile.rb", "spec/integration/association_spec.rb", "spec/integration/association_through_spec.rb", "spec/integration/associations/many_to_many_spec.rb", "spec/integration/associations/many_to_one_spec.rb", "spec/integration/associations/one_to_many_spec.rb", "spec/integration/auto_migrations_spec.rb", "spec/integration/collection_spec.rb", "spec/integration/data_objects_adapter_spec.rb", "spec/integration/dependency_queue_spec.rb", "spec/integration/model_spec.rb", "spec/integration/mysql_adapter_spec.rb", "spec/integration/postgres_adapter_spec.rb", "spec/integration/property_spec.rb", "spec/integration/query_spec.rb", "spec/integration/repository_spec.rb", "spec/integration/resource_spec.rb", "spec/integration/sqlite3_adapter_spec.rb", "spec/integration/sti_spec.rb", "spec/integration/strategic_eager_loading_spec.rb", "spec/integration/transaction_spec.rb", "spec/integration/type_spec.rb", "spec/lib/logging_helper.rb", "spec/lib/mock_adapter.rb", "spec/lib/model_loader.rb", "spec/lib/publicize_methods.rb", "spec/models/vehicles.rb", "spec/models/zoo.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/adapters/abstract_adapter_spec.rb", "spec/unit/adapters/adapter_shared_spec.rb", "spec/unit/adapters/data_objects_adapter_spec.rb", "spec/unit/adapters/postgres_adapter_spec.rb", "spec/unit/associations/many_to_many_spec.rb", "spec/unit/associations/many_to_one_spec.rb", "spec/unit/associations/one_to_many_spec.rb", "spec/unit/associations/one_to_one_spec.rb", "spec/unit/associations/relationship_spec.rb", "spec/unit/associations_spec.rb", "spec/unit/auto_migrations_spec.rb", "spec/unit/collection_spec.rb", "spec/unit/data_mapper_spec.rb", "spec/unit/identity_map_spec.rb", "spec/unit/is_spec.rb", "spec/unit/migrator_spec.rb", "spec/unit/model_spec.rb", "spec/unit/naming_conventions_spec.rb", "spec/unit/property_set_spec.rb", "spec/unit/property_spec.rb", "spec/unit/query_spec.rb", "spec/unit/repository_spec.rb", "spec/unit/resource_spec.rb", "spec/unit/scope_spec.rb", "spec/unit/transaction_spec.rb", "spec/unit/type_map_spec.rb", "spec/unit/type_spec.rb", "tasks/ci.rb", "tasks/dm.rb", "tasks/doc.rb", "tasks/gemspec.rb", "tasks/hoe.rb", "tasks/install.rb"]
12
12
  s.has_rdoc = true
@@ -22,16 +22,16 @@ Gem::Specification.new do |s|
22
22
  s.specification_version = 2
23
23
 
24
24
  if current_version >= 3 then
25
- s.add_runtime_dependency(%q<data_objects>, ["~> 0.9.9"])
25
+ s.add_runtime_dependency(%q<data_objects>, ["~> 0.9.10"])
26
26
  s.add_runtime_dependency(%q<extlib>, ["~> 0.9.9"])
27
27
  s.add_runtime_dependency(%q<addressable>, ["~> 2.0.1"])
28
28
  else
29
- s.add_dependency(%q<data_objects>, ["~> 0.9.9"])
29
+ s.add_dependency(%q<data_objects>, ["~> 0.9.10"])
30
30
  s.add_dependency(%q<extlib>, ["~> 0.9.9"])
31
31
  s.add_dependency(%q<addressable>, ["~> 2.0.1"])
32
32
  end
33
33
  else
34
- s.add_dependency(%q<data_objects>, ["~> 0.9.9"])
34
+ s.add_dependency(%q<data_objects>, ["~> 0.9.10"])
35
35
  s.add_dependency(%q<extlib>, ["~> 0.9.9"])
36
36
  s.add_dependency(%q<addressable>, ["~> 2.0.1"])
37
37
  end
@@ -1,4 +1,4 @@
1
- gem 'data_objects', '~>0.9.9'
1
+ gem 'data_objects', '~>0.9.10'
2
2
  require 'data_objects'
3
3
 
4
4
  module DataMapper
@@ -1,4 +1,4 @@
1
- gem 'do_mysql', '~>0.9.9'
1
+ gem 'do_mysql', '~>0.9.10'
2
2
  require 'do_mysql'
3
3
 
4
4
  module DataMapper
@@ -1,4 +1,4 @@
1
- gem 'do_postgres', '~>0.9.9'
1
+ gem 'do_postgres', '~>0.9.10'
2
2
  require 'do_postgres'
3
3
 
4
4
  module DataMapper
@@ -1,4 +1,4 @@
1
- gem 'do_sqlite3', '~>0.9.9'
1
+ gem 'do_sqlite3', '~>0.9.10'
2
2
  require 'do_sqlite3'
3
3
 
4
4
  module DataMapper
@@ -494,6 +494,32 @@ module DataMapper
494
494
  super || model.public_methods(false).include?(method.to_s) || relationships.has_key?(method)
495
495
  end
496
496
 
497
+ # TODO: add docs
498
+ # @api private
499
+ def _dump(*)
500
+ Marshal.dump([ query, to_a ])
501
+ end
502
+
503
+ # TODO: add docs
504
+ # @api private
505
+ def self._load(marshalled)
506
+ query, array = Marshal.load(marshalled)
507
+
508
+ # XXX: IMHO it is a code smell to be forced to use allocate
509
+ # and instance_variable_set to load an object. You should
510
+ # be able to use a constructor to provide all the info needed
511
+ # to initialize an object. This should be fixed in the edge
512
+ # branch dkubb/dm-core
513
+
514
+ collection = allocate
515
+ collection.instance_variable_set(:@query, query)
516
+ collection.instance_variable_set(:@array, array)
517
+ collection.instance_variable_set(:@loaded, true)
518
+ collection.instance_variable_set(:@key_properties, collection.send(:model).key(collection.repository.name))
519
+ collection.instance_variable_set(:@cache, {})
520
+ collection
521
+ end
522
+
497
523
  protected
498
524
 
499
525
  ##
@@ -306,11 +306,30 @@ module DataMapper
306
306
  resource
307
307
  end
308
308
 
309
- # TODO SPEC
309
+ ##
310
+ # Copy a set of records from one repository to another.
311
+ #
312
+ # @param [String] source
313
+ # The name of the Repository the resources should be copied _from_
314
+ # @param [String] destination
315
+ # The name of the Repository the resources should be copied _to_
316
+ # @param [Hash] query
317
+ # The conditions with which to find the records to copy. These
318
+ # conditions are merged with Model.query
319
+ #
320
+ # @return [DataMapper::Collection]
321
+ # A Collection of the Resource instances created in the operation
322
+ #
323
+ # @api public
310
324
  def copy(source, destination, query = {})
325
+
326
+ # get the list of properties that exist in the source and destination
327
+ destination_properties = properties(destination)
328
+ fields = query[:fields] ||= properties(source).select { |p| destination_properties.has_property?(p.name) }
329
+
311
330
  repository(destination) do
312
- repository(source).read_many(scoped_query(query)).each do |resource|
313
- self.create(resource.attributes)
331
+ all(query.merge(:repository => repository(source))).map do |resource|
332
+ create(fields.map { |p| [ p.name, p.get(resource) ] }.to_hash)
314
333
  end
315
334
  end
316
335
  end
@@ -366,6 +385,13 @@ module DataMapper
366
385
  Query.new(repository, self, query.merge(conditions))
367
386
  end
368
387
 
388
+ # TODO: add docs
389
+ # @api private
390
+ def _load(marshalled)
391
+ repository_name, attributes = Marshal.load(marshalled)
392
+ repository(repository_name) { new(attributes) }
393
+ end
394
+
369
395
  def typecast_key(key)
370
396
  self.key(repository_name).zip(key).map { |k, v| k.typecast(v) }
371
397
  end
@@ -512,6 +512,19 @@ module DataMapper
512
512
  "#<Property:#{@model}:#{@name}>"
513
513
  end
514
514
 
515
+ # TODO: add docs
516
+ # @api private
517
+ def _dump(*)
518
+ Marshal.dump([ repository, model, name ])
519
+ end
520
+
521
+ # TODO: add docs
522
+ # @api private
523
+ def self._load(marshalled)
524
+ repository, model, name = Marshal.load(marshalled)
525
+ model.properties(repository.name)[name]
526
+ end
527
+
515
528
  private
516
529
 
517
530
  def initialize(model, name, type, options = {})
@@ -151,6 +151,55 @@ module DataMapper
151
151
  "#<#{self.class.name} #{attrs.map { |(k,v)| "@#{k}=#{v.inspect}" } * ' '}>"
152
152
  end
153
153
 
154
+ # TODO: add docs
155
+ # @api public
156
+ def to_hash
157
+ hash = {
158
+ :reload => reload?,
159
+ :unique => unique?,
160
+ :offset => offset,
161
+ :order => order,
162
+ :add_reversed => add_reversed?,
163
+ :fields => fields,
164
+ }
165
+
166
+ hash[:limit] = limit unless limit == nil
167
+ hash[:links] = links unless links == []
168
+ hash[:includes] = includes unless includes == []
169
+
170
+ conditions = {}
171
+ raw_queries = []
172
+ bind_values = []
173
+
174
+ conditions.each do |condition|
175
+ if condition[0] == :raw
176
+ raw_queries << condition[1]
177
+ bind_values << condition[2]
178
+ else
179
+ operator, property, bind_value = condition
180
+ conditions[ Query::Operator.new(property, operator) ] = bind_value
181
+ end
182
+ end
183
+
184
+ if raw_queries.any?
185
+ hash[:conditions] = [ raw_queries.join(' ') ].concat(bind_values)
186
+ end
187
+
188
+ hash.update(conditions)
189
+ end
190
+
191
+ # TODO: add docs
192
+ # @api private
193
+ def _dump(*)
194
+ Marshal.dump([ repository, model, to_hash ])
195
+ end
196
+
197
+ # TODO: add docs
198
+ # @api private
199
+ def self._load(marshalled)
200
+ new(*Marshal.load(marshalled))
201
+ end
202
+
154
203
  private
155
204
 
156
205
  def initialize(repository, model, options = {})
@@ -91,6 +91,14 @@ module DataMapper
91
91
  "#<DataMapper::Repository:#{@name}>"
92
92
  end
93
93
 
94
+ def _dump(*)
95
+ name.to_s
96
+ end
97
+
98
+ def self._load(marshalled)
99
+ new(marshalled.to_sym)
100
+ end
101
+
94
102
  private
95
103
 
96
104
  def initialize(name)
@@ -528,6 +528,19 @@ module DataMapper
528
528
  model.to_query(repository, key, query) unless new_record?
529
529
  end
530
530
 
531
+ # TODO: add docs
532
+ # @api private
533
+ def _dump(*)
534
+ repository_name = repository.name
535
+ attributes = {}
536
+
537
+ model.properties(repository_name).slice(*loaded_attributes).compact.each do |property|
538
+ attributes[property.name] = property.get(self) if property.writer_visibility == :public
539
+ end
540
+
541
+ Marshal.dump([ repository_name, attributes ])
542
+ end
543
+
531
544
  protected
532
545
 
533
546
  def properties
@@ -1,3 +1,3 @@
1
1
  module DataMapper
2
- VERSION = '0.9.8' unless defined?(DataMapper::VERSION)
2
+ VERSION = '0.9.9' unless defined?(DataMapper::VERSION)
3
3
  end
@@ -127,6 +127,10 @@ if ADAPTER
127
127
  results.first.should == bob
128
128
  end
129
129
 
130
+ it 'should be serializable with Marshal' do
131
+ Marshal.load(Marshal.dump(Zebra.all)).should == Zebra.all
132
+ end
133
+
130
134
  describe 'model proxying' do
131
135
  it 'should delegate to a model method' do
132
136
  stripes = @model.first.stripes
@@ -123,5 +123,75 @@ if ADAPTER
123
123
  }.should_not raise_error(NoMethodError)
124
124
  end
125
125
  end
126
+
127
+ it { ModelSpec::STI.should respond_to(:copy) }
128
+
129
+ ([ :sqlite3, :mysql, :postgres ] - [ ADAPTER ]).each do |alternate|
130
+ describe '#copy' do
131
+ describe 'between identical models' do
132
+ before do
133
+ ModelSpec::STI.auto_migrate!(alternate)
134
+
135
+ ModelSpec::STI.create(:name => 'Record 1')
136
+ ModelSpec::STI.create(:name => 'Record 2')
137
+
138
+ # copy from the default to the alternate repository
139
+ @return = @resources = ModelSpec::STI.copy(:default, alternate)
140
+ end
141
+
142
+ it 'should return an Enumerable' do
143
+ @return.should be_a_kind_of(Enumerable)
144
+ end
145
+
146
+ it 'should return Resources' do
147
+ @return.each { |r| r.should be_a_kind_of(DataMapper::Resource) }
148
+ end
149
+
150
+ it 'should have each Resource set to the expected Repository' do
151
+ @resources.each { |r| r.repository.name.should == alternate }
152
+ end
153
+
154
+ it 'should create the Resources in the expected Repository' do
155
+ ModelSpec::STI.all(:repository => repository(alternate)).should == @resources
156
+ end
157
+ end
158
+
159
+ describe 'between different models' do
160
+ before do
161
+ # add an extra property to the alternate model
162
+ repository(alternate) do
163
+ ModelSpec::STI.property :status, String, :default => 'new'
164
+ end
165
+
166
+ ModelSpec::STI.auto_migrate!(alternate)
167
+
168
+ # add new resources to the alternate repository
169
+ repository(alternate) do
170
+ ModelSpec::STI.create(:name => 'Record 1')
171
+ ModelSpec::STI.create(:name => 'Record 2')
172
+ end
173
+
174
+ # copy from the alternate to the default repository
175
+ @return = @resources = ModelSpec::STI.copy(alternate, :default)
176
+ end
177
+
178
+ it 'should return an Enumerable' do
179
+ @return.should be_a_kind_of(Enumerable)
180
+ end
181
+
182
+ it 'should return Resources' do
183
+ @return.each { |r| r.should be_a_kind_of(DataMapper::Resource) }
184
+ end
185
+
186
+ it 'should have each Resource set to the expected Repository' do
187
+ @resources.each { |r| r.repository.name.should == :default }
188
+ end
189
+
190
+ it 'should create the Resources in the expected Repository' do
191
+ ModelSpec::STI.all.should == @resources
192
+ end
193
+ end
194
+ end
195
+ end
126
196
  end
127
197
  end
@@ -3,6 +3,22 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
3
3
  gem 'fastercsv', '~>1.4.0'
4
4
  require 'fastercsv'
5
5
 
6
+ describe DataMapper::Property do
7
+ before do
8
+ module PropertySpec
9
+ class Resource
10
+ include DataMapper::Resource
11
+ end
12
+ end
13
+
14
+ @property = PropertySpec::Resource.property :id, DM::Serial
15
+ end
16
+
17
+ it 'should be serializable with Marshal' do
18
+ Marshal.load(Marshal.dump(@property)).should == @property
19
+ end
20
+ end
21
+
6
22
  if ADAPTER
7
23
  describe DataMapper::Property, "with #{ADAPTER}" do
8
24
  describe " tracking strategies" do
@@ -125,6 +125,14 @@ if ADAPTER
125
125
  end
126
126
 
127
127
  describe DataMapper::Query, "with #{ADAPTER}" do
128
+ before do
129
+ @query = DataMapper::Query.new(repository(ADAPTER), QuerySpec::SailBoat)
130
+ end
131
+
132
+ it 'should be serializable with Marshal' do
133
+ Marshal.load(Marshal.dump(@query)).should == @query
134
+ end
135
+
128
136
  describe '#unique' do
129
137
  include LoggingHelper
130
138
 
@@ -137,7 +145,7 @@ if ADAPTER
137
145
  end
138
146
 
139
147
  def parse_statement(log)
140
- log.readlines.join.chomp.split(' ~ ').last
148
+ log.readlines.join.chomp.split(' ~ ').last.sub(/\A\(\d+\.\d+\)\s+/, '')
141
149
  end
142
150
 
143
151
  describe 'when true' do
@@ -21,6 +21,10 @@ if ADAPTER
21
21
  @query = DataMapper::Query.new(@repository, @model)
22
22
  end
23
23
 
24
+ it 'should be serializable with Marshal' do
25
+ Marshal.load(Marshal.dump(@repository)).should == @repository
26
+ end
27
+
24
28
  it "should throw an exception if the named repository is unknown" do
25
29
  r = DataMapper::Repository.new(:completely_bogus)
26
30
  lambda { r.adapter }.should raise_error(ArgumentError)
@@ -16,7 +16,11 @@ if ADAPTER
16
16
  repository(ADAPTER) { @zoo.save }
17
17
  end
18
18
 
19
- # --- Move somewhere ----
19
+ it 'should be serializable with Marshal' do
20
+ Marshal.load(Marshal.dump(@zoo)).should == @zoo
21
+ end
22
+
23
+ # --- Move somewhere ----
20
24
  it "should be able to destroy objects" do
21
25
  lambda { @zoo.destroy.should be_true }.should_not raise_error
22
26
  end
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.8
4
+ version: 0.9.9
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-12-07 00:00:00 -08:00
12
+ date: 2009-01-04 00:00:00 -08: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.9
23
+ version: 0.9.10
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: extlib