lib/simple_model/base.rb in simple_model-1.1.1 vs lib/simple_model/base.rb in simple_model-1.2.0

- old
+ new

@@ -16,23 +16,26 @@ require 'active_support/core_ext/object/duplicable' require 'active_support/core_ext/object/blank' # == SimpleModel::Base # - # Provides an interface for any class to build tabless models. + # Provides an interface for any class to build tableless models. # # Implements Validations, Callbacks and Dirty from ActiveModel, and datatype specific - # attribute definitions with default options + # attribute definitions with default options. SimpleModel::Base is intended as + # an example, while it may be used in production, which it is on many of my apps + # today, it is recommend you use SimpleModel::Base as an example to implement your + # own model actions. # # == SimpleModel Actions: # # Model actions provide a tool for making use of Active Model callbacks. Each # action creates an instance method representing the action, which calls the - # method(s) listed as symbolswhen defining the actions. Model actions also accept + # method(s) listed as symbols when defining the actions. Model actions also accept # a rollback option, which is called if the action fails. If you plan to - # implement SimpleModel's actions make avoid naming you own methods "save", "destory", - # "create", and "update", as this will override the methods defined by action. + # implement SimpleModel's actions, avoid naming you own methods "save", "destroy", + # "create", and "update", as these will override the methods defined by action. # # Available Actions: # # save # # update # # create @@ -51,52 +54,40 @@ # class MyModel < SimpleModel::Base # # has_integers :first_int, :second_int, :default => 1 # has_times :now, :default => :get_now # - # save :save_record, :rollback => :rollback + # save :save_record, :rollback => :rollback_save # # def save_record # puts "saved" # true # end # # def get_today # Time.now # end # - # def rollback + # def rollback_save # puts "rolled back" # end # end - # - # - # class Base include SimpleModel::Attributes include SimpleModel::ErrorHelpers - #Use ActiveModel Resources include ActiveModel::Validations include ActiveModel::Conversion extend ActiveModel::Naming extend ActiveModel::Callbacks include ActiveModel::Validations::Callbacks - include ActiveModel::Dirty define_model_callbacks :save, :update, :create, :destroy class << self - # Collect methods as they are defined, then add to define_attribute_methods - def after_attribute_definition(method) - @defined_attribute_methods ||= [] - @defined_attribute_methods << method - define_attribute_methods @defined_attribute_methods - end - def save(*methods) define_model_action(methods,:save) end def create(*methods) @@ -105,77 +96,75 @@ def update(*methods) define_model_action(methods,:update) end - #Destroy does not run normal validation by default. + # Destroy does not run normal validation in Rails, but with this we can if we choose to. def destroy(*methods) define_model_action(methods,:destroy, {:validate => false}) end end - has_boolean :saved + has_boolean :persisted has_boolean :new_record, :default => true - attr_accessor :id - - def persisted? - saved? - end - - def before_attribute_set(method,val) - change_methods_str = "#{method.to_s}_will_change!".to_sym - send(change_methods_str) if val != instance_variable_get("@#{method.to_s}") && self.respond_to?(change_methods_str.to_sym) - end - + has_attribute :id # may not be an integer + alias :saved? :persisted? + private # Skeleton for action instance methods def run_model_action(methods,options) completed = true - if !options[:validate] || - (options[:validation_methods] && valid_using_other?(options[:validation_methods])) || - self.valid? - + if (!options[:validate] || (options[:validation_methods] && valid_using_other?(options[:validation_methods])) || self.valid?) methods.each do |method| ran = self.send(method) completed = ran unless ran end - if completed - self.saved = true + self.persisted = true @previously_changed = changes @changed_attributes.clear else self.send(options[:rollback]) unless options[:rollback].blank? end - else + else completed = false - end + end + if !completed && options[:raise_exception] + if !self.errors.blank? + raise ValidationError, self.errors.full_messages.join(" ") + else + raise ActionError, "failed action: #{methods.join(', ')}" + end + end completed - end + end - - # Run supplied methods as valdation. Each method should return a boolean + # Run supplied methods as validation. Each method should return a boolean # If using this option, to see if errors are present use object_name.errors.blank?, # otherwise if you run object_name.valid? you will over write the errors # generated here. def valid_using_other?(methods) valid = true methods.each do |method| valid = false unless self.send(method) end valid - end + end - - # Defines the model action's instantace methods and applied defaults. - # Defines methods with :validate options as true by default. + # Defines the model action's instance methods and applied defaults. For every + # action defined, we also define that actions ! method which raises exceptions + # when the action fails. def self.define_model_action(methods,action,default_options={:validate => true}) default_options.merge!(methods.extract_options!) - define_method(action) do |opts={}| - options = default_options.merge(opts) - self.run_callbacks(action) do - run_model_action(methods,options) + actions = [action,"#{action}!".to_sym] + actions.each do |a| + define_method(a) do |opts={}| + options = default_options.merge(opts) + options[:raise_exception] = a.to_s.match(/\!$/) + self.run_callbacks(action) do + run_model_action(methods,options) + end end end end end end \ No newline at end of file