Commit f9109d366f8125612b0bba02b11880a1388f26db
1 parent
25d141bd
Exists in
master
and in
1 other branch
Finished #59 - Refactored Issue Trackers. Remember to run "rake db:migrate".
Showing
30 changed files
with
421 additions
and
378 deletions
Show diff stats
app/controllers/apps_controller.rb
| ... | ... | @@ -24,6 +24,18 @@ class AppsController < InheritedResources::Base |
| 24 | 24 | end |
| 25 | 25 | end |
| 26 | 26 | |
| 27 | + def create | |
| 28 | + @app = App.new(params[:app]) | |
| 29 | + initialize_subclassed_issue_tracker | |
| 30 | + create! | |
| 31 | + end | |
| 32 | + | |
| 33 | + def update | |
| 34 | + @app = resource | |
| 35 | + initialize_subclassed_issue_tracker | |
| 36 | + update! | |
| 37 | + end | |
| 38 | + | |
| 27 | 39 | def new |
| 28 | 40 | plug_params build_resource |
| 29 | 41 | new! |
| ... | ... | @@ -34,7 +46,16 @@ class AppsController < InheritedResources::Base |
| 34 | 46 | edit! |
| 35 | 47 | end |
| 36 | 48 | |
| 49 | + | |
| 37 | 50 | protected |
| 51 | + def initialize_subclassed_issue_tracker | |
| 52 | + if params[:app][:issue_tracker_attributes] && tracker_type = params[:app][:issue_tracker_attributes][:type] | |
| 53 | + if IssueTracker.subclasses.map(&:to_s).include?(tracker_type.to_s) | |
| 54 | + @app.issue_tracker = tracker_type.constantize.new(params[:app][:issue_tracker_attributes]) | |
| 55 | + end | |
| 56 | + end | |
| 57 | + end | |
| 58 | + | |
| 38 | 59 | def begin_of_association_chain |
| 39 | 60 | current_user unless current_user.admin? |
| 40 | 61 | end |
| ... | ... | @@ -45,7 +66,7 @@ class AppsController < InheritedResources::Base |
| 45 | 66 | |
| 46 | 67 | def plug_params app |
| 47 | 68 | app.watchers.build if app.watchers.none? |
| 48 | - app.issue_tracker = IssueTracker.new if app.issue_tracker.nil? | |
| 69 | + app.issue_tracker = IssueTracker.new unless app.issue_tracker_configured? | |
| 49 | 70 | end |
| 50 | 71 | |
| 51 | 72 | # email_at_notices is edited as a string, and stored as an array. | ... | ... |
app/helpers/application_helper.rb
| ... | ... | @@ -29,16 +29,5 @@ module ApplicationHelper |
| 29 | 29 | tallies.values.inject(0) {|sum, n| sum + n} |
| 30 | 30 | end |
| 31 | 31 | private :total_from_tallies |
| 32 | - | |
| 33 | - def no_tracker? object | |
| 34 | - object.issue_tracker_type == "none" | |
| 35 | - end | |
| 36 | - | |
| 37 | - %w(lighthouseapp redmine pivotal fogbugz mingle).each do |tracker| | |
| 38 | - define_method("#{tracker}_tracker?".to_sym) do |object| | |
| 39 | - object.issue_tracker_type == tracker | |
| 40 | - end | |
| 41 | - end | |
| 42 | - | |
| 43 | 32 | end |
| 44 | 33 | ... | ... |
app/models/app.rb
| ... | ... | @@ -11,7 +11,7 @@ class App |
| 11 | 11 | field :notify_on_deploys, :type => Boolean, :default => true |
| 12 | 12 | field :email_at_notices, :type => Array, :default => Errbit::Config.email_at_notices |
| 13 | 13 | |
| 14 | - # Some legacy apps may have sting as key instead of BSON::ObjectID | |
| 14 | + # Some legacy apps may have string as key instead of BSON::ObjectID | |
| 15 | 15 | identity :type => String |
| 16 | 16 | # There seems to be a Mongoid bug making it impossible to use String identity with references_many feature: |
| 17 | 17 | # https://github.com/mongoid/mongoid/issues/703 |
| ... | ... | @@ -37,7 +37,7 @@ class App |
| 37 | 37 | accepts_nested_attributes_for :watchers, :allow_destroy => true, |
| 38 | 38 | :reject_if => proc { |attrs| attrs[:user_id].blank? && attrs[:email].blank? } |
| 39 | 39 | accepts_nested_attributes_for :issue_tracker, :allow_destroy => true, |
| 40 | - :reject_if => proc { |attrs| !%w(none lighthouseapp redmine pivotal fogbugz mingle).include?(attrs[:issue_tracker_type]) } | |
| 40 | + :reject_if => proc { |attrs| !IssueTracker.subclasses.map(&:to_s).include?(attrs[:type].to_s) } | |
| 41 | 41 | |
| 42 | 42 | def self.find_by_id!(app_id) |
| 43 | 43 | find app_id |
| ... | ... | @@ -71,7 +71,7 @@ class App |
| 71 | 71 | end |
| 72 | 72 | |
| 73 | 73 | def issue_tracker_configured? |
| 74 | - issue_tracker && issue_tracker.issue_tracker_type != "none" && !issue_tracker.project_id.blank? | |
| 74 | + !!(issue_tracker && issue_tracker.class < IssueTracker && issue_tracker.project_id.present?) | |
| 75 | 75 | end |
| 76 | 76 | |
| 77 | 77 | def notification_recipients | ... | ... |
app/models/issue_tracker.rb
| ... | ... | @@ -5,171 +5,28 @@ class IssueTracker |
| 5 | 5 | include Rails.application.routes.url_helpers |
| 6 | 6 | default_url_options[:host] = Errbit::Application.config.action_mailer.default_url_options[:host] |
| 7 | 7 | |
| 8 | - validate :check_params | |
| 9 | - | |
| 10 | 8 | embedded_in :app, :inverse_of => :issue_tracker |
| 11 | 9 | |
| 12 | - field :account, :type => String | |
| 13 | - field :api_token, :type => String | |
| 14 | 10 | field :project_id, :type => String |
| 15 | - field :ticket_properties, :type => String | |
| 11 | + field :api_token, :type => String | |
| 12 | + field :account, :type => String | |
| 16 | 13 | field :username, :type => String |
| 17 | 14 | field :password, :type => String |
| 18 | - field :issue_tracker_type, :type => String, :default => 'none' | |
| 19 | - | |
| 20 | - def create_issue err | |
| 21 | - case issue_tracker_type | |
| 22 | - when 'lighthouseapp' | |
| 23 | - create_lighthouseapp_issue err | |
| 24 | - when 'redmine' | |
| 25 | - create_redmine_issue err | |
| 26 | - when 'pivotal' | |
| 27 | - create_pivotal_issue err | |
| 28 | - when 'fogbugz' | |
| 29 | - create_fogbugz_issue err | |
| 30 | - when 'mingle' | |
| 31 | - create_mingle_issue err | |
| 32 | - end | |
| 33 | - end | |
| 34 | - | |
| 35 | - def ticket_properties_hash | |
| 36 | - # Parses 'key=value, key2=value2' from user input into a ruby hash. | |
| 37 | - self.ticket_properties.split(",").inject({}) do |hash, pair| | |
| 38 | - key, value = pair.split("=").map(&:strip) | |
| 39 | - hash[key] = value | |
| 40 | - hash | |
| 41 | - end | |
| 42 | - end | |
| 43 | - | |
| 44 | - protected | |
| 45 | - def create_redmine_issue err | |
| 46 | - token = api_token | |
| 47 | - acc = account | |
| 48 | - RedmineClient::Base.configure do | |
| 49 | - self.token = token | |
| 50 | - self.site = acc | |
| 51 | - end | |
| 52 | - issue = RedmineClient::Issue.new(:project_id => project_id) | |
| 53 | - issue.subject = issue_title err | |
| 54 | - issue.description = self.class.redmine_body_template.result(binding) | |
| 55 | - issue.save! | |
| 56 | - err.update_attribute :issue_link, "#{RedmineClient::Issue.site.to_s.sub(/#{RedmineClient::Issue.site.path}$/, '')}#{RedmineClient::Issue.element_path(issue.id, :project_id => project_id)}".sub(/\.xml\?project_id=#{project_id}$/, "\?project_id=#{project_id}") | |
| 57 | - end | |
| 58 | - | |
| 59 | - def create_pivotal_issue err | |
| 60 | - PivotalTracker::Client.token = api_token | |
| 61 | - PivotalTracker::Client.use_ssl = true | |
| 62 | - project = PivotalTracker::Project.find project_id.to_i | |
| 63 | - story = project.stories.create :name => issue_title(err), :story_type => 'bug', :description => self.class.pivotal_body_template.result(binding) | |
| 64 | - err.update_attribute :issue_link, "https://www.pivotaltracker.com/story/show/#{story.id}" | |
| 65 | - end | |
| 66 | - | |
| 67 | - def create_lighthouseapp_issue err | |
| 68 | - Lighthouse.account = account | |
| 69 | - Lighthouse.token = api_token | |
| 70 | - | |
| 71 | - # updating lighthouse account | |
| 72 | - Lighthouse::Ticket.site | |
| 73 | - | |
| 74 | - ticket = Lighthouse::Ticket.new(:project_id => project_id) | |
| 75 | - ticket.title = issue_title err | |
| 76 | - | |
| 77 | - ticket.body = self.class.lighthouseapp_body_template.result(binding) | |
| 78 | - | |
| 79 | - ticket.tags << "errbit" | |
| 80 | - ticket.save! | |
| 81 | - err.update_attribute :issue_link, "#{Lighthouse::Ticket.site.to_s.sub(/#{Lighthouse::Ticket.site.path}$/, '')}#{Lighthouse::Ticket.element_path(ticket.id, :project_id => project_id)}".sub(/\.xml$/, '') | |
| 82 | - end | |
| 83 | - | |
| 84 | - def create_fogbugz_issue err | |
| 85 | - fogbugz = Fogbugz::Interface.new(:email => username, :password => password, :uri => "https://#{account}.fogbugz.com") | |
| 86 | - fogbugz.authenticate | |
| 87 | - | |
| 88 | - issue = {} | |
| 89 | - issue['sTitle'] = issue_title err | |
| 90 | - issue['sArea'] = project_id | |
| 91 | - issue['sEvent'] = self.class.fogbugz_body_template.result(binding) | |
| 92 | - issue['sTags'] = ['errbit'].join(',') | |
| 93 | - issue['cols'] = ['ixBug'].join(',') | |
| 94 | - | |
| 95 | - fb_resp = fogbugz.command(:new, issue) | |
| 96 | - err.update_attribute :issue_link, "https://#{account}.fogbugz.com/default.asp?#{fb_resp['case']['ixBug']}" | |
| 97 | - end | |
| 98 | - | |
| 99 | - def create_mingle_issue err | |
| 100 | - properties = ticket_properties_hash | |
| 101 | - basic_auth = account.gsub(/https?:\/\//, "https://#{username}:#{password}@") | |
| 102 | - Mingle.set_site "#{basic_auth}/api/v1/projects/#{project_id}/" | |
| 15 | + field :ticket_properties, :type => String | |
| 103 | 16 | |
| 104 | - card = Mingle::Card.new | |
| 105 | - card.card_type_name = properties.delete("card_type") | |
| 106 | - card.name = issue_title(err) | |
| 107 | - card.description = self.class.mingle_body_template.result(binding) | |
| 108 | - properties.each do |property, value| | |
| 109 | - card.send("cp_#{property}=", value) | |
| 110 | - end | |
| 17 | + validate :check_params | |
| 111 | 18 | |
| 112 | - card.save! | |
| 113 | - err.update_attribute :issue_link, URI.parse("#{account}/projects/#{project_id}/cards/#{card.id}").to_s | |
| 114 | - end | |
| 19 | + # Subclasses are responsible for overwriting this method. | |
| 20 | + def check_params; end | |
| 115 | 21 | |
| 116 | 22 | def issue_title err |
| 117 | 23 | "[#{ err.environment }][#{ err.where }] #{err.message.to_s.truncate(100)}" |
| 118 | 24 | end |
| 119 | 25 | |
| 120 | - def check_params | |
| 121 | - blank_flag_fields = %w(project_id) | |
| 122 | - if %w(fogbugz mingle).include?(issue_tracker_type) | |
| 123 | - blank_flag_fields += %w(username password) | |
| 124 | - else | |
| 125 | - blank_flag_fields << 'api_token' | |
| 126 | - end | |
| 127 | - blank_flag_fields << 'account' if(%w(fogbugz lighthouseapp redmine mingle).include?(issue_tracker_type)) | |
| 128 | - blank_flags = blank_flag_fields.map {|m| self[m].blank? } | |
| 129 | - | |
| 130 | - if issue_tracker_type == "mingle" | |
| 131 | - # Check that mingle was given a 'card_type' in the ticket_properties | |
| 132 | - blank_flags << "card_type" unless ticket_properties_hash["card_type"] | |
| 133 | - end | |
| 134 | - | |
| 135 | - if blank_flags.any? && !blank_flags.all? | |
| 136 | - message = case issue_tracker_type | |
| 137 | - when 'lighthouseapp' | |
| 138 | - 'You must specify your Lighthouseapp account, API token and Project ID' | |
| 139 | - when 'redmine' | |
| 140 | - 'You must specify your Redmine URL, API token and Project ID' | |
| 141 | - when 'pivotal' | |
| 142 | - 'You must specify your Pivotal Tracker API token and Project ID' | |
| 143 | - when 'fogbugz' | |
| 144 | - 'You must specify your FogBugz Area Name, Username, and Password' | |
| 145 | - when 'mingle' | |
| 146 | - 'You must specify your Mingle URL, Project ID, Card Type (in default card properties), Sign-in name, and Password' | |
| 147 | - end | |
| 148 | - errors.add(:base, message) | |
| 149 | - end | |
| 150 | - end | |
| 151 | - | |
| 152 | - class << self | |
| 153 | - def lighthouseapp_body_template | |
| 154 | - @@lighthouseapp_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/lighthouseapp_body.txt.erb").gsub(/^\s*/, '')) | |
| 155 | - end | |
| 26 | + # Allows us to set the issue tracker class from a single form. | |
| 27 | + def type; self._type; end | |
| 28 | + def type=(t); self._type=t; end | |
| 156 | 29 | |
| 157 | - def redmine_body_template | |
| 158 | - @@redmine_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/redmine_body.txt.erb")) | |
| 159 | - end | |
| 160 | - | |
| 161 | - def pivotal_body_template | |
| 162 | - @@pivotal_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/pivotal_body.txt.erb")) | |
| 163 | - end | |
| 164 | - | |
| 165 | - def fogbugz_body_template | |
| 166 | - @@fogbugz_body_template ||= ERB.new(File.read(Rails.root + "app/views/errs/fogbugz_body.txt.erb")) | |
| 167 | - end | |
| 168 | - | |
| 169 | - def mingle_body_template | |
| 170 | - # Mingle also uses textile markup, so the redmine template is perfect. | |
| 171 | - redmine_body_template | |
| 172 | - end | |
| 173 | - end | |
| 30 | + def self.label; "(none)"; end | |
| 174 | 31 | end |
| 175 | 32 | ... | ... |
| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | +class FogbugzTracker < IssueTracker | |
| 2 | + def self.label; "fogbugz"; end | |
| 3 | + | |
| 4 | + def check_params | |
| 5 | + if %w(project_id account username password).detect {|f| self[f].blank? } | |
| 6 | + errors.add :base, 'You must specify your FogBugz Area Name, FogBugz URL, Username, and Password' | |
| 7 | + end | |
| 8 | + end | |
| 9 | + | |
| 10 | + def create_issue(err) | |
| 11 | + fogbugz = Fogbugz::Interface.new(:email => username, :password => password, :uri => "https://#{account}.fogbugz.com") | |
| 12 | + fogbugz.authenticate | |
| 13 | + | |
| 14 | + issue = {} | |
| 15 | + issue['sTitle'] = issue_title err | |
| 16 | + issue['sArea'] = project_id | |
| 17 | + issue['sEvent'] = body_template.result(binding) | |
| 18 | + issue['sTags'] = ['errbit'].join(',') | |
| 19 | + issue['cols'] = ['ixBug'].join(',') | |
| 20 | + | |
| 21 | + fb_resp = fogbugz.command(:new, issue) | |
| 22 | + err.update_attribute :issue_link, "https://#{account}.fogbugz.com/default.asp?#{fb_resp['case']['ixBug']}" | |
| 23 | + end | |
| 24 | + | |
| 25 | + def body_template | |
| 26 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/fogbugz_body.txt.erb")) | |
| 27 | + end | |
| 28 | +end | |
| 29 | + | ... | ... |
| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | +class LighthouseTracker < IssueTracker | |
| 2 | + def self.label; "lighthouseapp"; end | |
| 3 | + | |
| 4 | + def check_params | |
| 5 | + if %w(account api_token project_id).detect {|f| self[f].blank? } | |
| 6 | + errors.add :base, 'You must specify your Lighthouseapp account, API token and Project ID' | |
| 7 | + end | |
| 8 | + end | |
| 9 | + | |
| 10 | + def create_issue(err) | |
| 11 | + Lighthouse.account = account | |
| 12 | + Lighthouse.token = api_token | |
| 13 | + # updating lighthouse account | |
| 14 | + Lighthouse::Ticket.site | |
| 15 | + | |
| 16 | + ticket = Lighthouse::Ticket.new(:project_id => project_id) | |
| 17 | + ticket.title = issue_title err | |
| 18 | + | |
| 19 | + ticket.body = body_template.result(binding) | |
| 20 | + | |
| 21 | + ticket.tags << "errbit" | |
| 22 | + ticket.save! | |
| 23 | + err.update_attribute :issue_link, "#{Lighthouse::Ticket.site.to_s.sub(/#{Lighthouse::Ticket.site.path}$/, '')}#{Lighthouse::Ticket.element_path(ticket.id, :project_id => project_id)}".sub(/\.xml$/, '') | |
| 24 | + end | |
| 25 | + | |
| 26 | + def body_template | |
| 27 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/lighthouseapp_body.txt.erb").gsub(/^\s*/, '')) | |
| 28 | + end | |
| 29 | +end | |
| 30 | + | ... | ... |
| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | +class MingleTracker < IssueTracker | |
| 2 | + def self.label; "mingle"; end | |
| 3 | + | |
| 4 | + def check_params | |
| 5 | + if %w(account project_id username password).detect {|f| self[f].blank? } or !ticket_properties_hash["card_type"] | |
| 6 | + errors.add :base, 'You must specify your Mingle URL, Project ID, Card Type (in default card properties), Sign-in name, and Password' | |
| 7 | + end | |
| 8 | + end | |
| 9 | + | |
| 10 | + def create_issue(err) | |
| 11 | + properties = ticket_properties_hash | |
| 12 | + basic_auth = account.gsub(/https?:\/\//, "https://#{username}:#{password}@") | |
| 13 | + Mingle.set_site "#{basic_auth}/api/v1/projects/#{project_id}/" | |
| 14 | + | |
| 15 | + card = Mingle::Card.new | |
| 16 | + card.card_type_name = properties.delete("card_type") | |
| 17 | + card.name = issue_title(err) | |
| 18 | + card.description = body_template.result(binding) | |
| 19 | + properties.each do |property, value| | |
| 20 | + card.send("cp_#{property}=", value) | |
| 21 | + end | |
| 22 | + | |
| 23 | + card.save! | |
| 24 | + err.update_attribute :issue_link, URI.parse("#{account}/projects/#{project_id}/cards/#{card.id}").to_s | |
| 25 | + end | |
| 26 | + | |
| 27 | + def body_template | |
| 28 | + # Mingle also uses textile markup, so the redmine template is perfect. | |
| 29 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/redmine_body.txt.erb")) | |
| 30 | + end | |
| 31 | + | |
| 32 | + def ticket_properties_hash | |
| 33 | + # Parses 'key=value, key2=value2' from ticket_properties into a ruby hash. | |
| 34 | + self.ticket_properties.split(",").inject({}) do |hash, pair| | |
| 35 | + key, value = pair.split("=").map(&:strip) | |
| 36 | + hash[key] = value | |
| 37 | + hash | |
| 38 | + end | |
| 39 | + end | |
| 40 | +end | |
| 41 | + | ... | ... |
| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | +class PivotalLabsTracker < IssueTracker | |
| 2 | + def self.label; "pivotal"; end | |
| 3 | + | |
| 4 | + def check_params | |
| 5 | + if %w(api_token project_id).detect {|f| self[f].blank? } | |
| 6 | + errors.add :base, 'You must specify your Pivotal Tracker API token and Project ID' | |
| 7 | + end | |
| 8 | + end | |
| 9 | + | |
| 10 | + def create_issue(err) | |
| 11 | + PivotalTracker::Client.token = api_token | |
| 12 | + PivotalTracker::Client.use_ssl = true | |
| 13 | + project = PivotalTracker::Project.find project_id.to_i | |
| 14 | + story = project.stories.create :name => issue_title(err), :story_type => 'bug', :description => body_template.result(binding) | |
| 15 | + err.update_attribute :issue_link, "https://www.pivotaltracker.com/story/show/#{story.id}" | |
| 16 | + end | |
| 17 | + | |
| 18 | + def body_template | |
| 19 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/pivotal_body.txt.erb")) | |
| 20 | + end | |
| 21 | +end | |
| 22 | + | ... | ... |
| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | +class RedmineTracker < IssueTracker | |
| 2 | + def self.label; "redmine"; end | |
| 3 | + | |
| 4 | + def check_params | |
| 5 | + if %w(account api_token project_id).detect {|f| self[f].blank? } | |
| 6 | + errors.add :base, 'You must specify your Redmine URL, API token and Project ID' | |
| 7 | + end | |
| 8 | + end | |
| 9 | + | |
| 10 | + def create_issue(err) | |
| 11 | + token = api_token | |
| 12 | + acc = account | |
| 13 | + RedmineClient::Base.configure do | |
| 14 | + self.token = token | |
| 15 | + self.site = acc | |
| 16 | + end | |
| 17 | + issue = RedmineClient::Issue.new(:project_id => project_id) | |
| 18 | + issue.subject = issue_title err | |
| 19 | + issue.description = body_template.result(binding) | |
| 20 | + issue.save! | |
| 21 | + err.update_attribute :issue_link, "#{RedmineClient::Issue.site.to_s.sub(/#{RedmineClient::Issue.site.path}$/, '')}#{RedmineClient::Issue.element_path(issue.id, :project_id => project_id)}".sub(/\.xml\?project_id=#{project_id}$/, "\?project_id=#{project_id}") | |
| 22 | + end | |
| 23 | + | |
| 24 | + def body_template | |
| 25 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/redmine_body.txt.erb")) | |
| 26 | + end | |
| 27 | +end | |
| 28 | + | ... | ... |
app/views/apps/_fields.html.haml
| ... | ... | @@ -50,40 +50,40 @@ |
| 50 | 50 | = f.fields_for :issue_tracker do |w| |
| 51 | 51 | %div.issue_tracker.nested |
| 52 | 52 | %div.choose |
| 53 | - = w.radio_button :issue_tracker_type, :none | |
| 54 | - = label_tag :issue_tracker_type_none, '(None)', :for => label_for_attr(w, 'issue_tracker_type_none') | |
| 55 | - = w.radio_button :issue_tracker_type, :lighthouseapp | |
| 56 | - = label_tag :issue_tracker_type_lighthouseapp, 'Lighthouse', :for => label_for_attr(w, 'issue_tracker_type_lighthouseapp') | |
| 57 | - = w.radio_button :issue_tracker_type, :redmine | |
| 58 | - = label_tag :issue_tracker_type_redmine, 'Redmine', :for => label_for_attr(w, 'issue_tracker_type_redmine') | |
| 59 | - = w.radio_button :issue_tracker_type, :pivotal | |
| 60 | - = label_tag :issue_tracker_type_pivotal, 'Pivotal Tracker', :for => label_for_attr(w, 'issue_tracker_type_pivotal') | |
| 61 | - = w.radio_button :issue_tracker_type, :fogbugz | |
| 62 | - = label_tag :issue_tracker_type_fogbugz, 'FogBugz', :for => label_for_attr(w, 'issue_tracker_type_fogbugz') | |
| 63 | - = w.radio_button :issue_tracker_type, :mingle | |
| 64 | - = label_tag :issue_tracker_type_fogbugz, 'Mingle', :for => label_for_attr(w, 'issue_tracker_type_mingle') | |
| 65 | - %div.tracker_params.none{:class => no_tracker?(w.object) ? 'chosen' : nil} | |
| 53 | + = w.radio_button :type, "IssueTracker", 'data-section' => 'none' | |
| 54 | + = label_tag :type_none, '(None)', :for => label_for_attr(w, 'type_none') | |
| 55 | + = w.radio_button :type, "LighthouseTracker", 'data-section' => 'lighthouse' | |
| 56 | + = label_tag :type_lighthouseapp, 'Lighthouse', :for => label_for_attr(w, 'type_lighthouseapp') | |
| 57 | + = w.radio_button :type, "RedmineTracker", 'data-section' => 'redmine' | |
| 58 | + = label_tag :type_redmine, 'Redmine', :for => label_for_attr(w, 'type_redmine') | |
| 59 | + = w.radio_button :type, "PivotalTracker", 'data-section' => 'pivotal' | |
| 60 | + = label_tag :type_pivotal, 'Pivotal Tracker', :for => label_for_attr(w, 'type_pivotal') | |
| 61 | + = w.radio_button :type, "FogbugzTracker", 'data-section' => 'fogbugz' | |
| 62 | + = label_tag :type_fogbugz, 'FogBugz', :for => label_for_attr(w, 'type_fogbugz') | |
| 63 | + = w.radio_button :type, "MingleTracker", 'data-section' => 'mingle' | |
| 64 | + = label_tag :type_fogbugz, 'Mingle', :for => label_for_attr(w, 'type_mingle') | |
| 65 | + %div.tracker_params.none{:class => (w.object && !(w.object.class < IssueTracker)) ? 'chosen' : nil} | |
| 66 | 66 | %p When no issue tracker has been configured, you will be able to leave comments on errors. |
| 67 | - %div.tracker_params.lighthouseapp{:class => lighthouseapp_tracker?(w.object) ? 'chosen' : nil} | |
| 67 | + %div.tracker_params.lighthouse{:class => w.object.is_a?(LighthouseTracker) ? 'chosen' : nil} | |
| 68 | 68 | = w.label :account, "Account" |
| 69 | 69 | = w.text_field :account, :placeholder => "abc from abc.lighthouseapp.com" |
| 70 | 70 | = w.label :api_token, "API token" |
| 71 | 71 | = w.text_field :api_token, :placeholder => "API Token for your account" |
| 72 | 72 | = w.label :project_id, "Project ID" |
| 73 | 73 | = w.text_field :project_id |
| 74 | - %div.tracker_params.redmine{:class => redmine_tracker?(w.object) ? 'chosen' : nil} | |
| 74 | + %div.tracker_params.redmine{:class => w.object.is_a?(RedmineTracker) ? 'chosen' : nil} | |
| 75 | 75 | = w.label :account, "Redmine URL" |
| 76 | 76 | = w.text_field :account, :placeholder => "like http://www.redmine.org/" |
| 77 | 77 | = w.label :api_token, "API token" |
| 78 | 78 | = w.text_field :api_token, :placeholder => "API Token for your account" |
| 79 | 79 | = w.label :project_id, "Project ID" |
| 80 | 80 | = w.text_field :project_id |
| 81 | - %div.tracker_params.pivotal{:class => pivotal_tracker?(w.object) ? 'chosen' : nil} | |
| 81 | + %div.tracker_params.pivotal{:class => w.object.is_a?(PivotalLabsTracker) ? 'chosen' : nil} | |
| 82 | 82 | = w.label :project_id, "Project ID" |
| 83 | 83 | = w.text_field :project_id |
| 84 | 84 | = w.label :api_token, "API token" |
| 85 | 85 | = w.text_field :api_token, :placeholder => "API Token for your account" |
| 86 | - %div.tracker_params.fogbugz{:class => fogbugz_tracker?(w.object) ? 'chosen' : nil} | |
| 86 | + %div.tracker_params.fogbugz{:class => w.object.is_a?(FogbugzTracker) ? 'chosen' : nil} | |
| 87 | 87 | = w.label :project_id, "Area Name" |
| 88 | 88 | = w.text_field :project_id |
| 89 | 89 | = w.label :account, "FogBugz URL" |
| ... | ... | @@ -92,7 +92,7 @@ |
| 92 | 92 | = w.text_field :username, :placeholder => 'Username/Email for your account' |
| 93 | 93 | = w.label :password, 'Password' |
| 94 | 94 | = w.password_field :password, :placeholder => 'Password for your account' |
| 95 | - %div.tracker_params.mingle{:class => mingle_tracker?(w.object) ? 'chosen' : nil} | |
| 95 | + %div.tracker_params.mingle{:class => w.object.is_a?(MingleTracker) ? 'chosen' : nil} | |
| 96 | 96 | = w.label :account, "Mingle URL" |
| 97 | 97 | = w.text_field :account, :placeholder => "http://mingle.yoursite.com/" |
| 98 | 98 | = w.label :project_id, "Project ID" | ... | ... |
app/views/errs/fogbugz_body.txt.erb
| ... | ... | @@ -1,31 +0,0 @@ |
| 1 | -"See this exception on Errbit": <%= app_err_url(err.app, err) %> | |
| 2 | -<% if notice = err.notices.first %> | |
| 3 | - <%= notice.message %> | |
| 4 | - | |
| 5 | - Summary | |
| 6 | - - Where | |
| 7 | - <%= notice.err.where %> | |
| 8 | - | |
| 9 | - - Occured | |
| 10 | - <%= notice.created_at.to_s(:micro) %> | |
| 11 | - | |
| 12 | - - Similar | |
| 13 | - <%= (notice.err.notices_count - 1).to_s %> | |
| 14 | - | |
| 15 | - Params | |
| 16 | - <%= pretty_hash(notice.params) %> | |
| 17 | - | |
| 18 | - Session | |
| 19 | - <%= pretty_hash(notice.session) %> | |
| 20 | - | |
| 21 | - Backtrace | |
| 22 | - <% for line in notice.backtrace %> | |
| 23 | - <%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> | |
| 24 | - <% end %> | |
| 25 | - | |
| 26 | - Environment | |
| 27 | - <% for key, val in notice.env_vars %> | |
| 28 | - <%= key %>: <%= val %> | |
| 29 | - <% end %> | |
| 30 | -<% end %> | |
| 31 | - |
app/views/errs/lighthouseapp_body.txt.erb
| ... | ... | @@ -1,34 +0,0 @@ |
| 1 | -[See this exception on Errbit](<%= app_err_url err.app, err %> "See this exception on Errbit") | |
| 2 | -<% if notice = err.notices.first %> | |
| 3 | - # <%= notice.message %> # | |
| 4 | - ## Summary ## | |
| 5 | - <% if notice.request['url'].present? %> | |
| 6 | - ### URL ### | |
| 7 | - [<%= notice.request['url'] %>](<%= notice.request['url'] %>)" | |
| 8 | - <% end %> | |
| 9 | - ### Where ### | |
| 10 | - <%= notice.err.where %> | |
| 11 | - | |
| 12 | - ### Occured ### | |
| 13 | - <%= notice.created_at.to_s(:micro) %> | |
| 14 | - | |
| 15 | - ### Similar ### | |
| 16 | - <%= (notice.err.notices_count - 1).to_s %> | |
| 17 | - | |
| 18 | - ## Params ## | |
| 19 | - <code><%= pretty_hash(notice.params) %></code> | |
| 20 | - | |
| 21 | - ## Session ## | |
| 22 | - <code><%= pretty_hash(notice.session) %></code> | |
| 23 | - | |
| 24 | - ## Backtrace ## | |
| 25 | - <code> | |
| 26 | - <% for line in notice.backtrace %><%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> -> **<%= line['method'] %>** | |
| 27 | - <% end %> | |
| 28 | - </code> | |
| 29 | - | |
| 30 | - ## Environment ## | |
| 31 | - <% for key, val in notice.env_vars %> | |
| 32 | - <%= key %>: <%= val %> | |
| 33 | - <% end %> | |
| 34 | -<% end %> |
app/views/errs/pivotal_body.txt.erb
| ... | ... | @@ -1,16 +0,0 @@ |
| 1 | -See this exception on Errbit: <%= app_err_url err.app, err %> | |
| 2 | -<% if notice = err.notices.first %> | |
| 3 | - <% if notice.request['url'].present? %>URL: <%= notice.request['url'] %><% end %> | |
| 4 | - Where: <%= notice.err.where %> | |
| 5 | - Occurred: <%= notice.created_at.to_s :micro %> | |
| 6 | - Similar: <%= (notice.err.notices.count - 1).to_s %> | |
| 7 | - | |
| 8 | - Params: | |
| 9 | - <%= pretty_hash notice.params %> | |
| 10 | - | |
| 11 | - Session: | |
| 12 | - <%= pretty_hash notice.session %> | |
| 13 | - | |
| 14 | - Backtrace: | |
| 15 | - <%= notice.backtrace[0..4].map { |line| "#{line['number']}: #{line['file'].sub(/^\[PROJECT_ROOT\]/, '')} -> *#{line['method']}*" }.join "\n" %> | |
| 16 | -<% end %> |
app/views/errs/redmine_body.txt.erb
| ... | ... | @@ -1,44 +0,0 @@ |
| 1 | -<% if notice = err.notices.first %> | |
| 2 | -h1. <%= notice.message %> | |
| 3 | - | |
| 4 | -h3. "See this exception on Errbit":<%= app_err_url err.app, err %> | |
| 5 | - | |
| 6 | -h2. Summary | |
| 7 | -<% if notice.request['url'].present? %> | |
| 8 | -h3. URL | |
| 9 | - | |
| 10 | -"<%= notice.request['url'] %>":<%= notice.request['url'] %> | |
| 11 | -<% end %> | |
| 12 | -h3. Where | |
| 13 | - | |
| 14 | -<%= notice.err.where %> | |
| 15 | - | |
| 16 | -h3. Occured | |
| 17 | - | |
| 18 | -<%= notice.created_at.to_s(:micro) %> | |
| 19 | - | |
| 20 | -h3. Similar | |
| 21 | - | |
| 22 | -<%= (notice.err.notices_count - 1).to_s %> | |
| 23 | - | |
| 24 | -h2. Params | |
| 25 | - | |
| 26 | -<pre><%= pretty_hash(notice.params) %></pre> | |
| 27 | - | |
| 28 | -h2. Session | |
| 29 | - | |
| 30 | -<pre><%= pretty_hash(notice.session) %></pre> | |
| 31 | - | |
| 32 | -h2. Backtrace | |
| 33 | - | |
| 34 | -| Line | File | Method | | |
| 35 | -<% for line in notice.backtrace %>| <%= line['number'] %> | <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> | *<%= line['method'] %>* | | |
| 36 | -<% end %> | |
| 37 | - | |
| 38 | -h2. Environment | |
| 39 | - | |
| 40 | -<% for key, val in notice.env_vars %>| <%= key %> | <%= val %> | | |
| 41 | -<% end %> | |
| 42 | - | |
| 43 | -<% end %> | |
| 44 | - |
app/views/errs/show.html.haml
| ... | ... | @@ -13,9 +13,9 @@ |
| 13 | 13 | - content_for :action_bar do |
| 14 | 14 | - if @err.app.issue_tracker_configured? |
| 15 | 15 | - if @err.issue_link.blank? |
| 16 | - %span= link_to 'create issue', create_issue_app_err_path(@app, @err), :method => :post, :class => "#{@app.issue_tracker.issue_tracker_type}_create create-issue" | |
| 16 | + %span= link_to 'create issue', create_issue_app_err_path(@app, @err), :method => :post, :class => "#{@app.issue_tracker.class.label}_create create-issue" | |
| 17 | 17 | - else |
| 18 | - %span= link_to 'go to issue', @err.issue_link, :class => "#{@app.issue_tracker.issue_tracker_type}_goto goto-issue" | |
| 18 | + %span= link_to 'go to issue', @err.issue_link, :class => "#{@app.issue_tracker.class.label}_goto goto-issue" | |
| 19 | 19 | = link_to 'unlink issue', unlink_issue_app_err_path(@app, @err), :method => :delete, :confirm => "Unlink err issues?", :class => "unlink-issue" |
| 20 | 20 | - if @err.unresolved? |
| 21 | 21 | %span= link_to 'resolve', resolve_app_err_path(@app, @err), :method => :put, :confirm => err_confirm, :class => 'resolve' | ... | ... |
| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | +"See this exception on Errbit": <%= app_err_url(err.app, err) %> | |
| 2 | +<% if notice = err.notices.first %> | |
| 3 | + <%= notice.message %> | |
| 4 | + | |
| 5 | + Summary | |
| 6 | + - Where | |
| 7 | + <%= notice.err.where %> | |
| 8 | + | |
| 9 | + - Occured | |
| 10 | + <%= notice.created_at.to_s(:micro) %> | |
| 11 | + | |
| 12 | + - Similar | |
| 13 | + <%= (notice.err.notices_count - 1).to_s %> | |
| 14 | + | |
| 15 | + Params | |
| 16 | + <%= pretty_hash(notice.params) %> | |
| 17 | + | |
| 18 | + Session | |
| 19 | + <%= pretty_hash(notice.session) %> | |
| 20 | + | |
| 21 | + Backtrace | |
| 22 | + <% for line in notice.backtrace %> | |
| 23 | + <%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> | |
| 24 | + <% end %> | |
| 25 | + | |
| 26 | + Environment | |
| 27 | + <% for key, val in notice.env_vars %> | |
| 28 | + <%= key %>: <%= val %> | |
| 29 | + <% end %> | |
| 30 | +<% end %> | |
| 31 | + | ... | ... |
| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | +[See this exception on Errbit](<%= app_err_url err.app, err %> "See this exception on Errbit") | |
| 2 | +<% if notice = err.notices.first %> | |
| 3 | + # <%= notice.message %> # | |
| 4 | + ## Summary ## | |
| 5 | + <% if notice.request['url'].present? %> | |
| 6 | + ### URL ### | |
| 7 | + [<%= notice.request['url'] %>](<%= notice.request['url'] %>)" | |
| 8 | + <% end %> | |
| 9 | + ### Where ### | |
| 10 | + <%= notice.err.where %> | |
| 11 | + | |
| 12 | + ### Occured ### | |
| 13 | + <%= notice.created_at.to_s(:micro) %> | |
| 14 | + | |
| 15 | + ### Similar ### | |
| 16 | + <%= (notice.err.notices_count - 1).to_s %> | |
| 17 | + | |
| 18 | + ## Params ## | |
| 19 | + <code><%= pretty_hash(notice.params) %></code> | |
| 20 | + | |
| 21 | + ## Session ## | |
| 22 | + <code><%= pretty_hash(notice.session) %></code> | |
| 23 | + | |
| 24 | + ## Backtrace ## | |
| 25 | + <code> | |
| 26 | + <% for line in notice.backtrace %><%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> -> **<%= line['method'] %>** | |
| 27 | + <% end %> | |
| 28 | + </code> | |
| 29 | + | |
| 30 | + ## Environment ## | |
| 31 | + <% for key, val in notice.env_vars %> | |
| 32 | + <%= key %>: <%= val %> | |
| 33 | + <% end %> | |
| 34 | +<% end %> | ... | ... |
| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | +See this exception on Errbit: <%= app_err_url err.app, err %> | |
| 2 | +<% if notice = err.notices.first %> | |
| 3 | + <% if notice.request['url'].present? %>URL: <%= notice.request['url'] %><% end %> | |
| 4 | + Where: <%= notice.err.where %> | |
| 5 | + Occurred: <%= notice.created_at.to_s :micro %> | |
| 6 | + Similar: <%= (notice.err.notices.count - 1).to_s %> | |
| 7 | + | |
| 8 | + Params: | |
| 9 | + <%= pretty_hash notice.params %> | |
| 10 | + | |
| 11 | + Session: | |
| 12 | + <%= pretty_hash notice.session %> | |
| 13 | + | |
| 14 | + Backtrace: | |
| 15 | + <%= notice.backtrace[0..4].map { |line| "#{line['number']}: #{line['file'].sub(/^\[PROJECT_ROOT\]/, '')} -> *#{line['method']}*" }.join "\n" %> | |
| 16 | +<% end %> | ... | ... |
| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | +<% if notice = err.notices.first %> | |
| 2 | +h1. <%= notice.message %> | |
| 3 | + | |
| 4 | +h3. "See this exception on Errbit":<%= app_err_url err.app, err %> | |
| 5 | + | |
| 6 | +h2. Summary | |
| 7 | +<% if notice.request['url'].present? %> | |
| 8 | +h3. URL | |
| 9 | + | |
| 10 | +"<%= notice.request['url'] %>":<%= notice.request['url'] %> | |
| 11 | +<% end %> | |
| 12 | +h3. Where | |
| 13 | + | |
| 14 | +<%= notice.err.where %> | |
| 15 | + | |
| 16 | +h3. Occured | |
| 17 | + | |
| 18 | +<%= notice.created_at.to_s(:micro) %> | |
| 19 | + | |
| 20 | +h3. Similar | |
| 21 | + | |
| 22 | +<%= (notice.err.notices_count - 1).to_s %> | |
| 23 | + | |
| 24 | +h2. Params | |
| 25 | + | |
| 26 | +<pre><%= pretty_hash(notice.params) %></pre> | |
| 27 | + | |
| 28 | +h2. Session | |
| 29 | + | |
| 30 | +<pre><%= pretty_hash(notice.session) %></pre> | |
| 31 | + | |
| 32 | +h2. Backtrace | |
| 33 | + | |
| 34 | +| Line | File | Method | | |
| 35 | +<% for line in notice.backtrace %>| <%= line['number'] %> | <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> | *<%= line['method'] %>* | | |
| 36 | +<% end %> | |
| 37 | + | |
| 38 | +h2. Environment | |
| 39 | + | |
| 40 | +<% for key, val in notice.env_vars %>| <%= key %> | <%= val %> | | |
| 41 | +<% end %> | |
| 42 | + | |
| 43 | +<% end %> | |
| 44 | + | ... | ... |
config/application.rb
| ... | ... | @@ -19,7 +19,7 @@ module Errbit |
| 19 | 19 | # -- all .rb files in that directory are automatically loaded. |
| 20 | 20 | |
| 21 | 21 | # Custom directories with classes and modules you want to be autoloadable. |
| 22 | - # config.autoload_paths += %W(#{config.root}/extras) | |
| 22 | + config.autoload_paths += %W(app/models/issue_trackers) | |
| 23 | 23 | |
| 24 | 24 | # Only load the plugins named here, in the order given (default is alphabetical). |
| 25 | 25 | # :all can be used as a placeholder for all plugins not explicitly named. |
| ... | ... | @@ -53,3 +53,4 @@ module Errbit |
| 53 | 53 | config.filter_parameters += [:password] |
| 54 | 54 | end |
| 55 | 55 | end |
| 56 | + | ... | ... |
config/initializers/issue_trackers.rb
| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | +class MoveIssueTrackersToSti < Mongoid::Migration | |
| 2 | + def self.up | |
| 3 | + App.all.each do |app| | |
| 4 | + # Update all embedded issue trackers to use STI patterns. | |
| 5 | + # All issue trackers now subclass the IssueTracker model, | |
| 6 | + # and their class is stored in the '_type' field, which is | |
| 7 | + # also aliased to 'type'. | |
| 8 | + if app.issue_tracker && app.issue_tracker.attributes["issue_tracker_type"] | |
| 9 | + app.issue_tracker._type = case app.issue_tracker.issue_tracker_type | |
| 10 | + when 'lighthouseapp'; "LighthouseTracker" | |
| 11 | + when 'redmine'; "RedmineTracker" | |
| 12 | + when 'pivotal'; "PivotalLabsTracker" | |
| 13 | + when 'fogbugz'; "FogbugzTracker" | |
| 14 | + when 'mingle'; "MingleTracker" | |
| 15 | + else; nil | |
| 16 | + end | |
| 17 | + if app.issue_tracker.issue_tracker_type == "none" | |
| 18 | + app.issue_tracker = nil | |
| 19 | + else | |
| 20 | + app.issue_tracker.issue_tracker_type = nil | |
| 21 | + end | |
| 22 | + app.save | |
| 23 | + end | |
| 24 | + end | |
| 25 | + end | |
| 26 | + | |
| 27 | + def self.down | |
| 28 | + end | |
| 29 | +end | |
| 30 | + | ... | ... |
| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | +module Mingle | |
| 2 | + class Card < ActiveResource::Base | |
| 3 | + # site template ~> "https://username:password@mingle.example.com/api/v1/projects/:project_id/" | |
| 4 | + end | |
| 5 | + def self.set_site(site) | |
| 6 | + # ActiveResource seems to clone and freeze the @site variable | |
| 7 | + # after the first use. It seems that the only way to change @site | |
| 8 | + # is to drop the subclass, and then reload it. | |
| 9 | + Mingle.send(:remove_const, :Card) | |
| 10 | + load File.join(Rails.root,'lib','issue_tracker_apis','mingle.rb') | |
| 11 | + Mingle::Card.site = site | |
| 12 | + end | |
| 13 | +end | |
| 14 | + | ... | ... |
lib/issue_trackers/mingle.rb
| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | -module Mingle | |
| 2 | - class Card < ActiveResource::Base | |
| 3 | - # site template ~> "https://username:password@mingle.example.com/api/v1/projects/:project_id/" | |
| 4 | - end | |
| 5 | - def self.set_site(site) | |
| 6 | - # ActiveResource seems to clone and freeze the @site variable | |
| 7 | - # after the first use. It seems that the only way to change @site | |
| 8 | - # is to drop the subclass, and then reload it. | |
| 9 | - Mingle.send(:remove_const, :Card) | |
| 10 | - load File.join(Rails.root,'lib','issue_trackers','mingle.rb') | |
| 11 | - Mingle::Card.site = site | |
| 12 | - end | |
| 13 | -end | |
| 14 | - |
public/javascripts/form.js
| ... | ... | @@ -71,8 +71,8 @@ function activateTypeSelector(field_class, section_class) { |
| 71 | 71 | $('div.'+field_class+' > div.'+section_class).not('.chosen').find('input') |
| 72 | 72 | .attr('disabled','disabled').val(''); |
| 73 | 73 | |
| 74 | - $('div.'+field_class+' input[name*='+field_class+'_type]').live('click', function(){ | |
| 75 | - var chosen = $(this).val(); | |
| 74 | + $('div.'+field_class+' input[name*=type]').live('click', function(){ | |
| 75 | + var chosen = $(this).data("section"); | |
| 76 | 76 | var wrapper = $(this).closest('.nested'); |
| 77 | 77 | wrapper.find('div.chosen.'+section_class).removeClass('chosen').find('input').attr('disabled','disabled'); |
| 78 | 78 | wrapper.find('div.'+section_class+'.'+chosen).addClass('chosen').find('input').removeAttr('disabled'); | ... | ... |
spec/controllers/apps_controller_spec.rb
| ... | ... | @@ -263,25 +263,25 @@ describe AppsController do |
| 263 | 263 | context "unknown tracker type" do |
| 264 | 264 | before(:each) do |
| 265 | 265 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 266 | - :issue_tracker_type => 'unknown', :project_id => '1234', :api_token => '123123', :account => 'myapp' | |
| 266 | + :type => 'unknown', :project_id => '1234', :api_token => '123123', :account => 'myapp' | |
| 267 | 267 | } } |
| 268 | 268 | @app.reload |
| 269 | 269 | end |
| 270 | 270 | |
| 271 | 271 | it "should not create issue tracker" do |
| 272 | - @app.issue_tracker.should be_nil | |
| 272 | + @app.issue_tracker_configured?.should == false | |
| 273 | 273 | end |
| 274 | 274 | end |
| 275 | 275 | |
| 276 | 276 | context "lighthouseapp" do |
| 277 | 277 | it "should save tracker params" do |
| 278 | 278 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 279 | - :issue_tracker_type => 'lighthouseapp', :project_id => '1234', :api_token => '123123', :account => 'myapp' | |
| 279 | + :type => 'LighthouseTracker', :project_id => '1234', :api_token => '123123', :account => 'myapp' | |
| 280 | 280 | } } |
| 281 | 281 | @app.reload |
| 282 | 282 | |
| 283 | 283 | tracker = @app.issue_tracker |
| 284 | - tracker.issue_tracker_type.should == 'lighthouseapp' | |
| 284 | + tracker.should be_a(LighthouseTracker) | |
| 285 | 285 | tracker.project_id.should == '1234' |
| 286 | 286 | tracker.api_token.should == '123123' |
| 287 | 287 | tracker.account.should == 'myapp' |
| ... | ... | @@ -289,11 +289,11 @@ describe AppsController do |
| 289 | 289 | |
| 290 | 290 | it "should show validation notice when sufficient params are not present" do |
| 291 | 291 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 292 | - :issue_tracker_type => 'lighthouseapp', :project_id => '1234', :api_token => '123123' | |
| 292 | + :type => 'LighthouseTracker', :project_id => '1234', :api_token => '123123' | |
| 293 | 293 | } } |
| 294 | 294 | @app.reload |
| 295 | 295 | |
| 296 | - @app.issue_tracker.should be_nil | |
| 296 | + @app.issue_tracker_configured?.should == false | |
| 297 | 297 | response.body.should match(/You must specify your Lighthouseapp account, API token and Project ID/) |
| 298 | 298 | end |
| 299 | 299 | end |
| ... | ... | @@ -301,12 +301,12 @@ describe AppsController do |
| 301 | 301 | context "redmine" do |
| 302 | 302 | it "should save tracker params" do |
| 303 | 303 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 304 | - :issue_tracker_type => 'redmine', :project_id => '1234', :api_token => '123123', :account => 'http://myapp.com' | |
| 304 | + :type => 'RedmineTracker', :project_id => '1234', :api_token => '123123', :account => 'http://myapp.com' | |
| 305 | 305 | } } |
| 306 | 306 | @app.reload |
| 307 | 307 | |
| 308 | 308 | tracker = @app.issue_tracker |
| 309 | - tracker.issue_tracker_type.should == 'redmine' | |
| 309 | + tracker.should be_a(RedmineTracker) | |
| 310 | 310 | tracker.project_id.should == '1234' |
| 311 | 311 | tracker.api_token.should == '123123' |
| 312 | 312 | tracker.account.should == 'http://myapp.com' |
| ... | ... | @@ -314,11 +314,11 @@ describe AppsController do |
| 314 | 314 | |
| 315 | 315 | it "should show validation notice when sufficient params are not present" do |
| 316 | 316 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 317 | - :issue_tracker_type => 'redmine', :project_id => '1234', :api_token => '123123' | |
| 317 | + :type => 'RedmineTracker', :project_id => '1234', :api_token => '123123' | |
| 318 | 318 | } } |
| 319 | 319 | @app.reload |
| 320 | 320 | |
| 321 | - @app.issue_tracker.should be_nil | |
| 321 | + @app.issue_tracker_configured?.should == false | |
| 322 | 322 | response.body.should match(/You must specify your Redmine URL, API token and Project ID/) |
| 323 | 323 | end |
| 324 | 324 | end |
| ... | ... | @@ -326,21 +326,21 @@ describe AppsController do |
| 326 | 326 | context "pivotal" do |
| 327 | 327 | it "should save tracker params" do |
| 328 | 328 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 329 | - :issue_tracker_type => 'pivotal', :project_id => '1234', :api_token => '123123' } } | |
| 329 | + :type => 'PivotalLabsTracker', :project_id => '1234', :api_token => '123123' } } | |
| 330 | 330 | @app.reload |
| 331 | 331 | |
| 332 | 332 | tracker = @app.issue_tracker |
| 333 | - tracker.issue_tracker_type.should == 'pivotal' | |
| 333 | + tracker.should be_a(PivotalLabsTracker) | |
| 334 | 334 | tracker.project_id.should == '1234' |
| 335 | 335 | tracker.api_token.should == '123123' |
| 336 | 336 | end |
| 337 | 337 | |
| 338 | 338 | it "should show validation notice when sufficient params are not present" do |
| 339 | 339 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 340 | - :issue_tracker_type => 'pivotal', :project_id => '1234' } } | |
| 340 | + :type => 'PivotalLabsTracker', :project_id => '1234' } } | |
| 341 | 341 | @app.reload |
| 342 | 342 | |
| 343 | - @app.issue_tracker.should be_nil | |
| 343 | + @app.issue_tracker_configured?.should == false | |
| 344 | 344 | response.body.should match(/You must specify your Pivotal Tracker API token and Project ID/) |
| 345 | 345 | end |
| 346 | 346 | end |
| ... | ... | @@ -349,12 +349,12 @@ describe AppsController do |
| 349 | 349 | context 'with correct params' do |
| 350 | 350 | before do |
| 351 | 351 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 352 | - :issue_tracker_type => 'fogbugz', :account => 'abc', :project_id => 'Service - Peon', :username => '1234', :password => '123123' } } | |
| 352 | + :type => 'FogbugzTracker', :account => 'abc', :project_id => 'Service - Peon', :username => '1234', :password => '123123' } } | |
| 353 | 353 | @app.reload |
| 354 | 354 | end |
| 355 | 355 | |
| 356 | 356 | subject {@app.issue_tracker} |
| 357 | - its(:issue_tracker_type) {should == 'fogbugz'} | |
| 357 | + its(:type) {should == "FogbugzTracker"} | |
| 358 | 358 | its(:account) {should == 'abc'} |
| 359 | 359 | its(:project_id) {should == 'Service - Peon'} |
| 360 | 360 | its(:username) {should == '1234'} |
| ... | ... | @@ -364,11 +364,11 @@ describe AppsController do |
| 364 | 364 | context 'insufficient params' do |
| 365 | 365 | it 'shows validation notice' do |
| 366 | 366 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 367 | - :issue_tracker_type => 'fogbugz', :project_id => '1234' } } | |
| 367 | + :type => 'FogbugzTracker', :project_id => '1234' } } | |
| 368 | 368 | @app.reload |
| 369 | 369 | |
| 370 | - @app.issue_tracker.should be_nil | |
| 371 | - response.body.should match(/You must specify your FogBugz Area Name, Username, and Password/) | |
| 370 | + @app.issue_tracker_configured?.should == false | |
| 371 | + response.body.should match(/You must specify your FogBugz Area Name, FogBugz URL, Username, and Password/) | |
| 372 | 372 | end |
| 373 | 373 | end |
| 374 | 374 | end |
| ... | ... | @@ -377,14 +377,14 @@ describe AppsController do |
| 377 | 377 | context 'with correct params' do |
| 378 | 378 | before do |
| 379 | 379 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 380 | - :issue_tracker_type => 'mingle', :project_id => 'test', :account => 'http://mingle.example.com', | |
| 380 | + :type => 'MingleTracker', :project_id => 'test', :account => 'http://mingle.example.com', | |
| 381 | 381 | :username => '1234', :password => '123123', :ticket_properties => "card_type = Defect" |
| 382 | 382 | } } |
| 383 | 383 | @app.reload |
| 384 | 384 | end |
| 385 | 385 | |
| 386 | 386 | subject {@app.issue_tracker} |
| 387 | - its(:issue_tracker_type) {should == 'mingle'} | |
| 387 | + its(:type) {should == "MingleTracker"} | |
| 388 | 388 | its(:project_id) {should == 'test'} |
| 389 | 389 | its(:username) {should == '1234'} |
| 390 | 390 | its(:password) {should == '123123'} |
| ... | ... | @@ -392,12 +392,12 @@ describe AppsController do |
| 392 | 392 | |
| 393 | 393 | it "should show validation notice when sufficient params are not present" do |
| 394 | 394 | put :update, :id => @app.id, :app => { :issue_tracker_attributes => { |
| 395 | - :issue_tracker_type => 'mingle', :project_id => 'test', :account => 'http://mingle.example.com', | |
| 395 | + :type => 'MingleTracker', :project_id => 'test', :account => 'http://mingle.example.com', | |
| 396 | 396 | :username => '1234', :password => '1234', :ticket_properties => "cards_type = Defect" |
| 397 | 397 | } } |
| 398 | 398 | @app.reload |
| 399 | 399 | |
| 400 | - @app.issue_tracker.should be_nil | |
| 400 | + @app.issue_tracker_configured?.should == false | |
| 401 | 401 | response.body.should match(/You must specify your Mingle URL, Project ID, Card Type \(in default card properties\), Sign-in name, and Password/) |
| 402 | 402 | end |
| 403 | 403 | end | ... | ... |
spec/controllers/errs_controller_spec.rb
| ... | ... | @@ -173,7 +173,7 @@ describe ErrsController do |
| 173 | 173 | end |
| 174 | 174 | |
| 175 | 175 | it "should exist for err's app with issue tracker" do |
| 176 | - tracker = Factory(:lighthouseapp_tracker) | |
| 176 | + tracker = Factory(:lighthouse_tracker) | |
| 177 | 177 | err = Factory(:err, :app => tracker.app) |
| 178 | 178 | get :show, :app_id => err.app.id, :id => err.id |
| 179 | 179 | |
| ... | ... | @@ -181,7 +181,7 @@ describe ErrsController do |
| 181 | 181 | end |
| 182 | 182 | |
| 183 | 183 | it "should not exist for err with issue_link" do |
| 184 | - tracker = Factory(:lighthouseapp_tracker) | |
| 184 | + tracker = Factory(:lighthouse_tracker) | |
| 185 | 185 | err = Factory(:err, :app => tracker.app, :issue_link => "http://some.host") |
| 186 | 186 | get :show, :app_id => err.app.id, :id => err.id |
| 187 | 187 | |
| ... | ... | @@ -262,7 +262,7 @@ describe ErrsController do |
| 262 | 262 | context "successful issue creation" do |
| 263 | 263 | context "lighthouseapp tracker" do |
| 264 | 264 | let(:notice) { Factory :notice } |
| 265 | - let(:tracker) { Factory :lighthouseapp_tracker, :app => notice.err.app } | |
| 265 | + let(:tracker) { Factory :lighthouse_tracker, :app => notice.err.app } | |
| 266 | 266 | let(:err) { notice.err } |
| 267 | 267 | |
| 268 | 268 | before(:each) do |
| ... | ... | @@ -326,7 +326,7 @@ describe ErrsController do |
| 326 | 326 | |
| 327 | 327 | context "pivotal tracker" do |
| 328 | 328 | let(:notice) { Factory :notice } |
| 329 | - let(:tracker) { Factory :pivotal_tracker, :app => notice.err.app, :project_id => 10 } | |
| 329 | + let(:tracker) { Factory :pivotal_labs_tracker, :app => notice.err.app, :project_id => 10 } | |
| 330 | 330 | let(:err) { notice.err } |
| 331 | 331 | |
| 332 | 332 | before(:each) do |
| ... | ... | @@ -370,7 +370,7 @@ describe ErrsController do |
| 370 | 370 | before(:each) do |
| 371 | 371 | number = 5 |
| 372 | 372 | @issue_link = "#{tracker.account}/projects/#{tracker.project_id}/cards/#{number}.xml" |
| 373 | - @basic_auth = tracker.account.gsub("https://", "https://#{tracker.username}:#{tracker.password}@") | |
| 373 | + @basic_auth = tracker.account.gsub("://", "://#{tracker.username}:#{tracker.password}@") | |
| 374 | 374 | body = "<card><id type=\"integer\">#{number}</id></card>" |
| 375 | 375 | stub_request(:post, "#{@basic_auth}/api/v1/projects/#{tracker.project_id}/cards.xml"). |
| 376 | 376 | to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) |
| ... | ... | @@ -415,7 +415,7 @@ describe ErrsController do |
| 415 | 415 | |
| 416 | 416 | context "error during request to a tracker" do |
| 417 | 417 | context "lighthouseapp tracker" do |
| 418 | - let(:tracker) { Factory :lighthouseapp_tracker } | |
| 418 | + let(:tracker) { Factory :lighthouse_tracker } | |
| 419 | 419 | let(:err) { Factory :err, :app => tracker.app } |
| 420 | 420 | |
| 421 | 421 | before(:each) do | ... | ... |
spec/factories/issue_tracker_factories.rb
| 1 | -Factory.define :generic_tracker, :class => IssueTracker do |e| | |
| 1 | +Factory.define :issue_tracker do |e| | |
| 2 | 2 | e.api_token { Factory.next :word } |
| 3 | 3 | e.project_id { Factory.next :word } |
| 4 | 4 | e.association :app, :factory => :app |
| 5 | -end | |
| 6 | - | |
| 7 | -Factory.define :lighthouseapp_tracker, :parent => :generic_tracker do |e| | |
| 8 | - e.issue_tracker_type 'lighthouseapp' | |
| 9 | 5 | e.account { Factory.next :word } |
| 6 | + e.username { Factory.next :word } | |
| 7 | + e.password { Factory.next :word } | |
| 10 | 8 | end |
| 11 | 9 | |
| 12 | -Factory.define :redmine_tracker, :parent => :generic_tracker do |e| | |
| 13 | - e.issue_tracker_type 'redmine' | |
| 14 | - e.account { "http://#{Factory.next(:word)}.com" } | |
| 10 | +%w(lighthouse pivotal_labs fogbugz).each do |t| | |
| 11 | + Factory.define "#{t}_tracker".to_sym, :parent => :issue_tracker, :class => "#{t}_tracker".to_sym do |e|; end | |
| 15 | 12 | end |
| 16 | 13 | |
| 17 | -Factory.define :pivotal_tracker, :parent => :generic_tracker do |e| | |
| 18 | - e.issue_tracker_type 'pivotal' | |
| 14 | +Factory.define :redmine_tracker, :parent => :issue_tracker, :class => :redmine_tracker do |e| | |
| 15 | + e.account 'http://redmine.example.com' | |
| 19 | 16 | end |
| 20 | 17 | |
| 21 | -Factory.define :mingle_tracker, :parent => :generic_tracker do |t| | |
| 22 | - t.issue_tracker_type 'mingle' | |
| 23 | - t.account "https://mingle.example.com" | |
| 24 | - t.ticket_properties 'card_type = Defect, defect_status = open, priority = essential' | |
| 25 | - t.username "test_user" | |
| 26 | - t.password "test_password" | |
| 18 | +Factory.define :mingle_tracker, :parent => :issue_tracker, :class => :mingle_tracker do |e| | |
| 19 | + e.account 'https://mingle.example.com' | |
| 20 | + e.ticket_properties 'card_type = Defect, defect_status = open, priority = essential' | |
| 27 | 21 | end |
| 28 | 22 | ... | ... |
spec/views/errs/show.html.haml_spec.rb
| ... | ... | @@ -51,7 +51,7 @@ describe "errs/show.html.erb" do |
| 51 | 51 | |
| 52 | 52 | context "with issue tracker" do |
| 53 | 53 | def with_issue_tracker(err) |
| 54 | - err.app.issue_tracker = IssueTracker.new :issue_tracker_type => "lighthouseapp", :project_id => "1234" | |
| 54 | + err.app.issue_tracker = PivotalLabsTracker.new :api_token => "token token token", :project_id => "1234" | |
| 55 | 55 | assign :err, err |
| 56 | 56 | assign :app, err.app |
| 57 | 57 | end | ... | ... |