tracker_api 0.2.9 → 0.2.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/README.md +1 -0
  4. data/lib/core_ext/object/blank.rb +132 -0
  5. data/lib/tracker_api/client.rb +1 -1
  6. data/lib/tracker_api/endpoints/comments.rb +1 -1
  7. data/lib/tracker_api/endpoints/epic.rb +2 -2
  8. data/lib/tracker_api/endpoints/labels.rb +26 -0
  9. data/lib/tracker_api/endpoints/memberships.rb +6 -0
  10. data/lib/tracker_api/endpoints/story.rb +4 -4
  11. data/lib/tracker_api/endpoints/task.rb +16 -0
  12. data/lib/tracker_api/endpoints/tasks.rb +1 -1
  13. data/lib/tracker_api/resources/account.rb +1 -2
  14. data/lib/tracker_api/resources/activity.rb +6 -4
  15. data/lib/tracker_api/resources/base.rb +5 -60
  16. data/lib/tracker_api/resources/change.rb +1 -2
  17. data/lib/tracker_api/resources/comment.rb +1 -2
  18. data/lib/tracker_api/resources/epic.rb +1 -2
  19. data/lib/tracker_api/resources/iteration.rb +2 -0
  20. data/lib/tracker_api/resources/label.rb +8 -2
  21. data/lib/tracker_api/resources/me.rb +1 -2
  22. data/lib/tracker_api/resources/membership_summary.rb +1 -2
  23. data/lib/tracker_api/resources/notification.rb +1 -2
  24. data/lib/tracker_api/resources/person.rb +1 -2
  25. data/lib/tracker_api/resources/primary_resource.rb +1 -2
  26. data/lib/tracker_api/resources/project.rb +45 -8
  27. data/lib/tracker_api/resources/project_membership.rb +1 -2
  28. data/lib/tracker_api/resources/story.rb +36 -10
  29. data/lib/tracker_api/resources/task.rb +1 -2
  30. data/lib/tracker_api/version.rb +1 -1
  31. data/lib/tracker_api.rb +8 -2
  32. data/test/project_test.rb +29 -1
  33. data/test/story_test.rb +56 -1
  34. data/test/vcr/cassettes/client_done_iterations_with_pagination.json +1 -1
  35. data/test/vcr/cassettes/client_get_all_stories_with_pagination.json +1 -1
  36. data/test/vcr/cassettes/client_get_limited_stories_with_no_pagination.json +1 -1
  37. data/test/vcr/cassettes/client_get_single_story_by_story_id.json +1 -1
  38. data/test/vcr/cassettes/create_story.json +1 -1
  39. data/test/vcr/cassettes/create_story_with_lengthy_params.json +1 -1
  40. data/test/vcr/cassettes/create_task.json +1 -0
  41. data/test/vcr/cassettes/get_all_projects.json +1 -1
  42. data/test/vcr/cassettes/get_another_story.json +1 -0
  43. data/test/vcr/cassettes/get_current_iteration.json +1 -1
  44. data/test/vcr/cassettes/get_done_iterations.json +1 -1
  45. data/test/vcr/cassettes/get_epics.json +1 -1
  46. data/test/vcr/cassettes/get_iteration_by_number.json +1 -1
  47. data/test/vcr/cassettes/get_labels.json +1 -0
  48. data/test/vcr/cassettes/get_me.json +1 -46
  49. data/test/vcr/cassettes/get_my_activities.json +1 -1
  50. data/test/vcr/cassettes/get_project.json +1 -1
  51. data/test/vcr/cassettes/get_project_activity.json +1 -1
  52. data/test/vcr/cassettes/get_project_with_epics.json +1 -1
  53. data/test/vcr/cassettes/get_project_with_labels.json +1 -0
  54. data/test/vcr/cassettes/get_story.json +1 -1
  55. data/test/vcr/cassettes/get_story_activity.json +1 -1
  56. data/test/vcr/cassettes/get_story_with_tasks.json +1 -0
  57. data/test/vcr/cassettes/get_tasks.json +1 -1
  58. data/test/vcr/cassettes/get_tasks_for_story.json +1 -0
  59. data/test/vcr/cassettes/get_tasks_when_stories_filtered.json +1 -1
  60. data/test/vcr/cassettes/get_unscheduled_stories.json +1 -1
  61. data/test/vcr/cassettes/get_unscheduled_story.json +1 -1
  62. data/test/vcr/cassettes/save_story.json +1 -1
  63. data/test/vcr/cassettes/save_story_with_multiple_changes.json +1 -1
  64. data/test/vcr/cassettes/save_story_with_new_label.json +1 -0
  65. data/test/vcr/cassettes/update_story_to_create_activity.json +1 -1
  66. data/tracker_api.gemspec +3 -2
  67. metadata +35 -6
  68. data/test/vcr/cassettes/get_activity.json +0 -148
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eb0f996134be9b6af61da9dbb41f47c23bbc79fd
4
- data.tar.gz: 3172bee693120381ce20b5f83c2037e604d7edd7
3
+ metadata.gz: a617d2b19c294a813a8edf94eed605c18daa6969
4
+ data.tar.gz: 8d05e8a155dcdf15e84c0efaba86dcd6b1914e86
5
5
  SHA512:
