##// END OF EJS Templates
Set inverse on custom_values association....
Jean-Philippe Lang -
r15838:2c70d9e9886e
parent child
Show More
@@ -1,168 +1,169
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 module Redmine
18 module Redmine
19 module Acts
19 module Acts
20 module Customizable
20 module Customizable
21 def self.included(base)
21 def self.included(base)
22 base.extend ClassMethods
22 base.extend ClassMethods
23 end
23 end
24
24
25 module ClassMethods
25 module ClassMethods
26 def acts_as_customizable(options = {})
26 def acts_as_customizable(options = {})
27 return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
27 return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
28 cattr_accessor :customizable_options
28 cattr_accessor :customizable_options
29 self.customizable_options = options
29 self.customizable_options = options
30 has_many :custom_values, lambda {includes(:custom_field).order("#{CustomField.table_name}.position")},
30 has_many :custom_values, lambda {includes(:custom_field).order("#{CustomField.table_name}.position")},
31 :as => :customized,
31 :as => :customized,
32 :inverse_of => :customized,
32 :dependent => :delete_all,
33 :dependent => :delete_all,
33 :validate => false
34 :validate => false
34
35
35 send :include, Redmine::Acts::Customizable::InstanceMethods
36 send :include, Redmine::Acts::Customizable::InstanceMethods
36 validate :validate_custom_field_values
37 validate :validate_custom_field_values
37 after_save :save_custom_field_values
38 after_save :save_custom_field_values
38 end
39 end
39 end
40 end
40
41
41 module InstanceMethods
42 module InstanceMethods
42 def self.included(base)
43 def self.included(base)
43 base.extend ClassMethods
44 base.extend ClassMethods
44 end
45 end
45
46
46 def available_custom_fields
47 def available_custom_fields
47 CustomField.where("type = '#{self.class.name}CustomField'").sorted.to_a
48 CustomField.where("type = '#{self.class.name}CustomField'").sorted.to_a
48 end
49 end
49
50
50 # Sets the values of the object's custom fields
51 # Sets the values of the object's custom fields
51 # values is an array like [{'id' => 1, 'value' => 'foo'}, {'id' => 2, 'value' => 'bar'}]
52 # values is an array like [{'id' => 1, 'value' => 'foo'}, {'id' => 2, 'value' => 'bar'}]
52 def custom_fields=(values)
53 def custom_fields=(values)
53 values_to_hash = values.inject({}) do |hash, v|
54 values_to_hash = values.inject({}) do |hash, v|
54 v = v.stringify_keys
55 v = v.stringify_keys
55 if v['id'] && v.has_key?('value')
56 if v['id'] && v.has_key?('value')
56 hash[v['id']] = v['value']
57 hash[v['id']] = v['value']
57 end
58 end
58 hash
59 hash
59 end
60 end
60 self.custom_field_values = values_to_hash
61 self.custom_field_values = values_to_hash
61 end
62 end
62
63
63 # Sets the values of the object's custom fields
64 # Sets the values of the object's custom fields
64 # values is a hash like {'1' => 'foo', 2 => 'bar'}
65 # values is a hash like {'1' => 'foo', 2 => 'bar'}
65 def custom_field_values=(values)
66 def custom_field_values=(values)
66 values = values.stringify_keys
67 values = values.stringify_keys
67
68
68 custom_field_values.each do |custom_field_value|
69 custom_field_values.each do |custom_field_value|
69 key = custom_field_value.custom_field_id.to_s
70 key = custom_field_value.custom_field_id.to_s
70 if values.has_key?(key)
71 if values.has_key?(key)
71 custom_field_value.value = values[key]
72 custom_field_value.value = values[key]
72 end
73 end
73 end
74 end
74 @custom_field_values_changed = true
75 @custom_field_values_changed = true
75 end
76 end
76
77
77 def custom_field_values
78 def custom_field_values
78 @custom_field_values ||= available_custom_fields.collect do |field|
79 @custom_field_values ||= available_custom_fields.collect do |field|
79 x = CustomFieldValue.new
80 x = CustomFieldValue.new
80 x.custom_field = field
81 x.custom_field = field
81 x.customized = self
82 x.customized = self
82 if field.multiple?
83 if field.multiple?
83 values = custom_values.select { |v| v.custom_field == field }
84 values = custom_values.select { |v| v.custom_field == field }
84 if values.empty?
85 if values.empty?
85 values << custom_values.build(:customized => self, :custom_field => field)
86 values << custom_values.build(:customized => self, :custom_field => field)
86 end
87 end
87 x.instance_variable_set("@value", values.map(&:value))
88 x.instance_variable_set("@value", values.map(&:value))
88 else
89 else
89 cv = custom_values.detect { |v| v.custom_field == field }
90 cv = custom_values.detect { |v| v.custom_field == field }
90 cv ||= custom_values.build(:customized => self, :custom_field => field)
91 cv ||= custom_values.build(:customized => self, :custom_field => field)
91 x.instance_variable_set("@value", cv.value)
92 x.instance_variable_set("@value", cv.value)
92 end
93 end
93 x.value_was = x.value.dup if x.value
94 x.value_was = x.value.dup if x.value
94 x
95 x
95 end
96 end
96 end
97 end
97
98
98 def visible_custom_field_values
99 def visible_custom_field_values
99 custom_field_values.select(&:visible?)
100 custom_field_values.select(&:visible?)
100 end
101 end
101
102
102 def custom_field_values_changed?
103 def custom_field_values_changed?
103 @custom_field_values_changed == true
104 @custom_field_values_changed == true
104 end
105 end
105
106
106 def custom_value_for(c)
107 def custom_value_for(c)
107 field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
108 field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
108 custom_values.detect {|v| v.custom_field_id == field_id }
109 custom_values.detect {|v| v.custom_field_id == field_id }
109 end
110 end
110
111
111 def custom_field_value(c)
112 def custom_field_value(c)
112 field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
113 field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
113 custom_field_values.detect {|v| v.custom_field_id == field_id }.try(:value)
114 custom_field_values.detect {|v| v.custom_field_id == field_id }.try(:value)
114 end
115 end
115
116
116 def validate_custom_field_values
117 def validate_custom_field_values
117 if new_record? || custom_field_values_changed?
118 if new_record? || custom_field_values_changed?
118 custom_field_values.each(&:validate_value)
119 custom_field_values.each(&:validate_value)
119 end
120 end
120 end
121 end
121
122
122 def save_custom_field_values
123 def save_custom_field_values
123 target_custom_values = []
124 target_custom_values = []
124 custom_field_values.each do |custom_field_value|
125 custom_field_values.each do |custom_field_value|
125 if custom_field_value.value.is_a?(Array)
126 if custom_field_value.value.is_a?(Array)
126 custom_field_value.value.each do |v|
127 custom_field_value.value.each do |v|
127 target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field && cv.value == v}
128 target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field && cv.value == v}
128 target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field, :value => v)
129 target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field, :value => v)
129 target_custom_values << target
130 target_custom_values << target
130 end
131 end
131 else
132 else
132 target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field}
133 target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field}
133 target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field)
134 target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field)
134 target.value = custom_field_value.value
135 target.value = custom_field_value.value
135 target_custom_values << target
136 target_custom_values << target
136 end
137 end
137 end
138 end
138 self.custom_values = target_custom_values
139 self.custom_values = target_custom_values
139 custom_values.each(&:save)
140 custom_values.each(&:save)
140 @custom_field_values_changed = false
141 @custom_field_values_changed = false
141 true
142 true
142 end
143 end
143
144
144 def reassign_custom_field_values
145 def reassign_custom_field_values
145 if @custom_field_values
146 if @custom_field_values
146 values = @custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
147 values = @custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
147 @custom_field_values = nil
148 @custom_field_values = nil
148 self.custom_field_values = values
149 self.custom_field_values = values
149 end
150 end
150 end
151 end
151
152
152 def reset_custom_values!
153 def reset_custom_values!
153 @custom_field_values = nil
154 @custom_field_values = nil
154 @custom_field_values_changed = true
155 @custom_field_values_changed = true
155 end
156 end
156
157
157 def reload(*args)
158 def reload(*args)
158 @custom_field_values = nil
159 @custom_field_values = nil
159 @custom_field_values_changed = false
160 @custom_field_values_changed = false
160 super
161 super
161 end
162 end
162
163
163 module ClassMethods
164 module ClassMethods
164 end
165 end
165 end
166 end
166 end
167 end
167 end
168 end
168 end
169 end
General Comments 0
You need to be logged in to leave comments. Login now