updater 0.9.4 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'rake/gempackagetask'
3
- gem 'rspec', '=1.3.0'
4
- require 'spec/rake/spectask'
3
+ require 'rspec/core/rake_task'
5
4
 
6
5
 
7
6
  VERSION_FILE = File.join(File.dirname(__FILE__), 'VERSION')
@@ -26,7 +25,7 @@ spec = Gem::Specification.new do |s|
26
25
  s.email = EMAIL
27
26
  s.homepage = HOMEPAGE
28
27
  s.add_development_dependency('datamapper', '>= 0.10.2')
29
- s.add_development_dependency('rspec', '=1.3.0')
28
+ s.add_development_dependency('rspec', '>= 2.0.0')
30
29
  s.add_development_dependency('timecop', '>= 0.2.1')
31
30
  s.add_development_dependency('chronic', '>= 0.2.3')
32
31
  s.require_path = 'lib'
@@ -40,21 +39,21 @@ Rake::GemPackageTask.new(spec) do |pkg|
40
39
  pkg.gem_spec = spec
41
40
  end
42
41
 
43
- Spec::Rake::SpecTask.new do |t|
44
- t.warning = false
42
+ RSpec::Core::RakeTask.new do |t|
43
+ ruby_opts="-w"
45
44
  t.rcov = false
46
45
  end
47
46
 
48
- Spec::Rake::SpecTask.new do |t|
47
+ RSpec::Core::RakeTask.new do |t|
49
48
  t.name="failing"
50
49
  #todo Make this run only failing specs
51
- t.warning = false
50
+ ruby_opts="-w"
52
51
  t.rcov = false
53
52
  end
54
53
 
55
- Spec::Rake::SpecTask.new do |t|
54
+ RSpec::Core::RakeTask.new do |t|
56
55
  t.name="rcov"
57
- t.warning = false
56
+ ruby_opts="-w"
58
57
  t.rcov = true
59
58
  end
60
59
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.4
1
+ 0.10.0
@@ -231,7 +231,7 @@ module Updater
231
231
 
232
232
  def add_worker(worker_number)
233
233
  worker = WorkerMonitor.new(worker_number,Updater::Util.tempio)
234
- Update.orm.before_fork
234
+ Update.orm.before_fork if Update.orm.respond_to? :before_fork
235
235
  pid = Process.fork do
236
236
  fork_cleanup
237
237
  self.new(@pipe,worker).run
@@ -0,0 +1,23 @@
1
+ module Updater
2
+ module ORm
3
+
4
+ class ActiveRecord
5
+ raise NoImplimentationError
6
+ def lock(worker)
7
+ return true if locked? && locked_by == worker.name
8
+ #all this to make sure the check and the lock are simultanious:
9
+ ccnt = self.class.where(id: self.id, lock: nil).update_all(:lock=>worker.name)
10
+ if 0 != cnt
11
+ @lock_name = worker.name
12
+ true
13
+ else
14
+ worker.say( "Worker #{worker.name} Failed to aquire lock on job #{id}" )
15
+ false
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -1,5 +1,6 @@
1
1
  require "dm-core"
2
2
  require "dm-types"
3
+ require "dm-migrations"
3
4
 
4
5
  module Updater
5
6
  module ORM
@@ -31,6 +32,10 @@ module Updater
31
32
 
32
33
  has n, :chains, :model=>'Updater::ORM::DMChained', :child_key=>[:caller_id]
33
34
 
35
+ def method
36
+ self[:method]
37
+ end
38
+
34
39
  #attempt to lock this record for the worker
35
40
  def lock(worker)
36
41
  return true if locked? && locked_by == worker.name
@@ -55,28 +60,33 @@ module Updater
55
60
  define_method "#{mode}=" do |chain|
56
61
  case chain
57
62
  when self.class
58
- chains.new(:target=>chain,:occasion=>mode)
63
+ self.chains.new(:target=>chain,:occasion=>mode)
59
64
  when Updater::Update
60
- chains.new(:target=>chain.orm,:occasion=>mode)
65
+ self.chains.new(:target=>chain.orm,:occasion=>mode)
61
66
  when Hash
62
67
  chain.each do |target, params|
63
68
  target = target.orm if target.kind_of? Updater::Update
64
- chains.new(:target=>target,:params=>params, :occasion=>mode)
69
+ self.chains.new(:target=>target,:params=>params, :occasion=>mode)
65
70
  end
