rallytastic 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -5,6 +5,10 @@ gem 'jeweler'
5
5
  gem 'mongoid', '2.0.0.beta.15'
6
6
  gem 'bson_ext'
7
7
  gem 'rest-client'
8
+ gem 'thor'
9
+
10
+ gem 'fabrication', :git => "git://github.com/winescout/fabrication.git"
8
11
  gem 'rspec'
9
12
  gem 'autotest'
10
- gem 'thor'
13
+
14
+
data/Gemfile.lock CHANGED
@@ -1,3 +1,9 @@
1
+ GIT
2
+ remote: git://github.com/winescout/fabrication.git
3
+ revision: 51d9cdf
4
+ specs:
5
+ fabrication (0.6.0)
6
+
1
7
  GEM
2
8
  remote: http://rubygems.org/
3
9
  specs:
@@ -17,7 +23,7 @@ GEM
17
23
  gemcutter (>= 0.1.0)
18
24
  git (>= 1.2.5)
19
25
  rubyforge (>= 2.0.0)
20
- json_pure (1.4.3)
26
+ json_pure (1.4.5)
21
27
  mime-types (1.16)
22
28
  mongo (1.0.6)
23
29
  bson (>= 1.0.4)
@@ -43,6 +49,7 @@ PLATFORMS
43
49
  DEPENDENCIES
44
50
  autotest
45
51
  bson_ext
52
+ fabrication!
46
53
  jeweler
47
54
  mongoid (= 2.0.0.beta.15)
48
55
  rake
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.2
1
+ 1.2.0
data/lib/parsers/base.rb CHANGED
@@ -1,23 +1,25 @@
1
- module Parser
2
- class Base
3
- attr_accessor :story
4
- def initialize story
5
- @story = story
6
- end
7
-
8
- def revisions
9
- @story.revisions
10
- end
11
-
12
- protected
13
- def latest_revision_date_matching regexp
14
- revision = revisions.desc(:created_on).select{|r| r.description =~ regexp}.first
15
- revision.created_on if revision
16
- end
17
-
18
- def first_revision_date_matching regexp
19
- revision = revisions.asc(:created_on).select{|r| r.description =~ regexp}.first
20
- revision.created_on if revision
1
+ module Rally
2
+ module Parser
3
+ class Base
4
+ attr_accessor :story
5
+ def initialize story
6
+ @story = story
7
+ end
8
+
9
+ def revisions
10
+ @story.revisions
11
+ end
12
+
13
+ protected
14
+ def latest_revision_date_matching regexp
15
+ revision = revisions.desc(:created_on).select{|r| r.description =~ regexp}.first
16
+ revision.created_on if revision
17
+ end
18
+
19
+ def first_revision_date_matching regexp
20
+ revision = revisions.asc(:created_on).select{|r| r.description =~ regexp}.first
21
+ revision.created_on if revision
22
+ end
21
23
  end
22
24
  end
23
25
  end
data/lib/project.rb CHANGED
@@ -16,12 +16,11 @@ class Project
16
16
  field :notes
17
17
  field :state
18
18
 
19
- field :revision_parser
20
-
21
19
  referenced_in :parent, :class_name => "Project"
22
20
  references_many :children, :class_name => "Project"
23
21
  references_many :iterations
24
-
22
+ embeds_one :revision_parser
23
+
25
24
  def refresh hash_values=nil
26
25
  @rally_hash = hash_values if hash_values
27
26
  from_rally :name
data/lib/rallytastic.rb CHANGED
@@ -21,9 +21,9 @@ require File.join(lib, 'project.rb')
21
21
  require File.join(lib, 'iteration.rb')
22
22
  require File.join(lib, 'revision_history.rb')
23
23
  require File.join(lib, 'revision.rb')
24
+ require File.join(lib, 'revision_parser.rb')
24
25
  require File.join(lib, 'rally/rally_api.rb')
25
26
  require File.join(lib, 'parsers/base.rb')
26
- require File.join(lib, 'parsers/madison.rb')
27
27
 
28
28
 
29
29
  #temp for rally and mongoid setup
data/lib/revision.rb CHANGED
@@ -6,6 +6,7 @@ class Revision
6
6
  field :description
7
7
  field :revision_number
8
8
  field :created_on
9
+ field :rally_uri
9
10
 
10
11
  embedded_in :story, :inverse_of => :revisions
11
12
 
@@ -3,7 +3,7 @@ class RevisionHistory
3
3
  include Rally::ParsingHelpers
4
4
  extend Rally::ParsingHelperClassMethods
5
5
 
6
- field :revisions, :type => Array
6
+ field :revision_uris, :type => Array
7
7
 
8
8
  class << self
9
9
  def rally_uri
@@ -12,8 +12,7 @@ class RevisionHistory
12
12
  end
13
13
 
14
14
  def refresh
15
- parse_refs :revisions, raw_json["Revisions"]
15
+ parse_refs :revision_uris, raw_json["Revisions"]
16
16
  self.save
17
17
  end
18
-
19
18
  end
@@ -0,0 +1,45 @@
1
+ class RevisionParser
2
+ include Mongoid::Document
3
+
4
+ field :name
5
+ field :sized_on_regex
6
+ field :prioritized_on_regex
7
+ field :started_on_regex
8
+ field :completed_on_regex
9
+
10
+ embedded_in :project, :inverse_of => :revision_parser
11
+
12
+
13
+ def sized_on(revisions)
14
+ regex = sized_on_regex ? eval(sized_on_regex) : /TASK ESTIMATE TOTAL changed from \[0.0\]/
15
+ first_revision_date_matching regex, revisions
16
+ end
17
+
18
+ def prioritized_on(revisions)
19
+ regex = prioritized_on_regex ? eval(prioritized_on_regex) : /PROJECT changed from \[[^\]]*\] to \[Madison\]/
20
+ latest_revision_date_matching regex, revisions
21
+ end
22
+
23
+ def started_on(revisions)
24
+ regex = started_on_regex ? eval(started_on_regex) : /ITERATION added/
25
+ latest_revision_date_matching regex, revisions
26
+ end
27
+
28
+ def completed_on(revisions)
29
+ #regex = completed_on_regex ? eval(completed_on_regex) : /SCHEDULE STATE changed from \[[^\]]*\] to [Complete]/
30
+ regex = completed_on_regex ? eval(completed_on_regex) : /SCHEDULE STATE changed from \[[^\]]*\] to \[Complete\]/
31
+ latest_revision_date_matching regex, revisions
32
+ end
33
+
34
+ protected
35
+ def latest_revision_date_matching regexp, revisions
36
+ revision = revisions.desc(:created_on).select{|r| r.description =~ regexp}.first
37
+ Time.parse(revision.created_on) if revision
38
+ end
39
+
40
+ def first_revision_date_matching regexp, revisions
41
+ revision = revisions.asc(:created_on).select{|r| r.description =~ regexp}.first
42
+ Time.parse(revision.created_on) if revision
43
+ end
44
+
45
+ end
data/lib/story.rb CHANGED
@@ -33,46 +33,46 @@ class Story
33
33
  field :completed_on, :type => DateTime
34
34
 
35
35
  embeds_many :revisions, :inverse_of => :story
36
+ embeds_one :revision_parser, :inverse_of => :story
36
37
  referenced_in :iteration
37
38
  referenced_in :parent, :class_name => "Story", :inverse_of => :children
38
39
  references_many :children, :class_name => "Story", :inverse_of => :parent
39
40
 
40
- def set_revision_history
41
+ def revision_fields
42
+ [:sized_on, :prioritized_on, :started_on, :completed_on]
43
+ end
44
+
45
+ def parse_revisions_for_status_changes
41
46
  revision_fields.each do |field|
42
- self.send("#{field}=", revision_parser.send(field))
47
+ timestamp = revision_parser.send(field, revisions)
48
+ self.send("#{field}=", timestamp)
43
49
  end
44
50
  end
45
51
 
46
- def revision_history
52
+ def status_changes
47
53
  set_revision_history
48
54
  revision_fields.inject({}){|h,field| h[field] = self.send(field.to_s); h}
49
55
  end
50
-
51
- def revision_fields
52
- [:sized_on, :prioritized_on, :started_on, :completed_on]
53
- end
54
-
56
+
55
57
  def revision_parser
56
58
  if self.iteration && self.iteration.project
57
- eval("Parser::#{self.iteration.project.revision_parser}").new(self)
59
+ self.iteration.project.revision_parser
58
60
  end
59
61
  end
60
62
 
61
63
 
62
64
  def pull_revisions
63
- revision_list = RevisionHistory.new(:rally_uri => self.revision_history_uri)
64
- revision_list.refresh
65
- revision_uris = story.revisions.collect{|r| r.rally_uri}
66
- if revision_list.revisions
67
- revision_list.revisions.each do |uri|
68
- unless revision_uris.include?(uri)
69
- r = Revision.new(:rally_uri => uri)
70
- r.refresh
71
- self.revisions << r
65
+ revision_history.refresh
66
+ revision_uris = self.revisions.collect{|r| r.rally_uri}
67
+ if revision_history.revisions
68
+ revision_history.revisions.each do |rally_revision|
69
+ unless revision_uris.include?(rally_revision.rally_uri)
70
+ rally_revision.refresh
71
+ self.revisions << rally_revision
72
72
  end
