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