48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
# File 'lib/active_tools/active_record/adaptive_belongs_to.rb', line 48
def adaptive_belongs_to(*args)
options = args.
assoc_name = args.first
unless reflection = reflections.with_indifferent_access[assoc_name]
raise(ArgumentError, ":#{assoc_name} method doesn't look like an association accessor!")
end
adapter_name = "#{assoc_name}_adaptive"
raise(TypeError, "Option :attributes must be a Hash. #{options[:attributes].class} passed!") unless options[:attributes].is_a?(Hash)
attr_map = HashWithIndifferentAccess.new(options.delete(:attributes))
valid_options = Hash(options.delete(:valid_with)).symbolize_keys
valid_with assoc_name, valid_options.merge(:attributes => attr_map)
class_attribute :adaptive_options unless defined?(adaptive_options)
self.adaptive_options ||= {}
self.adaptive_options[assoc_name.to_sym] = options.merge(:attr_map => attr_map)
class_eval <<-EOV
before_validation do
#{adapter_name}.try_nullify||#{adapter_name}.try_commit
#{adapter_name}.target_process_do
end
before_save do
#{adapter_name}.update_target_if_changed!
end
after_save do
#{adapter_name}.try_destroy_backup
#{adapter_name}.clear!
end
after_destroy do
#{adapter_name}.try_destroy
end
def #{adapter_name}
@#{adapter_name} ||= ActiveTools::ActiveRecord::AdaptiveBelongsTo::Adapter.new(self, :#{assoc_name}, adaptive_options[:#{assoc_name}])
end
EOV
attr_map.each do |remote_attribute, local_attribute|
if Rails.version >= "5.0"
attribute local_attribute, reflection.klass.attribute_types[remote_attribute].dup
after_initialize do
self[local_attribute] = send(local_attribute)
end
end
relation_options_under(local_attribute, assoc_name => remote_attribute)
class_eval do
define_method local_attribute do
send(adapter_name).read(remote_attribute)
end
define_method "#{local_attribute}=" do |value|
if Rails.version >= "5.0"
super send(adapter_name).write(remote_attribute, value)
else
send(adapter_name).write(remote_attribute, value)
end
end
end
end
end
|