acts_as_having_settings.rb
2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
# declare missing types
module ActiveRecord
module Type
class Symbol < Value
def cast_value value
value.to_sym
end
end
class Array < Value
def cast_value value
::Array.wrap(value)
end
end
class Hash < Value
def cast_value value
h = ::Hash[value]
h.symbolize_keys!
h
end
end
end
end
module ActsAsHavingSettings
def self.type_cast value, type
# do not cast nil
return value if value.nil?
type.send :cast_value, value
end
module ClassMethods
def acts_as_having_settings(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
field = (options[:field] || :settings).to_sym
serialize field, Hash
class_attribute :settings_field
self.settings_field = field
class_eval do
def settings_field
self[self.class.settings_field] ||= Hash.new
end
def setting_changed? setting_field
setting_field = setting_field.to_sym
changed_settings = self.changes[self.class.settings_field]
return false if changed_settings.nil?
old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field]
new_setting_value = changed_settings.last[setting_field]
old_setting_value != new_setting_value
end
end
settings_items *args
end
def settings_items *names
options = names.extract_options!
default = options[:default]
type = options[:type]
type = if type.present? then ActiveRecord::Type.const_get(type.to_s.camelize.to_sym).new else nil end
names.each do |setting|
# symbolize key
setting = setting.to_sym
define_method setting do
h = send self.class.settings_field
val = h[setting]
# translate default value if it is used
if not val.nil? then val elsif default.is_a? String then gettext default else default end
end
define_method "#{setting}=" do |value|
h = send self.class.settings_field
h[setting] = if type then ActsAsHavingSettings.type_cast value, type else value end
end
end
end
end
end
ActiveRecord::Base.send(:extend, ActsAsHavingSettings::ClassMethods)