66
71
  when Array
67
72
  chain.each do |target|
73
+ target, params = target
68
74
  target = target.orm if target.kind_of? Updater::Update
69
- chains.new(:target=>target,:occasion=>mode)
75
+ self.chains.new(:target=>target,:occasion=>mode, :params=>params)
70
76
  end
77
+ when Integer
78
+ self.chains.new(:target_id=>chain,:occasion=>mode)
71
79
  when nil
72
- chains=[]
80
+ self.chains=[]
73
81
  else
74
- raise ArgumentError
82
+ raise ArgumentError, "Cannot add #{chain.inspect} to a chain (%s:%s)" % [__FILE__,__LINE__]
75
83
  end
84
+ save
85
+ chain
76
86
  end
77
87
 
78
88
  define_method mode do
79
- chains.all(:occasion=>mode).map {|job| Updater.new(i.target).tap {|u| u.params = job.params}}
89
+ chains.all(:occasion=>mode).map {|job| Update.new(job.target).tap {|u| u.params = job.params}}
80
90
  end
81
91
  end
82
92
 
@@ -145,7 +155,7 @@ module Updater
145
155
  search = all(
146
156
  :target=>mytarget,
147
157
  :finder=>myfinder,
148
- :finder_args=>myfinder_args,
158
+ :finder_args=>myfinder_args.to_yaml,
149
159
  :lock_name=>nil
150
160
  )
151
161
  myname ? search.all(:name=>myname ) : search
@@ -154,7 +164,17 @@ module Updater
154
164
  #For the server only, setup the connection to the database
155
165
  def setup(options)
156
166
  ::DataMapper.logger = options.delete(:logger)
167
+ auto_migrate = options.delete(:auto_migrate)
157
168
  ::DataMapper.setup(:default,options)
169
+ ::DataMapper.auto_migrate! if auto_migrate
170
+ end
171
+
172
+ def logger
173
+ ::DataMapper.logger
174
+ end
175
+
176
+ def logger=(input)
177
+ ::DataMapper.logger = input
158
178
  end
159
179
 
160
180
  # For pooled connections it is necessary to empty the pool of the parents connections so that they
