Skip to content

Commit

Permalink
Explicit enable/disable API via NoPeepingToms.disable_observers / ena…
Browse files Browse the repository at this point in the history
…ble_observers

Rewrote specs to actually make sense
  • Loading branch information
Pat Maddox committed Jan 6, 2010
1 parent ddebd8c commit bbc2197
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 96 deletions.
6 changes: 5 additions & 1 deletion README
Expand Up @@ -9,7 +9,11 @@ To disable observers, place the following code in your test.rb, or spec_helper.r

NoPeepingToms.disable_observers

You can choose to run some code with observers turned on. This is useful when spec'ing an observer. For example, if you write the following observer:
You can easily reenable observers:

NoPeepingToms.enable_observers

You can choose to run some code with specific observers turned on. This is useful when spec'ing an observer. For example, if you write the following observer:

class PersonObserver < ActiveRecord::Observer
def before_update(person)
Expand Down
1 change: 1 addition & 0 deletions init.rb
@@ -0,0 +1 @@
require 'no_peeping_toms'
26 changes: 18 additions & 8 deletions lib/no_peeping_toms.rb
@@ -1,20 +1,30 @@
module NoPeepingToms
def self.disable_observers
ActiveRecord::Observer.send :include, NoPeepingToms
@default_observers_enabled = false
end

def self.enable_observers
@default_observers_enabled = true
end
enable_observers

def self.default_observers_enabled?
@default_observers_enabled
end

def self.included(base)
base.send :include, NoPeepingToms::InstanceMethods
base.extend NoPeepingToms::ClassMethods
base.alias_method_chain :update, :neighborhood_watch
base.cattr_accessor :allow_peeping_toms, :peeping_toms
base.allow_peeping_toms = false
base.peeping_toms = [] # toms that are allowed to peep
unless base.included_modules.include?(NoPeepingToms::InstanceMethods)
base.send :include, NoPeepingToms::InstanceMethods
base.extend NoPeepingToms::ClassMethods
base.alias_method_chain :update, :neighborhood_watch
base.cattr_accessor :peeping_toms
base.peeping_toms = [] # toms that are allowed to peep
end
end

module InstanceMethods
def update_with_neighborhood_watch(*args)
if self.class.allow_peeping_toms || self.class.peeping_toms.include?(self)
if NoPeepingToms.default_observers_enabled? || self.class.peeping_toms.include?(self)
update_without_neighborhood_watch(*args)
end
end
Expand Down
135 changes: 49 additions & 86 deletions spec/no_peeping_toms_spec.rb
@@ -1,118 +1,81 @@
require File.dirname(__FILE__) + '/spec_helper'

describe "Configuring NoPeepingToms" do
describe "#disable_observers" do
it "mixes in NoPeepingToms module to ActiveRecord::Observer" do
ActiveRecord::Observer.should_receive(:send).with(:include, NoPeepingToms)
NoPeepingToms.disable_observers
end
end
end

module NoPeepingTomsSpec
class Person < ActiveRecord::Base; end

class PersonObserver < ActiveRecord::Observer
def before_update(person)
$observer_called_names.push person.name
cattr_accessor :called

def before_create(person)
self.class.called = true
end
end

class AnotherObserver < ActiveRecord::Observer
observe Person
def before_update(person)
$calls_to_another_observer += 1
cattr_accessor :called

def before_create(person)
self.class.called = true
end
end

describe Person, " when changing a name" do
before(:each) do
$observer_called_names = []
$calls_to_another_observer = 0
@person = Person.create! :name => "Pat Maddox"
end

it "should not register a name change" do
@person.update_attribute :name, "Name change"
$observer_called_names.pop.should be_blank
$calls_to_another_observer.should == 0
describe NoPeepingToms, "configuration" do
it "enables observers by default" do
load 'no_peeping_toms.rb'
NoPeepingToms.default_observers_enabled?.should be_true
end

