refactor: Rename and generalize #accessor_name as #attribute_name

Also extract #attribute_getter and #attribute_setter when
using #attribute_name in the context of calling the getter/setter
methods.
pull/11932/head
Christophe Bliard 2 years ago
parent f21c1efb2a
commit 10085736da
No known key found for this signature in database
GPG Key ID: 2BC07603210C3FA4
  1. 2
      app/contracts/base_contract.rb
  2. 4
      app/models/attribute_help_text/project.rb
  3. 4
      app/models/custom_actions/actions/custom_field.rb
  4. 2
      app/models/custom_actions/actions/strategies/custom_field.rb
  5. 4
      app/models/custom_actions/actions/strategies/user_custom_field.rb
  6. 12
      app/models/custom_field.rb
  7. 2
      app/models/queries/filters/shared/custom_field_filter.rb
  8. 2
      app/models/type/attributes.rb
  9. 4
      app/seeders/development_data/custom_fields_seeder.rb
  10. 2
      app/views/customizable/_form.html.erb
  11. 10
      lib/api/v3/utilities/custom_field_injector.rb
  12. 2
      lib/custom_field_form_builder.rb
  13. 17
      lib_static/plugins/acts_as_customizable/lib/acts_as_customizable.rb
  14. 2
      modules/costs/spec/lib/api/v3/time_entries/schemas/time_entry_schema_representer_spec.rb
  15. 4
      modules/costs/spec/lib/api/v3/time_entries/time_entry_representer_rendering_spec.rb
  16. 2
      modules/costs/spec/requests/api/time_entry_resource_spec.rb
  17. 16
      modules/dashboards/spec/features/project_details_spec.rb
  18. 2
      modules/reporting/spec/features/custom_fields_spec.rb
  19. 8
      modules/reporting/spec/models/cost_query/filter_spec.rb
  20. 2
      modules/reporting/spec/models/cost_query/group_by_spec.rb
  21. 6
      modules/xls_export/spec/models/xls_export/work_package/exporter/xls_integration_spec.rb
  22. 2
      spec/contracts/work_packages/update_contract_spec.rb
  23. 2
      spec/features/statuses/read_only_statuses_spec.rb
  24. 8
      spec/features/types/form_configuration_spec.rb
  25. 4
      spec/features/types/reset_form_configuration_spec.rb
  26. 16
      spec/features/work_packages/bulk/update_work_package_spec.rb
  27. 2
      spec/features/work_packages/custom_actions/custom_actions_spec.rb
  28. 2
      spec/features/work_packages/details/custom_fields/custom_field_spec.rb
  29. 2
      spec/features/work_packages/new/attributes_from_filter_spec.rb
  30. 4
      spec/features/work_packages/table/edit_work_packages_spec.rb
  31. 8
      spec/features/work_packages/table/queries/filter_spec.rb
  32. 4
      spec/features/work_packages/table/queries/me_filter_spec.rb
  33. 2
      spec/features/work_packages/table/switch_types_spec.rb
  34. 2
      spec/lib/api/v3/projects/project_representer_rendering_spec.rb
  35. 10
      spec/lib/api/v3/utilities/custom_field_injector_spec.rb
  36. 4
      spec/lib/api/v3/versions/version_representer_rendering_spec.rb
  37. 6
      spec/lib/api/v3/work_packages/eager_loading/custom_value_integration_spec.rb
  38. 6
      spec/lib/custom_field_form_builder_spec.rb
  39. 2
      spec/lib/open_project/changed_by_system_spec.rb
  40. 2
      spec/models/attribute_help_text/work_package_spec.rb
  41. 10
      spec/models/custom_actions/actions/custom_field_spec.rb
  42. 26
      spec/models/custom_field_spec.rb
  43. 4
      spec/models/custom_value/list_strategy_integration_spec.rb
  44. 16
      spec/models/projects/exporter/exportable_project_context.rb
  45. 18
      spec/models/query/results_spec.rb
  46. 16
      spec/models/query/results_sums_integration_spec.rb
  47. 12
      spec/models/type/attribute_groups_spec.rb
  48. 12
      spec/models/work_package/work_package_acts_as_customizable_spec.rb
  49. 2
      spec/models/work_package/work_package_custom_fields_spec.rb
  50. 2
      spec/models/work_package/work_package_multi_value_custom_fields_spec.rb
  51. 2
      spec/requests/api/v3/help_texts/help_texts_resource_spec.rb
  52. 8
      spec/requests/api/v3/projects/update_form_resource_spec.rb
  53. 4
      spec/requests/api/v3/projects/update_resource_spec.rb
  54. 4
      spec/requests/api/v3/user/update_form_resource_spec.rb
  55. 4
      spec/requests/api/v3/work_packages/form/work_package_form_resource_spec.rb
  56. 4
      spec/requests/api/v3/work_packages/update_resource_spec.rb
  57. 6
      spec/services/projects/copy_service_integration_spec.rb
  58. 6
      spec/services/projects/update_service_integration_spec.rb
  59. 6
      spec/services/shared_type_service.rb
  60. 6
      spec/services/work_packages/update_service_integration_spec.rb
  61. 8
      spec/support/shared/acts_as_customizable.rb

@ -227,7 +227,7 @@ class BaseContract < Disposable::Twin
end end
if model.respond_to?(:available_custom_fields) if model.respond_to?(:available_custom_fields)
writable += model.available_custom_fields.map { |cf| "custom_field_#{cf.id}" } writable += model.available_custom_fields.map(&:attribute_name)
end end
writable writable

@ -35,8 +35,8 @@ class AttributeHelpText::Project < AttributeHelpText
.reject { |key, _| skip.include?(key.to_s) } .reject { |key, _| skip.include?(key.to_s) }
.transform_values { |definition| definition[:name_source].call } .transform_values { |definition| definition[:name_source].call }
ProjectCustomField.all.find_each do |field| ProjectCustomField.find_each do |field|
attributes["custom_field_#{field.id}"] = field.name attributes[field.attribute_name] = field.name
end end
attributes attributes

@ -28,7 +28,7 @@
class CustomActions::Actions::CustomField < CustomActions::Actions::Base class CustomActions::Actions::CustomField < CustomActions::Actions::Base
def self.key def self.key
:"custom_field_#{custom_field.id}" custom_field.attribute_name.to_sym
end end
def self.custom_field def self.custom_field
@ -44,7 +44,7 @@ class CustomActions::Actions::CustomField < CustomActions::Actions::Base
end end
def apply(work_package) def apply(work_package)
work_package.send(:"#{custom_field.accessor_name}=", values) if work_package.respond_to?(:"#{custom_field.accessor_name}=") work_package.send(custom_field.attribute_setter, values) if work_package.respond_to?(custom_field.attribute_setter)
end end
def self.all def self.all

@ -28,7 +28,7 @@
module CustomActions::Actions::Strategies::CustomField module CustomActions::Actions::Strategies::CustomField
def apply(work_package) def apply(work_package)
work_package.send(:"#{custom_field.accessor_name}=", values) if work_package.respond_to?(:"#{custom_field.accessor_name}=") work_package.send(custom_field.attribute_setter, values) if work_package.respond_to?(custom_field.attribute_setter)
end end
delegate :required?, to: :custom_field delegate :required?, to: :custom_field

@ -31,8 +31,8 @@ module CustomActions::Actions::Strategies::UserCustomField
include ::CustomActions::Actions::Strategies::MeAssociated include ::CustomActions::Actions::Strategies::MeAssociated
def apply(work_package) def apply(work_package)
if work_package.respond_to?(:"#{custom_field.accessor_name}=") if work_package.respond_to?(custom_field.attribute_setter)
work_package.send(:"#{custom_field.accessor_name}=", transformed_value(values.first)) work_package.send(custom_field.attribute_setter, transformed_value(values.first))
end end
end end

@ -232,10 +232,18 @@ class CustomField < ApplicationRecord
where(is_filter: true) where(is_filter: true)
end end
def accessor_name def attribute_name
"custom_field_#{id}" "custom_field_#{id}"
end end
def attribute_getter
attribute_name.to_sym
end
def attribute_setter
:"#{attribute_name}="
end
def type_name def type_name
nil nil
end end
@ -325,7 +333,7 @@ class CustomField < ApplicationRecord
def destroy_help_text def destroy_help_text
AttributeHelpText AttributeHelpText
.where(attribute_name: "custom_field_#{id}") .where(attribute_name:)
.destroy_all .destroy_all
end end
end end

@ -40,7 +40,7 @@ module Queries::Filters::Shared::CustomFieldFilter
end end
## ##
# TODO this differs from CustomField#accessor_name for reasons I don't see, # TODO this differs from CustomField#attribute_name for reasons I don't see,
# however this name will be persisted in queries so we can't just map one to the other. # however this name will be persisted in queries so we can't just map one to the other.
def custom_field_accessor(custom_field) def custom_field_accessor(custom_field)
"cf_#{custom_field.id}" "cf_#{custom_field.id}"

@ -144,7 +144,7 @@ module Type::Attributes
def add_custom_fields_to_form_attributes(attributes) def add_custom_fields_to_form_attributes(attributes)
WorkPackageCustomField.includes(:custom_options).all.find_each do |field| WorkPackageCustomField.includes(:custom_options).all.find_each do |field|
attributes["custom_field_#{field.id}"] = { attributes[field.attribute_name] = {
required: field.is_required, required: field.is_required,
has_default: field.default_value.present?, has_default: field.default_value.present?,
is_cf: true, is_cf: true,

@ -44,14 +44,14 @@ module DevelopmentData
def create_types!(cfs) def create_types!(cfs)
# Create ALL CFs types # Create ALL CFs types
non_req_cfs = cfs.reject(&:is_required).map { |cf| "custom_field_#{cf.id}" } non_req_cfs = cfs.reject(&:is_required).map(&:attribute_name)
type = FactoryBot.build :type, name: 'All CFS' type = FactoryBot.build :type, name: 'All CFS'
extend_group(type, ['Custom fields', non_req_cfs]) extend_group(type, ['Custom fields', non_req_cfs])
type.save! type.save!
print_status '.' print_status '.'
# Create type # Create type
req_cfs = cfs.select(&:is_required).map { |cf| "custom_field_#{cf.id}" } req_cfs = cfs.select(&:is_required).map(&:attribute_name)
type_req = FactoryBot.build :type, name: 'Required CF' type_req = FactoryBot.build :type, name: 'Required CF'
extend_group(type_req, ['Custom fields', req_cfs]) extend_group(type_req, ['Custom fields', req_cfs])
type_req.save! type_req.save!

@ -45,7 +45,7 @@ See COPYRIGHT and LICENSE files for more details.
<% show_required = custom_field.is_required? && !custom_field.boolean? %> <% show_required = custom_field.is_required? && !custom_field.boolean? %>
<%= content_tag :div, <%= content_tag :div,
class: ['form--field', class: ['form--field',
"custom_field_#{custom_field.id}", custom_field.attribute_name,
(show_required ? '-required' : ''), (show_required ? '-required' : ''),
wide_labels] do wide_labels] do
options = { options = {

@ -219,7 +219,7 @@ module API
[value].compact [value].compact
end end
represented.send(:"custom_field_#{custom_field.id}=", values) represented.send(custom_field.attribute_setter, values)
} }
end end
@ -233,7 +233,7 @@ module API
custom_field.list? || custom_field.list? ||
custom_field.multi_value? custom_field.multi_value?
value = represented.send custom_field.accessor_name value = represented.send custom_field.attribute_getter
next unless value next unless value
@ -243,7 +243,7 @@ module API
end end
def inject_property_value(custom_field) def inject_property_value(custom_field)
@class.property "custom_field_#{custom_field.id}".to_sym, @class.property custom_field.attribute_name.to_sym,
as: property_name(custom_field.id), as: property_name(custom_field.id),
getter: property_value_getter_for(custom_field), getter: property_value_getter_for(custom_field),
setter: property_value_setter_for(custom_field), setter: property_value_setter_for(custom_field),
@ -254,7 +254,7 @@ module API
->(*) { ->(*) {
next unless available_custom_fields.include?(custom_field) next unless available_custom_fields.include?(custom_field)
value = send custom_field.accessor_name value = send(custom_field.attribute_getter)
if custom_field.field_format == 'text' if custom_field.field_format == 'text'
::API::Decorators::Formattable.new(value, object: self) ::API::Decorators::Formattable.new(value, object: self)
@ -271,7 +271,7 @@ module API
else else
fragment fragment
end end
send(:"custom_field_#{custom_field.id}=", value) send(custom_field.attribute_setter, value)
} }
end end

@ -58,7 +58,7 @@ class CustomFieldFormBuilder < TabularFormBuilder
private private
def custom_field_input(options = {}) def custom_field_input(options = {})
field = custom_field.accessor_name field = custom_field.attribute_name
input_options = options.merge(no_label: true, input_options = options.merge(no_label: true,
name: custom_field_field_name, name: custom_field_field_name,

@ -269,7 +269,7 @@ module Redmine
def add_custom_value_errors!(custom_value) def add_custom_value_errors!(custom_value)
custom_value.errors.each do |error| custom_value.errors.each do |error|
name = custom_value.custom_field.accessor_name.to_sym name = custom_value.custom_field.attribute_name.to_sym
details = error.details details = error.details
@ -319,15 +319,12 @@ module Redmine
end end
def add_custom_field_accessors(custom_field) def add_custom_field_accessors(custom_field)
getter_name = custom_field.accessor_name define_custom_field_getter(custom_field)
setter_name = "#{getter_name}=" define_custom_field_setter(custom_field)
define_custom_field_getter(getter_name, custom_field)
define_custom_field_setter(setter_name, custom_field)
end end
def define_custom_field_getter(getter_name, custom_field) def define_custom_field_getter(custom_field)
define_singleton_method getter_name do define_singleton_method custom_field.attribute_getter do
custom_values = Array(custom_value_for(custom_field)).map do |custom_value| custom_values = Array(custom_value_for(custom_field)).map do |custom_value|
custom_value ? custom_value.typed_value : nil custom_value ? custom_value.typed_value : nil
end end
@ -340,8 +337,8 @@ module Redmine
end end
end end
def define_custom_field_setter(setter_name, custom_field) def define_custom_field_setter(custom_field)
define_singleton_method setter_name do |value| define_singleton_method custom_field.attribute_setter do |value|
# N.B. we do no strict type checking here, it would be possible to assign a user # N.B. we do no strict type checking here, it would be possible to assign a user
# to an integer custom field... # to an integer custom field...
value = value.id if value.respond_to?(:id) value = value.id if value.respond_to?(:id)

@ -273,7 +273,7 @@ describe API::V3::TimeEntries::Schemas::TimeEntrySchemaRepresenter do
context 'for a custom value' do context 'for a custom value' do
let(:custom_field) { build_stubbed(:text_time_entry_custom_field) } let(:custom_field) { build_stubbed(:text_time_entry_custom_field) }
let(:path) { "customField#{custom_field.id}" } let(:path) { "customField#{custom_field.id}" }
let(:writable_attributes) { ["custom_field_#{custom_field.id}"] } let(:writable_attributes) { [custom_field.attribute_name] }
before do before do
allow(contract) allow(contract)

@ -125,7 +125,7 @@ describe API::V3::TimeEntries::TimeEntryRepresenter, 'rendering' do
.and_return([custom_field]) .and_return([custom_field])
allow(time_entry) allow(time_entry)
.to receive(:"custom_field_#{custom_field.id}") .to receive(custom_field.attribute_getter)
.and_return(user) .and_return(user)
allow(time_entry) allow(time_entry)
@ -268,7 +268,7 @@ describe API::V3::TimeEntries::TimeEntryRepresenter, 'rendering' do
.and_return([custom_field]) .and_return([custom_field])
allow(time_entry) allow(time_entry)
.to receive(:"custom_field_#{custom_field.id}") .to receive(custom_field.attribute_getter)
.and_return(custom_value.value) .and_return(custom_value.value)
end end

@ -438,7 +438,7 @@ describe 'API v3 time_entry resource' do
expect(new_entry.spent_on) expect(new_entry.spent_on)
.to eql Date.parse("2017-07-28") .to eql Date.parse("2017-07-28")
expect(new_entry.send(:"custom_field_#{custom_field.id}")) expect(new_entry.send(custom_field.attribute_getter))
.to eql 'some cf text' .to eql 'some cf text'
end end

@ -44,14 +44,14 @@ describe 'Project details widget on dashboard', js: true do
let!(:project) do let!(:project) do
create(:project, members: { other_user => role }).tap do |p| create(:project, members: { other_user => role }).tap do |p|
p.send(:"custom_field_#{int_cf.id}=", 5) p.send(int_cf.attribute_setter, 5)
p.send(:"custom_field_#{bool_cf.id}=", true) p.send(bool_cf.attribute_setter, true)
p.send(:"custom_field_#{version_cf.id}=", system_version) p.send(version_cf.attribute_setter, system_version)
p.send(:"custom_field_#{float_cf.id}=", 4.5) p.send(float_cf.attribute_setter, 4.5)
p.send(:"custom_field_#{text_cf.id}=", 'Some **long** text') p.send(text_cf.attribute_setter, 'Some **long** text')
p.send(:"custom_field_#{string_cf.id}=", 'Some small text') p.send(string_cf.attribute_setter, 'Some small text')
p.send(:"custom_field_#{date_cf.id}=", Date.today) p.send(date_cf.attribute_setter, Date.today)
p.send(:"custom_field_#{user_cf.id}=", other_user) p.send(user_cf.attribute_setter, other_user)
p.save!(validate: false) p.save!(validate: false)
end end

@ -180,7 +180,7 @@ describe 'Custom fields reporting', js: true do
end end
it 'groups by the raw values when an invalid value exists' do it 'groups by the raw values when an invalid value exists' do
expect(work_package2.send("custom_field_#{custom_field_2.id}")).to eq(['invalid not found']) expect(work_package2.send(custom_field_2.attribute_getter)).to eq(['invalid not found'])
expect(page).to have_selector('#group-by--add-columns') expect(page).to have_selector('#group-by--add-columns')
expect(page).to have_selector('#group-by--add-rows') expect(page).to have_selector('#group-by--add-rows')

@ -457,15 +457,15 @@ describe CostQuery, reporting_query_helper: true do
it "is usable as filter" do it "is usable as filter" do
create_searchable_fields_and_values create_searchable_fields_and_values
id = WorkPackageCustomField.find_by(name: "Searchable Field").id cf = WorkPackageCustomField.find_by(name: "Searchable Field")
query.filter "custom_field_#{id}".to_sym, operator: '=', value: "125" query.filter cf.attribute_name, operator: '=', value: "125"
expect(query.result.count).to eq(2) expect(query.result.count).to eq(2)
end end
it "is usable as filter #2" do it "is usable as filter #2" do
create_searchable_fields_and_values create_searchable_fields_and_values
id = WorkPackageCustomField.find_by(name: "Searchable Field").id cf = WorkPackageCustomField.find_by(name: "Searchable Field")
query.filter "custom_field_#{id}".to_sym, operator: '=', value: "finnlabs" query.filter cf.attribute_name, operator: '=', value: "finnlabs"
expect(query.result.count).to eq(0) expect(query.result.count).to eq(0)
end end
end end

@ -306,7 +306,7 @@ describe CostQuery, reporting_query_helper: true do
check_cache check_cache
query.group_by "custom_field_#{custom_field2.id}".to_sym query.group_by custom_field2.attribute_name
footprint = query.result.each_direct_result.map { |c| [c.count, c.units.to_i] }.sort footprint = query.result.each_direct_result.map { |c| [c.count, c.units.to_i] }.sort
expect(footprint).to eq([[8, 8]]) expect(footprint).to eq([[8, 8]])
end end

@ -187,11 +187,11 @@ describe XlsExport::WorkPackage::Exporter::XLS do
type:) type:)
wps[0].estimated_hours = 27.5 wps[0].estimated_hours = 27.5
wps[0].save! wps[0].save!
wps[1].send(:"custom_field_#{custom_field.id}=", 1) wps[1].send(custom_field.attribute_setter, 1)
wps[1].save! wps[1].save!
wps[2].send(:"custom_field_#{custom_field.id}=", 99.99) wps[2].send(custom_field.attribute_setter, 99.99)
wps[2].save! wps[2].save!
wps[3].send(:"custom_field_#{custom_field.id}=", 1000) wps[3].send(custom_field.attribute_setter, 1000)
wps[3].save! wps[3].save!
wps wps
end end

@ -419,7 +419,7 @@ describe WorkPackages::UpdateContract do
shared_examples_for 'custom_field readonly errors' do shared_examples_for 'custom_field readonly errors' do
it 'adds an error to the written custom field attribute' do it 'adds an error to the written custom field attribute' do
expect(contract.errors.symbols_for(:"custom_field_#{cf1.id}")) expect(contract.errors.symbols_for(cf1.attribute_name.to_sym))
.to include(:error_readonly) .to include(:error_readonly)
end end

@ -102,7 +102,7 @@ describe 'Read-only statuses affect work package editing',
assignee_field.label_element.click assignee_field.label_element.click
assignee_field.expect_inactive! assignee_field.expect_inactive!
custom_field = wp_page.edit_field cf_all.accessor_name.camelcase(:lower) custom_field = wp_page.edit_field cf_all.attribute_name.camelcase(:lower)
custom_field.label_element.click custom_field.label_element.click
custom_field.expect_inactive! custom_field.expect_inactive!
end end

@ -249,8 +249,8 @@ describe 'form configuration', js: true do
describe 'required custom field' do describe 'required custom field' do
let(:custom_fields) { [custom_field] } let(:custom_fields) { [custom_field] }
let(:custom_field) { create(:integer_issue_custom_field, is_required: true, name: 'MyNumber') } let(:custom_field) { create(:integer_issue_custom_field, is_required: true, name: 'MyNumber') }
let(:cf_identifier) { "custom_field_#{custom_field.id}" } let(:cf_identifier) { custom_field.attribute_name }
let(:cf_identifier_api) { "customField#{custom_field.id}" } let(:cf_identifier_api) { cf_identifier.camelcase(:lower) }
before do before do
project project
@ -279,8 +279,8 @@ describe 'form configuration', js: true do
let(:custom_fields) { [custom_field] } let(:custom_fields) { [custom_field] }
let(:custom_field) { create(:integer_issue_custom_field, name: 'MyNumber') } let(:custom_field) { create(:integer_issue_custom_field, name: 'MyNumber') }
let(:cf_identifier) { "custom_field_#{custom_field.id}" } let(:cf_identifier) { custom_field.attribute_name }
let(:cf_identifier_api) { "customField#{custom_field.id}" } let(:cf_identifier_api) { cf_identifier.camelcase(:lower) }
before do before do
project project

@ -39,8 +39,8 @@ describe 'Reset form configuration', js: true do
describe "with EE token and CFs" do describe "with EE token and CFs" do
let(:custom_fields) { [custom_field] } let(:custom_fields) { [custom_field] }
let(:custom_field) { create(:integer_issue_custom_field, is_required: true, name: 'MyNumber') } let(:custom_field) { create(:integer_issue_custom_field, is_required: true, name: 'MyNumber') }
let(:cf_identifier) { "custom_field_#{custom_field.id}" } let(:cf_identifier) { custom_field.attribute_name }
let(:cf_identifier_api) { "customField#{custom_field.id}" } let(:cf_identifier_api) { cf_identifier.camelcase(:lower) }
before do before do
with_enterprise_token(:edit_attribute_groups) with_enterprise_token(:edit_attribute_groups)

@ -144,8 +144,8 @@ describe 'Bulk update work packages through Rails view', js: true do
context 'with enterprise', with_ee: [:readonly_work_packages] do context 'with enterprise', with_ee: [:readonly_work_packages] do
it 'does not update the work packages' do it 'does not update the work packages' do
expect(work_package.send(custom_field.accessor_name)).to be_nil expect(work_package.send(custom_field.attribute_getter)).to be_nil
expect(work_package2.send(custom_field.accessor_name)).to be_nil expect(work_package2.send(custom_field.attribute_getter)).to be_nil
fill_in custom_field.name, with: 'Custom field text' fill_in custom_field.name, with: 'Custom field text'
click_on 'Submit' click_on 'Submit'
@ -170,18 +170,18 @@ describe 'Bulk update work packages through Rails view', js: true do
work_package.reload work_package.reload
work_package2.reload work_package2.reload
expect(work_package.send(custom_field.accessor_name)) expect(work_package.send(custom_field.attribute_getter))
.to eq('Custom field text') .to eq('Custom field text')
expect(work_package2.send(custom_field.accessor_name)) expect(work_package2.send(custom_field.attribute_getter))
.to be_nil .to be_nil
end end
end end
context 'without enterprise', with_ee: false do context 'without enterprise', with_ee: false do
it 'ignores the readonly status and updates the work packages' do it 'ignores the readonly status and updates the work packages' do
expect(work_package.send(custom_field.accessor_name)).to be_nil expect(work_package.send(custom_field.attribute_getter)).to be_nil
expect(work_package2.send(custom_field.accessor_name)).to be_nil expect(work_package2.send(custom_field.attribute_getter)).to be_nil
fill_in custom_field.name, with: 'Custom field text' fill_in custom_field.name, with: 'Custom field text'
click_on 'Submit' click_on 'Submit'
@ -192,10 +192,10 @@ describe 'Bulk update work packages through Rails view', js: true do
work_package.reload work_package.reload
work_package2.reload work_package2.reload
expect(work_package.send(custom_field.accessor_name)) expect(work_package.send(custom_field.attribute_getter))
.to eq('Custom field text') .to eq('Custom field text')
expect(work_package2.send(custom_field.accessor_name)) expect(work_package2.send(custom_field.attribute_getter))
.to eq('Custom field text') .to eq('Custom field text')
end end
end end

@ -241,7 +241,7 @@ describe 'Custom actions', js: true do
# This custom field is not applicable # This custom field is not applicable
new_ca_page.add_action(int_custom_field.name, '1') new_ca_page.add_action(int_custom_field.name, '1')
new_ca_page.expect_action("custom_field_#{int_custom_field.id}", '1') new_ca_page.expect_action(int_custom_field.attribute_name, '1')
new_ca_page.set_condition('Status', closed_status.name) new_ca_page.set_condition('Status', closed_status.name)
new_ca_page.expect_selected_option closed_status.name new_ca_page.expect_selected_option closed_status.name

@ -188,7 +188,7 @@ describe 'custom field inplace editor', js: true do
field.save! field.save!
work_package.reload work_package.reload
expect(work_package.send("custom_field_#{custom_field.id}")).to eq 123 expect(work_package.send(custom_field.attribute_getter)).to eq 123
end end
end end
end end

@ -104,7 +104,7 @@ RSpec.describe 'Work package create uses attributes from filters', js: true, sel
) )
wp = WorkPackage.last wp = WorkPackage.last
expect(wp.subject).to eq 'Foobar!' expect(wp.subject).to eq 'Foobar!'
expect(wp.send("custom_field_#{custom_field.id}")).to eq %w(A) expect(wp.send(custom_field.attribute_getter)).to eq %w(A)
expect(wp.type_id).to eq type_task.id expect(wp.type_id).to eq type_task.id
end end
end end

@ -193,8 +193,8 @@ describe 'Inline editing work packages', js: true do
) )
work_package.reload work_package.reload
expect(work_package.send(custom_fields.first.accessor_name)).to eq('bar') expect(work_package.send(custom_fields.first.attribute_getter)).to eq('bar')
expect(work_package.send(custom_fields.last.accessor_name)).to eq('my custom text') expect(work_package.send(custom_fields.last.attribute_getter)).to eq('my custom text')
# Saveguard to let the background update complete # Saveguard to let the background update complete
wp_table.visit! wp_table.visit!

@ -216,14 +216,14 @@ describe 'filter work packages', js: true do
let(:work_package_with_list_value) do let(:work_package_with_list_value) do
wp = create :work_package, project: project, type: type wp = create :work_package, project: project, type: type
wp.send("#{list_cf.accessor_name}=", list_cf.custom_options.first.id) wp.send(list_cf.attribute_setter, list_cf.custom_options.first.id)
wp.save! wp.save!
wp wp
end end
let(:work_package_with_anti_list_value) do let(:work_package_with_anti_list_value) do
wp = create :work_package, project: project, type: type wp = create :work_package, project: project, type: type
wp.send("#{list_cf.accessor_name}=", list_cf.custom_options.last.id) wp.send(list_cf.attribute_setter, list_cf.custom_options.last.id)
wp.save! wp.save!
wp wp
end end
@ -294,14 +294,14 @@ describe 'filter work packages', js: true do
let(:work_package_plus) do let(:work_package_plus) do
wp = create :work_package, project: project, type: type wp = create :work_package, project: project, type: type
wp.send("#{string_cf.accessor_name}=", 'G+H') wp.send(string_cf.attribute_setter, 'G+H')
wp.save! wp.save!
wp wp
end end
let(:work_package_and) do let(:work_package_and) do
wp = create :work_package, project: project, type: type wp = create :work_package, project: project, type: type
wp.send("#{string_cf.accessor_name}=", 'A&B') wp.send(string_cf.attribute_setter, 'A&B')
wp.save! wp.save!
wp wp
end end

@ -147,8 +147,8 @@ describe 'filter me value', js: true do
members: project_members) members: project_members)
end end
let(:cf_accessor) { "cf_#{custom_field.id}" } let(:cf_accessor) { custom_field.attribute_name }
let(:cf_accessor_frontend) { "customField#{custom_field.id}" } let(:cf_accessor_frontend) { cf_accessor.camelcase(:lower) }
let(:wp_admin) do let(:wp_admin) do
create :work_package, create :work_package,
type: type_task, type: type_task,

@ -257,7 +257,7 @@ describe 'Switching types in work package table', js: true do
work_package.reload work_package.reload
expect(work_package.type_id).to eq(type_bug.id) expect(work_package.type_id).to eq(type_bug.id)
expect(work_package.send("custom_field_#{cf_req_bool.id}")).to be(false) expect(work_package.send(cf_req_bool.attribute_getter)).to be(false)
end end
end end

@ -43,7 +43,7 @@ describe API::V3::Projects::ProjectRepresenter, 'rendering' do
.and_return([int_custom_field, version_custom_field]) .and_return([int_custom_field, version_custom_field])
allow(p) allow(p)
.to receive(:"custom_field_#{int_custom_field.id}") .to receive(int_custom_field.attribute_getter)
.and_return(int_custom_value.value) .and_return(int_custom_value.value)
allow(p) allow(p)

@ -333,7 +333,7 @@ describe API::V3::Utilities::CustomFieldInjector do
it 'on writing it sets on the represented' do it 'on writing it sets on the represented' do
expected = { custom_field.id => expected_setter } expected = { custom_field.id => expected_setter }
expect(represented) expect(represented)
.to receive(:"custom_field_#{custom_field.id}=") .to receive(custom_field.attribute_setter)
.with(expected_setter) .with(expected_setter)
modified_class modified_class
.new(represented, current_user: nil) .new(represented, current_user: nil)
@ -346,7 +346,7 @@ describe API::V3::Utilities::CustomFieldInjector do
let(:represented) do let(:represented) do
double('represented', double('represented',
available_custom_fields: [custom_field], available_custom_fields: [custom_field],
custom_field.accessor_name => value) custom_field.attribute_name => value)
end end
let(:custom_value) { double('CustomValue', value: raw_value, typed_value:) } let(:custom_value) { double('CustomValue', value: raw_value, typed_value:) }
let(:raw_value) { nil } let(:raw_value) { nil }
@ -539,7 +539,7 @@ describe API::V3::Utilities::CustomFieldInjector do
before do before do
allow(represented).to receive(:custom_value_for).with(custom_field).and_return(custom_value) allow(represented).to receive(:custom_value_for).with(custom_field).and_return(custom_value)
allow(represented).to receive(:"custom_field_#{custom_field.id}").and_return(typed_value) allow(represented).to receive(custom_field.attribute_getter).and_return(typed_value)
end end
context 'reading' do context 'reading' do
@ -578,7 +578,7 @@ describe API::V3::Utilities::CustomFieldInjector do
json = { cf_path => { href: path } }.to_json json = { cf_path => { href: path } }.to_json
expected = ['2'] expected = ['2']
expect(represented).to receive(:"custom_field_#{custom_field.id}=").with(expected) expect(represented).to receive(custom_field.attribute_setter).with(expected)
modified_class.new(represented, current_user: nil).from_json(json) modified_class.new(represented, current_user: nil).from_json(json)
end end
end end
@ -587,7 +587,7 @@ describe API::V3::Utilities::CustomFieldInjector do
json = { cf_path => { href: nil } }.to_json json = { cf_path => { href: nil } }.to_json
expected = [] expected = []
expect(represented).to receive(:"custom_field_#{custom_field.id}=").with(expected) expect(represented).to receive(custom_field.attribute_setter).with(expected)
modified_class.new(represented, current_user: nil).from_json(json) modified_class.new(represented, current_user: nil).from_json(json)
end end
end end

@ -211,7 +211,7 @@ describe API::V3::Versions::VersionRepresenter, 'rendering' do
.and_return([custom_field]) .and_return([custom_field])
allow(version) allow(version)
.to receive(:"custom_field_#{custom_field.id}") .to receive(custom_field.attribute_getter)
.and_return(custom_value.value) .and_return(custom_value.value)
end end
@ -283,7 +283,7 @@ describe API::V3::Versions::VersionRepresenter, 'rendering' do
.and_return([custom_field]) .and_return([custom_field])
allow(version) allow(version)
.to receive(:"custom_field_#{custom_field.id}") .to receive(custom_field.attribute_getter)
.and_return('123') .and_return('123')
end end

@ -118,11 +118,11 @@ describe API::V3::WorkPackages::EagerLoading::CustomValue do
type_project_user_cf, type_project_user_cf,
for_all_type_cf] for_all_type_cf]
expect(work_package.send(:"custom_field_#{type_project_version_cf.id}")) expect(work_package.send(type_project_version_cf.attribute_getter))
.to eql version .to eql version
expect(work_package.send(:"custom_field_#{type_project_list_cf.id}")) expect(work_package.send(type_project_list_cf.attribute_getter))
.to eql type_project_list_cf.custom_options.last.name .to eql type_project_list_cf.custom_options.last.name
expect(work_package.send(:"custom_field_#{type_project_user_cf.id}")) expect(work_package.send(type_project_user_cf.attribute_getter))
.to eql user .to eql user
end end
end end

@ -59,7 +59,7 @@ describe CustomFieldFormBuilder do
before do before do
allow(resource) allow(resource)
.to receive(custom_field.accessor_name) .to receive(custom_field.attribute_getter)
.and_return(typed_value) .and_return(typed_value)
end end
@ -256,7 +256,7 @@ describe CustomFieldFormBuilder do
custom_field.field_format = 'user' custom_field.field_format = 'user'
allow(project) allow(project)
.to receive(custom_field.accessor_name) .to receive(custom_field.attribute_getter)
.and_return typed_value .and_return typed_value
allow(project) allow(project)
@ -311,7 +311,7 @@ describe CustomFieldFormBuilder do
before do before do
custom_field.field_format = 'version' custom_field.field_format = 'version'
allow(project) allow(project)
.to receive(custom_field.accessor_name) .to receive(custom_field.attribute_getter)
.and_return typed_value .and_return typed_value
allow(project) allow(project)

@ -109,7 +109,7 @@ describe OpenProject::ChangedBySystem do
it 'returns the custom fields too' do it 'returns the custom fields too' do
model.custom_field_values = { cf1.id => 'test' } model.custom_field_values = { cf1.id => 'test' }
expect(model.changed_by_user) expect(model.changed_by_user)
.to include("custom_field_#{cf1.id}") .to include(cf1.attribute_name)
end end
end end
end end

@ -35,7 +35,7 @@ describe AttributeHelpText::WorkPackage do
# need to clear the cache to free the memoized # need to clear the cache to free the memoized
# Type.translated_work_package_form_attributes # Type.translated_work_package_form_attributes
Rails.cache.clear Rails.cache.clear
create(:work_package_help_text, attribute_name: "custom_field_#{custom_field.id}") create(:work_package_help_text, attribute_name: custom_field.attribute_name)
end end
let(:wp_custom_field) { create :text_wp_custom_field } let(:wp_custom_field) { create :text_wp_custom_field }

@ -85,7 +85,7 @@ describe CustomActions::Actions::CustomField do
.with(id: custom_field.id.to_s) .with(id: custom_field.id.to_s)
.and_return(custom_field) .and_return(custom_field)
described_class.for(:"custom_field_#{custom_field.id}") described_class.for(custom_field.attribute_name)
end end
let(:instance) do let(:instance) do
klass.new klass.new
@ -113,14 +113,14 @@ describe CustomActions::Actions::CustomField do
describe '.key' do describe '.key' do
it 'is the custom field accessor' do it 'is the custom field accessor' do
expect(klass.key) expect(klass.key)
.to eql(:"custom_field_#{custom_field.id}") .to eql(custom_field.attribute_getter)
end end
end end
describe '#key' do describe '#key' do
it 'is the custom field accessor' do it 'is the custom field accessor' do
expect(instance.key) expect(instance.key)
.to eql(:"custom_field_#{custom_field.id}") .to eql(custom_field.attribute_getter)
end end
end end
@ -587,7 +587,7 @@ describe CustomActions::Actions::CustomField do
it "sets the value for #{type} custom fields" do it "sets the value for #{type} custom fields" do
expect(work_package) expect(work_package)
.to receive(:"custom_field_#{custom_field.id}=") .to receive(custom_field.attribute_setter)
.with([42]) .with([42])
instance.values = 42 instance.values = 42
@ -601,7 +601,7 @@ describe CustomActions::Actions::CustomField do
it "sets the value to today for a dynamic value" do it "sets the value to today for a dynamic value" do
expect(work_package) expect(work_package)
.to receive(:"custom_field_#{custom_field.id}=") .to receive(custom_field.attribute_setter)
.with(Date.today) .with(Date.today)
instance.values = '%CURRENT_DATE%' instance.values = '%CURRENT_DATE%'

@ -183,12 +183,28 @@ describe CustomField do
end end
end end
describe '#accessor_name' do describe '#attribute_name' do
let(:field) { build_stubbed :custom_field } let(:field) { build_stubbed(:custom_field) }
it 'is formatted as expected' do subject { field.attribute_name }
expect(field.accessor_name).to eql("custom_field_#{field.id}")
end it { is_expected.to eq("custom_field_#{field.id}") }
end
describe '#attribute_getter' do
let(:field) { build_stubbed(:custom_field) }
subject { field.attribute_getter }
it { is_expected.to eq(:"custom_field_#{field.id}") }
end
describe '#attribute_setter' do
let(:field) { build_stubbed(:custom_field) }
subject { field.attribute_setter }
it { is_expected.to eq(:"custom_field_#{field.id}=") }
end end
describe '#possible_values_options' do describe '#possible_values_options' do

@ -50,13 +50,13 @@ describe CustomValue::ListStrategy, 'integration tests' do
end end
it 'can handle invalid CustomOptions (Regression test)' do it 'can handle invalid CustomOptions (Regression test)' do
expect(work_package.public_send(:"custom_field_#{custom_field.id}")).to eq(%w(A)) expect(work_package.public_send(custom_field.attribute_getter)).to eq(%w(A))
# Remove the custom value without replacement # Remove the custom value without replacement
CustomValue.find_by(customized_id: work_package.id).update_columns(value: 'invalid') CustomValue.find_by(customized_id: work_package.id).update_columns(value: 'invalid')
work_package.reload work_package.reload
work_package.reset_custom_values! work_package.reset_custom_values!
expect(work_package.public_send(:"custom_field_#{custom_field.id}")).to eq(['invalid not found']) expect(work_package.public_send(custom_field.attribute_getter)).to eq(['invalid not found'])
end end
end end

@ -51,14 +51,14 @@ shared_context 'with a project with an arrangement of custom fields' do
shared_let(:project) do shared_let(:project) do
create(:project, members: { other_user => role }).tap do |p| create(:project, members: { other_user => role }).tap do |p|
p.description = "The description of the project" p.description = "The description of the project"
p.send(:"custom_field_#{int_cf.id}=", 5) p.send(int_cf.attribute_setter, 5)
p.send(:"custom_field_#{bool_cf.id}=", true) p.send(bool_cf.attribute_setter, true)
p.send(:"custom_field_#{version_cf.id}=", system_version) p.send(version_cf.attribute_setter, system_version)
p.send(:"custom_field_#{float_cf.id}=", 4.5) p.send(float_cf.attribute_setter, 4.5)
p.send(:"custom_field_#{text_cf.id}=", 'Some **long** text') p.send(text_cf.attribute_setter, 'Some **long** text')
p.send(:"custom_field_#{string_cf.id}=", 'Some small text') p.send(string_cf.attribute_setter, 'Some small text')
p.send(:"custom_field_#{date_cf.id}=", Time.zone.today) p.send(date_cf.attribute_setter, Time.zone.today)
p.send(:"custom_field_#{user_cf.id}=", other_user) p.send(user_cf.attribute_setter, other_user)
p.build_status(code: :off_track) p.build_status(code: :off_track)

@ -196,10 +196,10 @@ describe Query::Results, with_mail: false do
before do before do
login_as(user1) login_as(user1)
work_package1.send(:"custom_field_#{custom_field.id}=", first_value) work_package1.send(custom_field.attribute_setter, first_value)
work_package1.save! work_package1.save!
work_package2.send(:"custom_field_#{custom_field.id}=", [first_value, work_package2.send(custom_field.attribute_setter, [first_value,
last_value]) last_value])
work_package2.save! work_package2.save!
end end
@ -229,9 +229,9 @@ describe Query::Results, with_mail: false do
wp_p1[0].type.custom_fields << custom_field wp_p1[0].type.custom_fields << custom_field
project1.work_package_custom_fields << custom_field project1.work_package_custom_fields << custom_field
wp_p1[0].update_attribute(:"custom_field_#{custom_field.id}", 42) wp_p1[0].update_attribute(custom_field.attribute_name, 42)
wp_p1[0].save wp_p1[0].save
wp_p1[1].update_attribute(:"custom_field_#{custom_field.id}", 42) wp_p1[1].update_attribute(custom_field.attribute_name, 42)
wp_p1[1].save wp_p1[1].save
end end
@ -272,9 +272,9 @@ describe Query::Results, with_mail: false do
wp_p1[0].type.custom_fields << custom_field wp_p1[0].type.custom_fields << custom_field
project1.work_package_custom_fields << custom_field project1.work_package_custom_fields << custom_field
wp_p1[0].update_attribute(:"custom_field_#{custom_field.id}", true) wp_p1[0].update_attribute(custom_field.attribute_name, true)
wp_p1[0].save wp_p1[0].save
wp_p1[1].update_attribute(:"custom_field_#{custom_field.id}", true) wp_p1[1].update_attribute(custom_field.attribute_name, true)
wp_p1[1].save wp_p1[1].save
end end
@ -296,9 +296,9 @@ describe Query::Results, with_mail: false do
wp_p1[0].type.custom_fields << custom_field wp_p1[0].type.custom_fields << custom_field
project1.work_package_custom_fields << custom_field project1.work_package_custom_fields << custom_field
wp_p1[0].update_attribute(:"custom_field_#{custom_field.id}", Time.zone.today) wp_p1[0].update_attribute(custom_field.attribute_name, Time.zone.today)
wp_p1[0].save wp_p1[0].save
wp_p1[1].update_attribute(:"custom_field_#{custom_field.id}", Time.zone.today) wp_p1[1].update_attribute(custom_field.attribute_name, Time.zone.today)
wp_p1[1].save wp_p1[1].save
end end

@ -55,8 +55,8 @@ describe Query::Results, 'sums' do
project:, project:,
estimated_hours: 5, estimated_hours: 5,
done_ratio: 10, done_ratio: 10,
"custom_field_#{int_cf.id}" => 10, int_cf.attribute_name => 10,
"custom_field_#{float_cf.id}" => 3.414, float_cf.attribute_name => 3.414,
remaining_hours: 3, remaining_hours: 3,
story_points: 7) story_points: 7)
end end
@ -67,8 +67,8 @@ describe Query::Results, 'sums' do
assigned_to: current_user, assigned_to: current_user,
done_ratio: 50, done_ratio: 50,
estimated_hours: 5, estimated_hours: 5,
"custom_field_#{int_cf.id}" => 10, int_cf.attribute_name => 10,
"custom_field_#{float_cf.id}" => 3.414, float_cf.attribute_name => 3.414,
remaining_hours: 3, remaining_hours: 3,
story_points: 7) story_points: 7)
end end
@ -80,8 +80,8 @@ describe Query::Results, 'sums' do
responsible: current_user, responsible: current_user,
done_ratio: 50, done_ratio: 50,
estimated_hours: 5, estimated_hours: 5,
"custom_field_#{int_cf.id}" => 10, int_cf.attribute_name => 10,
"custom_field_#{float_cf.id}" => 3.414, float_cf.attribute_name => 3.414,
remaining_hours: 3, remaining_hours: 3,
story_points: 7) story_points: 7)
end end
@ -90,8 +90,8 @@ describe Query::Results, 'sums' do
type:, type:,
project: other_project, project: other_project,
estimated_hours: 5, estimated_hours: 5,
"custom_field_#{int_cf.id}" => 10, int_cf.attribute_name => 10,
"custom_field_#{float_cf.id}" => 3.414, float_cf.attribute_name => 3.414,
remaining_hours: 3, remaining_hours: 3,
story_points: 7) story_points: 7)
end end

@ -163,7 +163,7 @@ describe Type do
) )
end end
let(:cf_identifier) do let(:cf_identifier) do
:"custom_field_#{custom_field.id}" custom_field.attribute_name
end end
it 'can be put into attribute groups' do it 'can be put into attribute groups' do
@ -171,7 +171,7 @@ describe Type do
OpenProject::Cache.clear OpenProject::Cache.clear
# Can be enabled # Can be enabled
type.attribute_groups = [['foo', [cf_identifier.to_s]]] type.attribute_groups = [['foo', [cf_identifier]]]
expect(type.save).to be_truthy expect(type.save).to be_truthy
expect(type.read_attribute(:attribute_groups)).not_to be_empty expect(type.read_attribute(:attribute_groups)).not_to be_empty
end end
@ -184,7 +184,7 @@ describe Type do
) )
end end
let(:cf_identifier2) do let(:cf_identifier2) do
:"custom_field_#{custom_field2.id}" custom_field2.attribute_name
end end
it 'they are kept in their respective positions in the group (Regression test #27940)' do it 'they are kept in their respective positions in the group (Regression test #27940)' do
@ -192,12 +192,12 @@ describe Type do
OpenProject::Cache.clear OpenProject::Cache.clear
# Can be enabled # Can be enabled
type.attribute_groups = [['foo', [cf_identifier2.to_s, cf_identifier.to_s]]] type.attribute_groups = [['foo', [cf_identifier2, cf_identifier]]]
expect(type.save).to be_truthy expect(type.save).to be_truthy
expect(type.read_attribute(:attribute_groups)).not_to be_empty expect(type.read_attribute(:attribute_groups)).not_to be_empty
cf_group = type.attribute_groups[0] cf_group = type.attribute_groups[0]
expect(cf_group.members).to eq([cf_identifier2.to_s, cf_identifier.to_s]) expect(cf_group.members).to eq([cf_identifier2, cf_identifier])
end end
end end
end end
@ -220,7 +220,7 @@ describe Type do
other_group = type.attribute_groups.detect { |g| g.key == :other } other_group = type.attribute_groups.detect { |g| g.key == :other }
expect(other_group).to be_present expect(other_group).to be_present
expect(other_group.attributes).to eq([custom_field.accessor_name]) expect(other_group.attributes).to eq([custom_field.attribute_name])
# It is removed again when resetting it # It is removed again when resetting it
type.reset_attribute_groups type.reset_attribute_groups

