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
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
writable

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

@ -28,7 +28,7 @@
class CustomActions::Actions::CustomField < CustomActions::Actions::Base
def self.key
:"custom_field_#{custom_field.id}"
custom_field.attribute_name.to_sym
end
def self.custom_field
@ -44,7 +44,7 @@ class CustomActions::Actions::CustomField < CustomActions::Actions::Base
end
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
def self.all

@ -28,7 +28,7 @@
module CustomActions::Actions::Strategies::CustomField
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
delegate :required?, to: :custom_field

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

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

@ -40,7 +40,7 @@ module Queries::Filters::Shared::CustomFieldFilter
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.
def custom_field_accessor(custom_field)
"cf_#{custom_field.id}"

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

@ -44,14 +44,14 @@ module DevelopmentData
def create_types!(cfs)
# 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'
extend_group(type, ['Custom fields', non_req_cfs])
type.save!
print_status '.'
# 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'
extend_group(type_req, ['Custom fields', req_cfs])
type_req.save!

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

@ -219,7 +219,7 @@ module API
[value].compact
end
represented.send(:"custom_field_#{custom_field.id}=", values)
represented.send(custom_field.attribute_setter, values)
}
end
@ -233,7 +233,7 @@ module API
custom_field.list? ||
custom_field.multi_value?
value = represented.send custom_field.accessor_name
value = represented.send custom_field.attribute_getter
next unless value
@ -243,7 +243,7 @@ module API
end
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),
getter: property_value_getter_for(custom_field),
setter: property_value_setter_for(custom_field),
@ -254,7 +254,7 @@ module API
->(*) {
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'
::API::Decorators::Formattable.new(value, object: self)
@ -271,7 +271,7 @@ module API
else
fragment
end
send(:"custom_field_#{custom_field.id}=", value)
send(custom_field.attribute_setter, value)
}
end

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

@ -269,7 +269,7 @@ module Redmine
def add_custom_value_errors!(custom_value)
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
@ -319,15 +319,12 @@ module Redmine
end
def add_custom_field_accessors(custom_field)
getter_name = custom_field.accessor_name
setter_name = "#{getter_name}="
define_custom_field_getter(getter_name, custom_field)
define_custom_field_setter(setter_name, custom_field)
define_custom_field_getter(custom_field)
define_custom_field_setter(custom_field)
end
def define_custom_field_getter(getter_name, custom_field)
define_singleton_method getter_name do
def define_custom_field_getter(custom_field)
define_singleton_method custom_field.attribute_getter do
custom_values = Array(custom_value_for(custom_field)).map do |custom_value|
custom_value ? custom_value.typed_value : nil
end
@ -340,8 +337,8 @@ module Redmine
end
end
def define_custom_field_setter(setter_name, custom_field)
define_singleton_method setter_name do |value|
def define_custom_field_setter(custom_field)
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
# to an integer custom field...
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
let(:custom_field) { build_stubbed(:text_time_entry_custom_field) }
let(:path) { "customField#{custom_field.id}" }
let(:writable_attributes) { ["custom_field_#{custom_field.id}"] }
let(:writable_attributes) { [custom_field.attribute_name] }
before do
allow(contract)

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

@ -438,7 +438,7 @@ describe 'API v3 time_entry resource' do
expect(new_entry.spent_on)
.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'
end

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

@ -180,7 +180,7 @@ describe 'Custom fields reporting', js: true do
end
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-rows')

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

@ -306,7 +306,7 @@ describe CostQuery, reporting_query_helper: true do
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
expect(footprint).to eq([[8, 8]])
end

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

@ -419,7 +419,7 @@ describe WorkPackages::UpdateContract do
shared_examples_for 'custom_field readonly errors' 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)
end

@ -102,7 +102,7 @@ describe 'Read-only statuses affect work package editing',
assignee_field.label_element.click
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.expect_inactive!
end

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

@ -39,8 +39,8 @@ describe 'Reset form configuration', js: true do
describe "with EE token and CFs" do
let(:custom_fields) { [custom_field] }
let(:custom_field) { create(:integer_issue_custom_field, is_required: true, name: 'MyNumber') }
let(:cf_identifier) { "custom_field_#{custom_field.id}" }
let(:cf_identifier_api) { "customField#{custom_field.id}" }
let(:cf_identifier) { custom_field.attribute_name }
let(:cf_identifier_api) { cf_identifier.camelcase(:lower) }
before do
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
it 'does not update the work packages' do
expect(work_package.send(custom_field.accessor_name)).to be_nil
expect(work_package2.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.attribute_getter)).to be_nil
fill_in custom_field.name, with: 'Custom field text'
click_on 'Submit'
@ -170,18 +170,18 @@ describe 'Bulk update work packages through Rails view', js: true do
work_package.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')
expect(work_package2.send(custom_field.accessor_name))
expect(work_package2.send(custom_field.attribute_getter))
.to be_nil
end
end
context 'without enterprise', with_ee: false 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_package2.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.attribute_getter)).to be_nil
fill_in custom_field.name, with: 'Custom field text'
click_on 'Submit'
@ -192,10 +192,10 @@ describe 'Bulk update work packages through Rails view', js: true do
work_package.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')
expect(work_package2.send(custom_field.accessor_name))
expect(work_package2.send(custom_field.attribute_getter))
.to eq('Custom field text')
end
end

