##// END OF EJS Templates
Rails4: replace deprecated find_all_by_* at Journal model...
Toshi MARUYAMA -
r12224:89b5518e0b3a
parent child
Show More
@@ -1,193 +1,193
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2013 Jean-Philippe Lang
2 # Copyright (C) 2006-2013 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 class Journal < ActiveRecord::Base
18 class Journal < ActiveRecord::Base
19 belongs_to :journalized, :polymorphic => true
19 belongs_to :journalized, :polymorphic => true
20 # added as a quick fix to allow eager loading of the polymorphic association
20 # added as a quick fix to allow eager loading of the polymorphic association
21 # since always associated to an issue, for now
21 # since always associated to an issue, for now
22 belongs_to :issue, :foreign_key => :journalized_id
22 belongs_to :issue, :foreign_key => :journalized_id
23
23
24 belongs_to :user
24 belongs_to :user
25 has_many :details, :class_name => "JournalDetail", :dependent => :delete_all
25 has_many :details, :class_name => "JournalDetail", :dependent => :delete_all
26 attr_accessor :indice
26 attr_accessor :indice
27
27
28 acts_as_event :title => Proc.new {|o| status = ((s = o.new_status) ? " (#{s})" : nil); "#{o.issue.tracker} ##{o.issue.id}#{status}: #{o.issue.subject}" },
28 acts_as_event :title => Proc.new {|o| status = ((s = o.new_status) ? " (#{s})" : nil); "#{o.issue.tracker} ##{o.issue.id}#{status}: #{o.issue.subject}" },
29 :description => :notes,
29 :description => :notes,
30 :author => :user,
30 :author => :user,
31 :group => :issue,
31 :group => :issue,
32 :type => Proc.new {|o| (s = o.new_status) ? (s.is_closed? ? 'issue-closed' : 'issue-edit') : 'issue-note' },
32 :type => Proc.new {|o| (s = o.new_status) ? (s.is_closed? ? 'issue-closed' : 'issue-edit') : 'issue-note' },
33 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id, :anchor => "change-#{o.id}"}}
33 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id, :anchor => "change-#{o.id}"}}
34
34
35 acts_as_activity_provider :type => 'issues',
35 acts_as_activity_provider :type => 'issues',
36 :author_key => :user_id,
36 :author_key => :user_id,
37 :find_options => {:include => [{:issue => :project}, :details, :user],
37 :find_options => {:include => [{:issue => :project}, :details, :user],
38 :conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" +
38 :conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" +
39 " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"}
39 " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"}
40
40
41 before_create :split_private_notes
41 before_create :split_private_notes
42 after_create :send_notification
42 after_create :send_notification
43
43
44 scope :visible, lambda {|*args|
44 scope :visible, lambda {|*args|
45 user = args.shift || User.current
45 user = args.shift || User.current
46
46
47 includes(:issue => :project).
47 includes(:issue => :project).
48 where(Issue.visible_condition(user, *args)).
48 where(Issue.visible_condition(user, *args)).
49 where("(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(user, :view_private_notes, *args)}))", false)
49 where("(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(user, :view_private_notes, *args)}))", false)
50 }
50 }
51
51
52 def save(*args)
52 def save(*args)
53 # Do not save an empty journal
53 # Do not save an empty journal
54 (details.empty? && notes.blank?) ? false : super
54 (details.empty? && notes.blank?) ? false : super
55 end
55 end
56
56
57 # Returns journal details that are visible to user
57 # Returns journal details that are visible to user
58 def visible_details(user=User.current)
58 def visible_details(user=User.current)
59 details.select do |detail|
59 details.select do |detail|
60 if detail.property == 'cf'
60 if detail.property == 'cf'
61 detail.custom_field && detail.custom_field.visible_by?(project, user)
61 detail.custom_field && detail.custom_field.visible_by?(project, user)
62 elsif detail.property == 'relation'
62 elsif detail.property == 'relation'
63 Issue.find_by_id(detail.value || detail.old_value).try(:visible?, user)
63 Issue.find_by_id(detail.value || detail.old_value).try(:visible?, user)
64 else
64 else
65 true
65 true
66 end
66 end
67 end
67 end
68 end
68 end
69
69
70 def each_notification(users, &block)
70 def each_notification(users, &block)
71 if users.any?
71 if users.any?
72 users_by_details_visibility = users.group_by do |user|
72 users_by_details_visibility = users.group_by do |user|
73 visible_details(user)
73 visible_details(user)
74 end
74 end
75 users_by_details_visibility.each do |visible_details, users|
75 users_by_details_visibility.each do |visible_details, users|
76 if notes? || visible_details.any?
76 if notes? || visible_details.any?
77 yield(users)
77 yield(users)
78 end
78 end
79 end
79 end
80 end
80 end
81 end
81 end
82
82
83 # Returns the new status if the journal contains a status change, otherwise nil
83 # Returns the new status if the journal contains a status change, otherwise nil
84 def new_status
84 def new_status
85 c = details.detect {|detail| detail.prop_key == 'status_id'}
85 c = details.detect {|detail| detail.prop_key == 'status_id'}
86 (c && c.value) ? IssueStatus.find_by_id(c.value.to_i) : nil
86 (c && c.value) ? IssueStatus.find_by_id(c.value.to_i) : nil
87 end
87 end
88
88
89 def new_value_for(prop)
89 def new_value_for(prop)
90 c = details.detect {|detail| detail.prop_key == prop}
90 c = details.detect {|detail| detail.prop_key == prop}
91 c ? c.value : nil
91 c ? c.value : nil
92 end
92 end
93
93
94 def editable_by?(usr)
94 def editable_by?(usr)
95 usr && usr.logged? && (usr.allowed_to?(:edit_issue_notes, project) || (self.user == usr && usr.allowed_to?(:edit_own_issue_notes, project)))
95 usr && usr.logged? && (usr.allowed_to?(:edit_issue_notes, project) || (self.user == usr && usr.allowed_to?(:edit_own_issue_notes, project)))
96 end
96 end
97
97
98 def project
98 def project
99 journalized.respond_to?(:project) ? journalized.project : nil
99 journalized.respond_to?(:project) ? journalized.project : nil
100 end
100 end
101
101
102 def attachments
102 def attachments
103 journalized.respond_to?(:attachments) ? journalized.attachments : nil
103 journalized.respond_to?(:attachments) ? journalized.attachments : nil
104 end
104 end
105
105
106 # Returns a string of css classes
106 # Returns a string of css classes
107 def css_classes
107 def css_classes
108 s = 'journal'
108 s = 'journal'
109 s << ' has-notes' unless notes.blank?
109 s << ' has-notes' unless notes.blank?
110 s << ' has-details' unless details.blank?
110 s << ' has-details' unless details.blank?
111 s << ' private-notes' if private_notes?
111 s << ' private-notes' if private_notes?
112 s
112 s
113 end
113 end
114
114
115 def notify?
115 def notify?
116 @notify != false
116 @notify != false
117 end
117 end
118
118
119 def notify=(arg)
119 def notify=(arg)
120 @notify = arg
120 @notify = arg
121 end
121 end
122
122
123 def notified_users
123 def notified_users
124 notified = journalized.notified_users
124 notified = journalized.notified_users
125 if private_notes?
125 if private_notes?
126 notified = notified.select {|user| user.allowed_to?(:view_private_notes, journalized.project)}
126 notified = notified.select {|user| user.allowed_to?(:view_private_notes, journalized.project)}
127 end
127 end
128 notified
128 notified
129 end
129 end
130
130
131 def recipients
131 def recipients
132 notified_users.map(&:mail)
132 notified_users.map(&:mail)
133 end
133 end
134
134
135 def notified_watchers
135 def notified_watchers
136 notified = journalized.notified_watchers
136 notified = journalized.notified_watchers
137 if private_notes?
137 if private_notes?
138 notified = notified.select {|user| user.allowed_to?(:view_private_notes, journalized.project)}
138 notified = notified.select {|user| user.allowed_to?(:view_private_notes, journalized.project)}
139 end
139 end
140 notified
140 notified
141 end
141 end
142
142
143 def watcher_recipients
143 def watcher_recipients
144 notified_watchers.map(&:mail)
144 notified_watchers.map(&:mail)
145 end
145 end
146
146
147 # Sets @custom_field instance variable on journals details using a single query
147 # Sets @custom_field instance variable on journals details using a single query
148 def self.preload_journals_details_custom_fields(journals)
148 def self.preload_journals_details_custom_fields(journals)
149 field_ids = journals.map(&:details).flatten.select {|d| d.property == 'cf'}.map(&:prop_key).uniq
149 field_ids = journals.map(&:details).flatten.select {|d| d.property == 'cf'}.map(&:prop_key).uniq
150 if field_ids.any?
150 if field_ids.any?
151 fields_by_id = CustomField.find_all_by_id(field_ids).inject({}) {|h, f| h[f.id] = f; h}
151 fields_by_id = CustomField.where(:id => field_ids).all.inject({}) {|h, f| h[f.id] = f; h}
152 journals.each do |journal|
152 journals.each do |journal|
153 journal.details.each do |detail|
153 journal.details.each do |detail|
154 if detail.property == 'cf'
154 if detail.property == 'cf'
155 detail.instance_variable_set "@custom_field", fields_by_id[detail.prop_key.to_i]
155 detail.instance_variable_set "@custom_field", fields_by_id[detail.prop_key.to_i]
156 end
156 end
157 end
157 end
158 end
158 end
159 end
159 end
160 journals
160 journals
161 end
161 end
162
162
163 private
163 private
164
164
165 def split_private_notes
165 def split_private_notes
166 if private_notes?
166 if private_notes?
167 if notes.present?
167 if notes.present?
168 if details.any?
168 if details.any?
169 # Split the journal (notes/changes) so we don't have half-private journals
169 # Split the journal (notes/changes) so we don't have half-private journals
170 journal = Journal.new(:journalized => journalized, :user => user, :notes => nil, :private_notes => false)
170 journal = Journal.new(:journalized => journalized, :user => user, :notes => nil, :private_notes => false)
171 journal.details = details
171 journal.details = details
172 journal.save
172 journal.save
173 self.details = []
173 self.details = []
174 self.created_on = journal.created_on
174 self.created_on = journal.created_on
175 end
175 end
176 else
176 else
177 # Blank notes should not be private
177 # Blank notes should not be private
178 self.private_notes = false
178 self.private_notes = false
179 end
179 end
180 end
180 end
181 true
181 true
182 end
182 end
183
183
184 def send_notification
184 def send_notification
185 if notify? && (Setting.notified_events.include?('issue_updated') ||
185 if notify? && (Setting.notified_events.include?('issue_updated') ||
186 (Setting.notified_events.include?('issue_note_added') && notes.present?) ||
186 (Setting.notified_events.include?('issue_note_added') && notes.present?) ||
187 (Setting.notified_events.include?('issue_status_updated') && new_status.present?) ||
187 (Setting.notified_events.include?('issue_status_updated') && new_status.present?) ||
188 (Setting.notified_events.include?('issue_priority_updated') && new_value_for('priority_id').present?)
188 (Setting.notified_events.include?('issue_priority_updated') && new_value_for('priority_id').present?)
189 )
189 )
190 Mailer.deliver_issue_edit(self)
190 Mailer.deliver_issue_edit(self)
191 end
191 end
192 end
192 end
193 end
193 end
General Comments 0
You need to be logged in to leave comments. Login now