@ -67,7 +67,7 @@ describe WorkPackage, 'acts_as_customizable' do
end end
it 'sets the value' do it 'sets the value' do
expect(wp_with_assignee_cf.send(version_cf.accessor_name)) expect(wp_with_assignee_cf.send(version_cf.attribute_getter))
.to eql version .to eql version
end end
end end
@ -85,19 +85,19 @@ describe WorkPackage, 'acts_as_customizable' do
end end
it 'says to respond to valid custom field accessors' do it 'says to respond to valid custom field accessors' do
expect(work_package).to respond_to(included_cf.accessor_name) expect(work_package).to respond_to(included_cf.attribute_getter)
end end
it 'really responds to valid custom field accessors' do it 'really responds to valid custom field accessors' do
expect(work_package.send(included_cf.accessor_name)).to be_nil expect(work_package.send(included_cf.attribute_getter)).to be_nil
end end
it 'says to not respond to foreign custom field accessors' do it 'says to not respond to foreign custom field accessors' do
expect(work_package).not_to respond_to(other_cf.accessor_name) expect(work_package).not_to respond_to(other_cf.attribute_getter)
end end
it 'does really not respond to foreign custom field accessors' do it 'does really not respond to foreign custom field accessors' do
expect { work_package.send(other_cf.accessor_name) }.to raise_error(NoMethodError) expect { work_package.send(other_cf.attribute_getter) }.to raise_error(NoMethodError)
end end
end end
@ -125,7 +125,7 @@ describe WorkPackage, 'acts_as_customizable' do
# assert that there is only one error # assert that there is only one error
expect(work_package.errors.size).to eq 1 expect(work_package.errors.size).to eq 1
expect(work_package.errors["custom_field_#{cf2.id}"].size).to eq 1 expect(work_package.errors[cf2.attribute_name].size).to eq 1
end end
end end

@ -145,7 +145,7 @@ describe WorkPackage do
describe 'invalid custom field values' do describe 'invalid custom field values' do
context 'short error message' do context 'short error message' do
shared_examples_for 'custom field with invalid value' do shared_examples_for 'custom field with invalid value' do
let(:custom_field_key) { "custom_field_#{custom_field.id}".to_sym } let(:custom_field_key) { custom_field.attribute_name.to_sym }
before do before do
change_custom_field_value(work_package, custom_field_value) change_custom_field_value(work_package, custom_field_value)

@ -97,7 +97,7 @@ describe WorkPackage do
work_package.custom_field_values = { custom_field.id => ids } work_package.custom_field_values = { custom_field.id => ids }
work_package.save work_package.save
expect(work_package.send("custom_field_#{custom_field.id}")) expect(work_package.send(custom_field.attribute_getter))
.to eql values .to eql values
end end
end end

@ -51,7 +51,7 @@ describe 'API v3 Help texts resource' do
[ [
create(:work_package_help_text, attribute_name: 'assignee'), create(:work_package_help_text, attribute_name: 'assignee'),
create(:work_package_help_text, attribute_name: 'status'), create(:work_package_help_text, attribute_name: 'status'),
create(:work_package_help_text, attribute_name: "custom_field_#{custom_field.id}") create(:work_package_help_text, attribute_name: custom_field.attribute_name)
] ]
end end

@ -34,8 +34,8 @@ describe API::V3::Projects::UpdateFormAPI, content_type: :json do
let(:project) do let(:project) do
create(:project, create(:project,
"custom_field_#{text_custom_field.id}": "CF text", text_custom_field.attribute_name => "CF text",
"custom_field_#{list_custom_field.id}": list_custom_field.custom_options.first) list_custom_field.attribute_name => list_custom_field.custom_options.first)
end end
let(:current_user) do let(:current_user) do
create(:user, create(:user,
@ -224,10 +224,10 @@ describe API::V3::Projects::UpdateFormAPI, content_type: :json do
expect(project.identifier) expect(project.identifier)
.to eql attributes_before['identifier'] .to eql attributes_before['identifier']
expect(project.send("custom_field_#{text_custom_field.id}")) expect(project.send(text_custom_field.attribute_getter))
.to eql 'CF text' .to eql 'CF text'
expect(project.send("custom_field_#{list_custom_field.id}")) expect(project.send(list_custom_field.attribute_getter))
.to eql list_custom_field.custom_options.first.value .to eql list_custom_field.custom_options.first.value
expect(project.status) expect(project.status)

@ -105,7 +105,7 @@ describe 'API v3 Project resource update', content_type: :json do
end end
it 'sets the cf value' do it 'sets the cf value' do
expect(project.reload.send("custom_field_#{custom_field.id}")) expect(project.reload.send(custom_field.attribute_getter))
.to eql("CF text") .to eql("CF text")
end end
end end
@ -377,7 +377,7 @@ describe 'API v3 Project resource update', content_type: :json do
end end
it 'sets the cf value' do it 'sets the cf value' do
expect(project.reload.send("custom_field_#{custom_field.id}")) expect(project.reload.send(custom_field.attribute_getter))
.to eql("CF text") .to eql("CF text")
end end

@ -40,8 +40,8 @@ describe API::V3::Users::UpdateFormAPI, content_type: :json do
end end
shared_let(:user) do shared_let(:user) do
create(:user, create(:user,
"custom_field_#{text_custom_field.id}": "CF text", text_custom_field.attribute_getter => "CF text",
"custom_field_#{list_custom_field.id}": list_custom_field.custom_options.first) list_custom_field.attribute_getter => list_custom_field.custom_options.first)
end end
let(:path) { api_v3_paths.user_form(user.id) } let(:path) { api_v3_paths.user_form(user.id) }

@ -133,7 +133,7 @@ describe 'API v3 Work package form resource', with_mail: false do
it 'denotes string custom_field to be writable' do it 'denotes string custom_field to be writable' do
expect(subject) expect(subject)
.to be_json_eql(true) .to be_json_eql(true)
.at_path("_embedded/schema/#{cf_all.accessor_name.camelcase(:lower)}/writable") .at_path("_embedded/schema/#{cf_all.attribute_name.camelcase(:lower)}/writable")
end end
end end
@ -828,7 +828,7 @@ describe 'API v3 Work package form resource', with_mail: false do
it 'denotes custom_field to not be writable' do it 'denotes custom_field to not be writable' do
expect(subject) expect(subject)
.to be_json_eql(false) .to be_json_eql(false)
.at_path("_embedded/schema/#{cf_all.accessor_name.camelcase(:lower)}/writable") .at_path("_embedded/schema/#{cf_all.attribute_name.camelcase(:lower)}/writable")
end end
end end
end end

@ -718,7 +718,7 @@ describe 'API v3 Work package resource',
end end
let(:value_parameter) do let(:value_parameter) do
{ _links: { custom_field.accessor_name.camelize(:lower) => { href: value_link } } } { _links: { custom_field.attribute_name.camelize(:lower) => { href: value_link } } }
end end
let(:params) { valid_params.merge(value_parameter) } let(:params) { valid_params.merge(value_parameter) }
@ -736,7 +736,7 @@ describe 'API v3 Work package resource',
it 'responds with the work package assigned to the new value' do it 'responds with the work package assigned to the new value' do
expect(subject.body) expect(subject.body)
.to be_json_eql(value_link.to_json) .to be_json_eql(value_link.to_json)
.at_path("_links/#{custom_field.accessor_name.camelize(:lower)}/href") .at_path("_links/#{custom_field.attribute_name.camelize(:lower)}/href")
end end
it_behaves_like 'lock version updated' it_behaves_like 'lock version updated'

@ -672,7 +672,7 @@ describe Projects::CopyService, 'integration', type: :model do
before do before do
custom_field custom_field
work_package.reload work_package.reload
work_package.send(:"custom_field_#{custom_field.id}=", current_user.id) work_package.send(custom_field.attribute_setter, current_user.id)
work_package.save!(validate: false) work_package.save!(validate: false)
end end
@ -682,7 +682,7 @@ describe Projects::CopyService, 'integration', type: :model do
it 'copies the custom_field' do it 'copies the custom_field' do
expect(subject).to be_success expect(subject).to be_success
wp = project_copy.work_packages.find_by(subject: work_package.subject) wp = project_copy.work_packages.find_by(subject: work_package.subject)
expect(wp.send(:"custom_field_#{custom_field.id}")) expect(wp.send(custom_field.attribute_getter))
.to eql current_user .to eql current_user
end end
end end
@ -693,7 +693,7 @@ describe Projects::CopyService, 'integration', type: :model do
it 'nils the custom_field' do it 'nils the custom_field' do
expect(subject).to be_success expect(subject).to be_success
wp = project_copy.work_packages.find_by(subject: work_package.subject) wp = project_copy.work_packages.find_by(subject: work_package.subject)
expect(wp.send(:"custom_field_#{custom_field.id}")) expect(wp.send(custom_field.attribute_getter))
.to be_nil .to be_nil
end end
end end

@ -44,7 +44,7 @@ describe Projects::UpdateService, 'integration', type: :model do
let!(:project) do let!(:project) do
create(:project, create(:project,
"custom_field_#{custom_field.id}" => 1, custom_field.attribute_name => 1,
status: project_status) status: project_status)
end end
let(:instance) { described_class.new(user:, model: project) } let(:instance) { described_class.new(user:, model: project) }
@ -60,7 +60,7 @@ describe Projects::UpdateService, 'integration', type: :model do
describe '#call' do describe '#call' do
context 'if only a custom field is updated' do context 'if only a custom field is updated' do
let(:attributes) do let(:attributes) do
{ "custom_field_#{custom_field.id}" => 8 } { custom_field.attribute_name => 8 }
end end
it 'touches the project after saving' do it 'touches the project after saving' do
@ -79,7 +79,7 @@ describe Projects::UpdateService, 'integration', type: :model do
let(:custom_field2) { create(:text_project_custom_field) } let(:custom_field2) { create(:text_project_custom_field) }
let(:attributes) do let(:attributes) do
{ "custom_field_#{custom_field2.id}" => 'some text' } { custom_field2.attribute_name => 'some text' }
end end
it 'touches the project after saving' do it 'touches the project after saving' do

@ -36,10 +36,10 @@ shared_context 'with custom field params' do
attribute_groups: [ attribute_groups: [
{ 'type' => 'attribute', { 'type' => 'attribute',
'name' => 'group1', 'name' => 'group1',
'attributes' => [{ 'key' => "custom_field_#{cf1.id}" }, { 'key' => "custom_field_#{cf2.id}" }] }, 'attributes' => [{ 'key' => cf1.attribute_name }, { 'key' => cf2.attribute_name }] },
{ 'type' => 'attribute', { 'type' => 'attribute',
'name' => 'groups', 'name' => 'groups',
'attributes' => [{ 'key' => "custom_field_#{cf2.id}" }] } 'attributes' => [{ 'key' => cf2.attribute_name }] }
] ]
} }
end end
@ -138,7 +138,7 @@ shared_examples_for 'type service' do
it 'enables the custom fields that are passed via attribute_groups' do it 'enables the custom fields that are passed via attribute_groups' do
allow(type) allow(type)
.to receive(:work_package_attributes) .to receive(:work_package_attributes)
.and_return("custom_field_#{cf1.id}" => {}, "custom_field_#{cf2.id}" => {}) .and_return(cf1.attribute_name => {}, cf2.attribute_name => {})
allow(type) allow(type)
.to receive(:custom_field_ids=) .to receive(:custom_field_ids=)

@ -1253,7 +1253,7 @@ describe WorkPackages::UpdateService, 'integration tests', type: :model, with_ma
parent:, parent:,
start_date: Time.zone.today + 1.day, start_date: Time.zone.today + 1.day,
due_date: Time.zone.today + 5.days, due_date: Time.zone.today + 5.days,
"custom_field_#{custom_field.id}": 5) custom_field.attribute_name => 5)
end end
let!(:attributes) { { parent: nil } } let!(:attributes) { { parent: nil } }
@ -1264,7 +1264,7 @@ describe WorkPackages::UpdateService, 'integration tests', type: :model, with_ma
project:, project:,
type: project.types.first, type: project.types.first,
parent:, parent:,
"custom_field_#{custom_field.id}": 8 custom_field.attribute_name => 8
} }
end end
@ -1335,7 +1335,7 @@ describe WorkPackages::UpdateService, 'integration tests', type: :model, with_ma
{ {
type:, type:,
project:, project:,
"custom_field_#{custom_field_of_current_type.id}": 5 custom_field_of_current_type.attribute_name => 5
} }
end end

@ -45,7 +45,7 @@ shared_examples_for 'acts_as_customizable included' do
it 'returns the field changes' do it 'returns the field changes' do
model_instance.custom_field_values = { custom_field.id => 'test' } model_instance.custom_field_values = { custom_field.id => 'test' }
expect(model_instance.custom_field_changes) expect(model_instance.custom_field_changes)
.to eq({ "custom_field_#{custom_field.id}": [nil, 'test'] }) .to eq({ custom_field.attribute_name.to_sym => [nil, 'test'] })
end end
end end
end end
@ -54,7 +54,7 @@ shared_examples_for 'acts_as_customizable included' do
it 'returns the field changes' do it 'returns the field changes' do
model_instance.custom_field_values = { custom_field.id => 'test' } model_instance.custom_field_values = { custom_field.id => 'test' }
expect(model_instance.custom_field_changes) expect(model_instance.custom_field_changes)
.to eq({ "custom_field_#{custom_field.id}": [nil, 'test'] }) .to eq({ custom_field.attribute_name.to_sym => [nil, 'test'] })
end end
end end
@ -67,7 +67,7 @@ shared_examples_for 'acts_as_customizable included' do
it 'returns the field changes' do it 'returns the field changes' do
model_instance.custom_field_values = { custom_field.id => 'test2' } model_instance.custom_field_values = { custom_field.id => 'test2' }
expect(model_instance.custom_field_changes) expect(model_instance.custom_field_changes)
.to eq({ "custom_field_#{custom_field.id}": ['test', 'test2'] }) .to eq({ custom_field.attribute_name.to_sym => ['test', 'test2'] })
end end
end end
@ -92,7 +92,7 @@ shared_examples_for 'acts_as_customizable included' do
it 'returns the field changes' do it 'returns the field changes' do
model_instance.custom_field_values = { custom_field.id => nil } model_instance.custom_field_values = { custom_field.id => nil }
expect(model_instance.custom_field_changes) expect(model_instance.custom_field_changes)
.to eq({ "custom_field_#{custom_field.id}": ['test', nil] }) .to eq({ custom_field.attribute_name.to_sym => ['test', nil] })
end end
end end
end end

Loading…
Cancel
Save