dm-core 0.9.8 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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