From 1a2946a6d9b1dbcf3a4c77654693d73f9b11bde1 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Wed, 15 Jul 2009 14:16:30 -0700 Subject: Add some missing dependencies --- activemodel/lib/active_model/validations.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 5223cea135..54a869396d 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -1,5 +1,7 @@ require 'active_support/core_ext/array/extract_options' require 'active_support/core_ext/hash/keys' +require 'active_support/concern' +require 'active_support/callbacks' module ActiveModel module Validations -- cgit v1.2.3 From 5ffaaa71d149c9807260c950c9a61d01fe734827 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 20 Jul 2009 00:27:04 +0900 Subject: Define ActiveModel API Compliance - Define to_model on AR - Define to_model on ActiveModel::APICompliant - Update test fixtures to be API Compliant - Start using to_model in AP --- activemodel/lib/active_model.rb | 1 + activemodel/lib/active_model/api_compliant.rb | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 activemodel/lib/active_model/api_compliant.rb (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index f988cd71b8..c6f63d2fdc 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -26,6 +26,7 @@ $:.unshift(activesupport_path) if File.directory?(activesupport_path) require 'active_support' module ActiveModel + autoload :APICompliant, 'active_model/api_compliant' autoload :Attributes, 'active_model/attributes' autoload :Base, 'active_model/base' autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods' diff --git a/activemodel/lib/active_model/api_compliant.rb b/activemodel/lib/active_model/api_compliant.rb new file mode 100644 index 0000000000..26f83feb6b --- /dev/null +++ b/activemodel/lib/active_model/api_compliant.rb @@ -0,0 +1,25 @@ +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 -- cgit v1.2.3 From 2685d93b0728b647b6f49f3e1802c779d5fb9867 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 20 Jul 2009 23:28:58 -0500 Subject: Kill AMo ivar attributes helper --- activemodel/lib/active_model.rb | 1 - activemodel/lib/active_model/attributes.rb | 25 ------------------------ activemodel/lib/active_model/serializers/json.rb | 1 - activemodel/lib/active_model/serializers/xml.rb | 1 - 4 files changed, 28 deletions(-) delete mode 100644 activemodel/lib/active_model/attributes.rb (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index c6f63d2fdc..eed74731fa 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -27,7 +27,6 @@ require 'active_support' module ActiveModel autoload :APICompliant, 'active_model/api_compliant' - autoload :Attributes, 'active_model/attributes' autoload :Base, 'active_model/base' autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods' autoload :Errors, 'active_model/errors' 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/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: -- cgit v1.2.3 From 7c84bbf1607bf4059de04cc4c8ec84df2334574b Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 20 Jul 2009 23:57:01 -0500 Subject: Add wrap_with_notifications helper to AMo observing --- activemodel/lib/active_model/observing.rb | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index 7bad2397ae..707b1a0da6 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,6 +40,23 @@ 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) # string/symbol @@ -60,7 +78,7 @@ module ActiveModel end private - def notify(method) #:nodoc: + def notify_observers(method) self.class.changed self.class.notify_observers(method, self) end -- cgit v1.2.3 From 48bc39e03a077ed9a0684a181c1180c7f53b0cad Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 21 Jul 2009 00:11:26 -0500 Subject: Improve AMo observing docs --- activemodel/lib/active_model/observing.rb | 77 +++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 4 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index 707b1a0da6..3b230c43b9 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -42,7 +42,7 @@ module ActiveModel # Wraps methods with before and after notifications. # - # wrap_with_notifications :create, :save, :update, :destroy + # wrap_with_notifications :create, :save, :update, :destroy def wrap_with_notifications(*methods) methods.each do |method| class_eval(<<-EOS, __FILE__, __LINE__ + 1) @@ -58,7 +58,7 @@ module ActiveModel 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 @@ -78,12 +78,72 @@ module ActiveModel end private + # 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 @@ -95,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 @@ -115,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 @@ -132,7 +201,7 @@ module ActiveModel end protected - def add_observer!(klass) + def add_observer!(klass) #:nodoc: klass.add_observer(self) end end -- cgit v1.2.3 From 6944b391cddbf1a3ffb3ac4ac588fa4b3d50f430 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 21 Jul 2009 00:13:26 -0500 Subject: Kill AMo Base --- activemodel/lib/active_model.rb | 1 - activemodel/lib/active_model/base.rb | 8 -------- 2 files changed, 9 deletions(-) delete mode 100644 activemodel/lib/active_model/base.rb (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index eed74731fa..0665cfbae5 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -27,7 +27,6 @@ require 'active_support' module ActiveModel autoload :APICompliant, 'active_model/api_compliant' - autoload :Base, 'active_model/base' autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods' autoload :Errors, 'active_model/errors' autoload :Name, 'active_model/naming' 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 -- cgit v1.2.3 From 92c00d75869b173f44ff9d68f219a99e6dc3bd82 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 21 Jul 2009 00:51:57 -0500 Subject: AMo conversion helper --- activemodel/lib/active_model.rb | 2 +- activemodel/lib/active_model/api_compliant.rb | 25 ------------------------- activemodel/lib/active_model/conversion.rb | 8 ++++++++ 3 files changed, 9 insertions(+), 26 deletions(-) delete mode 100644 activemodel/lib/active_model/api_compliant.rb create mode 100644 activemodel/lib/active_model/conversion.rb (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index 0665cfbae5..2de19597b1 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -26,7 +26,7 @@ $:.unshift(activesupport_path) if File.directory?(activesupport_path) require 'active_support' module ActiveModel - autoload :APICompliant, 'active_model/api_compliant' + autoload :Conversion, 'active_model/conversion' autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods' autoload :Errors, 'active_model/errors' autoload :Name, 'active_model/naming' 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/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 -- cgit v1.2.3 From 574323df62ef6ddc666e55487733f14d787f2419 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 21 Jul 2009 00:52:50 -0500 Subject: So you can require 'activemodel' --- activemodel/lib/activemodel.rb | 1 + 1 file changed, 1 insertion(+) create mode 100644 activemodel/lib/activemodel.rb (limited to 'activemodel/lib') diff --git a/activemodel/lib/activemodel.rb b/activemodel/lib/activemodel.rb new file mode 100644 index 0000000000..da3133103b --- /dev/null +++ b/activemodel/lib/activemodel.rb @@ -0,0 +1 @@ +require 'active_model' -- cgit v1.2.3