summaryrefslogtreecommitdiffstats
path: root/app/models/issue.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/issue.rb')
-rw-r--r--app/models/issue.rb67
1 files changed, 25 insertions, 42 deletions
diff --git a/app/models/issue.rb b/app/models/issue.rb
index f984e0332..5798fef9f 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -69,7 +69,6 @@ class Issue < ActiveRecord::Base
validates :start_date, :date => true
validates :due_date, :date => true
validate :validate_issue, :validate_required_fields, :validate_permissions
- attr_protected :id
scope :visible, lambda {|*args|
joins(:project).
@@ -108,16 +107,14 @@ class Issue < ActiveRecord::Base
before_validation :default_assign, on: :create
before_validation :clear_disabled_fields
before_save :close_duplicates, :update_done_ratio_from_issue_status,
- :force_updated_on_change, :update_closed_on, :set_assigned_to_was
- after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?}
+ :force_updated_on_change, :update_closed_on
+ after_save {|issue| issue.send :after_project_change if !issue.saved_change_to_id? && issue.saved_change_to_project_id?}
after_save :reschedule_following_issues, :update_nested_set_attributes,
:update_parent_attributes, :delete_selected_attachments, :create_journal
# Should be after_create but would be called before previous after_save callbacks
after_save :after_create_from_copy
after_destroy :update_parent_attributes
after_create :send_notification
- # Keep it at the end of after_save callbacks
- after_save :clear_assigned_to_was
# Returns a SQL conditions string used to find all issues visible by the specified user
def self.visible_condition(user, options={})
@@ -208,7 +205,7 @@ class Issue < ActiveRecord::Base
end
end
- def create_or_update
+ def create_or_update(*args)
super
ensure
@status_was = nil
@@ -512,6 +509,10 @@ class Issue < ActiveRecord::Base
# attr_accessible is too rough because we still want things like
# Issue.new(:project => foo) to work
def safe_attributes=(attrs, user=User.current)
+ if attrs.respond_to?(:to_unsafe_hash)
+ attrs = attrs.to_unsafe_hash
+ end
+
@attributes_set_by = user
return unless attrs.is_a?(Hash)
@@ -586,8 +587,7 @@ class Issue < ActiveRecord::Base
attrs['custom_fields'].select! {|c| editable_custom_field_ids.include?(c['id'].to_s)}
end
- # mass-assignment security bypass
- assign_attributes attrs, :without_protection => true
+ assign_attributes attrs
end
def disabled_core_fields
@@ -1007,32 +1007,27 @@ class Issue < ActiveRecord::Base
statuses
end
- # Returns the previous assignee (user or group) if changed
- def assigned_to_was
- # assigned_to_id_was is reset before after_save callbacks
- user_id = @previous_assigned_to_id || assigned_to_id_was
- if user_id && user_id != assigned_to_id
- @assigned_to_was ||= Principal.find_by_id(user_id)
- end
- end
-
# Returns the original tracker
def tracker_was
- Tracker.find_by_id(tracker_id_was)
+ Tracker.find_by_id(tracker_id_in_database)
+ end
+
+ # Returns the previous assignee whenever we're before the save
+ # or in after_* callbacks
+ def previous_assignee
+ # This is how ActiveRecord::AttributeMethods::Dirty checks if we're in a after_* callback
+ if previous_assigned_to_id = mutation_tracker.equal?(mutations_from_database) ? assigned_to_id_in_database : assigned_to_id_before_last_save
+ Principal.find_by_id(previous_assigned_to_id)
+ end
end
# Returns the users that should be notified
def notified_users
- notified = []
# Author and assignee are always notified unless they have been
# locked or don't want to be notified
- notified << author if author
- if assigned_to
- notified += (assigned_to.is_a?(Group) ? assigned_to.users : [assigned_to])
- end
- if assigned_to_was
- notified += (assigned_to_was.is_a?(Group) ? assigned_to_was.users : [assigned_to_was])
- end
+ notified = [author, assigned_to, previous_assignee].compact.uniq
+ notified = notified.map {|n| n.is_a?(Group) ? n.users : n}.flatten
+ notified.uniq!
notified = notified.select {|u| u.active? && u.notify_about?(self)}
notified += project.notified_users
@@ -1587,7 +1582,7 @@ class Issue < ActiveRecord::Base
# Move subtasks that were in the same project
children.each do |child|
- next unless child.project_id == project_id_was
+ next unless child.project_id == project_id_before_last_save
# Change project and keep project
child.send :project=, project, true
unless child.save
@@ -1644,7 +1639,7 @@ class Issue < ActiveRecord::Base
end
def update_nested_set_attributes
- if parent_id_changed?
+ if saved_change_to_parent_id?
update_nested_set_attributes_on_parent_change
end
remove_instance_variable(:@parent_issue) if instance_variable_defined?(:@parent_issue)
@@ -1652,7 +1647,7 @@ class Issue < ActiveRecord::Base
# Updates the nested set for when an existing issue is moved
def update_nested_set_attributes_on_parent_change
- former_parent_id = parent_id_was
+ former_parent_id = parent_id_before_last_save
# delete invalid relations of all descendants
self_and_descendants.each do |issue|
issue.relations.each do |relation|
@@ -1789,7 +1784,7 @@ class Issue < ActiveRecord::Base
# Updates start/due dates of following issues
def reschedule_following_issues
- if start_date_changed? || due_date_changed?
+ if saved_change_to_start_date? || saved_change_to_due_date?
relations_from.each do |relation|
relation.set_issue_to_dates
end
@@ -1848,18 +1843,6 @@ class Issue < ActiveRecord::Base
end
end
- # Stores the previous assignee so we can still have access
- # to it during after_save callbacks (assigned_to_id_was is reset)
- def set_assigned_to_was
- @previous_assigned_to_id = assigned_to_id_was
- end
-
- # Clears the previous assignee at the end of after_save callbacks
- def clear_assigned_to_was
- @assigned_to_was = nil
- @previous_assigned_to_id = nil
- end
-
def clear_disabled_fields
if tracker
tracker.disabled_core_fields.each do |attribute|