6
- metadata.gz: 95c7d010ab3c59f30944c14a760736d5f3ebab13caeac8c8eed4471347a464b26bb34af3094e10af131ff254a8b2fedc4bc532717058853033cfd0c5b63dd2ac
7
- data.tar.gz: 4d1a3bd5ac33807a8219c05e7ad995b905857e960d4dee6ddf582e19a255c346102c0385b304d903672eb4fc098dee9579b6b255154fdf86808512491c1a98a6
6
+ metadata.gz: 374ec16671b186d2309513d2419e7839f98b0e71e88fee635660a18f2f5a406e5133cc24252fc8cebb6a5094d2b3cdc725edf879ad94c4bf585aa79ded685fd9
7
+ data.tar.gz: b8b668d588b2e6ffc4fd8455d0ef0b288e5f25c8ed896385fc707e35f608639e93781aef742aec4ef9483b48ef54a9ae8cf9e01fba4cc38dd43f2563d5f47de4
data/.travis.yml CHANGED
@@ -3,6 +3,7 @@ rvm:
3
3
  - "1.9.3"
4
4
  - "2.0.0"
5
5
  - "2.1.0"
6
+ - "2.2.2"
6
7
  # Faraday::ConnectionFailed: Could not generate DH keypair (Java::JavaLang::RuntimeException)
7
8
  # http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7044060
8
9
  # - jruby-19mode # JRuby in 1.9 mode
data/README.md CHANGED
@@ -53,6 +53,7 @@ story.activity # Get
53
53
 
54
54
  story.name = 'Save the Ewoks' # Update a single story attribute
55
55
  story.attributes = { name: 'Save the Ewoks', description: '...' } # Update multiple story attributes
56
+ story.labels << Label.new(name: 'Endor') # Add a new label to an existing story
56
57
  story.save # Save changes made to a story
57
58
 
58
59
  epics = project.epics # Get all epics for a project
