mirror of
https://github.com/ditkrg/validates_timeliness.git
synced 2026-01-23 06:16:44 +00:00
refactored to get attribute type from model types not validation type
reverts to behaviour of old version which allows you to define validations of any type for sake of the values it is validating against
This commit is contained in:
parent
2efcff2fd4
commit
f41903a769
@ -4,17 +4,20 @@ module ValidatesTimeliness
|
|||||||
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
def define_timeliness_methods(before_type_cast=false)
|
def define_timeliness_methods(before_type_cast=false)
|
||||||
return if timeliness_validated_attributes.blank?
|
return if timeliness_validated_attributes.blank?
|
||||||
timeliness_validated_attributes.each do |attr_name, type|
|
timeliness_validated_attributes.each do |attr_name|
|
||||||
define_timeliness_write_method(attr_name, type, timeliness_attribute_timezone_aware?(attr_name))
|
define_timeliness_write_method(attr_name)
|
||||||
define_timeliness_before_type_cast_method(attr_name) if before_type_cast
|
define_timeliness_before_type_cast_method(attr_name) if before_type_cast
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
def define_timeliness_write_method(attr_name)
|
||||||
|
type = timeliness_attribute_type(attr_name)
|
||||||
|
timezone_aware = timeliness_attribute_timezone_aware?(attr_name)
|
||||||
|
|
||||||
def define_timeliness_write_method(attr_name, type, timezone_aware)
|
|
||||||
method_body, line = <<-EOV, __LINE__ + 1
|
method_body, line = <<-EOV, __LINE__ + 1
|
||||||
def #{attr_name}=(value)
|
def #{attr_name}=(value)
|
||||||
@attributes_cache ||= {}
|
@attributes_cache ||= {}
|
||||||
@ -35,12 +38,16 @@ module ValidatesTimeliness
|
|||||||
class_eval(method_body, __FILE__, line)
|
class_eval(method_body, __FILE__, line)
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
# Override in ORM shim
|
||||||
|
|
||||||
def timeliness_attribute_timezone_aware?(attr_name)
|
def timeliness_attribute_timezone_aware?(attr_name)
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Override in ORM shim
|
||||||
|
def timeliness_attribute_type(attr_name)
|
||||||
|
:datetime
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
|
|||||||
@ -5,8 +5,8 @@ module ValidatesTimeliness
|
|||||||
included do
|
included do
|
||||||
include ValidationMethods
|
include ValidationMethods
|
||||||
extend ValidationMethods
|
extend ValidationMethods
|
||||||
class_inheritable_hash :timeliness_validated_attributes
|
class_inheritable_accessor :timeliness_validated_attributes
|
||||||
self.timeliness_validated_attributes = {}
|
self.timeliness_validated_attributes = []
|
||||||
end
|
end
|
||||||
|
|
||||||
module ValidationMethods
|
module ValidationMethods
|
||||||
@ -23,14 +23,9 @@ module ValidatesTimeliness
|
|||||||
end
|
end
|
||||||
|
|
||||||
def timeliness_validation_for(attr_names, type)
|
def timeliness_validation_for(attr_names, type)
|
||||||
options = _merge_attributes(attr_names)
|
options = _merge_attributes(attr_names).merge(:type => type)
|
||||||
options[:type] = type
|
self.timeliness_validated_attributes ||= []
|
||||||
attributes = attr_names.inject({}) {|validated, attr_name|
|
self.timeliness_validated_attributes += (attr_names - self.timeliness_validated_attributes)
|
||||||
attr_name = attr_name.to_s
|
|
||||||
validated[attr_name] = type
|
|
||||||
validated
|
|
||||||
}
|
|
||||||
self.timeliness_validated_attributes = attributes
|
|
||||||
validates_with Validator, options
|
validates_with Validator, options
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -2,13 +2,19 @@ class ActiveRecord::Base
|
|||||||
include ValidatesTimeliness::HelperMethods
|
include ValidatesTimeliness::HelperMethods
|
||||||
include ValidatesTimeliness::AttributeMethods
|
include ValidatesTimeliness::AttributeMethods
|
||||||
|
|
||||||
def self.define_attribute_methods
|
class << self
|
||||||
|
def define_attribute_methods
|
||||||
super
|
super
|
||||||
# Define write method and before_type_cast method
|
# Define write method and before_type_cast method
|
||||||
define_timeliness_methods(true)
|
define_timeliness_methods(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.timeliness_attribute_timezone_aware?(attr_name)
|
def timeliness_attribute_timezone_aware?(attr_name)
|
||||||
create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name])
|
create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def timeliness_attribute_type(attr_name)
|
||||||
|
columns_hash[attr_name.to_s].type
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -7,12 +7,17 @@ module ValidatesTimeliness
|
|||||||
# field value in Mongoid. Parser will return nil rather than error.
|
# field value in Mongoid. Parser will return nil rather than error.
|
||||||
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
|
# Mongoid has no bulk attribute method definition hook. It defines
|
||||||
|
# them with each field definition. So we likewise define them after
|
||||||
|
# each validation is defined.
|
||||||
|
#
|
||||||
def timeliness_validation_for(attr_names, type)
|
def timeliness_validation_for(attr_names, type)
|
||||||
super
|
super
|
||||||
attr_names.each { |attr_name| define_timeliness_write_method(attr_name, type, false) }
|
attr_names.each { |attr_name| define_timeliness_write_method(attr_name) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def define_timeliness_write_method(attr_name, type, timezone_aware)
|
def define_timeliness_write_method(attr_name)
|
||||||
|
type = timeliness_attribute_type(attr_name)
|
||||||
method_body, line = <<-EOV, __LINE__ + 1
|
method_body, line = <<-EOV, __LINE__ + 1
|
||||||
def #{attr_name}=(value)
|
def #{attr_name}=(value)
|
||||||
@attributes_cache ||= {}
|
@attributes_cache ||= {}
|
||||||
@ -23,8 +28,17 @@ module ValidatesTimeliness
|
|||||||
EOV
|
EOV
|
||||||
class_eval(method_body, __FILE__, line)
|
class_eval(method_body, __FILE__, line)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def timeliness_attribute_type(attr_name)
|
||||||
|
{
|
||||||
|
Date => :date,
|
||||||
|
Time => :datetime,
|
||||||
|
DateTime => :datetime
|
||||||
|
}[fields[attr_name.to_s].type] || :datetime
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -48,11 +48,13 @@ end
|
|||||||
|
|
||||||
class Person
|
class Person
|
||||||
include TestModel
|
include TestModel
|
||||||
self.model_attributes = :birth_date, :birth_time, :birth_datetime
|
attribute :birth_date, :date
|
||||||
|
attribute :birth_time, :time
|
||||||
|
attribute :birth_datetime, :datetime
|
||||||
validates_date :birth_date
|
validates_date :birth_date
|
||||||
validates_time :birth_time
|
validates_time :birth_time
|
||||||
validates_datetime :birth_datetime
|
validates_datetime :birth_datetime
|
||||||
define_attribute_methods model_attributes
|
define_attribute_methods model_attributes.keys
|
||||||
end
|
end
|
||||||
|
|
||||||
ActiveRecord::Base.time_zone_aware_attributes = true
|
ActiveRecord::Base.time_zone_aware_attributes = true
|
||||||
@ -62,8 +64,8 @@ ActiveRecord::Schema.define(:version => 1) do
|
|||||||
create_table :employees, :force => true do |t|
|
create_table :employees, :force => true do |t|
|
||||||
t.string :first_name
|
t.string :first_name
|
||||||
t.string :last_name
|
t.string :last_name
|
||||||
t.datetime :birth_date
|
t.date :birth_date
|
||||||
t.datetime :birth_time
|
t.time :birth_time
|
||||||
t.datetime :birth_datetime
|
t.datetime :birth_datetime
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -80,10 +82,10 @@ Rspec.configure do |c|
|
|||||||
c.include(RspecTagMatchers)
|
c.include(RspecTagMatchers)
|
||||||
c.before do
|
c.before do
|
||||||
Person.reset_callbacks(:validate)
|
Person.reset_callbacks(:validate)
|
||||||
Person.timeliness_validated_attributes = {}
|
Person.timeliness_validated_attributes = []
|
||||||
Person._validators.clear
|
Person._validators.clear
|
||||||
Employee.reset_callbacks(:validate)
|
Employee.reset_callbacks(:validate)
|
||||||
Employee.timeliness_validated_attributes = {}
|
Employee.timeliness_validated_attributes = []
|
||||||
Employee._validators.clear
|
Employee._validators.clear
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -13,24 +13,29 @@ module TestModel
|
|||||||
end
|
end
|
||||||
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
|
def attribute(name, type)
|
||||||
|
self.model_attributes ||= {}
|
||||||
|
self.model_attributes[name] = type
|
||||||
|
end
|
||||||
|
|
||||||
def define_method_attribute=(attr_name)
|
def define_method_attribute=(attr_name)
|
||||||
generated_attribute_methods.module_eval("def #{attr_name}=(new_value); @attributes['#{attr_name}']=self.class.type_cast(new_value); end", __FILE__, __LINE__)
|
generated_attribute_methods.module_eval("def #{attr_name}=(new_value); @attributes['#{attr_name}']=self.class.type_cast('#{attr_name}', new_value); end", __FILE__, __LINE__)
|
||||||
end
|
end
|
||||||
|
|
||||||
def define_method_attribute(attr_name)
|
def define_method_attribute(attr_name)
|
||||||
generated_attribute_methods.module_eval("def #{attr_name}; @attributes['#{attr_name}']; end", __FILE__, __LINE__)
|
generated_attribute_methods.module_eval("def #{attr_name}; @attributes['#{attr_name}']; end", __FILE__, __LINE__)
|
||||||
end
|
end
|
||||||
|
|
||||||
def type_cast(value)
|
def type_cast(attr_name, value)
|
||||||
return value unless value.is_a?(String)
|
return value unless value.is_a?(String)
|
||||||
value.to_time rescue nil
|
value.send("to_#{model_attributes[attr_name.to_sym]}") rescue nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module DynamicMethods
|
module DynamicMethods
|
||||||
def method_missing(method_id, *args, &block)
|
def method_missing(method_id, *args, &block)
|
||||||
if !self.class.attribute_methods_generated?
|
if !self.class.attribute_methods_generated?
|
||||||
self.class.define_attribute_methods self.class.model_attributes.map(&:to_s)
|
self.class.define_attribute_methods self.class.model_attributes.keys.map(&:to_s)
|
||||||
method_name = method_id.to_s
|
method_name = method_id.to_s
|
||||||
send(method_id, *args, &block)
|
send(method_id, *args, &block)
|
||||||
else
|
else
|
||||||
|
|||||||
@ -8,7 +8,9 @@ describe ValidatesTimeliness::AttributeMethods do
|
|||||||
context "attribute write method" do
|
context "attribute write method" do
|
||||||
class PersonWithCache
|
class PersonWithCache
|
||||||
include TestModel
|
include TestModel
|
||||||
self.model_attributes = :birth_date, :birth_time, :birth_datetime
|
attribute :birth_date, :date
|
||||||
|
attribute :birth_time, :time
|
||||||
|
attribute :birth_datetime, :datetime
|
||||||
validates_date :birth_date
|
validates_date :birth_date
|
||||||
validates_time :birth_time
|
validates_time :birth_time
|
||||||
validates_datetime :birth_datetime
|
validates_datetime :birth_datetime
|
||||||
@ -23,7 +25,9 @@ describe ValidatesTimeliness::AttributeMethods do
|
|||||||
context "with plugin parser" do
|
context "with plugin parser" do
|
||||||
class PersonWithParser
|
class PersonWithParser
|
||||||
include TestModel
|
include TestModel
|
||||||
self.model_attributes = :birth_date, :birth_time, :birth_datetime
|
attribute :birth_date, :date
|
||||||
|
attribute :birth_time, :time
|
||||||
|
attribute :birth_datetime, :datetime
|
||||||
validates_date :birth_date
|
validates_date :birth_date
|
||||||
validates_time :birth_time
|
validates_time :birth_time
|
||||||
validates_datetime :birth_datetime
|
validates_datetime :birth_datetime
|
||||||
|
|||||||
@ -21,16 +21,12 @@ describe ValidatesTimeliness::HelperMethods do
|
|||||||
|
|
||||||
describe ".timeliness_validated_attributes" do
|
describe ".timeliness_validated_attributes" do
|
||||||
it 'should return attributes validated with plugin validator' do
|
it 'should return attributes validated with plugin validator' do
|
||||||
Person.timeliness_validated_attributes = {}
|
Person.timeliness_validated_attributes = []
|
||||||
Person.validates_date :birth_date
|
Person.validates_date :birth_date
|
||||||
Person.validates_time :birth_time
|
Person.validates_time :birth_time
|
||||||
Person.validates_datetime :birth_datetime
|
Person.validates_datetime :birth_datetime
|
||||||
|
|
||||||
Person.timeliness_validated_attributes.should == {
|
Person.timeliness_validated_attributes.should == [ :birth_date, :birth_time, :birth_datetime ]
|
||||||
"birth_date" => :date,
|
|
||||||
"birth_time" => :time,
|
|
||||||
"birth_datetime" => :datetime
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -16,8 +16,8 @@ describe ValidatesTimeliness, 'ActiveRecord' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should define _timeliness_raw_value_for instance method' do
|
it 'should determine type for attribute' do
|
||||||
Employee.instance_methods.should include('_timeliness_raw_value_for')
|
Employee.timeliness_attribute_type(:birth_date).should == :date
|
||||||
end
|
end
|
||||||
|
|
||||||
context "attribute write method" do
|
context "attribute write method" do
|
||||||
|
|||||||
@ -38,8 +38,8 @@ describe ValidatesTimeliness, 'Mongoid' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should define _timeliness_raw_value_for instance method' do
|
it 'should determine type for attribute' do
|
||||||
Article.instance_methods.should include('_timeliness_raw_value_for')
|
Article.timeliness_attribute_type(:publish_date).should == :date
|
||||||
end
|
end
|
||||||
|
|
||||||
context "attribute write method" do
|
context "attribute write method" do
|
||||||
|
|||||||
@ -101,7 +101,9 @@ describe ValidatesTimeliness::Validator do
|
|||||||
describe ":format option" do
|
describe ":format option" do
|
||||||
class PersonWithFormatOption
|
class PersonWithFormatOption
|
||||||
include TestModel
|
include TestModel
|
||||||
self.model_attributes = :birth_date, :birth_time, :birth_datetime
|
attribute :birth_date, :date
|
||||||
|
attribute :birth_time, :time
|
||||||
|
attribute :birth_datetime, :datetime
|
||||||
validates_date :birth_date, :format => 'dd-mm-yyyy'
|
validates_date :birth_date, :format => 'dd-mm-yyyy'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user