diff options
author | Emilio Tagua <miloops@gmail.com> | 2009-07-21 11:27:23 -0300 |
---|---|---|
committer | Emilio Tagua <miloops@gmail.com> | 2009-07-21 11:27:23 -0300 |
commit | f32c3709830eb8d9f68a59c94f6791621c2b52ac (patch) | |
tree | b34cf0b9321dfd40b795cc761b158be4cbde48f6 /activemodel/lib/active_model | |
parent | 9a28bd787660b08aae36155066e61d3608d0b4dd (diff) | |
parent | 9d7aae710384fb5f04129c35b86c5ea5fb9d83a9 (diff) | |
download | rails-f32c3709830eb8d9f68a59c94f6791621c2b52ac.tar.gz rails-f32c3709830eb8d9f68a59c94f6791621c2b52ac.tar.bz2 rails-f32c3709830eb8d9f68a59c94f6791621c2b52ac.zip |
Merge commit 'rails/master'
Diffstat (limited to 'activemodel/lib/active_model')
-rw-r--r-- | activemodel/lib/active_model/api_compliant.rb | 25 | ||||
-rw-r--r-- | activemodel/lib/active_model/attributes.rb | 25 | ||||
-rw-r--r-- | activemodel/lib/active_model/base.rb | 8 | ||||
-rw-r--r-- | activemodel/lib/active_model/conversion.rb | 8 | ||||
-rw-r--r-- | activemodel/lib/active_model/observing.rb | 97 | ||||
-rw-r--r-- | activemodel/lib/active_model/serializers/json.rb | 1 | ||||
-rw-r--r-- | activemodel/lib/active_model/serializers/xml.rb | 1 |
7 files changed, 100 insertions, 65 deletions
diff --git a/activemodel/lib/active_model/api_compliant.rb b/activemodel/lib/active_model/api_compliant.rb deleted file mode 100644 index 26f83feb6b..0000000000 --- a/activemodel/lib/active_model/api_compliant.rb +++ /dev/null @@ -1,25 +0,0 @@ -module ActiveModel - module APICompliant - include Naming - - def self.extended(klass) - klass.class_eval do - include Validations - include InstanceMethods - end - end - - module InstanceMethods - def to_model - if respond_to?(:new_record?) - self.class.class_eval { def to_model() self end } - to_model - else - raise "In order to be ActiveModel API compliant, you need to define " \ - "a new_record? method, which should return true if it has not " \ - "yet been persisted." - end - end - end - end -end
\ No newline at end of file diff --git a/activemodel/lib/active_model/attributes.rb b/activemodel/lib/active_model/attributes.rb deleted file mode 100644 index ea8c8d5f72..0000000000 --- a/activemodel/lib/active_model/attributes.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'active_support/core_ext/object/instance_variables' - -module ActiveModel - module Attributes - def self.append_features(base) - unless base.instance_methods.include?('attributes') - super - else - false - end - end - - def attributes - instance_values - end - - def read_attribute(attr_name) - instance_variable_get(:"@#{attr_name}") - end - - def write_attribute(attr_name, value) - instance_variable_set(:"@#{attr_name}", value) - end - end -end diff --git a/activemodel/lib/active_model/base.rb b/activemodel/lib/active_model/base.rb deleted file mode 100644 index a500adfdf1..0000000000 --- a/activemodel/lib/active_model/base.rb +++ /dev/null @@ -1,8 +0,0 @@ -module ActiveModel - class Base - include Observing - # disabled, until they're tested - # include Callbacks - # include Validations - end -end
\ No newline at end of file diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb new file mode 100644 index 0000000000..d5c65920f6 --- /dev/null +++ b/activemodel/lib/active_model/conversion.rb @@ -0,0 +1,8 @@ +module ActiveModel + # Include ActiveModel::Conversion if your object "acts like an ActiveModel model". + module Conversion + def to_model + self + end + end +end diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index 7bad2397ae..3b230c43b9 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -1,7 +1,8 @@ require 'observer' require 'singleton' -require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/array/wrap' +require 'active_support/core_ext/module/aliasing' +require 'active_support/core_ext/string/inflections' module ActiveModel module Observing @@ -39,8 +40,25 @@ module ActiveModel observers.each { |o| instantiate_observer(o) } end + # Wraps methods with before and after notifications. + # + # wrap_with_notifications :create, :save, :update, :destroy + def wrap_with_notifications(*methods) + methods.each do |method| + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def #{method}_with_notifications(*args, &block) + notify_observers(:before_#{method}) + result = #{method}_without_notifications(*args, &block) + notify_observers(:after_#{method}) + result + end + EOS + alias_method_chain(method, :notifications) + end + end + protected - def instantiate_observer(observer) + def instantiate_observer(observer) #:nodoc: # string/symbol if observer.respond_to?(:to_sym) observer = observer.to_s.camelize.constantize.instance @@ -60,12 +78,72 @@ module ActiveModel end private - def notify(method) #:nodoc: + # Fires notifications to model's observers + # + # def save + # notify_observers(:before_save) + # ... + # notify_observers(:after_save) + # end + def notify_observers(method) self.class.changed self.class.notify_observers(method, self) 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 + # functionality that doesn't pertain to the core responsibility of the + # class. Example: + # + # class CommentObserver < ActiveModel::Observer + # def after_save(comment) + # Notifications.deliver_comment("admin@do.com", "New comment was posted", comment) + # end + # end + # + # This Observer sends an email when a Comment#save is finished. + # + # class ContactObserver < ActiveModel::Observer + # def after_create(contact) + # contact.logger.info('New contact added!') + # end + # + # def after_destroy(contact) + # contact.logger.warn("Contact with an id of #{contact.id} was destroyed!") + # end + # end + # + # This Observer uses logger to log when specific callbacks are triggered. + # + # == Observing a class that can't be inferred + # + # Observers will by default be mapped to the class with which they share a name. So CommentObserver will + # be tied to observing Comment, ProductManagerObserver to ProductManager, and so on. If you want to name your observer + # differently than the class you're interested in observing, you can use the Observer.observe class method which takes + # either the concrete class (Product) or a symbol for that class (:product): + # + # class AuditObserver < ActiveModel::Observer + # observe :account + # + # def after_update(account) + # AuditTrail.new(account, "UPDATED") + # end + # end + # + # If the audit observer needs to watch more than one kind of object, this can be specified with multiple arguments: + # + # class AuditObserver < ActiveModel::Observer + # observe :account, :balance + # + # def after_update(record) + # AuditTrail.new(record, "UPDATED") + # end + # end + # + # The AuditObserver will now act on both updates to Account and Balance by treating them both as records. + # class Observer include Singleton @@ -77,6 +155,15 @@ module ActiveModel define_method(:observed_classes) { models } end + # Returns an array of Classes to observe. + # + # You can override this instead of using the +observe+ helper. + # + # class AuditObserver < ActiveModel::Observer + # def self.observed_classes + # [AccountObserver, BalanceObserver] + # end + # end def observed_classes Array.wrap(observed_class) end @@ -97,7 +184,7 @@ module ActiveModel observed_classes.each { |klass| add_observer!(klass) } end - def observed_classes + def observed_classes #:nodoc: self.class.observed_classes end @@ -114,7 +201,7 @@ module ActiveModel end protected - def add_observer!(klass) + def add_observer!(klass) #:nodoc: klass.add_observer(self) end end diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb index adf200597d..e94512fd64 100644 --- a/activemodel/lib/active_model/serializers/json.rb +++ b/activemodel/lib/active_model/serializers/json.rb @@ -5,7 +5,6 @@ module ActiveModel module Serializers module JSON extend ActiveSupport::Concern - include ActiveModel::Attributes included do extend ActiveModel::Naming diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index 7cdd281223..76a0e54a56 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -5,7 +5,6 @@ module ActiveModel module Serializers module Xml extend ActiveSupport::Concern - include ActiveModel::Attributes class Serializer < ActiveModel::Serializer #:nodoc: class Attribute #:nodoc: |