it "should register a name change with the person observer turned on by name" do
ActiveRecord::Observer.with_observers("NoPeepingTomsSpec::PersonObserver") do
@person.update_attribute :name, "Name change"
$observer_called_names.pop.should == "Name change"
end
it "runs default observers when default observers are enabled" do
NoPeepingToms.enable_observers
PersonObserver.called = false
Person.create!
PersonObserver.called.should be_true
end

@person.update_attribute :name, "Man Without a Name"
$observer_called_names.pop.should be_blank

$calls_to_another_observer.should == 0
it "does not run default observers when default observers are disabled" do
NoPeepingToms.disable_observers
PersonObserver.called = false
Person.create!
PersonObserver.called.should be_false
end

it "should register a name change with the person observer turned on by class reference" do
ActiveRecord::Observer.with_observers(NoPeepingTomsSpec::PersonObserver) do
@person.update_attribute :name, "Name change"
$observer_called_names.pop.should == "Name change"
end
end

@person.update_attribute :name, "Man Without a Name"
$observer_called_names.pop.should be_blank

$calls_to_another_observer.should == 0
describe ActiveRecord::Observer, 'with_observers' do
before(:each) do
NoPeepingToms.disable_observers
end

it "should register a name change with an anonymous observer" do
observer = Class.new(ActiveRecord::Observer) do
observe NoPeepingTomsSpec::Person
def before_update(person)
$observer_called_names.push person.name
end
end
ActiveRecord::Observer.with_observers(observer) do
@person.update_attribute :name, "Name change"
$observer_called_names.pop.should == "Name change"
end
it "should enable an observer via stringified class name" do
PersonObserver.called = false
ActiveRecord::Observer.with_observers("NoPeepingTomsSpec::PersonObserver") { Person.create! }
PersonObserver.called.should be_true
end

@person.update_attribute :name, "Man Without a Name"
$observer_called_names.pop.should be_blank

$calls_to_another_observer.should == 0
it "should enable an observer via class" do
PersonObserver.called = false
ActiveRecord::Observer.with_observers(NoPeepingTomsSpec::PersonObserver) { Person.create! }
PersonObserver.called.should be_true
end


it "should handle multiple observers" do
ActiveRecord::Observer.with_observers("NoPeepingTomsSpec::PersonObserver", "NoPeepingTomsSpec::AnotherObserver") do
@person.update_attribute :name, "Name change"
$observer_called_names.pop.should == "Name change"
it "should accept multiple observers" do
PersonObserver.called = false
AnotherObserver.called = false
ActiveRecord::Observer.with_observers(NoPeepingTomsSpec::PersonObserver, NoPeepingTomsSpec::AnotherObserver) do
Person.create!
end

@person.update_attribute :name, "Man Without a Name"
$observer_called_names.pop.should be_blank

$calls_to_another_observer.should == 1
PersonObserver.called.should be_true
AnotherObserver.called.should be_true
end

it "should handle multiple anonymous observers" do
observer1 = Class.new(ActiveRecord::Observer) do
observe NoPeepingTomsSpec::Person
def before_update(person) ; $observer_called_names.push "#{person.name} 1" ; end
end
observer2 = Class.new(ActiveRecord::Observer) do
it "should accept anonymous observers" do
called = false
observer = Class.new(ActiveRecord::Observer) do
observe NoPeepingTomsSpec::Person
def before_update(person) ; $observer_called_names.push "#{person.name} 2" ; end
define_method(:before_create) {|person| called = true }
end

ActiveRecord::Observer.with_observers(observer1, observer2) do
@person.update_attribute :name, "Name change"
$observer_called_names.pop.should == "Name change 2"
$observer_called_names.pop.should == "Name change 1"
end

@person.update_attribute :name, "Man Without a Name"
$observer_called_names.pop.should be_blank

$calls_to_another_observer.should == 0
ActiveRecord::Observer.with_observers(observer) { Person.create! }
called.should be_true
end

it "should ensure peeping toms are reset after raised exception" do
Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
@@ -1,4 +1,4 @@
require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
require File.expand_path(File.dirname(__FILE__) + '/../../../../spec/spec_helper')

plugin_spec_dir = File.dirname(__FILE__)
ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + "/debug.log")
Expand Down

0 comments on commit bbc2197

Please sign in to comment.