From 777566a0b8075fd80fd1c3f9521b2cce2e0fa70e Mon Sep 17 00:00:00 2001 From: Jan Sandbrink Date: Wed, 11 Feb 2015 11:36:39 +0100 Subject: [PATCH] restructure schemas with allowed values - own representer for property schema - two subclasses for either linked or embedded allowed values - no special subclasses per represented type --- .../allowed_reference_link_representer.rb | 85 ------------------ ...lowed_values_by_collection_representer.rb} | 36 ++++---- ... => allowed_values_by_link_representer.rb} | 25 +----- .../property_schema_representer.rb} | 42 +++++---- .../schema_allowed_values_representer.rb | 86 ------------------- .../schema_allowed_priorities_representer.rb | 58 ------------- .../schema/work_package_schema_representer.rb | 85 ++++++++++++------ 7 files changed, 103 insertions(+), 314 deletions(-) delete mode 100644 lib/api/decorators/allowed_reference_link_representer.rb rename lib/api/{v3/work_packages/schema/schema_allowed_statuses_representer.rb => decorators/allowed_values_by_collection_representer.rb} (65%) rename lib/api/decorators/{allowed_links_representer.rb => allowed_values_by_link_representer.rb} (70%) rename lib/api/{v3/work_packages/schema/schema_allowed_versions_representer.rb => decorators/property_schema_representer.rb} (61%) delete mode 100644 lib/api/decorators/schema_allowed_values_representer.rb delete mode 100644 lib/api/v3/work_packages/schema/schema_allowed_priorities_representer.rb diff --git a/lib/api/decorators/allowed_reference_link_representer.rb b/lib/api/decorators/allowed_reference_link_representer.rb deleted file mode 100644 index e70086ad00..0000000000 --- a/lib/api/decorators/allowed_reference_link_representer.rb +++ /dev/null @@ -1,85 +0,0 @@ -#-- encoding: UTF-8 -#-- copyright -# OpenProject is a project management system. -# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See doc/COPYRIGHT.rdoc for more details. -#++ - -require 'roar/decorator' -require 'roar/json/hal' - -module API - module Decorators - class AllowedReferenceLinkRepresenter < Roar::Decorator - include Roar::JSON::HAL - - def initialize(link, type, title, required, writable) - @link = link - @type = type - @name = title - @required = required - @writable = writable - - super(link) - end - - self.as_strategy = ::API::Utilities::CamelCasingStrategy.new - - property :_links, - exec_context: :decorator, - getter: -> (*) { link } do - include API::V3::Utilities::PathHelper - - self.as_strategy = ::API::Utilities::CamelCasingStrategy.new - - property :allowed_values, - getter: -> (*) { - { href: represented } - }, - exec_context: :decorator - end - - property :type, - exec_context: :decorator - - property :name, - exec_context: :decorator - - property :required, - exec_context: :decorator - - property :writable, - exec_context: :decorator - - private - - attr_reader :link, - :type, - :name, - :required, - :writable - end - end -end diff --git a/lib/api/v3/work_packages/schema/schema_allowed_statuses_representer.rb b/lib/api/decorators/allowed_values_by_collection_representer.rb similarity index 65% rename from lib/api/v3/work_packages/schema/schema_allowed_statuses_representer.rb rename to lib/api/decorators/allowed_values_by_collection_representer.rb index 4b903d1ce2..a3935d1235 100644 --- a/lib/api/v3/work_packages/schema/schema_allowed_statuses_representer.rb +++ b/lib/api/decorators/allowed_values_by_collection_representer.rb @@ -31,28 +31,26 @@ require 'roar/decorator' require 'roar/json/hal' module API - module V3 - module WorkPackages - module Schema - class SchemaAllowedStatusesRepresenter < Decorators::SchemaAllowedValuesRepresenter - def initialize(model, context = {}) - super(model, - 'Status', - I18n.t('activerecord.attributes.work_package.status'), - true, - true, - context) - end + module Decorators + class AllowedValuesByCollectionRepresenter < PropertySchemaRepresenter + attr_accessor :allowed_values, :value_representer, :link_factory - self.value_representer = Statuses::StatusRepresenter + links :allowedValues do + title_property = :name unless title_property - self.links_factory = -> (status) do - extend API::V3::Utilities::PathHelper - - { href: api_v3_paths.status(status.id), title: status.name } - end - end + allowed_values.map do |value| + link_factory.call(value) + end if allowed_values end + + collection :allowed_values, + exec_context: :decorator, + embedded: true, + getter: -> (*) { + allowed_values.map do |value| + value_representer.new(value, current_user: context[:current_user]) + end if allowed_values + } end end end diff --git a/lib/api/decorators/allowed_links_representer.rb b/lib/api/decorators/allowed_values_by_link_representer.rb similarity index 70% rename from lib/api/decorators/allowed_links_representer.rb rename to lib/api/decorators/allowed_values_by_link_representer.rb index e64f3d273b..0a884080eb 100644 --- a/lib/api/decorators/allowed_links_representer.rb +++ b/lib/api/decorators/allowed_values_by_link_representer.rb @@ -32,29 +32,12 @@ require 'roar/json/hal' module API module Decorators - class AllowedLinksRepresenter < Roar::Decorator - include API::V3::Utilities::PathHelper - include Roar::JSON::HAL + class AllowedValuesByLinkRepresenter < PropertySchemaRepresenter + attr_accessor :allowed_values_href - def initialize(represented, link_factory) - super(represented) - @link_factory = link_factory + link :allowedValues do + { href: allowed_values_href } if allowed_values_href end - - self.as_strategy = ::API::Utilities::CamelCasingStrategy.new - - property :allowed_values, - exec_context: :decorator - - private - - def allowed_values - represented.map do |object| - link_factory.call(object) - end - end - - attr_reader :link_factory end end end diff --git a/lib/api/v3/work_packages/schema/schema_allowed_versions_representer.rb b/lib/api/decorators/property_schema_representer.rb similarity index 61% rename from lib/api/v3/work_packages/schema/schema_allowed_versions_representer.rb rename to lib/api/decorators/property_schema_representer.rb index 49dbe9e1bd..b0f2be36b9 100644 --- a/lib/api/v3/work_packages/schema/schema_allowed_versions_representer.rb +++ b/lib/api/decorators/property_schema_representer.rb @@ -31,28 +31,32 @@ require 'roar/decorator' require 'roar/json/hal' module API - module V3 - module WorkPackages - module Schema - class SchemaAllowedVersionsRepresenter < Decorators::SchemaAllowedValuesRepresenter - def initialize(model, context = {}) - super(model, - 'Version', - I18n.t('activerecord.attributes.work_package.fixed_version'), - false, - true, - context) - end + module Decorators + class PropertySchemaRepresenter < ::API::Decorators::Single + def initialize(type: nil, name: nil, current_user: nil) + raise ArgumentError unless type && name - self.value_representer = Versions::VersionRepresenter + @type = type + @name = name + @required = true + @writable = true - self.links_factory = -> (version) do - extend API::V3::Utilities::PathHelper - - { href: api_v3_paths.version(version.id), title: version.name } - end - end + super(nil, current_user: current_user) end + + attr_accessor :type, + :name, + :required, + :writable, + :min_length, + :max_length + + property :type, exec_context: :decorator + property :name, exec_context: :decorator + property :required, exec_context: :decorator + property :writable, exec_context: :decorator + property :min_length, exec_context: :decorator + property :max_length, exec_context: :decorator end end end diff --git a/lib/api/decorators/schema_allowed_values_representer.rb b/lib/api/decorators/schema_allowed_values_representer.rb deleted file mode 100644 index e40e5aac4d..0000000000 --- a/lib/api/decorators/schema_allowed_values_representer.rb +++ /dev/null @@ -1,86 +0,0 @@ -#-- encoding: UTF-8 -#-- copyright -# OpenProject is a project management system. -# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See doc/COPYRIGHT.rdoc for more details. -#++ - -require 'roar/decorator' -require 'roar/json/hal' - -module API - module Decorators - class SchemaAllowedValuesRepresenter < Single - def initialize(model, type, name, required, writable, context = {}) - @type = type - @name = name - @required = required - @writable = writable - - super(model, context) - end - - property :links, - as: :_links, - exec_context: :decorator - - property :type, - exec_context: :decorator - - property :name, - exec_context: :decorator - - property :required, - exec_context: :decorator - - property :writable, - exec_context: :decorator - - collection :allowed_values, - exec_context: :decorator, - embedded: true - - private - - class_attribute :value_representer, - :links_factory - - attr_reader :type, - :name, - :required, - :writable - - def links - AllowedLinksRepresenter.new(represented, links_factory) - end - - def allowed_values - represented.map do |object| - value_representer.new(object, current_user: context[:current_user]) - end - end - end - end -end diff --git a/lib/api/v3/work_packages/schema/schema_allowed_priorities_representer.rb b/lib/api/v3/work_packages/schema/schema_allowed_priorities_representer.rb deleted file mode 100644 index baaf0d76f0..0000000000 --- a/lib/api/v3/work_packages/schema/schema_allowed_priorities_representer.rb +++ /dev/null @@ -1,58 +0,0 @@ -#-- encoding: UTF-8 -#-- copyright -# OpenProject is a project management system. -# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See doc/COPYRIGHT.rdoc for more details. -#++ - -require 'roar/decorator' -require 'roar/json/hal' - -module API - module V3 - module WorkPackages - module Schema - class SchemaAllowedPrioritiesRepresenter < Decorators::SchemaAllowedValuesRepresenter - def initialize(model, context = {}) - super(model, - 'Priority', - I18n.t('activerecord.attributes.work_package.priority'), - true, - true, - context) - end - - self.value_representer = Priorities::PriorityRepresenter - - self.links_factory = -> (priority) do - extend API::V3::Utilities::PathHelper - - { href: api_v3_paths.priority(priority.id), title: priority.name } - end - end - end - end - end -end diff --git a/lib/api/v3/work_packages/schema/work_package_schema_representer.rb b/lib/api/v3/work_packages/schema/work_package_schema_representer.rb index 51560a8202..b66d0ad8cd 100644 --- a/lib/api/v3/work_packages/schema/work_package_schema_representer.rb +++ b/lib/api/v3/work_packages/schema/work_package_schema_representer.rb @@ -47,15 +47,14 @@ module API title = I18n.t("activerecord.attributes.work_package.#{property}") unless title - schema = { - type: type, - name: title, - required: required, - writable: writable - } - schema[:minLength] = min_length if min_length - schema[:maxLength] = max_length if max_length + schema = ::API::Decorators::PropertySchemaRepresenter.new(type: type, + name: title) + + schema.required = required + schema.writable = writable + schema.min_length = min_length if min_length + schema.max_length = max_length if max_length property property, getter: -> (*) { schema }, @@ -95,48 +94,82 @@ module API exec_context: :decorator, getter: -> (*) { link = api_v3_paths.available_assignees(represented.project.id) + representer = ::API::Decorators::AllowedValuesByLinkRepresenter.new( + type: 'User', + name: I18n.t('activerecord.attributes.work_package.assigned_to')) + representer.required = false + + if represented.defines_assignable_values? + representer.allowed_values_href = link + end - ::API::Decorators::AllowedReferenceLinkRepresenter.new( - link, - 'User', - I18n.t('activerecord.attributes.work_package.assigned_to'), - false, - true) + representer } property :responsible, exec_context: :decorator, getter: -> (*) { link = api_v3_paths.available_responsibles(represented.project.id) + representer = ::API::Decorators::AllowedValuesByLinkRepresenter.new( + type: 'User', + name: I18n.t('activerecord.attributes.work_package.responsible')) + representer.required = false + + if represented.defines_assignable_values? + representer.allowed_values_href = link + end - ::API::Decorators::AllowedReferenceLinkRepresenter.new( - link, - 'User', - I18n.t('activerecord.attributes.work_package.responsible'), - false, - true) + representer } property :status, exec_context: :decorator, getter: -> (*) { assignable_statuses = represented.assignable_statuses_for(current_user) - SchemaAllowedStatusesRepresenter.new(assignable_statuses || [], - current_user: current_user) + representer = ::API::Decorators::AllowedValuesByCollectionRepresenter.new( + type: 'Status', + name: I18n.t('activerecord.attributes.work_package.status'), + current_user: current_user) + representer.allowed_values = assignable_statuses + representer.value_representer = API::V3::Statuses::StatusRepresenter + representer.link_factory = -> (status) do + { href: api_v3_paths.status(status.id), title: status.name } + end + + representer } property :version, exec_context: :decorator, getter: -> (*) { - SchemaAllowedVersionsRepresenter.new(represented.assignable_versions || [], - current_user: current_user) + representer = ::API::Decorators::AllowedValuesByCollectionRepresenter.new( + type: 'Version', + name: I18n.t('activerecord.attributes.work_package.fixed_version'), + current_user: current_user) + representer.required = false + representer.allowed_values = represented.assignable_versions + representer.value_representer = API::V3::Versions::VersionRepresenter + representer.link_factory = -> (version) do + { href: api_v3_paths.version(version.id), title: version.name } + end + + representer } property :priority, exec_context: :decorator, getter: -> (*) { - SchemaAllowedPrioritiesRepresenter.new(represented.assignable_priorities || [], - current_user: current_user) + representer = ::API::Decorators::AllowedValuesByCollectionRepresenter.new( + type: 'Priority', + name: I18n.t('activerecord.attributes.work_package.priority'), + current_user: current_user) + representer.allowed_values = represented.assignable_priorities + representer.value_representer = API::V3::Priorities::PriorityRepresenter + representer.link_factory = -> (priority) do + { href: api_v3_paths.priority(priority.id), title: priority.name } + end + + representer } def current_user