active-record-without-callbacks 0.0.2 → 0.0.3

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.
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: