diff --git a/lib/api/decorators/schema_representer.rb b/lib/api/decorators/schema_representer.rb index 6d5f7d0378..1c81c6f4b6 100644 --- a/lib/api/decorators/schema_representer.rb +++ b/lib/api/decorators/schema_representer.rb @@ -62,34 +62,24 @@ module API max_length: nil, regular_expression: nil, show_if: true) - raise ArgumentError if property.nil? + getter = ->(*) do + schema_property_getter(type, + name_source, + required, + has_default, + writable, + visibility, + min_length, + max_length, + regular_expression) + end - property property, - exec_context: :decorator, - getter: -> (*) { - name = call_or_translate(name_source) - schema = ::API::Decorators::PropertySchemaRepresenter.new( - type: type, - name: name, - required: call_or_use(required), - has_default: call_or_use(has_default), - writable: call_or_use(writable), - visibility: call_or_use(visibility)) - schema.min_length = min_length - schema.max_length = max_length - schema.regular_expression = regular_expression - - schema - }, - writeable: false, - if: show_if, - required: required, - has_default: has_default, - name_source: lambda { - API::Decorators::SchemaRepresenter::InstanceMethods - .call_or_translate name_source, - self.represented_class - } + schema_property(property, + getter, + show_if, + required, + has_default, + name_source) end def schema_with_allowed_link(property, @@ -101,41 +91,30 @@ module API writable: default_writable_property(property), visibility: nil, show_if: true) - raise ArgumentError if property.nil? + getter = ->(*) do + schema_with_allowed_link_property_getter(type, + name_source, + required, + has_default, + writable, + visibility, + href_callback) + end - property property, - exec_context: :decorator, - getter: -> (*) { - representer = ::API::Decorators::AllowedValuesByLinkRepresenter.new( - type: type, - name: call_or_translate(name_source), - required: call_or_use(required), - has_default: call_or_use(has_default), - writable: call_or_use(writable), - visibility: call_or_use(visibility)) - - if form_embedded - representer.allowed_values_href = instance_eval(&href_callback) - end - - representer - }, - if: show_if, - required: required, - has_default: has_default, - name_source: lambda { - API::Decorators::SchemaRepresenter::InstanceMethods - .call_or_translate name_source, - self.represented_class - } + schema_property(property, + getter, + show_if, + required, + has_default, + name_source) end def schema_with_allowed_collection(property, type: make_type(property), name_source: property, - values_callback: -> { + values_callback: -> do represented.assignable_values(property, current_user) - }, + end, value_representer:, link_factory:, required: true, @@ -143,41 +122,30 @@ module API writable: default_writable_property(property), visibility: nil, show_if: true) - raise ArgumentError unless property - property property, - exec_context: :decorator, - getter: -> (*) { - representer = ::API::Decorators::AllowedValuesByCollectionRepresenter.new( - type: type, - name: call_or_translate(name_source), - current_user: current_user, - value_representer: value_representer, - link_factory: -> (value) { instance_exec(value, &link_factory) }, - required: call_or_use(required), - has_default: call_or_use(has_default), - writable: call_or_use(writable), - visibility: call_or_use(visibility)) - - if form_embedded - representer.allowed_values = instance_exec(&values_callback) - end - - representer - }, - if: show_if, - required: required, - has_default: has_default, - name_source: lambda { - API::Decorators::SchemaRepresenter::InstanceMethods - .call_or_translate name_source, - represented_class - } - end + getter = ->(*) do + schema_with_allowed_collection_getter(type, + name_source, + current_user, + value_representer, + link_factory, + required, + has_default, + writable, + visibility, + values_callback) + end - def represented_class + schema_property(property, + getter, + show_if, + required, + has_default, + name_source) end + def represented_class; end + private def make_type(property_name) @@ -193,6 +161,26 @@ module API end end end + + def schema_property(property, + getter, + show_if, + required, + has_default, + name_source) + raise ArgumentError unless property + + property property, + exec_context: :decorator, + getter: getter, + if: show_if, + required: required, + has_default: has_default, + name_source: lambda { + API::Decorators::SchemaRepresenter::InstanceMethods + .call_or_translate name_source, represented_class + } + end end include InstanceMethods @@ -220,6 +208,80 @@ module API def _type 'Schema' end + + def schema_property_getter(type, + name_source, + required, + has_default, + writable, + visibility, + min_length, + max_length, + regular_expression) + name = call_or_translate(name_source) + schema = ::API::Decorators::PropertySchemaRepresenter + .new(type: type, + name: name, + required: call_or_use(required), + has_default: call_or_use(has_default), + writable: call_or_use(writable), + visibility: call_or_use(visibility)) + schema.min_length = min_length + schema.max_length = max_length + schema.regular_expression = regular_expression + + schema + end + + def schema_with_allowed_link_property_getter(type, + name_source, + required, + has_default, + writable, + visibility, + href_callback) + representer = ::API::Decorators::AllowedValuesByLinkRepresenter + .new(type: type, + name: call_or_translate(name_source), + required: call_or_use(required), + has_default: call_or_use(has_default), + writable: call_or_use(writable), + visibility: call_or_use(visibility)) + + if form_embedded + representer.allowed_values_href = instance_eval(&href_callback) + end + + representer + end + + def schema_with_allowed_collection_getter(type, + name_source, + current_user, + value_representer, + link_factory, + required, + has_default, + writable, + visibility, + values_callback) + representer = ::API::Decorators::AllowedValuesByCollectionRepresenter + .new(type: type, + name: call_or_translate(name_source), + current_user: current_user, + value_representer: value_representer, + link_factory: ->(value) { instance_exec(value, &link_factory) }, + required: call_or_use(required), + has_default: call_or_use(has_default), + writable: call_or_use(writable), + visibility: call_or_use(visibility)) + + if form_embedded + representer.allowed_values = instance_exec(&values_callback) + end + + representer + end end end end diff --git a/lib/api/v3/queries/schemas/query_schema_representer.rb b/lib/api/v3/queries/schemas/query_schema_representer.rb index 130038f6ce..b9b20f48e5 100644 --- a/lib/api/v3/queries/schemas/query_schema_representer.rb +++ b/lib/api/v3/queries/schemas/query_schema_representer.rb @@ -63,7 +63,7 @@ module API required: false, writable: true, visibility: false, - href_callback: -> (*) { + href_callback: ->(*) { api_v3_paths.available_query_projects } schema :public, @@ -95,7 +95,7 @@ module API visibility: false, values_callback: -> { represented.available_columns }, value_representer: Columns::QueryColumnRepresenter, - link_factory: -> (column) { + link_factory: ->(column) { converted_name = convert_attribute(column.name) { @@ -118,7 +118,7 @@ module API visibility: false, values_callback: -> { represented.groupable_columns }, value_representer: GroupBys::QueryGroupByRepresenter, - link_factory: -> (column) { + link_factory: ->(column) { converted_name = convert_attribute(column.name) { @@ -142,7 +142,7 @@ module API values.flatten end, value_representer: SortBys::QuerySortByRepresenter, - link_factory: -> (sort_by) { + link_factory: ->(sort_by) { name = sort_by.converted_name direction = sort_by.direction_name { diff --git a/spec/lib/api/v3/utilities/custom_field_injector_spec.rb b/spec/lib/api/v3/utilities/custom_field_injector_spec.rb index 64a6fe29f7..fdde7b3084 100644 --- a/spec/lib/api/v3/utilities/custom_field_injector_spec.rb +++ b/spec/lib/api/v3/utilities/custom_field_injector_spec.rb @@ -33,12 +33,12 @@ describe ::API::V3::Utilities::CustomFieldInjector do let(:cf_path) { "customField#{custom_field.id}" } let(:field_format) { 'bool' } - let(:custom_field) { + let(:custom_field) do FactoryGirl.build(:custom_field, id: 1, field_format: field_format, is_required: true) - } + end describe 'TYPE_MAP' do it 'supports all available formats' do @@ -51,12 +51,12 @@ describe ::API::V3::Utilities::CustomFieldInjector do describe '#inject_schema' do let(:base_class) { Class.new(::API::Decorators::SchemaRepresenter) } let(:modified_class) { described_class.create_schema_representer(schema, base_class) } - let(:schema) { + let(:schema) do double('WorkPackageSchema', project: double(id: 42), defines_assignable_values?: true, available_custom_fields: [custom_field]) - } + end subject { modified_class.new(schema, current_user: nil, form_embedded: true).to_json } @@ -75,7 +75,8 @@ describe ::API::V3::Utilities::CustomFieldInjector do is_expected.not_to have_json_path("#{cf_path}/regularExpression") end - it_behaves_like 'indicates length requirements' # meaning they won't as no values are specified + # meaning they won't as no values are specified + it_behaves_like 'indicates length requirements' context 'custom field is not required' do let(:custom_field) { FactoryGirl.build(:custom_field, is_required: false) } @@ -111,10 +112,10 @@ describe ::API::V3::Utilities::CustomFieldInjector do end describe 'version custom field' do - let(:custom_field) { + let(:custom_field) do FactoryGirl.build(:version_wp_custom_field, is_required: true) - } + end let(:assignable_versions) { FactoryGirl.build_list(:version, 3) } @@ -157,11 +158,11 @@ describe ::API::V3::Utilities::CustomFieldInjector do .and_return(custom_field.possible_values) end - let(:custom_field) { + let(:custom_field) do FactoryGirl.build(:list_wp_custom_field, is_required: true, possible_values: values) - } + end let(:values) { ['foo', 'bar', 'baz'] } it_behaves_like 'has basic schema properties' do @@ -179,11 +180,11 @@ describe ::API::V3::Utilities::CustomFieldInjector do end describe 'user custom field' do - let(:custom_field) { + let(:custom_field) do FactoryGirl.build(:custom_field, field_format: 'user', is_required: true) - } + end it_behaves_like 'has basic schema properties' do let(:path) { cf_path } @@ -217,11 +218,11 @@ describe ::API::V3::Utilities::CustomFieldInjector do let(:base_class) { Class.new(::API::Decorators::Single) } let(:modified_class) { described_class.create_value_representer(represented, base_class) } - let(:represented) { + let(:represented) do double('represented', available_custom_fields: [custom_field], custom_field.accessor_name => value) - } + end let(:custom_value) { double('CustomValue', value: raw_value, typed_value: typed_value) } let(:raw_value) { nil } let(:typed_value) { raw_value } @@ -376,13 +377,13 @@ describe ::API::V3::Utilities::CustomFieldInjector do describe '#inject_patchable_link_value' do let(:base_class) { Class.new(::API::Decorators::Single) } - let(:modified_class) { + let(:modified_class) do described_class.create_value_representer_for_link_patching(represented, base_class) - } - let(:represented) { + end + let(:represented) do double('represented', available_custom_fields: [custom_field]) - } + end let(:custom_value) { double('CustomValue', value: value, typed_value: typed_value) } let(:value) { '' } let(:typed_value) { value } diff --git a/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb b/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb index c466287e7e..9537eba257 100644 --- a/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb +++ b/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb @@ -33,25 +33,25 @@ describe ::API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do let(:custom_field) { FactoryGirl.build(:custom_field) } let(:work_package) { FactoryGirl.build(:work_package) } - let(:current_user) { + let(:current_user) do FactoryGirl.build(:user, member_in_project: work_package.project) - } - let(:schema) { + end + let(:schema) do ::API::V3::WorkPackages::Schema::SpecificWorkPackageSchema.new(work_package: work_package) - } + end let(:self_link) { '/a/self/link' } let(:base_schema_link) { nil } let(:hide_self_link) { false } let(:embedded) { true } let(:action) { :update } - let(:representer) { + let(:representer) do described_class.create(schema, form_embedded: embedded, self_link: self_link, base_schema_link: base_schema_link, current_user: current_user, action: action) - } + end before do allow(schema).to receive(:writable?).and_call_original @@ -143,11 +143,11 @@ describe ::API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do end context 'lockVersion disabled' do - let(:representer) { + let(:representer) do described_class.create(schema, current_user: current_user, hide_lock_version: true) - } + end it 'is hidden' do is_expected.to_not have_json_path('lockVersion')