mavenlink 0.0.1

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.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +3 -0
  6. data/README.md +241 -0
  7. data/Rakefile +28 -0
  8. data/bin/mavenlink-console +18 -0
  9. data/doc/ml_logo_lb-primary.png +0 -0
  10. data/lib/config/specification.yml +1665 -0
  11. data/lib/mavenlink.rb +134 -0
  12. data/lib/mavenlink/account_invitation.rb +4 -0
  13. data/lib/mavenlink/account_membership.rb +4 -0
  14. data/lib/mavenlink/additional_item.rb +4 -0
  15. data/lib/mavenlink/assignment.rb +5 -0
  16. data/lib/mavenlink/attachment.rb +11 -0
  17. data/lib/mavenlink/backup_approver_association.rb +4 -0
  18. data/lib/mavenlink/client.rb +116 -0
  19. data/lib/mavenlink/concerns/custom_fieldable.rb +9 -0
  20. data/lib/mavenlink/concerns/indestructible.rb +11 -0
  21. data/lib/mavenlink/concerns/locked_record.rb +30 -0
  22. data/lib/mavenlink/cost_rate.rb +4 -0
  23. data/lib/mavenlink/custom_field.rb +4 -0
  24. data/lib/mavenlink/custom_field_choice.rb +5 -0
  25. data/lib/mavenlink/custom_field_value.rb +4 -0
  26. data/lib/mavenlink/errors.rb +47 -0
  27. data/lib/mavenlink/expense.rb +4 -0
  28. data/lib/mavenlink/expense_category.rb +4 -0
  29. data/lib/mavenlink/expense_report_submission.rb +7 -0
  30. data/lib/mavenlink/external_payment.rb +4 -0
  31. data/lib/mavenlink/external_reference.rb +24 -0
  32. data/lib/mavenlink/fixed_fee_item.rb +4 -0
  33. data/lib/mavenlink/holiday.rb +4 -0
  34. data/lib/mavenlink/holiday_calendar.rb +4 -0
  35. data/lib/mavenlink/holiday_calendar_association.rb +4 -0
  36. data/lib/mavenlink/holiday_calendar_membership.rb +4 -0
  37. data/lib/mavenlink/invoice.rb +4 -0
  38. data/lib/mavenlink/logger.rb +62 -0
  39. data/lib/mavenlink/model.rb +279 -0
  40. data/lib/mavenlink/organization.rb +4 -0
  41. data/lib/mavenlink/organization_membership.rb +4 -0
  42. data/lib/mavenlink/participation.rb +4 -0
  43. data/lib/mavenlink/post.rb +4 -0
  44. data/lib/mavenlink/project_template.rb +4 -0
  45. data/lib/mavenlink/project_template_assignment.rb +4 -0
  46. data/lib/mavenlink/railtie.rb +7 -0
  47. data/lib/mavenlink/rate_card.rb +4 -0
  48. data/lib/mavenlink/rate_card_role.rb +4 -0
  49. data/lib/mavenlink/rate_card_set.rb +4 -0
  50. data/lib/mavenlink/rate_card_set_version.rb +30 -0
  51. data/lib/mavenlink/rate_card_version.rb +4 -0
  52. data/lib/mavenlink/request.rb +241 -0
  53. data/lib/mavenlink/resolution.rb +4 -0
  54. data/lib/mavenlink/response.rb +22 -0
  55. data/lib/mavenlink/role.rb +5 -0
  56. data/lib/mavenlink/settings.rb +11 -0
  57. data/lib/mavenlink/skill.rb +4 -0
  58. data/lib/mavenlink/skill_category.rb +4 -0
  59. data/lib/mavenlink/skill_membership.rb +4 -0
  60. data/lib/mavenlink/specificators/association.rb +13 -0
  61. data/lib/mavenlink/specificators/attribute.rb +13 -0
  62. data/lib/mavenlink/specificators/base.rb +24 -0
  63. data/lib/mavenlink/specificators/validation.rb +27 -0
  64. data/lib/mavenlink/status_report.rb +4 -0
  65. data/lib/mavenlink/story.rb +8 -0
  66. data/lib/mavenlink/story_allocation_day.rb +5 -0
  67. data/lib/mavenlink/story_dependency.rb +5 -0
  68. data/lib/mavenlink/story_task.rb +5 -0
  69. data/lib/mavenlink/tag.rb +5 -0
  70. data/lib/mavenlink/time_adjustment.rb +4 -0
  71. data/lib/mavenlink/time_entry.rb +4 -0
  72. data/lib/mavenlink/time_off_entry.rb +4 -0
  73. data/lib/mavenlink/timesheet_submission.rb +4 -0
  74. data/lib/mavenlink/user.rb +5 -0
  75. data/lib/mavenlink/vendor.rb +4 -0
  76. data/lib/mavenlink/workspace.rb +21 -0
  77. data/lib/mavenlink/workspace_group.rb +5 -0
  78. data/lib/mavenlink/workspace_invoice_preference.rb +4 -0
  79. data/lib/mavenlink/workweek.rb +4 -0
  80. data/lib/mavenlink/workweek_membership.rb +4 -0
  81. data/mavenlink.gemspec +29 -0
  82. data/spec/lib/mavenlink/account_membership_spec.rb +8 -0
  83. data/spec/lib/mavenlink/assignment_spec.rb +17 -0
  84. data/spec/lib/mavenlink/attachment_spec.rb +30 -0
  85. data/spec/lib/mavenlink/backup_approver_association_spec.rb +9 -0
  86. data/spec/lib/mavenlink/client_spec.rb +187 -0
  87. data/spec/lib/mavenlink/concerns/indestructible_spec.rb +13 -0
  88. data/spec/lib/mavenlink/concerns/locked_record_spec.rb +28 -0
  89. data/spec/lib/mavenlink/cost_rate_spec.rb +9 -0
  90. data/spec/lib/mavenlink/custom_field_value_spec.rb +10 -0
  91. data/spec/lib/mavenlink/expense_report_submission_spec.rb +16 -0
  92. data/spec/lib/mavenlink/expense_spec.rb +23 -0
  93. data/spec/lib/mavenlink/external_references_spec.rb +144 -0
  94. data/spec/lib/mavenlink/holiday_calendar_association_spec.rb +8 -0
  95. data/spec/lib/mavenlink/holiday_calendar_membership_spec.rb +8 -0
  96. data/spec/lib/mavenlink/holiday_spec.rb +7 -0
  97. data/spec/lib/mavenlink/invalid_request_error_spec.rb +9 -0
  98. data/spec/lib/mavenlink/invoice_spec.rb +176 -0
  99. data/spec/lib/mavenlink/model_spec.rb +439 -0
  100. data/spec/lib/mavenlink/post_spec.rb +23 -0
  101. data/spec/lib/mavenlink/rate_card_set_version_spec.rb +119 -0
  102. data/spec/lib/mavenlink/record_invalid_error_spec.rb +16 -0
  103. data/spec/lib/mavenlink/record_not_found_error_spec.rb +9 -0
  104. data/spec/lib/mavenlink/request_spec.rb +381 -0
  105. data/spec/lib/mavenlink/response_spec.rb +50 -0
  106. data/spec/lib/mavenlink/role_spec.rb +9 -0
  107. data/spec/lib/mavenlink/settings_spec.rb +23 -0
  108. data/spec/lib/mavenlink/skill_category_spec.rb +7 -0
  109. data/spec/lib/mavenlink/skill_membership_spec.rb +9 -0
  110. data/spec/lib/mavenlink/skill_spec.rb +8 -0
  111. data/spec/lib/mavenlink/specificators/association_spec.rb +25 -0
  112. data/spec/lib/mavenlink/specificators/attribute_spec.rb +25 -0
  113. data/spec/lib/mavenlink/specificators/validation_spec.rb +39 -0
  114. data/spec/lib/mavenlink/story_allocation_day_spec.rb +64 -0
  115. data/spec/lib/mavenlink/story_dependency_spec.rb +16 -0
  116. data/spec/lib/mavenlink/story_spec.rb +69 -0
  117. data/spec/lib/mavenlink/time_adjustment_spec.rb +13 -0
  118. data/spec/lib/mavenlink/time_entry_spec.rb +43 -0
  119. data/spec/lib/mavenlink/time_off_entry_spec.rb +9 -0
  120. data/spec/lib/mavenlink/user_spec.rb +138 -0
  121. data/spec/lib/mavenlink/workspace_group_spec.rb +25 -0
  122. data/spec/lib/mavenlink/workspace_spec.rb +431 -0
  123. data/spec/lib/mavenlink_spec.rb +43 -0
  124. data/spec/spec_helper.rb +31 -0
  125. data/spec/support/shared_examples.rb +148 -0
  126. metadata +267 -0
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class ExternalPayment < Model
3
+ end
4
+ end
@@ -0,0 +1,24 @@
1
+ module Mavenlink
2
+ class ExternalReference < Model
3
+ def save
4
+ if valid?
5
+ reload(create_or_update(attributes_for_create_or_update))
6
+ true
7
+ else
8
+ false
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def create_or_update(attributes)
15
+ request.perform do
16
+ client.post("external_references/create_or_update", { external_reference: attributes})
17
+ end
18
+ end
19
+
20
+ def attributes_for_create_or_update
21
+ specification_attributes("create_or_update_attributes")
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class FixedFeeItem < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class Holiday < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class HolidayCalendar < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class HolidayCalendarAssociation < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class HolidayCalendarMembership < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class Invoice < Model
3
+ end
4
+ end
@@ -0,0 +1,62 @@
1
+ module Mavenlink
2
+ class Logger < ::Logger
3
+ # @todo(SZ) YARD, docu, describe colors, when to use each one
4
+
5
+ # @param device [nil, STDOUT, STDERR]
6
+ def initialize(device)
7
+ super
8
+ self.level = Logger::FATAL
9
+ end
10
+
11
+ # @param [String] message
12
+ def disappointment(message)
13
+ info("\e[#{35}m[Maven]\e[0m \e[#{31}m#{message}\e[0m") if error?
14
+ end
15
+
16
+ # @param [String] message
17
+ def hint(message)
18
+ info("\e[#{32}m[Maven]\e[1m \e[#{33}m#{message}\e[0m") if warn?
19
+ end
20
+
21
+ # @param [String] message
22
+ def note(message)
23
+ info("\e[#{32}m[Maven]\e[0m \e[#{36}m#{message}\e[0m") if info?
24
+ end
25
+
26
+ # @param [String] message
27
+ def whisper(message)
28
+ info("\e[#{32}m[Maven]\e[0m \e[#{37}m#{message}\e[0m") if debug?
29
+ end
30
+
31
+ # @param [String] message
32
+ def inspection(message)
33
+ if debug?
34
+ if message.respond_to?(:awesome_inspect)
35
+ info(message.awesome_inspect)
36
+ else
37
+ info(message.inspect)
38
+ end
39
+ end
40
+ end
41
+
42
+ # @param [String] message
43
+ def self.disappointment(message)
44
+ Mavenlink.logger.disappointment(message)
45
+ end
46
+
47
+ # @param [String] message
48
+ def self.hint(message)
49
+ Mavenlink.logger.hint(message)
50
+ end
51
+
52
+ # @param [String] message
53
+ def self.note(message)
54
+ Mavenlink.logger.note(message)
55
+ end
56
+
57
+ # @param [String] message
58
+ def self.whisper(message)
59
+ Mavenlink.logger.whisper(message)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,279 @@
1
+ module Mavenlink
2
+ class Model < BrainstemAdaptor::Record
3
+ include ActiveModel::Validations
4
+
5
+ attr_reader :client
6
+
7
+ class << self
8
+ delegate :only, :find, :search, :filter, :page, :total_count, :per_page, :limit, :offset, :order, :all, to: :scoped
9
+ end
10
+
11
+ # @return [String]
12
+ def self.collection_name
13
+ (self.name || 'undefined').split(/\W+/).last.tableize.pluralize
14
+ end
15
+
16
+ # @param attributes [Hash]
17
+ # @return [Mavenlink::Model]
18
+ def self.create(attributes = {})
19
+ self.new(attributes).tap(&:save)
20
+ end
21
+
22
+ # @raise [Mavenlink::RecordInvalidError]
23
+ # @param attributes [Hash]
24
+ # @return [Mavenlink::Model]
25
+ def self.create!(attributes = {})
26
+ create(attributes).tap do |record|
27
+ record.valid? or raise RecordInvalidError.new(record)
28
+ end
29
+ end
30
+
31
+ # @return [Mavenlink::Request]
32
+ def self.includes(*args)
33
+ scoped.include(*args)
34
+ end
35
+
36
+ # @param client [Mavenlink::Client]
37
+ # @return [Mavenlink::Request]
38
+ def self.scoped(client = Mavenlink.client)
39
+ Mavenlink::Request.new(collection_name, client)
40
+ end
41
+
42
+ # @return [Mavenlink::Request]
43
+ def scoped_im
44
+ Mavenlink::Request.new(collection_name, client)
45
+ end
46
+
47
+ # @param model_class [Mavenlink::Model]
48
+ def self.inherited(model_class)
49
+ ::Mavenlink::Model.models[model_class.collection_name] = model_class
50
+
51
+ # Applies specification file to the model
52
+ Mavenlink::Specificators::Attribute.apply(model_class)
53
+ Mavenlink::Specificators::Association.apply(model_class)
54
+ Mavenlink::Specificators::Validation.apply(model_class)
55
+ end
56
+
57
+ # Returns all models registered in the app
58
+ # @return [Hash<String, Class>] key is collection name and value is a model assigned to this collection
59
+ def self.models
60
+ @models ||= ActiveSupport::HashWithIndifferentAccess.new
61
+ end
62
+
63
+ # Returns collection specification
64
+ # @return [Hash]
65
+ def self.specification
66
+ @specification ||= Mavenlink.specification[collection_name] || {}
67
+ end
68
+
69
+ # @todo REFACTOR NA
70
+ # @param association_name [String, Symbol]
71
+ def self.association(association_name)
72
+ define_method association_name do |reload = false|
73
+ return nil if new_record?
74
+
75
+ association = association_by_name(association_name)
76
+ reload = true unless association.loaded?
77
+
78
+ if reload
79
+ reload_association(association)
80
+ associations_cache[association_name] = fetch_association_records(association)
81
+ elsif associations_cache.has_key?(association_name)
82
+ associations_cache[association_name]
83
+ else
84
+ associations_cache[association_name] = fetch_association_records(association)
85
+ end
86
+ end
87
+ end
88
+
89
+ # @param names [String, Symbol]
90
+ def self.attribute(*names)
91
+ names.each do |name|
92
+ define_method(name) { self[name.to_s] }
93
+ define_method("#{name}=") { |value| self[name.to_s] = value }
94
+ end
95
+ end
96
+
97
+ # Returns list of available attributes
98
+ # @return [Array<String>]
99
+ def self.attributes
100
+ specification['attributes'] ||= []
101
+ end
102
+
103
+ # Returns list of all available attributes
104
+ # @return [Array<String>]
105
+ def self.available_attributes
106
+ create_attributes | update_attributes | attributes
107
+ end
108
+
109
+ # Returns the list of attributes available for new record
110
+ # @return [Array<String>]
111
+ def self.create_attributes
112
+ specification['create_attributes'] ||= []
113
+ end
114
+
115
+ # Returns the list of attributes available for update
116
+ # @return [Array<String>]
117
+ def self.update_attributes
118
+ specification['update_attributes'] ||= []
119
+ end
120
+
121
+ # @param source_record [Brainstem::Record, nil]
122
+ # @param client [Mavenlink::Client]
123
+ def self.wrap(source_record = nil, client = Mavenlink.client)
124
+ self.new({}, source_record, client)
125
+ end
126
+
127
+ # @param attributes [Hash]
128
+ # @param source_record [BrainstemAdaptor::Record]
129
+ # @param client [Mavenlink::Client]
130
+ def initialize(attributes = {}, source_record = nil, client = Mavenlink.client)
131
+ super(self.class.collection_name, (attributes[:id] || attributes['id'] || source_record.try(:id)), source_record.try(:response))
132
+ @client = client
133
+ merge!(attributes)
134
+ end
135
+
136
+ # @param attributes [Hash]
137
+ def attributes=(attributes)
138
+ merge!(attributes)
139
+ end
140
+
141
+ def persisted?
142
+ !!id
143
+ end
144
+
145
+ def new_record?
146
+ !persisted?
147
+ end
148
+
149
+ # @return [true, false]
150
+ def save
151
+ if valid?
152
+ reload(new_record? ? create : update)
153
+ true
154
+ else
155
+ false
156
+ end
157
+ end
158
+
159
+ # @raise [Mavenlink::RecordInvalidError]
160
+ # @return [true]
161
+ def save!
162
+ save or raise Mavenlink::RecordInvalidError.new(self)
163
+ end
164
+
165
+ # @param attributes [Hash]
166
+ # @return [true, false]
167
+ def update_attributes(attributes)
168
+ self.attributes = attributes
169
+ save
170
+ end
171
+
172
+ # @param attributes [Hash]
173
+ # @raise [Mavenlink::RecordInvalidError]
174
+ # @return [true]
175
+ def update_attributes!(attributes)
176
+ self.attributes = attributes
177
+ save!
178
+ end
179
+
180
+ # @note does not work, don't know what to do with removed record.
181
+ # will just return RecordNotFound error if you call #save after #destroy
182
+ def destroy
183
+ request.delete
184
+ end
185
+ alias_method :delete, :destroy
186
+
187
+ # Reloads record from server
188
+ # @return [self]
189
+ def reload(response = nil)
190
+ response ||= request.find(id).try(:response) or raise RecordNotFoundError.new(request)
191
+ @id ||= response.results.first.try(:[], 'id')
192
+ load_fields_with(response)
193
+ self
194
+ end
195
+
196
+ # @overload
197
+ # @param context [:create, :update]
198
+ # @return [true, false]
199
+ def valid?(context = saving_context)
200
+ Mavenlink::Settings[:default][:perform_validations] ? super(context.try(:to_sym)) : true
201
+ end
202
+
203
+ # @return [String, nil]
204
+ def to_param
205
+ id.try(:to_s)
206
+ end
207
+
208
+ protected
209
+
210
+ # @return [Mavenlink::Response]
211
+ def create
212
+ request.create(attributes_for_create)
213
+ end
214
+
215
+ # @return [Mavenlink::Response]
216
+ def update
217
+ request.update(attributes_for_update)
218
+ end
219
+
220
+ # @return [Hash]
221
+ def attributes_for_create
222
+ specification_attributes('create_attributes')
223
+ end
224
+
225
+ # @return [Hash]
226
+ def attributes_for_update
227
+ specification_attributes('update_attributes')
228
+ end
229
+
230
+ # @return [Mavenlink::Request]
231
+ def request
232
+ collection_scope.only(id)
233
+ end
234
+
235
+ private
236
+
237
+ # Stores requested data in a Hash
238
+ # @return [Hash]
239
+ def associations_cache
240
+ @associations_cache ||= {}.with_indifferent_access
241
+ end
242
+
243
+ # @return [Mavenlink::Request]
244
+ def collection_scope
245
+ @collection_scope ||= self.class.scoped(client)
246
+ end
247
+
248
+ # @param association [BrainstemAdaptor::Association]
249
+ # @return [Array<Mavenlink::Model>, nil]
250
+ def fetch_association_records(association)
251
+ records = association.reflect
252
+
253
+ if records
254
+ wrapper = proc { |record| Mavenlink::Model.models[association.collection_name].wrap(record, client) }
255
+ records.kind_of?(BrainstemAdaptor::Association) ? records.map(&wrapper) : wrapper.call(records, client)
256
+ end
257
+ end
258
+
259
+ # @param association [BrainstemAdaptor::Association]
260
+ def reload_association(association)
261
+ response = request.include(association.name).find(id).try(:response) or raise RecordNotFoundError.new(request)
262
+ load_fields_with(response, [association.foreign_key])
263
+ end
264
+
265
+ def saving_context
266
+ new_record? ? :create : :update
267
+ end
268
+
269
+ # @param key [String]
270
+ # @return [Hash]
271
+ def specification_attributes(key)
272
+ {}.tap do |result|
273
+ self.to_hash.slice(*self.class.specification[key]).each do |attr_name, value|
274
+ result[attr_name] = value
275
+ end
276
+ end
277
+ end
278
+ end
279
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class Organization < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class OrganizationMembership < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class Participation < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class Post < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class ProjectTemplate < Model
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mavenlink
2
+ class ProjectTemplateAssignment < Model
3
+ end
4
+ end