@ -241,7 +241,7 @@ describe 'Custom actions', js: true do
# This custom field is not applicable
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.expect_selected_option closed_status.name

@ -188,7 +188,7 @@ describe 'custom field inplace editor', js: true do
field.save!
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

@ -104,7 +104,7 @@ RSpec.describe 'Work package create uses attributes from filters', js: true, sel
)
wp = WorkPackage.last
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
end
end

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

@ -216,14 +216,14 @@ describe 'filter work packages', js: true do
let(:work_package_with_list_value) do
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
end
let(:work_package_with_anti_list_value) do
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
end
@ -294,14 +294,14 @@ describe 'filter work packages', js: true do
let(:work_package_plus) do
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
end
let(:work_package_and) do
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
end

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

@ -257,7 +257,7 @@ describe 'Switching types in work package table', js: true do
work_package.reload
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

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

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

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

@ -118,11 +118,11 @@ describe API::V3::WorkPackages::EagerLoading::CustomValue do
type_project_user_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
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
expect(work_package.send(:"custom_field_#{type_project_user_cf.id}"))
expect(work_package.send(type_project_user_cf.attribute_getter))
.to eql user
end
end

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

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

@ -35,7 +35,7 @@ describe AttributeHelpText::WorkPackage do
# need to clear the cache to free the memoized
# Type.translated_work_package_form_attributes
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
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)
.and_return(custom_field)
described_class.for(:"custom_field_#{custom_field.id}")
described_class.for(custom_field.attribute_name)
end
let(:instance) do
klass.new
@ -113,14 +113,14 @@ describe CustomActions::Actions::CustomField do
describe '.key' do
it 'is the custom field accessor' do
expect(klass.key)
.to eql(:"custom_field_#{custom_field.id}")
.to eql(custom_field.attribute_getter)
end
end
describe '#key' do
it 'is the custom field accessor' do
expect(instance.key)
.to eql(:"custom_field_#{custom_field.id}")
.to eql(custom_field.attribute_getter)
end
end
@ -587,7 +587,7 @@ describe CustomActions::Actions::CustomField do
it "sets the value for #{type} custom fields" do
expect(work_package)
.to receive(:"custom_field_#{custom_field.id}=")
.to receive(custom_field.attribute_setter)
.with([42])
instance.values = 42
@ -601,7 +601,7 @@ describe CustomActions::Actions::CustomField do
it "sets the value to today for a dynamic value" do
expect(work_package)
.to receive(:"custom_field_#{custom_field.id}=")
.to receive(custom_field.attribute_setter)
.with(Date.today)
instance.values = '%CURRENT_DATE%'

@ -183,12 +183,28 @@ describe CustomField do
end
end
describe '#accessor_name' do
let(:field) { build_stubbed :custom_field }
describe '#attribute_name' do
let(:field) { build_stubbed(:custom_field) }
it 'is formatted as expected' do
expect(field.accessor_name).to eql("custom_field_#{field.id}")
end
subject { field.attribute_name }
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
describe '#possible_values_options' do

@ -50,13 +50,13 @@ describe CustomValue::ListStrategy, 'integration tests' do
end
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
CustomValue.find_by(customized_id: work_package.id).update_columns(value: 'invalid')
work_package.reload
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

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

