aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmilio Tagua <miloops@gmail.com>2009-06-12 16:20:27 -0300
committerEmilio Tagua <miloops@gmail.com>2009-06-12 16:20:27 -0300
commita924b2f66e955dcc82b691ca5e48ef5b84035286 (patch)
tree8ea40389c9cae3568652a17d6892169179eb8bad
parent247ac954132222fdd399cddc264bc1d4029f750c (diff)
parent8f7c657f4b1c037348b24f0b9dd1e45099fbc760 (diff)
downloadrails-a924b2f66e955dcc82b691ca5e48ef5b84035286.tar.gz
rails-a924b2f66e955dcc82b691ca5e48ef5b84035286.tar.bz2
rails-a924b2f66e955dcc82b691ca5e48ef5b84035286.zip
Merge commit 'rails/master'
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb6
-rw-r--r--actionpack/test/template/asset_tag_helper_test.rb16
-rw-r--r--activemodel/lib/active_model.rb9
-rw-r--r--activemodel/lib/active_model/observing.rb116
-rw-r--r--activemodel/test/cases/observing_test.rb32
-rw-r--r--activerecord/lib/active_record.rb2
-rwxr-xr-xactiverecord/lib/active_record/base.rb2
-rw-r--r--activerecord/lib/active_record/callbacks.rb5
-rw-r--r--activerecord/lib/active_record/observer.rb95
9 files changed, 120 insertions, 163 deletions
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index a32beb6100..dffb7089b8 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -277,7 +277,7 @@ module ActionView
if ActionController::Base.perform_caching && cache
joined_javascript_name = (cache == true ? "all" : cache) + ".js"
- joined_javascript_path = File.join(JAVASCRIPTS_DIR, joined_javascript_name)
+ joined_javascript_path = File.join(joined_javascript_name[/^#{File::SEPARATOR}/] ? ASSETS_DIR : JAVASCRIPTS_DIR, joined_javascript_name)
write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources, recursive)) unless File.exists?(joined_javascript_path)
javascript_src_tag(joined_javascript_name, options)
@@ -417,7 +417,7 @@ module ActionView
if ActionController::Base.perform_caching && cache
joined_stylesheet_name = (cache == true ? "all" : cache) + ".css"
- joined_stylesheet_path = File.join(STYLESHEETS_DIR, joined_stylesheet_name)
+ joined_stylesheet_path = File.join(joined_stylesheet_name[/^#{File::SEPARATOR}/] ? ASSETS_DIR : STYLESHEETS_DIR, joined_stylesheet_name)
write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources, recursive)) unless File.exists?(joined_stylesheet_path)
stylesheet_tag(joined_stylesheet_name, options)
@@ -679,4 +679,4 @@ module ActionView
end
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index 76ceff8d6c..d586afdef6 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -317,9 +317,17 @@ class AssetTagHelperTest < ActionView::TestCase
assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js'))
+ assert_dom_equal(
+ %(<script src="http://a0.example.com/absolute/test.js" type="text/javascript"></script>),
+ javascript_include_tag(:all, :cache => "/absolute/test")
+ )
+
+ assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute', 'test.js'))
+
ensure
FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js'))
FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js'))
+ FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute'))
end
def test_caching_javascript_include_tag_when_caching_on_with_proc_asset_host
@@ -547,9 +555,17 @@ class AssetTagHelperTest < ActionView::TestCase
)
assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
+
+ assert_dom_equal(
+ %(<link href="http://a0.example.com/absolute/test.css" media="screen" rel="stylesheet" type="text/css" />),
+ stylesheet_link_tag(:all, :cache => "/absolute/test")
+ )
+
+ assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute', 'test.css'))
ensure
FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
+ FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute'))
end
def test_caching_stylesheet_link_tag_when_caching_on_with_proc_asset_host
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index a3545f1d53..73cee9b88f 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -27,12 +27,13 @@ require 'active_support'
module ActiveModel
autoload :Base, 'active_model/base'
- autoload :Observing, 'active_model/observing'
- autoload :Validations, 'active_model/validations'
- autoload :Errors, 'active_model/errors'
autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods'
- autoload :TestCase, 'active_model/test_case'
+ autoload :Errors, 'active_model/errors'
+ autoload :Observer, 'active_model/observing'
+ autoload :Observing, 'active_model/observing'
autoload :StateMachine, 'active_model/state_machine'
+ autoload :TestCase, 'active_model/test_case'
+ autoload :Validations, 'active_model/validations'
autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper'
end
diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb
index d3c6d8e482..7bad2397ae 100644
--- a/activemodel/lib/active_model/observing.rb
+++ b/activemodel/lib/active_model/observing.rb
@@ -1,69 +1,90 @@
require 'observer'
require 'singleton'
+require 'active_support/core_ext/string/inflections'
+require 'active_support/core_ext/array/wrap'
module ActiveModel
module Observing
+ extend ActiveSupport::Concern
+
+ included do
+ extend Observable
+ end
+
module ClassMethods
- def observers
- @observers ||= []
- end
-
+ # Activates the observers assigned. Examples:
+ #
+ # # Calls PersonObserver.instance
+ # ActiveRecord::Base.observers = :person_observer
+ #
+ # # Calls Cacher.instance and GarbageCollector.instance
+ # ActiveRecord::Base.observers = :cacher, :garbage_collector
+ #
+ # # Same as above, just using explicit class references
+ # ActiveRecord::Base.observers = Cacher, GarbageCollector
+ #
+ # Note: Setting this does not instantiate the observers yet. +instantiate_observers+ is
+ # called during startup, and before each development request.
def observers=(*values)
@observers = values.flatten
end
-
+
+ # Gets the current observers.
+ def observers
+ @observers ||= []
+ end
+
+ # Instantiate the global Active Record observers.
def instantiate_observers
observers.each { |o| instantiate_observer(o) }
end
-
- protected
- def instantiate_observer(observer)
- # string/symbol
- if observer.respond_to?(:to_sym)
- observer = observer.to_s.camelize.constantize.instance
- elsif observer.respond_to?(:instance)
- observer.instance
- else
- raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance"
+
+ protected
+ def instantiate_observer(observer)
+ # string/symbol
+ if observer.respond_to?(:to_sym)
+ observer = observer.to_s.camelize.constantize.instance
+ elsif observer.respond_to?(:instance)
+ observer.instance
+ else
+ raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance"
+ end
+ end
+
+ # Notify observers when the observed class is subclassed.
+ def inherited(subclass)
+ super
+ changed
+ notify_observers :observed_class_inherited, subclass
end
- end
-
- # Notify observers when the observed class is subclassed.
- def inherited(subclass)
- super
- changed
- notify_observers :observed_class_inherited, subclass
- end
- end
-
- def self.included(receiver)
- receiver.extend Observable, ClassMethods
end
+
+ private
+ def notify(method) #:nodoc:
+ self.class.changed
+ self.class.notify_observers(method, self)
+ end
end
class Observer
include Singleton
- attr_writer :observed_classes
class << self
- attr_accessor :models
# Attaches the observer to the supplied model classes.
def observe(*models)
- @models = models.flatten
- @models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model }
+ models.flatten!
+ models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model }
+ define_method(:observed_classes) { models }
end
- def observed_class_name
- @observed_class_name ||=
- if guessed_name = name.scan(/(.*)Observer/)[0]
- @observed_class_name = guessed_name[0]
- end
+ def observed_classes
+ Array.wrap(observed_class)
end
# The class observed by default is inferred from the observer's class name:
- # assert_equal [Person], PersonObserver.observed_class
+ # assert_equal Person, PersonObserver.observed_class
def observed_class
- if observed_class_name
+ if observed_class_name = name[/(.*)Observer/, 1]
observed_class_name.constantize
else
nil
@@ -73,8 +94,11 @@ module ActiveModel
# Start observing the declared classes and their subclasses.
def initialize
- self.observed_classes = self.class.models if self.class.models
- observed_classes.each { |klass| klass.add_observer(self) }
+ observed_classes.each { |klass| add_observer!(klass) }
+ end
+
+ def observed_classes
+ self.class.observed_classes
end
# Send observed_method(object) if the method exists.
@@ -86,12 +110,12 @@ module ActiveModel
# Passes the new subclass.
def observed_class_inherited(subclass) #:nodoc:
self.class.observe(observed_classes + [subclass])
- subclass.add_observer(self)
+ add_observer!(subclass)
end
- protected
- def observed_classes
- @observed_classes ||= [self.class.observed_class]
- end
+ protected
+ def add_observer!(klass)
+ klass.add_observer(self)
+ end
end
-end \ No newline at end of file
+end
diff --git a/activemodel/test/cases/observing_test.rb b/activemodel/test/cases/observing_test.rb
index 421ac4b4f8..564451fa2f 100644
--- a/activemodel/test/cases/observing_test.rb
+++ b/activemodel/test/cases/observing_test.rb
@@ -9,7 +9,7 @@ class FooObserver < ActiveModel::Observer
class << self
public :new
end
-
+
attr_accessor :stub
def on_spec(record)
@@ -28,12 +28,12 @@ class ObservingTest < ActiveModel::TestCase
test "initializes model with no cached observers" do
assert ObservedModel.observers.empty?, "Not empty: #{ObservedModel.observers.inspect}"
end
-
+
test "stores cached observers in an array" do
ObservedModel.observers << :foo
assert ObservedModel.observers.include?(:foo), ":foo not in #{ObservedModel.observers.inspect}"
end
-
+
test "flattens array of assigned cached observers" do
ObservedModel.observers = [[:foo], :bar]
assert ObservedModel.observers.include?(:foo), ":foo not in #{ObservedModel.observers.inspect}"
@@ -57,22 +57,30 @@ class ObservingTest < ActiveModel::TestCase
ObservedModel::Observer.expects(:instance)
ObservedModel.instantiate_observers
end
-
+
test "passes observers to subclasses" do
FooObserver.instance
bar = Class.new(Foo)
assert_equal Foo.count_observers, bar.count_observers
end
end
-
+
class ObserverTest < ActiveModel::TestCase
def setup
ObservedModel.observers = :foo_observer
- FooObserver.models = nil
+ FooObserver.instance_eval do
+ alias_method :original_observed_classes, :observed_classes
+ end
+ end
+
+ def teardown
+ FooObserver.instance_eval do
+ alias_method :observed_classes, :original_observed_classes
+ end
end
test "guesses implicit observable model name" do
- assert_equal 'Foo', FooObserver.observed_class_name
+ assert_equal Foo, FooObserver.observed_class
end
test "tracks implicit observable models" do
@@ -80,7 +88,7 @@ class ObserverTest < ActiveModel::TestCase
assert instance.send(:observed_classes).include?(Foo), "Foo not in #{instance.send(:observed_classes).inspect}"
assert !instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{instance.send(:observed_classes).inspect}"
end
-
+
test "tracks explicit observed model class" do
old_instance = FooObserver.new
assert !old_instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{old_instance.send(:observed_classes).inspect}"
@@ -88,7 +96,7 @@ class ObserverTest < ActiveModel::TestCase
instance = FooObserver.new
assert instance.send(:observed_classes).include?(ObservedModel), "ObservedModel not in #{instance.send(:observed_classes).inspect}"
end
-
+
test "tracks explicit observed model as string" do
old_instance = FooObserver.new
assert !old_instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{old_instance.send(:observed_classes).inspect}"
@@ -96,7 +104,7 @@ class ObserverTest < ActiveModel::TestCase
instance = FooObserver.new
assert instance.send(:observed_classes).include?(ObservedModel), "ObservedModel not in #{instance.send(:observed_classes).inspect}"
end
-
+
test "tracks explicit observed model as symbol" do
old_instance = FooObserver.new
assert !old_instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{old_instance.send(:observed_classes).inspect}"
@@ -104,7 +112,7 @@ class ObserverTest < ActiveModel::TestCase
instance = FooObserver.new
assert instance.send(:observed_classes).include?(ObservedModel), "ObservedModel not in #{instance.send(:observed_classes).inspect}"
end
-
+
test "calls existing observer event" do
foo = Foo.new
FooObserver.instance.stub = stub
@@ -112,7 +120,7 @@ class ObserverTest < ActiveModel::TestCase
Foo.send(:changed)
Foo.send(:notify_observers, :on_spec, foo)
end
-
+
test "skips nonexistent observer event" do
foo = Foo.new
Foo.send(:changed)
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 36adc7b6f2..3b8b9826fe 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -63,7 +63,7 @@ module ActiveRecord
autoload :Migrator, 'active_record/migration'
autoload :NamedScope, 'active_record/named_scope'
autoload :NestedAttributes, 'active_record/nested_attributes'
- autoload :Observing, 'active_record/observer'
+ autoload :Observer, 'active_record/observer'
autoload :QueryCache, 'active_record/query_cache'
autoload :Reflection, 'active_record/reflection'
autoload :Schema, 'active_record/schema'
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 4f0c11d883..4e7979cfff 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -3247,7 +3247,7 @@ module ActiveRecord #:nodoc:
include Locking::Optimistic, Locking::Pessimistic
include AttributeMethods
include Dirty
- include Callbacks, Observing, Timestamp
+ include Callbacks, ActiveModel::Observing, Timestamp
include Associations, AssociationPreload, NamedScope
# AutosaveAssociation needs to be included before Transactions, because we want
diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb
index 36f5f2ce47..01e41c04df 100644
--- a/activerecord/lib/active_record/callbacks.rb
+++ b/activerecord/lib/active_record/callbacks.rb
@@ -353,10 +353,5 @@ module ActiveRecord
return result
end
-
- def notify(method) #:nodoc:
- self.class.changed
- self.class.notify_observers(method, self)
- end
end
end
diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb
index 89ec0962bf..a34ff4a47a 100644
--- a/activerecord/lib/active_record/observer.rb
+++ b/activerecord/lib/active_record/observer.rb
@@ -2,56 +2,6 @@ require 'singleton'
require 'set'
module ActiveRecord
- module Observing # :nodoc:
- extend ActiveSupport::Concern
-
- module ClassMethods
- # Activates the observers assigned. Examples:
- #
- # # Calls PersonObserver.instance
- # ActiveRecord::Base.observers = :person_observer
- #
- # # Calls Cacher.instance and GarbageCollector.instance
- # ActiveRecord::Base.observers = :cacher, :garbage_collector
- #
- # # Same as above, just using explicit class references
- # ActiveRecord::Base.observers = Cacher, GarbageCollector
- #
- # Note: Setting this does not instantiate the observers yet. +instantiate_observers+ is
- # called during startup, and before each development request.
- def observers=(*observers)
- @observers = observers.flatten
- end
-
- # Gets the current observers.
- def observers
- @observers ||= []
- end
-
- # Instantiate the global Active Record observers.
- def instantiate_observers
- return if @observers.blank?
- @observers.each do |observer|
- if observer.respond_to?(:to_sym) # Symbol or String
- observer.to_s.camelize.constantize.instance
- elsif observer.respond_to?(:instance)
- observer.instance
- else
- raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance"
- end
- end
- end
-
- protected
- # Notify observers when the observed class is subclassed.
- def inherited(subclass)
- super
- changed
- notify_observers :observed_class_inherited, subclass
- end
- end
- end
-
# Observer classes respond to lifecycle callbacks to implement trigger-like
# behavior outside the original class. This is a great way to reduce the
# clutter that normally comes when the model class is burdened with
@@ -137,56 +87,19 @@ module ActiveRecord
# load their observers by calling <tt>ModelObserver.instance</tt> before. Observers are
# singletons and that call instantiates and registers them.
#
- class Observer
- include Singleton
-
- class << self
- # Attaches the observer to the supplied model classes.
- def observe(*models)
- models.flatten!
- models.collect! { |model| model.is_a?(Symbol) ? model.to_s.camelize.constantize : model }
- define_method(:observed_classes) { Set.new(models) }
- end
-
- # The class observed by default is inferred from the observer's class name:
- # assert_equal Person, PersonObserver.observed_class
- def observed_class
- if observed_class_name = name[/(.*)Observer/, 1]
- observed_class_name.constantize
- else
- nil
- end
- end
- end
-
- # Start observing the declared classes and their subclasses.
+ class Observer < ActiveModel::Observer
def initialize
- Set.new(observed_classes + observed_subclasses).each { |klass| add_observer! klass }
- end
-
- # Send observed_method(object) if the method exists.
- def update(observed_method, object) #:nodoc:
- send(observed_method, object) if respond_to?(observed_method)
- end
-
- # Special method sent by the observed class when it is inherited.
- # Passes the new subclass.
- def observed_class_inherited(subclass) #:nodoc:
- self.class.observe(observed_classes + [subclass])
- add_observer!(subclass)
+ super
+ observed_subclasses.each { |klass| add_observer!(klass) }
end
protected
- def observed_classes
- Set.new([self.class.observed_class].compact.flatten)
- end
-
def observed_subclasses
observed_classes.sum([]) { |klass| klass.send(:subclasses) }
end
def add_observer!(klass)
- klass.add_observer(self)
+ super
if respond_to?(:after_find) && !klass.method_defined?(:after_find)
klass.class_eval 'def after_find() end'
end