73
73
  end
74
74
  end
75
- self.set_revision_history
75
+ self.parse_revisions_for_status_changes
76
76
  self.save
77
77
  end
78
78
 
@@ -116,4 +116,9 @@ class Story
116
116
 
117
117
  self.save
118
118
  end
119
+
120
+ private
121
+ def revision_history
122
+ RevisionHistory.new(:rally_uri => self.revision_history_uri)
123
+ end
119
124
  end
@@ -0,0 +1,108 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rallytastic}
8
+ s.version = "1.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Matt Clark"]
12
+ s.date = %q{2010-08-08}
13
+ s.description = %q{longer description of your gem}
14
+ s.email = %q{winescout@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "lib/iteration.rb",
29
+ "lib/parsers/base.rb",
30
+ "lib/project.rb",
31
+ "lib/rally/parsing_helpers.rb",
32
+ "lib/rally/rally_api.rb",
33
+ "lib/rallytastic.rb",
34
+ "lib/revision.rb",
35
+ "lib/revision_history.rb",
36
+ "lib/revision_parser.rb",
37
+ "lib/story.rb",
38
+ "lib/tasks/docs.thor",
39
+ "lib/tasks/scraper.thor",
40
+ "rallytastic.gemspec",
41
+ "spec/fabricators/iteration.rb",
42
+ "spec/fabricators/project.rb",
43
+ "spec/fabricators/revision.rb",
44
+ "spec/fabricators/revision_history.rb",
45
+ "spec/fabricators/revision_parser.rb",
46
+ "spec/fabricators/story.rb",
47
+ "spec/fixtures/child_project.txt",
48
+ "spec/fixtures/iteration.txt",
49
+ "spec/fixtures/project.txt",
50
+ "spec/fixtures/story.txt",
51
+ "spec/fixtures/story_query.txt",
52
+ "spec/iteration_spec.rb",
53
+ "spec/project_spec.rb",
54
+ "spec/rally/rally_api_spec.rb",
55
+ "spec/revision_parser_spec.rb",
56
+ "spec/spec.opts",
57
+ "spec/spec_helper.rb",
58
+ "spec/story_spec.rb"
59
+ ]
60
+ s.homepage = %q{http://github.com/winescout/rallytastic}
61
+ s.rdoc_options = ["--charset=UTF-8"]
62
+ s.require_paths = ["lib"]
63
+ s.rubygems_version = %q{1.3.7}
64
+ s.summary = %q{Its a Rally story teleporter}
65
+ s.test_files = [
66
+ "spec/fabricators/iteration.rb",
67
+ "spec/fabricators/project.rb",
68
+ "spec/fabricators/revision.rb",
69
+ "spec/fabricators/revision_history.rb",
70
+ "spec/fabricators/revision_parser.rb",
71
+ "spec/fabricators/story.rb",
72
+ "spec/iteration_spec.rb",
73
+ "spec/project_spec.rb",
74
+ "spec/rally/rally_api_spec.rb",
75
+ "spec/revision_parser_spec.rb",
76
+ "spec/spec_helper.rb",
77
+ "spec/story_spec.rb"
78
+ ]
79
+
80
+ if s.respond_to? :specification_version then
81
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
82
+ s.specification_version = 3
83
+
84
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
85
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
86
+ s.add_runtime_dependency(%q<rake>, [">= 0"])
87
+ s.add_runtime_dependency(%q<mongoid>, [">= 0"])
88
+ s.add_runtime_dependency(%q<bson_ext>, [">= 0"])
89
+ s.add_runtime_dependency(%q<rest-client>, [">= 0"])
90
+ s.add_runtime_dependency(%q<thor>, [">= 0"])
91
+ else
92
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
93
+ s.add_dependency(%q<rake>, [">= 0"])
94
+ s.add_dependency(%q<mongoid>, [">= 0"])
95
+ s.add_dependency(%q<bson_ext>, [">= 0"])
96
+ s.add_dependency(%q<rest-client>, [">= 0"])
97
+ s.add_dependency(%q<thor>, [">= 0"])
98
+ end
99
+ else
100
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
101
+ s.add_dependency(%q<rake>, [">= 0"])
102
+ s.add_dependency(%q<mongoid>, [">= 0"])
103
+ s.add_dependency(%q<bson_ext>, [">= 0"])
104
+ s.add_dependency(%q<rest-client>, [">= 0"])
105
+ s.add_dependency(%q<thor>, [">= 0"])
106
+ end
107
+ end
108
+
@@ -0,0 +1,9 @@
1
+ Fabricator(:iteration) do
2
+ name "Fabricated iteration"
3
+ project {Fabricate(:project)}
4
+ end
5
+
6
+ Fabricator(:iteration_unmocked_parser, :from => :iteration) do
7
+ name "Fabricated iteration"
8
+ project {Fabricate(:project_unmocked_parser)}
9
+ end
@@ -0,0 +1,11 @@
1
+ Fabricator(:project) do
2
+ name "Fabricated project"
3
+ after_create{|project| project.create_revision_parser}
4
+ end
5
+
6
+ Fabricator(:project_mocked_parser, :from => :project) do
7
+ name "Fabricated project, bmocked_parser"
8
+ revision_parser(:force => true){Fabricate.build(:revision_parser)}
9
+ end
10
+
11
+
@@ -0,0 +1,4 @@
1
+ Fabricator(:revision) do
2
+ rally_uri "http://fabricated_revision_uri.com"
3
+ refresh true
4
+ end
@@ -0,0 +1,5 @@
1
+ Fabricator(:revision_history) do
2
+ revision_uris ["http://revision_1.uri", "http://revision_2.uri"]
3
+ revisions(:force => true){[Fabricate.build(:revision), Fabricate.build(:revision)]}
4
+ refresh true
5
+ end
@@ -0,0 +1,9 @@
1
+ Fabricator(:mocked_revision_parser, :from => :revision_parser) do
2
+ name "Mocked Revision Parser"
3
+ sized_on(:force => true){ 5.days.ago}
4
+ prioritized_on(:force => true){ 4.days.ago}
5
+ started_on(:force => true){ 3.days.ago}
6
+ completed_on(:force => true){ 2.days.ago}
7
+ junk(:force => true) {"dsaf"}
8
+ end
9
+
@@ -0,0 +1,27 @@
1
+ Fabricator(:story) do
2
+ name "Factory Story"
3
+ iteration {Fabricate(:iteration)}
4
+ revision_history(:force => true){Fabricate.build(:revision_history)}
5
+ end
6
+
7
+ Fabricator(:story_with_revisions, :from => :story) do
8
+ name "Factory Story with revisions"
9
+ revisions {[Fabricate.build(:revision,
10
+ :created_on => 4.days.ago,
11
+ :description => "TASK ESTIMATE TOTAL changed from [0.0] to [2.0]"),
12
+ Fabricate.build(:revision,
13
+ :created_on => 3.days.ago,
14
+ :description => "PROJECT changed from [Photos.com] to [Madison]"),
15
+ Fabricate.build(:revision,
16
+ :created_on => 2.days.ago,
17
+ :description => "ITERATION added"),
18
+ Fabricate.build(:revision,
19
+ :created_on => 1.days.ago,
20
+ :description => "SCHEDULE STATE changed from [InProgress] to [Complete]")]}
21
+ end
22
+
23
+ #Fabricator(:story_unmocked_parser, :from => :story) do
24
+ # name "Factory Story, Unmocked Parser"
25
+ # iteration {Fabricate(:iteration_unmocked_parser)}
26
+ # revision_history(:force => true){Fabricate.build(:revision_history)}
27
+ #end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe RevisionParser do
4
+ before do
5
+ @story = Fabricate(:story_with_revisions)
6
+ @parser = @story.iteration.project.create_revision_parser(:name => "live parser")
7
+ end
8
+
9
+ it "should calculate sized_on" do
10
+ @parser.sized_on(@story.revisions).to_s.should == 4.days.ago.to_s
11
+ end
12
+
13
+ it "should calculate prioritized_on" do
14
+ @parser.prioritized_on(@story.revisions).to_s.should == 3.days.ago.to_s
15
+ end
16
+
17
+ it "should calculate started_on" do
18
+ @parser.started_on(@story.revisions).to_s.should == 2.days.ago.to_s
19
+ end
20
+
21
+ it "should calculate completed_on" do
22
+ @parser.completed_on(@story.revisions).to_s.should == 1.days.ago.to_s
23
+ end
24
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,9 +3,9 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'rallytastic'
4
4
  require 'spec'
5
5
  require 'spec/autorun'
6
+ require 'fabrication'
6
7
 
7
- Spec::Runner.configure do |config|
8
-
8
+ Spec::Runner.configure do |config|
9
9
  end
10
10
 
11
11
 
@@ -15,3 +15,4 @@ Mongoid.configure do |config|
15
15
  config.master = Mongo::Connection.new.db(name)
16
16
  config.persist_in_safe_mode = false
17
17
  end
18
+
data/spec/story_spec.rb CHANGED
@@ -79,4 +79,26 @@ describe Story do
79
79
  @story.theme.should == "this is the theme"
80
80
  end
81
81
  end
82
+
83
+ describe "#revision_parser" do
84
+ before do
85
+ @story = Fabricate(:story)
86
+ end
87
+
88
+ it "should return new parser" do
89
+ @story.revision_parser.class.should == RevisionParser
90
+ end
91
+ end
92
+
93
+ describe "#pull_revisions" do
94
+ before do
95
+ @story = Fabricate(:story)
96
+ end
97
+
98
+ it "should pull revisions from revision history" do
99
+ @story.revisions.count.should == 0
100
+ @story.pull_revisions
101
+ @story.revisions.count.should == 2
102
+ end
103
+ end
82
104
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 1
8
7
  - 2
9
- version: 1.1.2
8
+ - 0
9
+ version: 1.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Matt Clark
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-08-06 00:00:00 -05:00
17
+ date: 2010-08-08 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -117,16 +117,23 @@ files:
117
117
  - VERSION
118
118
  - lib/iteration.rb
119
119
  - lib/parsers/base.rb
120
- - lib/parsers/madison.rb
121
120
  - lib/project.rb
122
121
  - lib/rally/parsing_helpers.rb
123
122
  - lib/rally/rally_api.rb
124
123
  - lib/rallytastic.rb
125
124
  - lib/revision.rb
126
125
  - lib/revision_history.rb
126
+ - lib/revision_parser.rb
127
127
  - lib/story.rb
128
128
  - lib/tasks/docs.thor
129
129
  - lib/tasks/scraper.thor
130
+ - rallytastic.gemspec
131
+ - spec/fabricators/iteration.rb
132
+ - spec/fabricators/project.rb
133
+ - spec/fabricators/revision.rb
134
+ - spec/fabricators/revision_history.rb
135
+ - spec/fabricators/revision_parser.rb
136
+ - spec/fabricators/story.rb
130
137
  - spec/fixtures/child_project.txt
131
138
  - spec/fixtures/iteration.txt
132
139
  - spec/fixtures/project.txt
@@ -135,6 +142,7 @@ files:
135
142
  - spec/iteration_spec.rb
136
143
  - spec/project_spec.rb
137
144
  - spec/rally/rally_api_spec.rb
145
+ - spec/revision_parser_spec.rb
138
146
  - spec/spec.opts
139
147
  - spec/spec_helper.rb
140
148
  - spec/story_spec.rb
@@ -152,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
152
160
  requirements:
153
161
  - - ">="
154
162
  - !ruby/object:Gem::Version
155
- hash: -1539841577661887094
163
+ hash: 3446221705390582300
156
164
  segments:
157
165
  - 0
158
166
  version: "0"
@@ -172,8 +180,15 @@ signing_key:
172
180
  specification_version: 3
173
181
  summary: Its a Rally story teleporter
174
182
  test_files:
183
+ - spec/fabricators/iteration.rb
184
+ - spec/fabricators/project.rb
185
+ - spec/fabricators/revision.rb
186
+ - spec/fabricators/revision_history.rb
187
+ - spec/fabricators/revision_parser.rb
188
+ - spec/fabricators/story.rb
175
189
  - spec/iteration_spec.rb
176
190
  - spec/project_spec.rb
177
191
  - spec/rally/rally_api_spec.rb
192
+ - spec/revision_parser_spec.rb
178
193
  - spec/spec_helper.rb
179
194
  - spec/story_spec.rb
@@ -1,19 +0,0 @@
1
- module Parser
2
- class Madison < Base
3
- def sized_on
4
- first_revision_date_matching /TASK ESTIMATE TOTAL changed from \[0.0\]/
5
- end
6
-
7
- def prioritized_on
8
- last_revision_date_matching /PROJECT changed from \[[^\]]*\] to \[Madison\]/
9
- end
10
-
11
- def started_on
12
- last_revision_date_matching /ITERATION added/
13
- end
14
-
15
- def completed_on
16
- last_revision_date_matching /SCHEDULE STATE changed from \[[^\]]*\] to [Complete]/
17
- end
18
- end
19
- end