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 | ... | ... |