@@ -0,0 +1,155 @@
1
+ module Updater
2
+ module ORM
3
+ class Mock
4
+
5
+ FINDER = :find
6
+
7
+ ID = :id
8
+
9
+ class << self
10
+ attr_accessor :logger
11
+
12
+ def index
13
+ @index ||= 0
14
+ @index += 1
15
+ end
16
+
17
+ def get(id)
18
+ storage[id]
19
+ end
20
+
21
+ def create(hash)
22
+ new(hash).tap {|n| storage[n.id] = n}
23
+ end
24
+
25
+ def current
26
+ storage.values.find_all{|x|
27
+ x.time && x.time <= tnow && !x.lock_name
28
+ }.sort{|a,b| a.time <=> b.time}
29
+ end
30
+
31
+ def current_load
32
+ current.length
33
+ end
34
+
35
+ def _delayed
36
+ storage.values.find_all{|x|
37
+ x.time && x.time > tnow
38
+ }.sort{|a,b| a.time <=> b.time}
39
+ end
40
+
41
+ def delayed
42
+ _delayed.length
43
+ end
44
+
45
+ def future(start, finish)
46
+ _delayed.find_all{|x| x.time >= start+tnow && x.time < finish+tnow}
47
+ end
48
+
49
+ def queue_time
50
+ return 0 unless current.empty?
51
+ return nil if (d = _delayed).empty? #tricky assignment in conditional
52
+ d.first.time - tnow
53
+ end
54
+
55
+ def lock_next(worker)
56
+ job = current.first
57
+ job.lock(worker) if job
58
+ job
59
+ end
60
+
61
+ def clear_locks(worker)
62
+ storage.values.each{|x| x.lock_name = nil if x.lock_name == worker.name}
63
+ end
64
+
65
+
66
+ def clear_all
67
+ @storage = {}
68
+ end
69
+
70
+ def setup(options)
71
+ @storage = {}
72
+ end
73
+
74
+ def for(target, finder, finder_args, name=nil)
75
+ @storage.values.find_all do |x|
76
+ naming = name ? x.name == name : true
77
+ naming && x.finder == finder && x.finder_args == finder_args && x.target == target && !x.lock_name
78
+ end
79
+ end
80
+
81
+ def storage
82
+ @storage ||= {}
83
+ end
84
+
85
+ private
86
+ def tnow
87
+ Updater::Update.time.now.to_i
88
+ end
89
+ end #class << self
90
+
91
+ attr_reader :id
92
+
93
+ attr_accessor :time, :target, :finder, :finder_args, :method, :method_args, :name, :lock_name, :persistant
94
+
95
+ def initialize(hash = {})
96
+ @id = self.class.index
97
+ hash.each do |k,v|
98
+ self.send("#{k}=",v)
99
+ end
100
+ end
101
+
102
+ def lock(worker)
103
+ return false if @lock_name && @lock_name != worker.name
104
+ @lock_name = worker.name
105
+ end
106
+
107
+ def save
108
+ self.class.storage[id] = self
109
+ end
110
+
111
+ def destroy
112
+ self.class.storage.delete(id)
113
+ end
114
+
115
+ %w{failure success ensure}.each do |mode|
116
+ eval(<<-EOF, binding ,__FILE__, __LINE__+1)
117
+ def #{mode}
118
+ @#{mode} ||= []
119
+ end
120
+
121
+ def #{mode}=(chain)
122
+ return @#{mode} = nil if chain.nil?
123
+ @#{mode} ||= []
124
+ mchain = chain.kind_of?(Array) ? chain : [chain]
125
+ @#{mode} += mchain.map { |x| rationalize_instance(x) }.flatten
126
+ # attach_intellegent_insertion(@#{mode},:#{mode},self) if @#{mode}
127
+ chain
128
+ end
129
+ EOF
130
+ end
131
+
132
+ private
133
+
134
+ def rationalize_instance(val)
135
+ case val
136
+ when Updater::Update
137
+ val
138
+ when self.class
139
+ Updater::Update.new(val)
140
+ when Integer
141
+ Updater::Update.new(self.class.storage[val])
142
+ when Hash
143
+ val.map do |target, params|
144
+ rationalize_instance(target).tap{|u| u.params = params}
145
+ end
146
+ when Array #an array within an array
147
+ rationalize_instance(val[0]).tap {|u| u.params = val[1]}
148
+ else
149
+ raise ArgumentError, "Cannot add #{val.inspect} to a chain (%s:%s)" % [__FILE__,__LINE__]
150
+ end
151
+ end
152
+
153
+ end
154
+ end
155
+ end
@@ -71,7 +71,16 @@ module Updater
71
71
  end
72
72
 
73
73
  def lock(worker)
74
- raise NotImplimentedError, "Use lock_next"
74
+ return true if @lock_name && @lock_name == worker.name
75
+ hash = Hash.new
76
+ hash['findandmodify'] = self.class.collection.name
77
+ hash['query'] = {:_id=>id,:lock_name=>nil}
78
+ hash['update'] = {'$set'=>{:lock_name=>worker.name}}
79
+ hash['new'] = true
80
+
81
+ ret = self.class.db.command hash, :check_response=>false
82
+ @lock_name = worker.name if ret['ok'] == 1
83
+ return ret['ok'] == 1
75
84
  end
76
85
 
77
86
  # Non API Standard. This method returns the collection used by this instance.
@@ -97,23 +106,32 @@ module Updater
97
106
  end
98
107
 
99
108
  def #{mode}=(chain)
