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
|
||||
end
|
||||
|
||||
def undefine_attribute_methods
|
||||
super
|
||||
undefine_timeliness_attribute_methods
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def define_timeliness_methods(before_type_cast=false)
|
||||
return if timeliness_validated_attributes.blank?
|
||||
timeliness_validated_attributes.each do |attr_name|
|
||||
@ -34,55 +27,62 @@ module ValidatesTimeliness
|
||||
end
|
||||
end
|
||||
|
||||
def generated_timeliness_methods
|
||||
@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
|
||||
|
||||
def undefine_timeliness_attribute_methods
|
||||
generated_timeliness_methods.synchronize do
|
||||
generated_timeliness_methods.module_eval do
|
||||
instance_methods.each { |m| undef_method(m) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
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
|
||||
generated_timeliness_methods.module_eval <<-STR, __FILE__, __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)
|
||||
write_timeliness_attribute('#{attr_name}', value)
|
||||
end
|
||||
EOV
|
||||
generated_timeliness_methods.module_eval(method_body, __FILE__, line)
|
||||
STR
|
||||
end
|
||||
|
||||
def define_timeliness_before_type_cast_method(attr_name)
|
||||
method_body, line = <<-EOV, __LINE__ + 1
|
||||
generated_timeliness_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
||||
def #{attr_name}_before_type_cast
|
||||
_timeliness_raw_value_for('#{attr_name}') || @attributes['#{attr_name}']
|
||||
read_timeliness_attribute_before_type_cast('#{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
|
||||
@generated_timeliness_methods ||= Module.new.tap { |m| include(m) }
|
||||
end
|
||||
|
||||
def undefine_timeliness_attribute_methods
|
||||
generated_timeliness_methods.module_eval do
|
||||
instance_methods.each { |m| undef_method(m) }
|
||||
end
|
||||
STR
|
||||
end
|
||||
end
|
||||
|
||||
def _timeliness_raw_value_for(attr_name)
|
||||
@timeliness_cache && @timeliness_cache[attr_name]
|
||||
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
|
||||
|
||||
def _clear_timeliness_cache
|
||||
|
||||
@ -14,30 +14,74 @@ module ValidatesTimeliness
|
||||
timeliness_column_for_attribute(attr_name).type
|
||||
end
|
||||
|
||||
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
|
||||
::ActiveRecord::ConnectionAdapters::Column.new(attr_name, nil, validation_type.to_s)
|
||||
if ActiveModel.version >= Gem::Version.new('4.2')
|
||||
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, 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
|
||||
|
||||
def define_attribute_methods
|
||||
super.tap do |attribute_methods_generated|
|
||||
return false if @timeliness_methods_generated
|
||||
define_timeliness_methods true
|
||||
@timeliness_methods_generated = true
|
||||
end
|
||||
super.tap {
|
||||
generated_timeliness_methods.synchronize do
|
||||
return if @timeliness_methods_generated
|
||||
define_timeliness_methods true
|
||||
@timeliness_methods_generated = true
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def timeliness_type_cast_code(attr_name, var_name)
|
||||
type = timeliness_attribute_type(attr_name)
|
||||
|
||||
method_body = super
|
||||
method_body << "\n#{var_name} = #{var_name}.to_date if #{var_name}" if type == :date
|
||||
method_body
|
||||
def undefine_attribute_methods
|
||||
super.tap {
|
||||
generated_timeliness_methods.synchronize do
|
||||
return unless @timeliness_methods_generated
|
||||
undefine_timeliness_attribute_methods
|
||||
@timeliness_methods_generated = true
|
||||
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
|
||||
|
||||
def reload(*args)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user