<commit_before># Represents an issue that affects a particular project.
# Issues can be part of a sprint and they have an issue type.
class Issue < ActiveRecord::Base
  include Extensions::Issues::Workflow
  include Extensions::Votable

  # Array of all valid estimation options.
  VALID_ESTIMATES = [0, 0.5, 1, 2, 3, 5, 8, 13, 20, 40, 100]

  audited :associated_with => :project, :allow_mass_assignment => true

  belongs_to :reported_by, :class_name => "User"
  belongs_to :project, :touch => true
  belongs_to :issue_type
  belongs_to :issue_priority
  belongs_to :assigned_to, :class_name => "User"
  belongs_to :sprint
  has_many :comments, :dependent => :destroy

  attr_accessible :project_id, :summary, :description, :issue_type_id, :issue_priority_id, :assigned_to_id, :estimate

  validates :project_id, :summary, :issue_type_id, :number, :presence => true
  validates :number, :uniqueness => { :scope => :project_id }
  validates :estimate, :inclusion => { :in => VALID_ESTIMATES }, :allow_blank => true
  validate :security_assigned_to

  default_scope includes(:project).includes(:reported_by).includes(:issue_type).includes(:comments).includes(:issue_priority)

  after_initialize :set_defaults
  before_validation :set_number, :on => :create

  scope :sort_by_issue_type, lambda { |sord| joins(:issue_type).order("issue_types.name #{sord}") }
  scope :sort_by_issue_priority, lambda { |sord| includes(:issue_priority).order("issue_priorities.number #{sord}") }

  # Returns the issue number prefixed with the projecy key
  # to better identify issues.
  #
  # e.g. TYNE-1337
  #
  # @return [String] issue-key
  def key
    "#{project.key}-#{number}"
  end

  def closed?
    %w(done invalid).include? self.state
  end

  # Returns the description converted into markdown.
  def description_markdown
    @@markdown_renderer ||= Redcarpet::Markdown.new(MdEmoji::Render, :autolink => true, :space_after_headers => true, :no_intra_emphasis => true)
    @@markdown_renderer.render(description).html_safe
  end
  alias_method :display_as, :description_markdown

  # Removes the issue from the backlog if not part of a sprint.
  # Logs sprint activity if part of a sprint.
  def after_close
    if sprint
      change = (self.estimate || 0) * -1
      log_sprint_activity('close', change)
    else
      self.becomes(BacklogItem).remove_from_list
    end
  end

  # Adds issue to the backlog if not part of a sprint.
  # Logs sprint activity if part of a sprint.
  def after_reopen
    if sprint
      log_sprint_activity('reopen', (estimate || 0))
    else
      self.becomes(BacklogItem).insert_at(1)
    end
  end

  private

  def log_sprint_activity(type, change)
    sprint.log_activity(self, type, change)
    sprint.save
  end

  def set_defaults
    self.issue_type_id ||= IssueType.first.id if attributes.include?("issue_type_id")
    self.issue_priority_id ||= get_medium_priority if attributes.include?("issue_priority_id")<commit_msg>removed some duplication and cleared up the callbacks<commit_after># Represents an issue that affects a particular project.
# Issues can be part of a sprint and they have an issue type.
class Issue < ActiveRecord::Base
  include Extensions::Issues::Workflow
  include Extensions::Votable

  # Array of all valid estimation options.
  VALID_ESTIMATES = [0, 0.5, 1, 2, 3, 5, 8, 13, 20, 40, 100]

  audited :associated_with => :project, :allow_mass_assignment => true

  belongs_to :reported_by, :class_name => "User"
  belongs_to :project, :touch => true
  belongs_to :issue_type
  belongs_to :issue_priority
  belongs_to :assigned_to, :class_name => "User"
  belongs_to :sprint
  has_many :comments, :dependent => :destroy

  attr_accessible :project_id, :summary, :description, :issue_type_id, :issue_priority_id, :assigned_to_id, :estimate

  validates :project_id, :summary, :issue_type_id, :number, :presence => true
  validates :number, :uniqueness => { :scope => :project_id }
  validates :estimate, :inclusion => { :in => VALID_ESTIMATES }, :allow_blank => true
  validate :security_assigned_to

  default_scope includes(:project).includes(:reported_by).includes(:issue_type).includes(:comments).includes(:issue_priority)

  after_initialize :set_defaults
  before_validation :set_number, :on => :create

  scope :sort_by_issue_type, lambda { |sord| joins(:issue_type).order("issue_types.name #{sord}") }
  scope :sort_by_issue_priority, lambda { |sord| includes(:issue_priority).order("issue_priorities.number #{sord}") }

  # Returns the issue number prefixed with the projecy key
  # to better identify issues.
  #
  # e.g. TYNE-1337
  #
  # @return [String] issue-key
  def key
    "#{project.key}-#{number}"
  end

  def closed?
    %w(done invalid).include? self.state
  end

  # Returns the description converted into markdown.
  def description_markdown
    @@markdown_renderer ||= Redcarpet::Markdown.new(MdEmoji::Render, :autolink => true, :space_after_headers => true, :no_intra_emphasis => true)
    @@markdown_renderer.render(description).html_safe
  end
  alias_method :display_as, :description_markdown

  # Callback fired after ticked closed
  def after_close
    if sprint
      log_sprint_activity('close', 0 - estimated_remaining)
    else
      remove_from_backlog
    end
  end

  # Callback fired afer ticket reopened
  def after_reopen
    if sprint
      log_sprint_activity('reopen', estimated_remaining)
    else
      add_to_backlog
    end
  end

  private

  def remove_from_backlog
    becomes(BacklogItem).remove_from_list
  end

  def add_to_backlog
    becomes(BacklogItem).insert_at(1)
  end

  def estimated_remaining
    estimate || 0
  end

  def log_sprint_activity(type, change)
    sprint.log_activity(self, type, change)
    sprint.save
  end

  def set_defaults
    self.issue_type_id ||= IssueType.first.id if attributes.include?("issue_type_id")
    self.issue_priority_id ||= get_medium_priority if attributes.include?("issue_priority_id")
{'fraction_non_alphanumeric': 0.10374978980998822, 'fraction_numerical': 0.008239448461409114, 'mean_word_length': 4.5278810408921935, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6675281', 'n_tokens_mistral': 2004, 'n_tokens_neox': 1926, 'n_words': 496}