@ -196,10 +196,10 @@ describe Query::Results, with_mail: false do
before do
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_package2.send(:"custom_field_#{custom_field.id}=", [first_value,
last_value])
work_package2.send(custom_field.attribute_setter, [first_value,
last_value])
work_package2.save!
end
@ -229,9 +229,9 @@ describe Query::Results, with_mail: false do
wp_p1[0].type.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[1].update_attribute(:"custom_field_#{custom_field.id}", 42)
wp_p1[1].update_attribute(custom_field.attribute_name, 42)
wp_p1[1].save
end
@ -272,9 +272,9 @@ describe Query::Results, with_mail: false do
wp_p1[0].type.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[1].update_attribute(:"custom_field_#{custom_field.id}", true)
wp_p1[1].update_attribute(custom_field.attribute_name, true)
wp_p1[1].save
end
@ -296,9 +296,9 @@ describe Query::Results, with_mail: false do
wp_p1[0].type.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[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
end

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

@ -163,7 +163,7 @@ describe Type do
)
end
let(:cf_identifier) do
:"custom_field_#{custom_field.id}"
custom_field.attribute_name
end
it 'can be put into attribute groups' do
@ -171,7 +171,7 @@ describe Type do
OpenProject::Cache.clear
# 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.read_attribute(:attribute_groups)).not_to be_empty
end
@ -184,7 +184,7 @@ describe Type do
)
end
let(:cf_identifier2) do
:"custom_field_#{custom_field2.id}"
custom_field2.attribute_name
end
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
# 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.read_attribute(:attribute_groups)).not_to be_empty
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
@ -220,7 +220,7 @@ describe Type do
other_group = type.attribute_groups.detect { |g| g.key == :other }
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
type.reset_attribute_groups

@ -67,7 +67,7 @@ describe WorkPackage, 'acts_as_customizable' do
end
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
end
end
@ -85,19 +85,19 @@ describe WorkPackage, 'acts_as_customizable' do
end
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
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
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
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
@ -125,7 +125,7 @@ describe WorkPackage, 'acts_as_customizable' do
# assert that there is only one error
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

@ -145,7 +145,7 @@ describe WorkPackage do
describe 'invalid custom field values' do
context 'short error message' 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
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.save
expect(work_package.send("custom_field_#{custom_field.id}"))
expect(work_package.send(custom_field.attribute_getter))
.to eql values
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: '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

@ -34,8 +34,8 @@ describe API::V3::Projects::UpdateFormAPI, content_type: :json do
let(:project) do
create(:project,
"custom_field_#{text_custom_field.id}": "CF text",
"custom_field_#{list_custom_field.id}": list_custom_field.custom_options.first)
text_custom_field.attribute_name => "CF text",
list_custom_field.attribute_name => list_custom_field.custom_options.first)
end
let(:current_user) do
create(:user,
@ -224,10 +224,10 @@ describe API::V3::Projects::UpdateFormAPI, content_type: :json do
expect(project.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'
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
expect(project.status)

@ -105,7 +105,7 @@ describe 'API v3 Project resource update', content_type: :json do
end
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")
end
end
@ -377,7 +377,7 @@ describe 'API v3 Project resource update', content_type: :json do
end
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")
end

@ -40,8 +40,8 @@ describe API::V3::Users::UpdateFormAPI, content_type: :json do
end
shared_let(:user) do
create(:user,
"custom_field_#{text_custom_field.id}": "CF text",
"custom_field_#{list_custom_field.id}": list_custom_field.custom_options.first)
text_custom_field.attribute_getter => "CF text",
list_custom_field.attribute_getter => list_custom_field.custom_options.first)
end
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
expect(subject)
.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
@ -828,7 +828,7 @@ describe 'API v3 Work package form resource', with_mail: false do
it 'denotes custom_field to not be writable' do
expect(subject)
.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

@ -718,7 +718,7 @@ describe 'API v3 Work package resource',
end
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
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
expect(subject.body)
.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
it_behaves_like 'lock version updated'

@ -672,7 +672,7 @@ describe Projects::CopyService, 'integration', type: :model do
before do
custom_field
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)
end
@ -682,7 +682,7 @@ describe Projects::CopyService, 'integration', type: :model do
it 'copies the custom_field' do
expect(subject).to be_success
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
end
end
@ -693,7 +693,7 @@ describe Projects::CopyService, 'integration', type: :model do
it 'nils the custom_field' do
expect(subject).to be_success
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
end
end

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

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

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

@ -45,7 +45,7 @@ shared_examples_for 'acts_as_customizable included' do
it 'returns the field changes' do
model_instance.custom_field_values = { custom_field.id => 'test' }
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
@ -54,7 +54,7 @@ shared_examples_for 'acts_as_customizable included' do
it 'returns the field changes' do
model_instance.custom_field_values = { custom_field.id => 'test' }
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
@ -67,7 +67,7 @@ shared_examples_for 'acts_as_customizable included' do
it 'returns the field changes' do
model_instance.custom_field_values = { custom_field.id => 'test2' }
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
@ -92,7 +92,7 @@ shared_examples_for 'acts_as_customizable included' do
it 'returns the field changes' do
model_instance.custom_field_values = { custom_field.id => nil }
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

Loading…
Cancel
Save