active-record-without-callbacks 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "active-record-without-callbacks"
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = "2013-04-05"
12
+ s.date = "2013-04-08"
13
13
  s.description = "A method that allows you to run code without callbacks for a specific active-record model."
14
14
  s.email = "kj@gfish.com"
15
15
  s.extra_rdoc_files = [
@@ -1,39 +1,74 @@
1
+ #This class can disable all callbacks for a model, run a block and then re-enable all callbacks.
1
2
  class ActiveRecordWithoutCallbacks
2
3
  TRUE_BLOCK = proc{ true }
3
4
 
4
- def self.wo_callbacks(klass)
5
- #List of various possible callbacks.
6
- takes = [:_create_callbacks, :_find_callbacks, :_initialize_callbacks, :_destroy_callbacks, :_commit_callbacks, :_rollback_callbacks, :_save_callbacks, :_touch_callbacks, :_update_callbacks, :_validate_callbacks, :_validation_callbacks, ]
5
+ def self.wo_callbacks(args)
6
+ klass = args[:class]
7
+ @debug = args[:debug]
8
+
9
+ #Callback-types that we will clear or recompile.
10
+ callbacks = [:create, :find, :initialize, :destroy, :commit, :rollback, :save, :touch, :update, :validate, :validation]
11
+ callback_types = [:before, :after]
12
+ previous_values = []
7
13
 
8
- #Array containing previous values.
9
- saved = []
14
+ #List of various possible callbacks.
15
+ takes = [:_create_callbacks, :_find_callbacks, :_initialize_callbacks, :_destroy_callbacks, :_commit_callbacks, :_rollback_callbacks, :_save_callbacks, :_touch_callbacks, :_update_callbacks, :_validate_callbacks, :_validation_callbacks]
10
16
 
17
+ #Run inside exclusive, so we are sure no other thread suffers from the horrible hack, that we are about to do.
11
18
  Thread.exclusive do
12
- takes.each do |take|
19
+ callbacks.each do |callback|
20
+ puts "Disabling callbacks for '#{callback}'." if @debug
21
+
22
+ #Method-name for callbacks to reset.
23
+ callbacks_method_name = "_#{callback}_callbacks"
24
+
13
25
  #Store previous value for restoring later.
14
- saved << {
15
- :take => take,
16
- :value => klass.__send__(take)
26
+ previous_values << {
27
+ :callbacks_method_name => callbacks_method_name,
28
+ :value => klass.__send__(callbacks_method_name).clone
17
29
  }
18
30
 
19
31
  #Clear all callbacks.
20
- klass.__send__("#{take}=", [])
32
+ puts "Clearing callbacks in '#{callbacks_method_name}'." if @debug
33
+ klass.__send__(callbacks_method_name).clear
21
34
 
22
35
  #Test that callbacks really was cleared.
23
- raise "Expected '#{take}' to be empty but it wasnt: #{klass.__send__(take)}" unless klass.__send__(take).empty?
36
+ puts "Checking if everything is okay for '#{callback}'." if @debug
37
+ raise "Expected '#{callbacks_method_name}' to be empty but it wasnt: #{klass.__send__(callbacks_method_name)}" unless klass.__send__(callbacks_method_name).empty?
38
+
39
+ #Trick ActiveRecord to recompile callbacks.
40
+ callback_types.each do |callback_type|
41
+ method_name = "#{callback_type}_#{callback}"
42
+
43
+ if klass.respond_to?(method_name)
44
+ klass.__send__(method_name, &TRUE_BLOCK)
45
+ end
46
+ end
24
47
  end
25
48
 
26
- klass.after_save(&TRUE_BLOCK)
27
-
28
49
  begin
50
+ #Run the given block, now that all callbacks are disabled.
51
+ puts "Yielding block." if @debug
29
52
  return yield
30
53
  ensure
54
+ puts "Restoring callbacks." if @debug
55
+
31
56
  #Restore previous callbacks.
32
- saved.each do |save|
33
- klass.__send__("#{save[:take]}=", save[:value])
57
+ previous_values.each do |previous_value|
58
+ method_name = "#{previous_value[:callbacks_method_name]}="
59
+ klass.__send__(method_name, previous_value[:value])
34
60
  end
35
61
 
36
- klass.after_save(&TRUE_BLOCK)
62
+ #Trick ActiveRecord to recompile old callbacks.
63
+ callbacks.each do |callback|
64
+ callback_types.each do |callback_type|
65
+ method_name = "#{callback_type}_#{callback}"
66
+
67
+ if klass.respond_to?(method_name)
68
+ klass.__send__(method_name, &TRUE_BLOCK)
69
+ end
70
+ end
71
+ end
37
72
  end
38
73
  end
39
74
  end
@@ -2,6 +2,36 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "ActiveRecordWithoutCallbacks" do
4
4
  it "doesnt fail" do
5
- #no tests
5
+ #The following code tests disabled callbacks.
6
+
7
+ #Deal.after_create do
8
+ # raise "Create WTF!?"
9
+ #end
10
+
11
+ #Deal.after_save do
12
+ # raise "Save WTF!?"
13
+ #end
14
+
15
+ Deal.before_create do
16
+ raise "Before create!"
17
+ end
18
+
19
+ Deal.after_create do
20
+ raise "After create!"
21
+ end
22
+
23
+ ActiveRecordWithoutCallbacks.wo_callbacks(Deal) do
24
+ deal = Deal.new(:legacy_id => 999999)
25
+
26
+ #puts deal.methods.sort
27
+
28
+ deal.save! :validate => false
29
+ puts "Deal created as expected"
30
+ end
31
+
32
+ deal = Deal.new(:legacy_id => 999999999)
33
+
34
+ deal.save! :validate => false
35
+ puts "Second deal creation did not fail."
6
36
  end
7
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-record-without-callbacks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-05 00:00:00.000000000 Z
12
+ date: 2013-04-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -111,7 +111,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
111
  version: '0'
112
112
  segments:
113
113
  - 0
114
- hash: -1341027000292272561
114
+ hash: 1788919925078652095
115
115
  required_rubygems_version: !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements: