Created GET work package endpoint

pull/1435/head
Marek Takac 11 years ago
parent 1490621af1
commit 97d4e9a1e6
  1. 2
      Gemfile
  2. 26
      Gemfile.lock
  3. 1
      app/api/api.rb
  4. 11
      app/api/work_packages/relation_mapper.rb
  5. 26
      app/api/work_packages/user_representer.rb
  6. 90
      app/api/work_packages/work_package_mapper.rb
  7. 80
      app/api/work_packages/work_package_model.rb
  8. 75
      app/api/work_packages/work_package_representer.rb
  9. 15
      app/api/work_packages/work_packages.rb

@ -186,7 +186,7 @@ gem 'pundit'
# API gems # API gems
gem 'grape', '~> 0.7.0' gem 'grape', '~> 0.7.0'
gem 'roar', '~> 0.12.6' gem 'roar', '~> 0.12.6'
gem 'yaks' gem 'reform'
# Use the commented pure ruby gems, if you have not the needed prerequisites on # Use the commented pure ruby gems, if you have not the needed prerequisites on
# board to compile the native ones. Note, that their use is discouraged, since # board to compile the native ones. Note, that their use is discouraged, since

@ -61,9 +61,6 @@ GEM
multi_json (~> 1.0) multi_json (~> 1.0)
acts_as_list (0.2.0) acts_as_list (0.2.0)
activerecord (>= 3.0) activerecord (>= 3.0)
adamantium (0.2.0)
ice_nine (~> 0.11.0)
memoizable (~> 0.4.0)
addressable (2.3.4) addressable (2.3.4)
arel (3.0.3) arel (3.0.3)
awesome_nested_set (2.1.6) awesome_nested_set (2.1.6)
@ -106,9 +103,6 @@ GEM
coffee-script-source (1.6.2) coffee-script-source (1.6.2)
color-tools (1.3.0) color-tools (1.3.0)
columnize (0.3.6) columnize (0.3.6)
concord (0.1.5)
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
cucumber (1.3.8) cucumber (1.3.8)
builder (>= 2.1.2) builder (>= 2.1.2)
diff-lcs (>= 1.1.3) diff-lcs (>= 1.1.3)
@ -142,6 +136,9 @@ GEM
descendants_tracker (0.0.4) descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
diff-lcs (1.2.5) diff-lcs (1.2.5)
disposable (0.0.3)
representable (~> 1.8.1)
uber
equalizer (0.0.9) equalizer (0.0.9)
erubis (2.7.0) erubis (2.7.0)
eventmachine (1.0.3) eventmachine (1.0.3)
@ -187,13 +184,11 @@ GEM
guard-test (1.0.0) guard-test (1.0.0)
guard (>= 1.8) guard (>= 1.8)
test-unit (~> 2.2) test-unit (~> 2.2)
hamster (0.4.3)
hashie (2.1.1) hashie (2.1.1)
hike (1.2.3) hike (1.2.3)
htmldiff (0.0.1) htmldiff (0.0.1)
i18n (0.6.5) i18n (0.6.5)
ice_nine (0.11.0) ice_nine (0.11.0)
inflection (1.0.0)
interception (0.3) interception (0.3)
journey (1.0.4) journey (1.0.4)
jquery-atwho-rails (0.4.7) jquery-atwho-rails (0.4.7)
@ -220,8 +215,6 @@ GEM
mail (2.5.4) mail (2.5.4)
mime-types (~> 1.16) mime-types (~> 1.16)
treetop (~> 1.4.8) treetop (~> 1.4.8)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
metaclass (0.0.1) metaclass (0.0.1)
method_source (0.8.2) method_source (0.8.2)
mime-types (1.25.1) mime-types (1.25.1)
@ -309,6 +302,11 @@ GEM
rdoc (3.12.2) rdoc (3.12.2)
json (~> 1.4) json (~> 1.4)
ref (1.0.5) ref (1.0.5)
reform (1.0.0)
activemodel
disposable (~> 0.0.3)
representable (~> 1.8.1)
uber (~> 0.0.4)
representable (1.8.1) representable (1.8.1)
multi_json multi_json
nokogiri nokogiri
@ -398,7 +396,6 @@ GEM
uglifier (2.1.1) uglifier (2.1.1)
execjs (>= 0.3.0) execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2) multi_json (~> 1.0, >= 1.0.2)
uri_template (0.6.0)
virtus (1.0.2) virtus (1.0.2)
axiom-types (~> 0.1) axiom-types (~> 0.1)
coercible (~> 1.0) coercible (~> 1.0)
@ -408,11 +405,6 @@ GEM
will_paginate (3.0.5) will_paginate (3.0.5)
xpath (2.0.0) xpath (2.0.0)
nokogiri (~> 1.3) nokogiri (~> 1.3)
yaks (0.2.0)
concord (~> 0.1.4)
hamster (~> 0.4.3)
inflection (~> 1.0.0)
uri_template (~> 0.6.0)
yard (0.8.7.2) yard (0.8.7.2)
PLATFORMS PLATFORMS
@ -479,6 +471,7 @@ DEPENDENCIES
rb-fsevent rb-fsevent
rb-readline rb-readline
rdoc (>= 2.4.2) rdoc (>= 2.4.2)
reform
request_store request_store
roar (~> 0.12.6) roar (~> 0.12.6)
rspec (~> 2.14) rspec (~> 2.14)
@ -503,4 +496,3 @@ DEPENDENCIES
timecop (~> 0.6.1) timecop (~> 0.6.1)
uglifier (>= 1.0.3) uglifier (>= 1.0.3)
will_paginate (~> 3.0) will_paginate (~> 3.0)
yaks

@ -52,5 +52,4 @@ class API < Grape::API
mount Projects::API mount Projects::API
mount WorkPackages::API mount WorkPackages::API
mount Users::API mount Users::API
end end

@ -1,11 +0,0 @@
module WorkPackages
class RelationMapper < Yaks::Mapper
link :self, '/api/v3/work_packages/{work_package_id}/relations'
attributes :id
def work_package_id
1
end
end
end

@ -0,0 +1,26 @@
require 'roar/representer/json'
require 'roar/decorator'
require 'roar/representer/json/hal'
module WorkPackages
class UserRepresenter < Roar::Decorator
include Roar::Representer::JSON
include Roar::Representer::JSON::HAL
include Roar::Representer::Feature::Hypermedia
include Rails.application.routes.url_helpers
property :login
property :firstname
property :lastname
property :mail
property :_type, exec_context: :decorator
link :self do
{ href: "http://localhost:3000/api/v3/users/#{represented.id}", title: "User." }
end
def _type
"User"
end
end
end

@ -1,90 +0,0 @@
module WorkPackages
class WorkPackageMapper < Yaks::Mapper
def initialize(object, embedded)
super(object)
end
link :self, '/api/v3/work_packages/{id}'
link :createChildren, '/api/v3/work_packages?parent_id={id}', method: :post
link :update, '/api/v3/work_packages/{id}', method: :patch
link :delete, '/api/v3/work_packages/{id}', method: :delete
link :project, '/api/v3/projects/{project_id}'
link :author, '/api/v3/users/{author_id}'
link :assignee, '/api/v3/users/{assigned_to_id}'
link :responsible, '/api/v3/users/{responsible_id}'
link :targetVersion, '/api/v3/versions/{fixed_version_id}'
link :projectWorkPackages, '/api/v3/work_packages?filter=project_ideql{project_id}'
link :descendants, '/api/v3/work_packages?filter=ancestors_idscontain{id}'
link :children, '/api/v3/work_packages?filter=parent_ideql{id}'
link :parent, '/api/v3/work_packages?filter=children_idscontain{id}'
link :ancestors, '/api/v3/work_packages?filter=descendants_idscontain{id}'
link :relations, '/api/v3/work_packages/{id}/relations'
attributes :id, :subject, :description, :type, :dueDate, :status, :priority, :percentageDone,
:estimatedTime, :startDate, :createdAt, :updatedAt, :customFields, :_type
has_one :project, mapper: Projects::ProjectMapper
has_one :author, mapper: Users::UserMapper
has_one :assigned_to, mapper: Users::UserMapper, as: :assignee
has_one :responsible, mapper: Users::UserMapper
has_one :fixed_version, mapper: Versions::VersionMapper, as: :targetVersion
has_one :parent, mapper: WorkPackages::WorkPackageMapper
has_many :descendants, mapper: WorkPackages::WorkPackageMapper
has_many :ancestors, mapper: WorkPackages::WorkPackageMapper
has_many :children, mapper: WorkPackages::WorkPackageMapper
has_many :relations, mapper: WorkPackages::RelationMapper
def type
object.type.name
end
def dueDate
object.due_date.to_s
end
def status
object.status.name
end
def priority
object.priority.name
end
def percentageDone
object.done_ratio
end
def estimatedTime
{ unit: 'hours', value: object.estimated_hours }
end
def startDate
object.start_date.to_s
end
def createdAt
object.created_at.to_s
end
def updatedAt
object.updated_at.to_s
end
def customFields
fields = [ ]
object.custom_field_values.each do |custom_value|
fields << { name: custom_value.custom_field.name, format: custom_value.custom_field.field_format, value: custom_value.value }
end
fields
end
def _type
"WorkPackage"
end
def relations
[]
end
end
end

@ -0,0 +1,80 @@
module WorkPackages
class WorkPackageModel < Reform::Form
include Composition
model :work_package
property :subject, on: :work_package
property :description, on: :work_package
property :due_date, on: :work_package
property :percentage_done, as: :done_ratio, on: :work_package
property :start_date, on: :work_package
property :created_at, on: :work_package
property :updated_at, on: :work_package
property :author, on: :work_package
def type
work_package.type.name
end
def type=(value)
type = Type.find(:first, conditions: ['name ilike ?', value])
work_package.type = type
end
def status
work_package.status.name
end
def status=(value)
status = Status.find(:first, conditions: ['name ilike ?', value])
work_package.status = status
end
def priority
work_package.priority.name
end
def priority=(value)
priority = IssuePriority.find(:first, conditions: ['name ilike ?', value])
work_package.priority = priority
end
def responsible_login
work_package.responsible.try(:login)
end
def responsible_login=(value)
responsible_user = User.find(:first, conditions: ['login ilike ?', value])
work_package.responsible = responsible_user
end
def responsible
work_package.responsible
end
def assignee_login
work_package.assigned_to.try(:login)
end
def assignee_login=(value)
assignee_user = User.find(:first, conditions: ['login ilike ?', value])
work_package.assigned_to = assignee_user
end
def assignee
work_package.assigned_to
end
def estimated_time
{ units: 'hours', value: work_package.estimated_hours }
end
def estimated_time=(value)
hours = ActiveSupport::JSON.decode(value)['value']
work_package.estimated_hours = hours
end
validates :subject, presence: true
end
end

@ -2,48 +2,47 @@ require 'roar/representer/json'
require 'roar/decorator' require 'roar/decorator'
require 'roar/representer/json/hal' require 'roar/representer/json/hal'
class WorkPackageRepresenter < Roar::Decorator module WorkPackages
include Roar::Representer::JSON class WorkPackageRepresenter < Roar::Decorator
include Roar::Representer::JSON::HAL include Roar::Representer::JSON
include Roar::Representer::Feature::Hypermedia include Roar::Representer::JSON::HAL
include Rails.application.routes.url_helpers include Roar::Representer::Feature::Hypermedia
include Rails.application.routes.url_helpers
property :id property :_type, exec_context: :decorator
property :subject
property :description
property :type, getter: lambda { |*| self.type.try(:name) }
property :due_date, as: :dueDate, getter: lambda { |*| self.due_date.try(:to_s) }
property :status, getter: lambda { |*| self.status.try(:name) }
property :priority, getter: lambda { |*| self.priority.try(:name) }
property :done_ratio, as: :percentageDone
property :estimated_time, as: :estimatedTime, exec_context: :decorator
property :start_date, as: :startDate, getter: lambda { |*| self.start_date.try(:to_s) }
property :created_at, as: :createdAt, getter: lambda { |*| self.created_at.try(:to_s) }
property :updated_at, as: :updatedAt, getter: lambda { |*| self.updated_at.try(:to_s) }
property :custom_fields, as: :customFields, exec_context: :decorator
property :_type, exec_context: :decorator
property :_links, exec_context: :decorator
def estimated_time link :self do
{ units: :hours, value: represented.estimated_hours} { href: "http://localhost:3000/api/v3/work_packages/#{represented.work_package.id}", title: "Work package" }
end
def custom_fields
fields = []
represented.custom_field_values.each do |value|
fields << { name: value.custom_field.name, format: value.custom_field.field_format, value: value.value }
end end
fields
end
def _type property :id, getter: lambda { |*| work_package.id }
"WorkPackage" property :subject
end property :type
property :description
property :status
property :priority
property :start_date
property :due_date
property :estimated_time
property :percentage_done
property :project_id, getter: lambda { |*| work_package.project.id }
property :project_name, getter: lambda { |*| work_package.project.name }
property :responsible_id, getter: lambda { |*| work_package.responsible.try(:id) }, render_nil: true
property :responsible_name, getter: lambda { |*| work_package.responsible.try(:name) }, render_nil: true
property :responsible_login, getter: lambda { |*| work_package.responsible.try(:login) }, render_nil: true
property :responsible_mail, getter: lambda { |*| work_package.responsible.try(:mail) }, render_nil: true
property :assignee_id, getter: lambda { |*| work_package.assigned_to.try(:id) }, render_nil: true
property :assignee_name, getter: lambda { |*| work_package.assigned_to.try(:name) }, render_nil: true
property :assignee_login, getter: lambda { |*| work_package.assigned_to.try(:login) }, render_nil: true
property :assignee_mail, getter: lambda { |*| work_package.assigned_to.try(:mail) }, render_nil: true
property :author_name, getter: lambda { |*| work_package.author.name }
property :author_login, getter: lambda { |*| work_package.author.login }
property :author_mail, getter: lambda { |*| work_package.author.mail }
property :created_at
property :updated_at
def _links def _type
{ "WorkPackage"
self: { href: api_v3_work_package_path(represented.id) }, end
update: { href: api_v3_work_package_path(represented.id), method: :put }
}
end end
end end

@ -29,7 +29,9 @@ module WorkPackages
end end
get do get do
'show a work package' work_package_model = WorkPackageModel.new(work_package: @work_package)
work_package_representer = WorkPackageRepresenter.new(work_package_model)
work_package_representer.to_json
end end
put do put do
@ -37,7 +39,16 @@ module WorkPackages
end end
patch do patch do
@work_package work_package_model = WorkPackageModel.new(work_package: @work_package)
work_package_representer = WorkPackageRepresenter.new(work_package_model)
work_package_representer.from_json(request.POST.to_json)
if work_package_representer.represented.valid?
work_package_representer.represented.save!
work_package_representer.to_json
else
work_package_representer.represented.errors.to_json
end
end end
delete do delete do

Loading…
Cancel
Save