artisan-ar-repository 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/artisan-ar-repository/base_repository.rb +35 -0
- data/lib/artisan-ar-repository/change_repository.rb +45 -0
- data/lib/artisan-ar-repository/future_user_repository.rb +34 -0
- data/lib/artisan-ar-repository/iteration_repository.rb +29 -0
- data/lib/artisan-ar-repository/member_repository.rb +12 -0
- data/lib/artisan-ar-repository/models/change.rb +5 -0
- data/lib/artisan-ar-repository/models/day.rb +4 -0
- data/lib/artisan-ar-repository/models/future_user.rb +4 -0
- data/lib/artisan-ar-repository/models/iteration.rb +20 -0
- data/lib/artisan-ar-repository/models/iteration_change.rb +2 -0
- data/lib/artisan-ar-repository/models/member.rb +4 -0
- data/lib/artisan-ar-repository/models/project.rb +20 -0
- data/lib/artisan-ar-repository/models/project_change.rb +2 -0
- data/lib/artisan-ar-repository/models/project_configuration.rb +13 -0
- data/lib/artisan-ar-repository/models/story.rb +61 -0
- data/lib/artisan-ar-repository/models/story_assigned_email.rb +4 -0
- data/lib/artisan-ar-repository/models/story_change.rb +2 -0
- data/lib/artisan-ar-repository/models/story_completed_email.rb +3 -0
- data/lib/artisan-ar-repository/models/user.rb +33 -0
- data/lib/artisan-ar-repository/project_configuration_repository.rb +9 -0
- data/lib/artisan-ar-repository/project_repository.rb +73 -0
- data/lib/artisan-ar-repository/story_repository.rb +66 -0
- data/lib/artisan-ar-repository/user_repository.rb +37 -0
- metadata +25 -2
@@ -0,0 +1,35 @@
|
|
1
|
+
module ArtisanArRepository
|
2
|
+
module BaseRepository
|
3
|
+
def new(attributes = {})
|
4
|
+
model_class.new(attributes)
|
5
|
+
end
|
6
|
+
|
7
|
+
def find(id)
|
8
|
+
model_class.find(id)
|
9
|
+
rescue ActiveRecord::RecordNotFound => e
|
10
|
+
raise Artisan::RecordNotFound.new(e)
|
11
|
+
end
|
12
|
+
|
13
|
+
def save(instance)
|
14
|
+
instance.save
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(attributes = {})
|
18
|
+
model_class.create!(attributes)
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy_all(*args)
|
22
|
+
model_class.destroy_all(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_each(&block)
|
26
|
+
model_class.find_each(&block)
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def model_class
|
32
|
+
raise "implement model_class method on your the repository #{self.class} to return the name of the Active Record Model"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'artisan-ar-repository/base_repository'
|
2
|
+
require 'artisan-ar-repository/models/change'
|
3
|
+
require 'artisan-ar-repository/models/story_change'
|
4
|
+
require 'artisan-ar-repository/models/iteration_change'
|
5
|
+
require 'artisan-ar-repository/models/project_change'
|
6
|
+
|
7
|
+
module ArtisanArRepository
|
8
|
+
class ChangeRepository
|
9
|
+
include BaseRepository
|
10
|
+
|
11
|
+
def model_class
|
12
|
+
::Change
|
13
|
+
end
|
14
|
+
|
15
|
+
def project_change_class
|
16
|
+
::ProjectChange
|
17
|
+
end
|
18
|
+
|
19
|
+
def iteration_change_class
|
20
|
+
::IterationChange
|
21
|
+
end
|
22
|
+
|
23
|
+
def story_change_class
|
24
|
+
::StoryChange
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_project_change(attributes = {})
|
28
|
+
project_change_class.create!(attributes)
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_iteration_change(attributes = {})
|
32
|
+
iteration_change_class.create!(attributes)
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_story_change(attributes = {})
|
36
|
+
story_change_class.create!(attributes)
|
37
|
+
end
|
38
|
+
|
39
|
+
def find_all_by_project_id(id)
|
40
|
+
Change.find_all_by_project_id(id)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'artisan-ar-repository/models/future_user'
|
2
|
+
require 'artisan-ar-repository/base_repository'
|
3
|
+
|
4
|
+
module ArtisanArRepository
|
5
|
+
class FutureUserRepository
|
6
|
+
include BaseRepository
|
7
|
+
|
8
|
+
def model_class
|
9
|
+
::FutureUser
|
10
|
+
end
|
11
|
+
|
12
|
+
def create(attributes = {})
|
13
|
+
begin
|
14
|
+
future_user = model_class.new(attributes)
|
15
|
+
future_user.save!
|
16
|
+
future_user
|
17
|
+
rescue ActiveRecord::RecordInvalid
|
18
|
+
raise Artisan::RecordNotValid.new(future_user)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_by_email(email)
|
23
|
+
model_class.find_by_email(email)
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_by_project_id(project_id)
|
27
|
+
model_class.find_by_project_id(project_id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete(id)
|
31
|
+
model_class.delete(id)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'artisan-ar-repository/models/iteration'
|
2
|
+
require 'artisan-ar-repository/base_repository'
|
3
|
+
|
4
|
+
module ArtisanArRepository
|
5
|
+
class IterationRepository
|
6
|
+
include BaseRepository
|
7
|
+
|
8
|
+
def model_class
|
9
|
+
::Iteration
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_for_project(project, attrs)
|
13
|
+
model_class.create!(attrs.merge(:project => project))
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_by_number(project, number)
|
17
|
+
project.iterations.find_by_number(number)
|
18
|
+
end
|
19
|
+
|
20
|
+
def by_project(project)
|
21
|
+
project.iterations
|
22
|
+
end
|
23
|
+
|
24
|
+
def by_project_by_finish_date(project)
|
25
|
+
project.iterations.by_finish_date
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'artisan-ar-repository/models/story'
|
3
|
+
require 'artisan-ar-repository/models/day'
|
4
|
+
require 'artisan/stories/story_collection'
|
5
|
+
|
6
|
+
class Iteration < ActiveRecord::Base
|
7
|
+
belongs_to :project
|
8
|
+
has_many :stories
|
9
|
+
has_many :days
|
10
|
+
has_many :users, :through => :days
|
11
|
+
accepts_nested_attributes_for :days
|
12
|
+
|
13
|
+
default_scope :order => "number DESC"
|
14
|
+
|
15
|
+
scope :by_finish_date, order("finish_date DESC")
|
16
|
+
|
17
|
+
def total_billed_points
|
18
|
+
Artisan::Stories::StoryCollection.new(stories).billed_points
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'artisan-ar-repository/models/project_configuration'
|
2
|
+
|
3
|
+
class Project < ActiveRecord::Base
|
4
|
+
|
5
|
+
has_many :stories, :dependent => :destroy
|
6
|
+
has_many :iterations, :dependent => :destroy
|
7
|
+
has_many :members
|
8
|
+
has_many :users, :through => :members, :order => :login
|
9
|
+
|
10
|
+
has_many :pages
|
11
|
+
|
12
|
+
|
13
|
+
has_one :project_configuration, :dependent => :destroy
|
14
|
+
accepts_nested_attributes_for :project_configuration
|
15
|
+
|
16
|
+
scope :unarchived, where('archived = ? OR archived is NULL', false).order("name ASC")
|
17
|
+
scope :archived, where(:archived => true).order("name ASC")
|
18
|
+
scope :order_by_name, order("name ASC")
|
19
|
+
scope :by_date, order("updated_at DESC")
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ProjectConfiguration < ActiveRecord::Base
|
2
|
+
belongs_to :project
|
3
|
+
|
4
|
+
serialize :story_completed_email_list, Array
|
5
|
+
serialize :story_assigned_email_list, Array
|
6
|
+
|
7
|
+
STANDARD_DEVIATION = "stddev"
|
8
|
+
WEIGHTED_MEAN = "weighted_mean"
|
9
|
+
|
10
|
+
def estimate_mode
|
11
|
+
read_attribute(:estimate_mode) || STANDARD_DEVIATION
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'artisan/stories/pert_calculator'
|
2
|
+
|
3
|
+
class Story < ActiveRecord::Base
|
4
|
+
belongs_to :project
|
5
|
+
belongs_to :iteration
|
6
|
+
belongs_to :assigned_user, :class_name => "User"
|
7
|
+
belongs_to :creator, :class_name => "User"
|
8
|
+
acts_as_taggable
|
9
|
+
|
10
|
+
default_scope where("deleted = ?", false).order("position ASC")
|
11
|
+
|
12
|
+
scope :completed, where("complete = ?", true).order("position ASC")
|
13
|
+
scope :ready, where("assigned_user_id IS NULL AND (complete = ? OR complete IS NULL)", false).order("position ASC")
|
14
|
+
scope :working, where("assigned_user_id IS NOT NULL AND (complete = ? OR complete IS NULL)", false).order("position ASC")
|
15
|
+
scope :for_user, lambda { |user| where "assigned_user_id = ?", user.id }
|
16
|
+
scope :by_project, lambda { |project| where "project_id = ?", project.id }
|
17
|
+
|
18
|
+
scope :backlog, where(:iteration_id => nil)
|
19
|
+
scope :complete, where(:complete => true)
|
20
|
+
|
21
|
+
def to_param
|
22
|
+
number.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.by_number_and_project(number, project)
|
26
|
+
find_by_number_and_project_id!(number, project.id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def estimate
|
30
|
+
pert_calculator.estimate
|
31
|
+
end
|
32
|
+
|
33
|
+
def standard_deviation
|
34
|
+
pert_calculator.standard_deviation
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete
|
38
|
+
update_attributes(:deleted => true, :iteration => nil)
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_to_iteration(iteration)
|
42
|
+
update_attribute(:iteration, iteration) unless iteration.complete?
|
43
|
+
end
|
44
|
+
|
45
|
+
def assigned_user_name
|
46
|
+
assigned_user.full_name if assigned_user
|
47
|
+
end
|
48
|
+
|
49
|
+
def assigned_user_email
|
50
|
+
assigned_user.email if assigned_user
|
51
|
+
end
|
52
|
+
|
53
|
+
#TODO - PWP - to remove this dependency we need to remove dependency on super as_json
|
54
|
+
def as_json(options={})
|
55
|
+
return Artisan::Stories::StoryExporter.new(self).as_json(super(options), options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def pert_calculator
|
59
|
+
Artisan::Stories::PertCalculator.new(self, project.project_configuration.estimate_mode)
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'artisan/repository'
|
2
|
+
|
3
|
+
class User < ActiveRecord::Base
|
4
|
+
# Setup accessible (or protected) attributes for your model
|
5
|
+
attr_accessible :login, :project_id, :full_name, :email, :password, :password_confirmation, :remember_me
|
6
|
+
|
7
|
+
has_many :days
|
8
|
+
has_many :iterations, :through => :days
|
9
|
+
has_many :stories
|
10
|
+
|
11
|
+
has_many :projects, :through => :members
|
12
|
+
has_many :members
|
13
|
+
|
14
|
+
validates :full_name, :presence => true
|
15
|
+
validates_length_of :login, :minimum => 3
|
16
|
+
validates_format_of :login, :with => /\A\w[\w\.+\-_@ ]+$/, :message => "should use only letters, numbers, spaces, and .-_@ please."
|
17
|
+
validates_uniqueness_of :login, :case_sensitive => false
|
18
|
+
|
19
|
+
after_create :join_team
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def join_team
|
24
|
+
future_user_repository = Artisan::Repository.future_user
|
25
|
+
future_user = future_user_repository.find_by_email(self.email)
|
26
|
+
if future_user
|
27
|
+
project = Artisan::Repository.project.find(future_user.project_id)
|
28
|
+
team = Team.new(project, self)
|
29
|
+
team.add_team_member(self)
|
30
|
+
future_user_repository.delete(future_user.id)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'artisan-ar-repository/models/project'
|
2
|
+
require 'artisan-ar-repository/base_repository'
|
3
|
+
require 'artisan-ar-repository/models/member'
|
4
|
+
|
5
|
+
module ArtisanArRepository
|
6
|
+
class ProjectRepository
|
7
|
+
include BaseRepository
|
8
|
+
|
9
|
+
def model_class
|
10
|
+
::Project
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_by_api_key(id)
|
14
|
+
model_class.find_by_api_key(id)
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_by_name(id)
|
18
|
+
model_class.find_by_name(id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def order_by_name(*args)
|
22
|
+
model_class.order_by_name(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def unarchived(*args)
|
26
|
+
model_class.unarchived(*args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def archived(*args)
|
30
|
+
model_class.archived(*args)
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_iteration(project, iteration)
|
34
|
+
project.iterations << iteration
|
35
|
+
return iteration
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_member(project, user, owner)
|
39
|
+
Artisan::Repository.member.create(:user_id => user.id, :project_id => project.id , :owner => owner)
|
40
|
+
end
|
41
|
+
|
42
|
+
def remove_member(project, user)
|
43
|
+
membership_for(project, user).destroy
|
44
|
+
end
|
45
|
+
|
46
|
+
def is_member?(project, user)
|
47
|
+
return !membership_for(project, user).nil?
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_owner?(project, user)
|
51
|
+
return false if project.nil? || not_a_member_of?(project, user)
|
52
|
+
return membership_for(project, user).owner?
|
53
|
+
end
|
54
|
+
|
55
|
+
def not_a_member_of?(project, user)
|
56
|
+
return membership_for(project, user).nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
def membership_for(project, user)
|
60
|
+
return project.members.find_by_user_id(user.id)
|
61
|
+
end
|
62
|
+
|
63
|
+
def owners(project)
|
64
|
+
project.members.find_all_by_owner(true).collect(&:user)
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_project_configuration(project)
|
68
|
+
project.create_project_configuration
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'artisan-ar-repository/base_repository'
|
2
|
+
require 'artisan-ar-repository/models/story'
|
3
|
+
|
4
|
+
module ArtisanArRepository
|
5
|
+
class StoryRepository
|
6
|
+
include BaseRepository
|
7
|
+
|
8
|
+
def model_class
|
9
|
+
::Story
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(number, project)
|
13
|
+
begin
|
14
|
+
model_class.by_number_and_project(number, project)
|
15
|
+
rescue ActiveRecord::RecordNotFound => e
|
16
|
+
raise Artisan::RecordNotFound.new(e)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def for_user(user)
|
21
|
+
model_class.for_user(user)
|
22
|
+
end
|
23
|
+
|
24
|
+
def by_project(project)
|
25
|
+
model_class.by_project(project)
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_to_iteration(iteration, story)
|
29
|
+
iteration.stories << story
|
30
|
+
end
|
31
|
+
|
32
|
+
def remove_from_iteration(story)
|
33
|
+
story.update_attribute(:iteration_id, nil)
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_for_project(project, attrs = {})
|
37
|
+
project.stories.create!(attrs)
|
38
|
+
end
|
39
|
+
|
40
|
+
def all(iteration)
|
41
|
+
iteration.stories
|
42
|
+
end
|
43
|
+
|
44
|
+
def ready(iteration)
|
45
|
+
iteration.stories.ready
|
46
|
+
end
|
47
|
+
|
48
|
+
def working(iteration)
|
49
|
+
iteration.stories.working
|
50
|
+
end
|
51
|
+
|
52
|
+
def completed(iteration)
|
53
|
+
iteration.stories.completed
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete(story)
|
57
|
+
story.update_attributes(:deleted => true, :iteration => nil)
|
58
|
+
story
|
59
|
+
end
|
60
|
+
|
61
|
+
def backlog(project)
|
62
|
+
project.stories.backlog
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'artisan-ar-repository/models/user'
|
2
|
+
require 'artisan-ar-repository/base_repository'
|
3
|
+
|
4
|
+
module ArtisanArRepository
|
5
|
+
class UserRepository
|
6
|
+
include BaseRepository
|
7
|
+
|
8
|
+
def model_class
|
9
|
+
::User
|
10
|
+
end
|
11
|
+
|
12
|
+
def create(attributes = {})
|
13
|
+
begin
|
14
|
+
user = model_class.new(attributes)
|
15
|
+
user.save!
|
16
|
+
user
|
17
|
+
rescue ActiveRecord::RecordInvalid
|
18
|
+
raise Artisan::RecordNotValid.new(user)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_by_login(login)
|
23
|
+
model_class.find_by_login(login)
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_by_email(email)
|
27
|
+
model_class.find_by_email(email)
|
28
|
+
end
|
29
|
+
|
30
|
+
def active_stories_for(user)
|
31
|
+
Artisan::Repository.story.for_user(user).working.reject do |story|
|
32
|
+
story.iteration.nil?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: artisan-ar-repository
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- 8th Light Craftsmen
|
@@ -22,6 +22,29 @@ extensions: []
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
+
- lib/artisan-ar-repository/base_repository.rb
|
26
|
+
- lib/artisan-ar-repository/change_repository.rb
|
27
|
+
- lib/artisan-ar-repository/future_user_repository.rb
|
28
|
+
- lib/artisan-ar-repository/iteration_repository.rb
|
29
|
+
- lib/artisan-ar-repository/member_repository.rb
|
30
|
+
- lib/artisan-ar-repository/models/change.rb
|
31
|
+
- lib/artisan-ar-repository/models/day.rb
|
32
|
+
- lib/artisan-ar-repository/models/future_user.rb
|
33
|
+
- lib/artisan-ar-repository/models/iteration.rb
|
34
|
+
- lib/artisan-ar-repository/models/iteration_change.rb
|
35
|
+
- lib/artisan-ar-repository/models/member.rb
|
36
|
+
- lib/artisan-ar-repository/models/project.rb
|
37
|
+
- lib/artisan-ar-repository/models/project_change.rb
|
38
|
+
- lib/artisan-ar-repository/models/project_configuration.rb
|
39
|
+
- lib/artisan-ar-repository/models/story.rb
|
40
|
+
- lib/artisan-ar-repository/models/story_assigned_email.rb
|
41
|
+
- lib/artisan-ar-repository/models/story_change.rb
|
42
|
+
- lib/artisan-ar-repository/models/story_completed_email.rb
|
43
|
+
- lib/artisan-ar-repository/models/user.rb
|
44
|
+
- lib/artisan-ar-repository/project_configuration_repository.rb
|
45
|
+
- lib/artisan-ar-repository/project_repository.rb
|
46
|
+
- lib/artisan-ar-repository/story_repository.rb
|
47
|
+
- lib/artisan-ar-repository/user_repository.rb
|
25
48
|
- spec/artisan_ar_repository_spec.rb
|
26
49
|
- spec/change_repository_spec.rb
|
27
50
|
- spec/future_user_repository_spec.rb
|
@@ -43,7 +66,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
43
66
|
requirements:
|
44
67
|
- - ">="
|
45
68
|
- !ruby/object:Gem::Version
|
46
|
-
hash:
|
69
|
+
hash: -3449863664794801791
|
47
70
|
segments:
|
48
71
|
- 0
|
49
72
|
version: "0"
|