So you want to use ActiveRecords Validations but don’t want to inherit from ActiveRecord::Base?
There are a few different approaches
class ValidatingBase
def save; end
def save!; end
def update_attribute; end
def new_record?; end
def self.human_attribute_name(arg)
arg.to_s
end
include ActiveRecord::Validations
def [](key)
instance_variable_get(key)
end
def initialize(attributes = nil)
return nil if attributes.nil?
attributes.each do |key, value|
method("#{key}=").call(value)
end
end
end
Dispatcher.reset_application
Copy Dispatcher.reset_application from dispatcher.rb in the rails library in to public/dispatch.rb, and add ValidatingBase to the list of arguments passed to Dependencies.remove_subclasses_for. This will allow reloading pages in development mode to pick up changes to ValidatingBase subclasses. You should end up with something like this:
Note: with the latest version of Edge Rails, just add ‘include Reloadable’ to ValidatingBase and skip this step.
Note about previous note: “the latest version of Edge Rails” is a moving target; it is possibly quite different from what it was when this was first written up. At the very least such statements should be labelled with the current release number, so we can tell how stale this information has become.
Further note: The ‘latest version’ must be before 1.2. In the release candidate for 1.2, Reloadable is deprecated. It looks like you do not have to do anything to get the class reloadable as of 1.2.
require "dispatcher"
# Add this:
class Dispatcher
class << self
private
def reset_application
if Dependencies.load?
Controllers.clear!
Dependencies.clear
Dependencies.remove_subclasses_for(
ActiveRecord::Base,
ActiveRecord::Observer,
ActionController::Base,
ValidatingBase)
end
Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT)
end
end
end
ADDITIONAL_LOAD_PATHS.reverse.each \
{ |dir| $:.unshift(dir) if File.directory?(dir) } \
if defined?(Apache::RubyRun)
Dispatcher.dispatch
class Something < ValidatingBase
attr_accessor :foo
validates_length_of :foo, :within => 5..8
end
s = Something.new
s.foo = "wibble"
s.valid?
Note: Do not set model :something in your controller, as it will result in compounding error messages and they will not be reset. Another problem is that you will receive an error for a dynamic method called _XXXX_before_type_cast_ when trying to use _validates_numaricality_of_ which I have not investigated yet.
Note: Adding a method_missing to your validating base will eliminate the dynamic method error:
def method_missing( method_id, *args )
method_name = method_id.to_s
if md = /_before_type_cast$/.match(method_name)
attribute_name, method_type = md.pre_match, md.to_s
if self.respond_to?(attribute_name)
self.instance_variable_get("@#{attribute_name}")
else
super
end
else
super
end
end
category: Howto