100
- chain = [chain] unless chain.kind_of? Array
101
- @#{mode} , @hash[:#{mode}] = build_chain_arrays(chain)
109
+ return @#{mode} = @hash[:#{mode}] = nil if chain.nil?
110
+ mchain = chain.kind_of?(Array) ? chain : [chain]
111
+ inst, hsh = build_chain_arrays(mchain)
112
+ @#{mode} = (@#{mode} || [] ) + inst if inst
113
+ @hash[:#{mode}] = (@hash[:#{mode}] || []) + hsh
102
114
  attach_intellegent_insertion(@#{mode},:#{mode},self) if @#{mode}
115
+ chain
103
116
  end
104
117
  EOF
105
118
  end
106
119
 
120
+ def ==(other)
121
+ other.class == self.class && id == other.id
122
+ end
123
+
107
124
  private
108
- # this method is calld from he chain asignment methods eg. failure=(chain)
125
+ # This method is calleppd from he chain asignment methods eg. failure=(chain)
109
126
  # chain is an array which may contain BSON::ObjectId's or Updater::Update's or both
110
- # For BSON::ObjectId's we cannot initialize them as this could leed to infinate loops.
127
+ # For BSON::ObjectId's we cannot initialize them as this could lead to infinate loops.
111
128
  # (an object pool would solve this problem, but feels like overkill)
112
129
  # The final result must be a @hash containing all the BSON::ObjectId' (forign keys)
113
130
  # and possibly @failure containting all instanciated UpdaterUpdates read to be called
114
131
  # or @failure set to nil with the chain instanciated on first use.
115
132
  def build_chain_arrays(arr, build = false)
116
- build ||= arr.any? {|j| k,_ = j; Updater::Update === k || Hash === k}
133
+ arr = arr[0].to_a if arr[0].is_a? Hash
134
+ build ||= arr.any? {|j| k,_ = j; Updater::Update === k || self.class === k}
117
135
  output = arr.inject({:ids=>[],:instances=>[]}) do |accl,j|
118
136
  inst, id = rationalize_instance(j)
119
137
  if inst.nil? && build
@@ -134,7 +152,7 @@ module Updater
134
152
  # This method takes something that may be a reference to an instance(BSON::ObjectId/String),
135
153
  # an instance its self (Updater::Update), or a Hash
136
154
  # and returns a touple of the Updater::Update,BSON::ObjectId.
137
- # This method will bot instanciate object from BSON::ObjectId's
155
+ # This method will not instanciate object from BSON::ObjectId's
138
156
  # nor will it save Hashes inorder to obtain an ID (it will creat a new Updater::Update from the hash).
139
157
  # Instead it will return nil in the appropriate place.
140
158
  def rationalize_instance(val)
@@ -142,8 +160,10 @@ module Updater
142
160
  case val #aval is the actual runable object, hval is a BSON::ObjectId that we can put into the Database
143
161
  when Updater::Update
144
162
  val.params ? [val,[val.id,val.params]] : [val,val.id]
145
- when Hash
146
- [Updater::Update.new(val),val['_id']]
163
+ #~ when Hash # I think this ought to be deleted outright, but I whant to pass the functional test before I delete it.
164
+ #~ [Updater::Update.new(val),val['_id']]
165
+ when self.class
166
+ [Updater::Update.new(val), val.id]
147
167
  when BSON::ObjectId
148
168
  [nil,val]
149
169
  when Array
@@ -228,11 +248,15 @@ module Updater
228
248
 
229
249
  def get(id)
230
250
  id = BSON::ObjectId.from_string(id) if id.kind_of? String
231
- new(@collection.find_one(id))
251
+ inst = @collection.find_one(id)
252
+ inst && new(inst)
232
253
  end
233
254
 
234
255
  def current
235
- raise NotImplementedError, "Mongo does not support lazy evaluation"
256
+ # raise NotImplementedError, "Mongo does not support lazy evaluation"
257
+ @collection.find(:time=>{'$lte'=>tnow}).map do |x|
258
+ new(x)
259
+ end
236
260
  end
237
261
 
238
262
  def current_load
@@ -268,12 +292,23 @@ module Updater
268
292
  @collection.update({:lock_name=>worker.name},{'$unset'=>{:lock_name=>1}},:multi=>true)
269
293
  end
270
294
 
271
- def for(target,finder,args,name)
295
+ def for(target,finder,args,name=nil)
272
296
  if name
273
- @collection.find(:target=>target.to_s, :finder_args=>args,:name=>name)
297
+ @collection.find(
298
+ :target=>target.to_s,
299
+ :finder_args=>args,
300
+ :finder=>finder,
301
+ :lock_name=>nil,
302
+ :name=>name
303
+ )
274
304
  else
275
- @collection.find(:target=>target.to_s, :finder_args=>args)
276
- end
305
+ @collection.find(
306
+ :target=>target.to_s,
307
+ :finder_args=>args,
308
+ :finder=>finder,
309
+ :lock_name=>nil,
310
+ )
311
+ end.map {|x| new(x) }
277
312
  end
278
313
 
279
314
  private
@@ -30,7 +30,7 @@ module Updater
30
30
  # always in reference to Updater::Update.time (by default Time). This value will be
31
31
  # nil for chained methods.
32
32
  #
33
- # target [Class]: The class of the target for this job. the API spesifies that it must be
33
+ # target [Class]: The class of the target for this job. The API spesifies that it must be
34
34
  # a Ruby class currently in scope in both the workers' and clients' frames of reference.
35
35
  # (see configuration documentation for how to achieve this.) The writer must accept an
36
36
  # actual class, which it may store in the datastore as a string (by calling to_s on it). The
@@ -232,6 +232,8 @@ module Updater
232
232
  end
233
233
 
234
234
  def after_fork
235
+
236
+ end
235
237
 
236
238
  # Optional, but strongly recomended.
237
239
  #
data/lib/updater/setup.rb CHANGED
@@ -6,6 +6,7 @@ require 'erb'
6
6
  module Updater
7
7
  class Setup
8
8
  class << self
9
+ attr_accessor :init
9
10
  #start a new server
10
11
  def start(options={})
11
12
  new(config_file(options), options).start
@@ -27,6 +28,10 @@ module Updater
27
28
  new(config_file(options), options).client_setup
28
29
  end
29
30
 
31
+ def test_setup(options = {})
32
+ new(options).test_setup
33
+ end
34
+
30
35
  # pendeing
31
36
  def monitor
32
37
 
@@ -83,14 +88,14 @@ module Updater
83
88
  end
84
89
 
85
90
  # The client is responcible for loading classes and making connections. We will simply setup the Updater spesifics.
86
- def client_setup
87
- @logger.info "Updater Client is being initialized..."
91
+ def client_setup(init = true)
92
+ @logger.info "Updater Client is being initialized... (#{__FILE__}:#{__LINE__})"
93
+ @logger.debug " Call Stack:\n - #{caller[0..3].join("\n - ")}"
88
94
  set_orm
89
95
 
90
96
  Updater::Update.socket = socket_for_client
91
97
 
92
-
93
- init_orm
98
+ init_orm if init
94
99
 
95
100
  #set PID
96
101
  if File.exists? @options[:pid_file]
@@ -101,6 +106,16 @@ module Updater
101
106
  self
102
107
  end
103
108
 
109
+ def test_setup
110
+ @options[:orm] ||= 'mock'
111
+ set_orm
112
+ init_orm
113
+
114
+ Updater::Update.socket = @options[:socket] ||= File.open('/dev/null','w')
115
+
116
+ self
117
+ end
118
+
104
119
  def socket_for_client
105
120
  if @options[:socket] && File.exists?(@options[:socket])
106
121
  @logger.debug "Using UNIX Socket \"#{@options[:socket]}\""
@@ -145,13 +160,15 @@ module Updater
145
160
  require 'updater/orm/activerecord'
146
161
  Updater::Update.orm = ORM::ActiveRecord
147
162
  else
148
- require "update/orm/#{orm}"
149
- Updater::Update.orm = Object.const_get("ORM").const_get(orm.capitalize)
163
+ require "updater/orm/#{orm}"
164
+ Updater::Update.orm = Updater::ORM.const_get(orm.capitalize)
150
165
  end
151
166
  @logger.info "Data store '#{orm}' selected"
152
167
  end
153
168
 
154
169
  def init_orm
170
+ return false if self.class.init
171
+ self.class.init = true
155
172
  default_options = {:adapter=>'sqlite3', :database=>'./default.db'}
156
173
  Updater::Update.orm.setup((@options[:database] || @options[:orm_setup] || default_options).merge(:logger=>@logger))
157
174
  end
@@ -206,7 +223,7 @@ module Updater
206
223
  #Log PID
207
224
  File.open(@options[:pid_file],'w') { |f| f.write(Process.pid.to_s)}
208
225
 
209
- client_setup
226
+ client_setup(false)
210
227
 
211
228
  #start Worker
212
229
  worker = @options[:worker] || 'fork' #todo make this line windows safe
@@ -9,6 +9,7 @@ module Updater
9
9
  class ThreadWorker
10
10
  attr_accessor :pid
11
11
  attr_accessor :name
12
+ attr_accessor :logger
12
13
 
13
14
  def initialize(options={})
14
15
  @quiet = options[:quiet]
@@ -53,6 +54,10 @@ module Updater
53
54
  end
54
55
  end
55
56
 
57
+ def logger
58
+ @logger ||= Logger.new(nil)
59
+ end
60
+
56
61
  private
57
62
 
58
63
  def run_job_loop
@@ -53,14 +53,17 @@ module Updater
53
53
  # (or the recreation of an object) on EACH invocation. Methods that need to refer to the target more then once should
54
54
  # take care to store this value locally after initial retreavel.
55
55
  def target
56
- target = @orm.finder.nil? ? @orm.target : @orm.target.send(@orm.finder,@orm.finder_args)
56
+ target = @orm.finder.nil? ? @orm.target : @orm.target.send(@orm.finder,*@orm.finder_args)
57
57
  raise TargetMissingError, "Target missing --Class:'#{@orm.target}' Finder:'#{@orm.finder}', Args:'#{@orm.finder_args.inspect}'" unless target
58
58
  target
59
59
  end
60
60
 
61
61
  # orm_inst must be set to an instacne of the class Update.orm
62
62
  def initialize(orm_inst)
63
- raise ArgumentError if orm_inst.nil? || !orm_inst.kind_of?(self.class.orm)
63
+ if orm_inst.nil? || !orm_inst.kind_of?(self.class.orm)
64
+ raise ArgumentError,
65
+ "Update has been set to use %s but recieved a %s (%s:%s)\n recieved %s." % [self.class.orm.inspect, orm_inst.class.inspect, __FILE__,__LINE__-1,orm_inst.inspect]
66
+ end
64
67
  @orm = orm_inst
65
68
  end
66
69
 
@@ -80,7 +83,7 @@ module Updater
80
83
  end
81
84
 
82
85
  def ==(other)
83
- id = other.id
86
+ other.kind_of?(self.class) && id == other.id
84
87
  end
85
88
 
86
89
  # If this is true, the job will NOT be removed after it is run. This is usually true for chained Jobs.
@@ -172,7 +175,7 @@ module Updater
172
175
  #
173
176
  # MongoDB is one significant exception to this rule. The Updater Mongo ORM layer uses the
174
177
  # 10gen MongoDB dirver directly without an ORM such as Mongoid or Mongo_Mapper. If the
175
- # application uses ond of thes ORMs #finder_method and #finder_id should be explicitly set.
178
+ # application uses one of thes ORMs #finder_method and #finder_id should be explicitly set.
176
179
  attr_accessor :finder_method
177
180
 
178
181
  # This is the application level default method to call on an instance type target. It should
@@ -480,7 +483,7 @@ module Updater
480
483
 
481
484
  # Given some instance return the information needed to recreate that target
482
485
  def target_for(inst,options = {})
483
- return [inst, nil, nil] if (inst.kind_of?(Class) || inst.kind_of?(Module))
486
+ return [inst, options[:finder], options[:finder_args]] if (inst.kind_of?(Class) || inst.kind_of?(Module))
484
487
  [ inst.class, #target's class
485
488
  options[:finder] || @finder_method || orm::FINDER, #method to call on targets class to find/create target
486
489
  options[:finder_args] || inst.send(@finder_id || orm::ID) #value to pass to above method
data/spec/chained_spec.rb CHANGED
@@ -8,15 +8,16 @@ describe "Chained Methods:" do
8
8
 
9
9
  before :each do
10
10
  Update.clear_all
11
- Foo.all.destroy!
11
+ Foo.reset
12
12
  @u = Update.chain(Foo,:chained,[:__job__,:__params__])
13
13
  @v = Update.chain(Foo,:chained2,[:__job__,:__params__])
14
+ #pending "Chained Worker not implimented in datamapper, Waiting form ORM code refactor"
14
15
  end
15
16
 
16
17
  [:failure, :success, :ensure].each do |mode|
17
18
  specify "adding '#{mode.to_s}' chain" do
18
19
  v = Update.immidiate(Foo,:method1,[],mode=>@u)
19
- v.orm.send(mode).should_not be_empty
20
+ v.send(mode).should_not be_empty
20
21
  end
21
22
  end
22
23
 
@@ -0,0 +1,7 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper" )
2
+ require 'updater/orm/datamapper'
3
+
4
+ describe Updater::ORM::DataMapper do
5
+ it_behaves_like "an orm", :adapter=>'sqlite3',:database=>':memory:',:auto_migrate=>true
6
+
7
+ end
data/spec/errors_spec.rb CHANGED
@@ -6,7 +6,7 @@ require File.join( File.dirname(__FILE__), "fooclass" )
6
6
 
7
7
  describe "Job Error Handeling" do
8
8
  before(:each) do
9
- Foo.all.destroy!
9
+ Foo.reset
10
10
  end
11
11
 
12
12
  it "should return false when run" do