methods for validated attributes for write cache and before type cast

cache raw value in @attributes_cache which is AR convention but should
work fine with non-AR ORM
before type cast method for reading back cached raw value
This commit is contained in:
Adam Meehan 2010-08-03 15:01:57 +10:00
parent 6bed71152a
commit 34a2d4b558
6 changed files with 90 additions and 1 deletions

View File

@ -29,13 +29,17 @@ module ValidatesTimeliness
# Setup method for plugin configuration
def self.setup
yield self
extend_classes.each {|klass| klass.send(:include, ValidatesTimeliness::HelperMethods) }
extend_classes.each {|klass|
klass.send(:include, ValidatesTimeliness::HelperMethods)
klass.send(:include, ValidatesTimeliness::AttributeMethods)
}
end
end
require 'validates_timeliness/conversion'
require 'validates_timeliness/validator'
require 'validates_timeliness/helper_methods'
require 'validates_timeliness/attribute_methods'
require 'validates_timeliness/extensions'
require 'validates_timeliness/version'

View File

@ -0,0 +1,43 @@
module ValidatesTimeliness
module AttributeMethods
extend ActiveSupport::Concern
included do
attribute_method_suffix "_before_type_cast"
end
module ClassMethods
protected
def define_method_attribute=(attr_name)
if timeliness_validated_attributes.include?(attr_name)
method_body, line = <<-EOV, __LINE__ + 1
def #{attr_name}=(value)
@attributes_cache ||= {}
@attributes_cache["_#{attr_name}_before_type_cast"] = value
super
end
EOV
class_eval(method_body, __FILE__, line)
else
super
end
end
def define_method_attribute_before_type_cast(attr_name)
if timeliness_validated_attributes.include?(attr_name)
method_body, line = <<-EOV, __LINE__ + 1
def #{attr_name}_before_type_cast
@attributes_cache && @attributes_cache["_#{attr_name}_before_type_cast"]
end
EOV
class_eval(method_body, __FILE__, line)
else
super rescue(NoMethodError)
end
end
end
end
end

View File

@ -20,5 +20,15 @@ module ValidatesTimeliness
validates_with Validator, _merge_attributes(attr_names).merge(:type => :datetime)
end
end
module ClassMethods
def timeliness_validated_attributes
@timeliness_validated_attributes ||= begin
_validators.map do |attr_name, validators|
attr_name.to_s if validators.any? {|v| v.is_a?(ValidatesTimeliness::Validator) }
end.compact
end
end
end
end
end

View File

@ -25,12 +25,15 @@ LOCALE_PATH = File.expand_path(File.dirname(__FILE__) + '/../lib/validates_timel
I18n.load_path.unshift(LOCALE_PATH)
class Person
include ActiveModel::AttributeMethods
include ActiveModel::Validations
extend ActiveModel::Translation
attr_accessor :birth_date, :birth_time, :birth_datetime
attr_accessor :attributes
def initialize(attributes = {})
@attributes = {}
attributes.each do |key, value|
send "#{key}=", value
end

View File

@ -0,0 +1,22 @@
require 'spec_helper'
describe ValidatesTimeliness::AttributeMethods do
before do
Employee.validates_datetime :birth_datetime
Employee.define_attribute_methods
end
it 'should define attribute write method for validated attributes' do
Employee.instance_methods(false).should include("birth_datetime=")
end
it 'should define attribute before_type_cast method for validated attributes' do
Employee.instance_methods(false).should include("birth_datetime_before_type_cast")
end
it 'should store original raw value on attribute write' do
r = Employee.new
r.birth_datetime = '2010-01-01'
r.birth_datetime_before_type_cast.should == '2010-01-01'
end
end

View File

@ -12,4 +12,11 @@ describe ValidatesTimeliness::HelperMethods do
ActiveRecord::Base.instance_methods.should include('validates_time')
ActiveRecord::Base.instance_methods.should include('validates_datetime')
end
describe ".timeliness_validated_attributes" do
it 'should return attributes validated with plugin validator' do
Person.validates_date :birth_date
Person.timeliness_validated_attributes.should == ["birth_date"]
end
end
end