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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
# File 'lib/has_constant/orm/mongoid.rb', line 19
def has_constant( name, values = lambda { I18n.t(name) }, options = {} )
super(name, values, options)
singular = (options[:accessor] || name.to_s.singularize).to_s
plural = (options[:accessor] || name.to_s)
class_eval do
unless fields.map(&:first).include?(singular.to_s)
if options[:as] == :array
field plural.to_sym, { :type => Array, :default => [] }.
merge(options)
else
if values.is_a?(Hash) || values.respond_to?(:call) &&
values.call.is_a?(Hash)
type = String
else
type = Integer
end
field singular.to_sym, { :type => type }.merge(options)
end
end
index singular.to_sym, :background => true if options[:index]
unless respond_to?(:by_constant)
scope :by_constant, lambda { |constant, value|
if self.send(constant.pluralize).respond_to?(:key)
value_for_query = self.send(constant.pluralize).key(value)
value_for_query ||= I18n.with_locale(:en) do
self.send(constant.pluralize).key(value)
end
else
value_for_query = self.send(constant.pluralize).index(value)
value_for_query ||= I18n.with_locale(:en) do
send(contant.pluralize).index(value)
end
end
where(constant.to_sym => value_for_query)
}
end
end
if options[:as] == :array
define_method("#{plural}=") do |value_set|
indexes = (value_set.blank? ? [] : value_set).map do |value|
if self.class.send(plural).respond_to?(:key)
self.class.send(plural).key(value)
else
self.class.send(plural).index(value)
end
end
write_attribute plural, indexes
end
end
define_method("#{singular}=") do |val|
if val.instance_of?(String)
if self.class.send(name).respond_to?(:key)
index = self.class.send(name.to_s).key(val).to_s
elsif self.class.send(name).respond_to?(:index)
index = self.class.send(name.to_s).index(val)
index = index.to_s if self.class.send(name.to_s).is_a?(Hash)
end
if index
write_attribute singular.to_sym, index
elsif !val.blank?
values = values.call if values.respond_to?(:call)
@has_constant_errors ||= {}
@has_constant_errors.merge!(singular.to_sym => "must be one of #{values.join(', ')}")
end
else
write_attribute singular.to_sym, val
end
end
if options[:as] == :array
define_method(plural) do
attributes[plural].map { |val| self.class.send(plural)[val] }
end
end
define_method(singular) do
if attributes[singular]
res = self.class.send(name.to_s)[attributes[singular].to_i] rescue nil
res ||= self.class.send(name.to_s)[attributes[singular]]
res ||= self.class.send(name.to_s)[attributes[singular].to_sym]
end
end
(class << self; self; end).instance_eval do
if options[:as] == :array
define_method "#{plural}_include".to_sym do |value|
if value.is_a?(String)
if values.respond_to?(:key)
where(plural.to_sym => values.key(value))
else
where(plural.to_sym => values.index(value))
end
else
if values.respond_to?(:key)
where(plural.to_sym => value.map { |v| send(plural).key(v) })
else
where(plural.to_sym => value.map { |v| send(plural).index(v) })
end
end
end
else
define_method "#{singular}_is".to_sym do |values|
values = values.lines.to_a if values.respond_to?(:lines)
where(singular.to_sym.in => values.map do |v|
if send(name).respond_to?(:key)
send(name).key(v) || I18n.with_locale(:en) { send(name).key(v) }
else
send(name).index(v) || I18n.with_locale(:en) { send(name).index(v) }
end
end)
end
define_method "#{singular}_is_not".to_sym do |values|
values = values.lines.to_a if values.respond_to?(:lines)
if send(plural).respond_to?(:key)
values_for_query = values.map { |v| send(plural).key(v) }.compact
values_for_query = values.map do |v|
I18n.with_locale(:en) { send(plural).key(v) }
end.compact if values_for_query.blank?
else
values_for_query = values.map { |v| send(plural).index(v) }.compact
values_for_query = values.map do |v|
I18n.with_locale(:en) { send(plural).index(v) }
end.compact if values_for_query.blank?
end
where(singular.to_sym.nin => values_for_query)
end
end
end
end
|