@@ -0,0 +1,132 @@
1
+ # encoding: utf-8
2
+
3
+ # Borrowed from: activesupport-4.2.2/lib/active_support/core_ext/object/blank.rb
4
+ class Object
5
+ # An object is blank if it's false, empty, or a whitespace string.
6
+ # For example, '', ' ', +nil+, [], and {} are all blank.
7
+ #
8
+ # This simplifies
9
+ #
10
+ # address.nil? || address.empty?
11
+ #
12
+ # to
13
+ #
14
+ # address.blank?
15
+ #
16
+ # @return [true, false]
17
+ def blank?
18
+ respond_to?(:empty?) ? !!empty? : !self
19
+ end
20
+
21
+ # An object is present if it's not blank.
22
+ #
23
+ # @return [true, false]
24
+ def present?
25
+ !blank?
26
+ end
27
+
28
+ # Returns the receiver if it's present otherwise returns +nil+.
29
+ # <tt>object.presence</tt> is equivalent to
30
+ #
31
+ # object.present? ? object : nil
32
+ #
33
+ # For example, something like
34
+ #
35
+ # state = params[:state] if params[:state].present?
36
+ # country = params[:country] if params[:country].present?
37
+ # region = state || country || 'US'
38
+ #
39
+ # becomes
40
+ #
41
+ # region = params[:state].presence || params[:country].presence || 'US'
42
+ #
43
+ # @return [Object]
44
+ def presence
45
+ self if present?
46
+ end
47
+ end
48
+
49
+ class NilClass
50
+ # +nil+ is blank:
51
+ #
52
+ # nil.blank? # => true
53
+ #
54
+ # @return [true]
55
+ def blank?
56
+ true
57
+ end
58
+ end
59
+
60
+ class FalseClass
61
+ # +false+ is blank:
62
+ #
63
+ # false.blank? # => true
64
+ #
65
+ # @return [true]
66
+ def blank?
67
+ true
68
+ end
69
+ end
70
+
71
+ class TrueClass
72
+ # +true+ is not blank:
73
+ #
74
+ # true.blank? # => false
75
+ #
76
+ # @return [false]
77
+ def blank?
78
+ false
79
+ end
80
+ end
81
+
82
+ class Array
83
+ # An array is blank if it's empty:
84
+ #
85
+ # [].blank? # => true
86
+ # [1,2,3].blank? # => false
87
+ #
88
+ # @return [true, false]
89
+ alias_method :blank?, :empty?
90
+ end
91
+
92
+ class Hash
93
+ # A hash is blank if it's empty:
94
+ #
95
+ # {}.blank? # => true
96
+ # { key: 'value' }.blank? # => false
97
+ #
98
+ # @return [true, false]
99
+ alias_method :blank?, :empty?
100
+ end
101
+
102
+ class String
103
+ BLANK_RE = /\A[[:space:]]*\z/
104
+
105
+ # A string is blank if it's empty or contains whitespaces only:
106
+ #
107
+ # ''.blank? # => true
108
+ # ' '.blank? # => true
109
+ # "\t\n\r".blank? # => true
110
+ # ' blah '.blank? # => false
111
+ #
112
+ # Unicode whitespace is supported:
113
+ #
114
+ # "\u00a0".blank? # => true
115
+ #
116
+ # @return [true, false]
117
+ def blank?
118
+ BLANK_RE === self
119
+ end
120
+ end
121
+
122
+ class Numeric #:nodoc:
123
+ # No number is blank:
124
+ #
125
+ # 1.blank? # => false
126
+ # 0.blank? # => false
127
+ #
128
+ # @return [false]
129
+ def blank?
130
+ false
131
+ end
132
+ end
@@ -187,7 +187,7 @@ module TrackerApi
187
187
  headers = options[:headers]
188
188
 
189
189
  if (method == :post || method == :put) && options[:body].blank?
190
- body = params.to_json
190
+ body = Oj.dump(params)
191
191
  headers['Content-Type'] = 'application/json'
192
192
 
193
193
  params = {}
@@ -7,7 +7,7 @@ module TrackerApi
7
7
  @client = client
8
8
  end
9
9
 
10
- def get(project_id, story_id, params={})
10
+ def get(project_id, story_id, params={})
11
11
  data = client.paginate("/projects/#{project_id}/stories/#{story_id}/comments", params: params)
12
12
  raise TrackerApi::Errors::UnexpectedData, 'Array of comments expected' unless data.is_a? Array
13
13
 
@@ -7,8 +7,8 @@ module TrackerApi
7
7
  @client = client
8
8
  end
9
9
 
10
- def get(project_id, id)
11
- data = client.get("/projects/#{project_id}/epics/#{id}").body
10
+ def get(project_id, id, params={})
11
+ data = client.get("/projects/#{project_id}/epics/#{id}", params: params).body
12
12
 
13
13
  Resources::Epic.new({ project_id: project_id }.merge(data))
14
14
  end
@@ -0,0 +1,26 @@
1
+ module TrackerApi
2
+ module Endpoints
3
+ class Labels
4
+ attr_accessor :client
5
+
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def get(project_id, params={})
11
+ data = client.paginate("/projects/#{project_id}/labels", params: params)
12
+ raise TrackerApi::Errors::UnexpectedData, 'Array of labels expected' unless data.is_a? Array
13
+
14
+ data.map do |label|
15
+ Resources::Label.new({ project_id: project_id }.merge(label))
16
+ end
17
+ end
18
+
19
+ def add(project_id, params={})
20
+ data = client.post("/projects/#{project_id}/labels", params: params).body
21
+
22
+ Resources::Label.new({ project_id: project_id }.merge(data))
23
+ end
24
+ end
25
+ end
26
+ end
@@ -15,6 +15,12 @@ module TrackerApi
15
15
  Resources::ProjectMembership.new({ project_id: project_id }.merge(membership))
16
16
  end
17
17
  end
18
+
19
+ def add(project_id, params={})
20
+ data = client.post("/projects/#{project_id}/memberships", params: params).body
21
+
22
+ Resources::ProjectMembership.new({ project_id: project_id }.merge(data))
23
+ end
18
24
  end
19
25
  end
20
26
  end
@@ -7,14 +7,14 @@ module TrackerApi
7
7
  @client = client
8
8
  end
9
9
 
10
- def get(project_id, id)
11
- data = client.get("/projects/#{project_id}/stories/#{id}").body
10
+ def get(project_id, id, params={})
11
+ data = client.get("/projects/#{project_id}/stories/#{id}", params: params).body
12
12
 
13
13
  Resources::Story.new({ client: client, project_id: project_id }.merge(data))
14
14
  end
15
15
 
16
- def get_story(story_id)
17
- data = client.get("/stories/#{story_id}").body
16
+ def get_story(story_id, params={})
17
+ data = client.get("/stories/#{story_id}", params: params).body
18
18
 
19
19
  Resources::Story.new({ client: client }.merge(data))
20
20
  end
@@ -0,0 +1,16 @@
1
+ module TrackerApi
2
+ module Endpoints
3
+ class Task
4
+ attr_accessor :client
5
+
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def create(project_id, story_id, params={})
11
+ data = client.post("/projects/#{project_id}/stories/#{story_id}/tasks", params: params).body
12
+ Resources::Task.new(data)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -7,7 +7,7 @@ module TrackerApi
7
7
  @client = client
8
8
  end
9
9
 
10
- def get(project_id, story_id, params={})
10
+ def get(project_id, story_id, params={})
11
11
  data = client.paginate("/projects/#{project_id}/stories/#{story_id}/tasks", params: params)
12
12
  raise TrackerApi::Errors::UnexpectedData, 'Array of tasks expected' unless data.is_a? Array
13
13
 
@@ -1,9 +1,8 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class Account
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
- attribute :id, Integer
7
6
  attribute :created_at, DateTime
8
7
  attribute :status, String
9
8
  attribute :kind, String
@@ -3,6 +3,8 @@ module TrackerApi
3
3
  class Activity
4
4
  include Virtus.model
5
5
 
6
+ include Equalizer.new(:guid)
7
+
6
8
  attribute :client
7
9
 
8
10
  attribute :kind, String
@@ -10,10 +12,10 @@ module TrackerApi
10
12
  attribute :project_version, Integer
11
13
  attribute :message, String
12
14
  attribute :highlight, String
13
- attribute :changes, Array[TrackerApi::Resources::Change]
14
- attribute :primary_resources, Array[TrackerApi::Resources::PrimaryResource]
15
- attribute :project, TrackerApi::Resources::Project
16
- attribute :performed_by, TrackerApi::Resources::Person
15
+ attribute :changes, Array[Resources::Change]
16
+ attribute :primary_resources, Array[Resources::PrimaryResource]
17
+ attribute :project, Resources::Project
18
+ attribute :performed_by, Resources::Person
17
19
  attribute :occurred_at, DateTime
18
20
 
19
21
  def project=(data)
@@ -1,69 +1,14 @@
1
1
  require 'virtus'
2
- require 'active_support/concern'
3
- require 'active_model'
4
2
 
5
3
  module TrackerApi
6
4
  module Resources
7
5
  module Base
8
- extend ActiveSupport::Concern
6
+ def self.included(base)
7
+ base.class_eval do
8
+ include Virtus.model
9
+ include Equalizer.new(:id)
9
10
 
10
- include ActiveModel::Model
11
- include ActiveModel::Dirty
12
-
13
- included do
14
- include Virtus.model
15
- include OverrideAttributes
16
-
17
- attribute :id, Integer
18
-
19
- def initialize(attrs)
20
- super
21
-
22
- # always reset dirty tracking on initialize
23
- clear_changes_information
24
- end
25
-
26
- private
27
-
28
- # @return [Hash] key value pairs for just the changed attributes with their new values.
29
- def just_changes
30
- # @see changes in ActiveModel::Dirty in active_model/dirty.rb
31
- # { attr => [original value, new value] }
32
- changes.inject({}) do |h, (k, v)|
33
- h[k] = v[1]; h;
34
- end
35
- end
36
- end
37
-
38
- module OverrideAttributes
39
- extend ActiveSupport::Concern
40
-
41
- module ClassMethods
42
- def attribute(name, type, options = {})
43
- define_attribute_methods name
44
-
45
- attribute = super
46
- create_writer_with_dirty_tracking(name)
47
- attribute
48
- end
49
-
50
- private
51
-
52
- def create_writer_with_dirty_tracking(name)
53
- method_str = <<-RUBY
54
- def #{name}=(value)
55
- prev_value = #{name}
56
- new_value = value
57
- if prev_value != new_value
58
- #{name}_will_change!
59
- new_value = super(value)
60
- end
61
- new_value
62
- end
63
- RUBY
64
-
65
- class_eval method_str, __FILE__, __LINE__ + 1
66
- end
11
+ attribute :id, Integer
67
12
  end
68
13
  end
69
14
  end
@@ -1,10 +1,9 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class Change
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
6
  attribute :change_type, String
7
- attribute :id, Integer
8
7
  attribute :kind, String
9
8
  attribute :name, String
10
9
  attribute :new_values, Hash
@@ -1,9 +1,8 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class Comment
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
- attribute :id, Integer
7
6
  attribute :story_id, Integer
8
7
  attribute :epic_id, Integer
9
8
  attribute :text, String
@@ -1,9 +1,8 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class Epic
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
- attribute :id, Integer
7
6
  attribute :created_at, DateTime
8
7
  attribute :description, String
9
8
  attribute :kind, String
@@ -3,6 +3,8 @@ module TrackerApi
3
3
  class Iteration
4
4
  include Virtus.model
5
5
 
6
+ include Equalizer.new(:number, :project_id)
7
+
6
8
  attribute :client
7
9
 
8
10
  attribute :finish, DateTime
@@ -1,14 +1,20 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class Label
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
- attribute :id, Integer
7
6
  attribute :created_at, DateTime
8
7
  attribute :kind, String
9
8
  attribute :name, String
10
9
  attribute :project_id, Integer
11
10
  attribute :updated_at, DateTime
11
+
12
+ class UpdateRepresenter < Representable::Decorator
13
+ include Representable::JSON
14
+
15
+ property :id
16
+ property :name
17
+ end
12
18
  end
13
19
  end
14
20
  end
@@ -1,9 +1,8 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class Me
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
- attribute :id, Integer
7
6
  attribute :name, String
8
7
  attribute :initials, String
9
8
  attribute :username, String
@@ -1,9 +1,8 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class MembershipSummary
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
- attribute :id, Integer
7
6
  attribute :kind, String
8
7
  attribute :last_viewed_at, DateTime
9
8
  attribute :project_color, String
@@ -1,11 +1,10 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class Notification
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
6
  attribute :client
7
7
 
8
- attribute :id, Integer
9
8
  attribute :message, String
10
9
  attribute :kind, String
11
10
  attribute :project, TrackerApi::Resources::Project
@@ -1,10 +1,9 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class Person
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
6
  attribute :kind, String
7
- attribute :id, Integer
8
7
  attribute :name, String
9
8
  attribute :email, String
10
9
  attribute :initials, String
@@ -1,9 +1,8 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class PrimaryResource
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
- attribute :id, Integer
7
6
  attribute :kind, String
8
7
  attribute :name, String
9
8
  attribute :story_type, String
@@ -1,7 +1,7 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class Project
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
6
  attribute :client
7
7
 
@@ -20,7 +20,6 @@ module TrackerApi
20
20
  attribute :epic_ids, Array[Integer]
21
21
  attribute :epics, Array[TrackerApi::Resources::Epic]
22
22
  attribute :has_google_domain, Boolean
23
- attribute :id, Integer
24
23
  attribute :initial_velocity, Integer
25
24
  attribute :iteration_length, Integer
26
25
  attribute :kind, String
@@ -45,6 +44,25 @@ module TrackerApi
45
44
  @label_list ||= labels.collect(&:name).join(',')
46
45
  end
47
46
 
47
+ # @return [Integer] comma separated list of label_ids
48
+ def label_ids
49
+ @label_ids ||= labels.collect(&:id).join(',')
50
+ end
51
+
52
+ # Provides a list of all the labels on the project.
53
+ #
54
+ # @param [Hash] params
55
+ # @return [Array[Label]] labels of this project
56
+ def labels(params = {})
57
+ if @labels && @labels.any?
58
+ @labels
59
+ else
60
+ @labels = Endpoints::Labels.new(client).get(id, params)
61
+ end
62
+ end
63
+
64
+ # Provides a list of all the epics in the project.
65
+ #
48
66
  # @param [Hash] params
49
67
  # @return [Array[Epic]] epics associated with this project
50
68
  def epics(params={})
@@ -54,6 +72,8 @@ module TrackerApi
54
72
  @epics = Endpoints::Epics.new(client).get(id, params)
55
73
  end
56
74
 
75
+ # Provides a list of all the iterations in the project.
76
+ #
57
77
  # @param [Hash] params
58
78
  # @option params [String] :scope Restricts the state of iterations to return.
59
79
  # If not specified, it defaults to all iterations including done.
@@ -63,7 +83,7 @@ module TrackerApi
63
83
  # set of iterations specified by 'scope', with zero being the first iteration in the scope.
64
84
  # @option params [Integer] :limit The number of iterations to return relative to the offset.
65
85
  # @return [Array[Iteration]] iterations associated with this project
66
- def iterations(params = {})
86
+ def iterations(params={})
67
87
  if params.include?(:number)
68
88
  number = params[:number].to_i
69
89
  raise ArgumentError, ':number must be > 0' unless number > 0
@@ -78,6 +98,9 @@ module TrackerApi
78
98
  Endpoints::Iterations.new(client).get(id, params)
79
99
  end
80
100
 
101
+
102
+ # Provides a list of all the stories in the project.
103
+ #
81
104
  # @param [Hash] params
82
105
  # @option params [String] :with_label A label name which all returned stories must match.
83
106
  # @option params [String] :with_state A story's current_state which all returned stories must match.
@@ -90,13 +113,15 @@ module TrackerApi
90
113
  # the index of the first story you want returned.
91
114
  # @option params [Integer] :limit The number of stories you want returned.
92
115
  # @return [Array[Story]] stories associated with this project
93
- def stories(params = {})
116
+ def stories(params={})
94
117
  Endpoints::Stories.new(client).get(id, params)
95
118
  end
96
119
 
120
+ # Provides a list of all the memberships in the project.
121
+ #
97
122
  # @param [Hash] params
98
123
  # @return [Array[ProjectMembership]] memberships of this project
99
- def memberships(params = {})
124
+ def memberships(params={})
100
125
  Endpoints::Memberships.new(client).get(id, params)
101
126
  end
102
127
 
@@ -104,21 +129,33 @@ module TrackerApi
104
129
  #
105
130
  # @param [Hash] params
106
131
  # @return [Array[Activity]]
107
- def activity(params = {})
132
+ def activity(params={})
108
133
  Endpoints::Activity.new(client).get_project(id, params)
109
134
  end
110
135
 
136
+ # Find a story by id for the project.
137
+ #
111
138
  # @param [Fixnum] story_id id of story to get
112
139
  # @return [Story] story with given id
113
- def story(story_id)
114
- Endpoints::Story.new(client).get(id, story_id)
140
+ def story(story_id, params={})
141
+ Endpoints::Story.new(client).get(id, story_id, params)
115
142
  end
116
143
 
144
+ # Create a new story in the project.
145
+ #
117
146
  # @param [Hash] params attributes to create the story with
118
147
  # @return [Story] newly created Story
119
148
  def create_story(params)
120
149
  Endpoints::Story.new(client).create(id, params)
121
150
  end
151
+
152
+ # Add a new membership for the project.
153
+ #
154
+ # @param [Hash] params attributes to add a member; must have at least email or user_id
155
+ # @return [ProjectMembership] member that was added to project
156
+ def add_membership(params)
157
+ Endpoints::Memberships.new(client).add(id, params)
158
+ end
122
159
  end
123
160
  end
124
161
  end
@@ -1,9 +1,8 @@
1
1
  module TrackerApi
2
2
  module Resources
3
3
  class ProjectMembership
4
- include Virtus.model
4
+ include Resources::Base
5
5
 
6
- attribute :id, Integer
7
6
  attribute :person_id, Integer
8
7
  attribute :project_id, Integer
9
8
  attribute :role, String