mirror of
https://github.com/ditkrg/validates_timeliness.git
synced 2026-01-22 22:06:45 +00:00
Rails 4.x attribute assignment compatability
This commit is contained in:
parent
08b16f155c
commit
afa8dee6ab
@ -20,13 +20,6 @@ module ValidatesTimeliness
|
|||||||
:datetime
|
:datetime
|
||||||
end
|
end
|
||||||
|
|
||||||
def undefine_attribute_methods
|
|
||||||
super
|
|
||||||
undefine_timeliness_attribute_methods
|
|
||||||
end
|
|
||||||
|
|
||||||
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|
|
timeliness_validated_attributes.each do |attr_name|
|
||||||
@ -34,55 +27,62 @@ module ValidatesTimeliness
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def define_attribute_timeliness_methods(attr_name, before_type_cast=false)
|
|
||||||
define_timeliness_write_method(attr_name)
|
|
||||||
define_timeliness_before_type_cast_method(attr_name) if before_type_cast
|
|
||||||
end
|
|
||||||
|
|
||||||
def define_timeliness_write_method(attr_name)
|
|
||||||
method_body, line = <<-EOV, __LINE__ + 1
|
|
||||||
def #{attr_name}=(value)
|
|
||||||
original_value = value
|
|
||||||
@timeliness_cache ||= {}
|
|
||||||
@timeliness_cache["#{attr_name}"] = original_value
|
|
||||||
#{ "if value.is_a?(String)\n#{timeliness_type_cast_code(attr_name, 'value')}\nend" if ValidatesTimeliness.use_plugin_parser }
|
|
||||||
|
|
||||||
super(value)
|
|
||||||
end
|
|
||||||
EOV
|
|
||||||
generated_timeliness_methods.module_eval(method_body, __FILE__, line)
|
|
||||||
end
|
|
||||||
|
|
||||||
def define_timeliness_before_type_cast_method(attr_name)
|
|
||||||
method_body, line = <<-EOV, __LINE__ + 1
|
|
||||||
def #{attr_name}_before_type_cast
|
|
||||||
_timeliness_raw_value_for('#{attr_name}') || @attributes['#{attr_name}']
|
|
||||||
end
|
|
||||||
EOV
|
|
||||||
generated_timeliness_methods.module_eval(method_body, __FILE__, line)
|
|
||||||
end
|
|
||||||
|
|
||||||
def timeliness_type_cast_code(attr_name, var_name)
|
|
||||||
type = timeliness_attribute_type(attr_name)
|
|
||||||
timezone_aware = timeliness_attribute_timezone_aware?(attr_name)
|
|
||||||
timezone = :current if timezone_aware
|
|
||||||
|
|
||||||
"#{var_name} = Timeliness::Parser.parse(#{var_name}, :#{type}, :zone => #{timezone.inspect})"
|
|
||||||
end
|
|
||||||
|
|
||||||
def generated_timeliness_methods
|
def generated_timeliness_methods
|
||||||
@generated_timeliness_methods ||= Module.new.tap { |m| include(m) }
|
@generated_timeliness_methods ||= Module.new { |m|
|
||||||
|
extend Mutex_m
|
||||||
|
}.tap { |mod| include mod }
|
||||||
|
end
|
||||||
|
|
||||||
|
def undefine_attribute_methods
|
||||||
|
super.tap { undefine_timeliness_attribute_methods }
|
||||||
end
|
end
|
||||||
|
|
||||||
def undefine_timeliness_attribute_methods
|
def undefine_timeliness_attribute_methods
|
||||||
|
generated_timeliness_methods.synchronize do
|
||||||
generated_timeliness_methods.module_eval do
|
generated_timeliness_methods.module_eval do
|
||||||
instance_methods.each { |m| undef_method(m) }
|
instance_methods.each { |m| undef_method(m) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def _timeliness_raw_value_for(attr_name)
|
protected
|
||||||
@timeliness_cache && @timeliness_cache[attr_name]
|
|
||||||
|
def define_attribute_timeliness_methods(attr_name, before_type_cast=false)
|
||||||
|
define_timeliness_write_method(attr_name)
|
||||||
|
define_timeliness_before_type_cast_method(attr_name) if before_type_cast
|
||||||
|
end
|
||||||
|
|
||||||
|
def define_timeliness_write_method(attr_name)
|
||||||
|
generated_timeliness_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
||||||
|
def #{attr_name}=(value)
|
||||||
|
write_timeliness_attribute('#{attr_name}', value)
|
||||||
|
end
|
||||||
|
STR
|
||||||
|
end
|
||||||
|
|
||||||
|
def define_timeliness_before_type_cast_method(attr_name)
|
||||||
|
generated_timeliness_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
||||||
|
def #{attr_name}_before_type_cast
|
||||||
|
read_timeliness_attribute_before_type_cast('#{attr_name}')
|
||||||
|
end
|
||||||
|
STR
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_timeliness_attribute(attr_name, value)
|
||||||
|
@timeliness_cache ||= {}
|
||||||
|
@timeliness_cache[attr_name] = value
|
||||||
|
|
||||||
|
if ValidatesTimeliness.use_plugin_parser
|
||||||
|
timezone = :current if self.class.timeliness_attribute_timezone_aware?(attr_name)
|
||||||
|
value = Timeliness::Parser.parse(value, self.class.timeliness_attribute_type(attr_name), :zone => timezone)
|
||||||
|
end
|
||||||
|
|
||||||
|
@attributes[attr_name] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_timeliness_attribute_before_type_cast(attr_name)
|
||||||
|
@timeliness_cache && @timeliness_cache[attr_name] || @attributes[attr_name]
|
||||||
end
|
end
|
||||||
|
|
||||||
def _clear_timeliness_cache
|
def _clear_timeliness_cache
|
||||||
|
|||||||
@ -14,30 +14,74 @@ module ValidatesTimeliness
|
|||||||
timeliness_column_for_attribute(attr_name).type
|
timeliness_column_for_attribute(attr_name).type
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if ActiveModel.version >= Gem::Version.new('4.2')
|
||||||
def timeliness_column_for_attribute(attr_name)
|
def timeliness_column_for_attribute(attr_name)
|
||||||
columns_hash.fetch(attr_name.to_s) do |attr_name|
|
columns_hash.fetch(attr_name.to_s) do |attr_name|
|
||||||
validation_type = _validators[attr_name.to_sym].find {|v| v.kind == :timeliness }.type
|
validation_type = _validators[attr_name.to_sym].find {|v| v.kind == :timeliness }.type.to_s
|
||||||
::ActiveRecord::ConnectionAdapters::Column.new(attr_name, nil, validation_type.to_s)
|
::ActiveRecord::ConnectionAdapters::Column.new(attr_name, nil, lookup_cast_type(validation_type), validation_type)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def lookup_cast_type(sql_type)
|
||||||
|
case sql_type
|
||||||
|
when 'datetime' then ::ActiveRecord::Type::DateTime.new
|
||||||
|
when 'date' then ::ActiveRecord::Type::Date.new
|
||||||
|
when 'time' then ::ActiveRecord::Type::Time.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
def timeliness_column_for_attribute(attr_name)
|
||||||
|
columns_hash.fetch(attr_name.to_s) do |attr_name|
|
||||||
|
validation_type = _validators[attr_name.to_sym].find {|v| v.kind == :timeliness }.type.to_s
|
||||||
|
::ActiveRecord::ConnectionAdapters::Column.new(attr_name, nil, validation_type)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def define_attribute_methods
|
def define_attribute_methods
|
||||||
super.tap do |attribute_methods_generated|
|
super.tap {
|
||||||
return false if @timeliness_methods_generated
|
generated_timeliness_methods.synchronize do
|
||||||
|
return if @timeliness_methods_generated
|
||||||
define_timeliness_methods true
|
define_timeliness_methods true
|
||||||
@timeliness_methods_generated = true
|
@timeliness_methods_generated = true
|
||||||
end
|
end
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
def undefine_attribute_methods
|
||||||
|
super.tap {
|
||||||
def timeliness_type_cast_code(attr_name, var_name)
|
generated_timeliness_methods.synchronize do
|
||||||
type = timeliness_attribute_type(attr_name)
|
return unless @timeliness_methods_generated
|
||||||
|
undefine_timeliness_attribute_methods
|
||||||
method_body = super
|
@timeliness_methods_generated = true
|
||||||
method_body << "\n#{var_name} = #{var_name}.to_date if #{var_name}" if type == :date
|
|
||||||
method_body
|
|
||||||
end
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
# Override to overwrite methods in ActiveRecord attribute method module because in AR 4+
|
||||||
|
# there is curious code which calls the method directly from the generated methods module
|
||||||
|
# via bind inside method_missing. This means our method in the formerly custom timeliness
|
||||||
|
# methods module was never reached.
|
||||||
|
def generated_timeliness_methods
|
||||||
|
generated_attribute_methods
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_timeliness_attribute(attr_name, value)
|
||||||
|
@timeliness_cache ||= {}
|
||||||
|
@timeliness_cache[attr_name] = value
|
||||||
|
|
||||||
|
if ValidatesTimeliness.use_plugin_parser
|
||||||
|
type = self.class.timeliness_attribute_type(attr_name)
|
||||||
|
timezone = :current if self.class.timeliness_attribute_timezone_aware?(attr_name)
|
||||||
|
value = Timeliness::Parser.parse(value, type, :zone => timezone)
|
||||||
|
value = value.to_date if value && type == :date
|
||||||
|
end
|
||||||
|
|
||||||
|
write_attribute(attr_name, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_timeliness_attribute_before_type_cast(attr_name)
|
||||||
|
@timeliness_cache && @timeliness_cache[attr_name] || read_attribute_before_type_cast(attr_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reload(*args)
|
def reload(*args)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user