diff --git a/lib/administrate/field/base.rb b/lib/administrate/field/base.rb index c086603afb..a87eea5687 100644 --- a/lib/administrate/field/base.rb +++ b/lib/administrate/field/base.rb @@ -38,6 +38,7 @@ def initialize(attribute, data, page, options = {}) @page = page @resource = options.delete(:resource) @options = options + @data = read_value if @data.nil? end def html_class @@ -52,6 +53,18 @@ def name attribute.to_s end + def read_value + if options.key?(:getter) + if options[:getter].respond_to?(:call) + options[:getter].call(self) + else + resource&.public_send(options[:getter]) + end + else + resource&.public_send(attribute) + end + end + def to_partial_path "/fields/#{self.class.field_type}/#{page}" end diff --git a/lib/administrate/field/deferred.rb b/lib/administrate/field/deferred.rb index 10609735af..06ac106ff1 100644 --- a/lib/administrate/field/deferred.rb +++ b/lib/administrate/field/deferred.rb @@ -21,6 +21,10 @@ def ==(other) options == other.options end + def getter + options.fetch(:getter, nil) + end + def associative? deferred_class.associative? end @@ -57,6 +61,10 @@ def permitted_attribute(attr, opts = {}) end end + def read_value(resource, attribute_name) + @deferred_class.read_value(resource, attribute_name, options) + end + delegate :html_class, to: :deferred_class end end diff --git a/lib/administrate/page/base.rb b/lib/administrate/page/base.rb index 78fbf1a6bd..56c61892d3 100644 --- a/lib/administrate/page/base.rb +++ b/lib/administrate/page/base.rb @@ -30,13 +30,8 @@ def item_associations private def attribute_field(dashboard, resource, attribute_name, page) - value = get_attribute_value(resource, attribute_name) field = dashboard.attribute_type_for(attribute_name) - field.new(attribute_name, value, page, resource: resource) - end - - def get_attribute_value(resource, attribute_name) - resource.public_send(attribute_name) + field.new(attribute_name, nil, page, resource: resource) end attr_reader :dashboard, :options diff --git a/spec/example_app/app/dashboards/customer_dashboard.rb b/spec/example_app/app/dashboards/customer_dashboard.rb index 79786fa4f7..ad73e4a306 100644 --- a/spec/example_app/app/dashboards/customer_dashboard.rb +++ b/spec/example_app/app/dashboards/customer_dashboard.rb @@ -8,6 +8,11 @@ class CustomerDashboard < Administrate::BaseDashboard email_subscriber: Field::Boolean, lifetime_value: Field::Number.with_options(prefix: "$", decimals: 2), name: Field::String, + nickname: Field::String.with_options( + getter: ->(field) { "Mr. #{field.resource.name}man" if field.resource.name.present? }, + sorting_field: :name, + searchable: false + ), orders: Field::HasMany.with_options(limit: 2, sort_by: :id), log_entries: Field::HasManyVariant.with_options(limit: 2, sort_by: :id), updated_at: Field::DateTime, diff --git a/spec/lib/fields/base_spec.rb b/spec/lib/fields/base_spec.rb index 43b71efc50..459207468b 100644 --- a/spec/lib/fields/base_spec.rb +++ b/spec/lib/fields/base_spec.rb @@ -167,4 +167,34 @@ expect(field.required?).to eq(false) end end + + describe "read_value" do + it "reads the value from the resource" do + resource = double(attribute: "value") + field = field_class.new(:attribute, :date, :page, resource: resource) + + expect(field.read_value).to eq("value") + end + + it "reads the value from the resource with a custom getter" do + resource = double(custom_getter: "value") + field = field_class.new(:attribute, :date, :page, resource: resource, getter: :custom_getter) + + expect(field.read_value).to eq("value") + end + + it "reads the value from the resource with a custom getter block" do + resource = double + field = field_class.new(:attribute, :date, :page, resource: resource, getter: ->(field) { field.resource.custom_getter }) + + expect(resource).to receive(:custom_getter) + field.read_value + end + + it "returns nil if the resource is nil" do + field = field_class.new(:attribute, :date, :page, resource: nil) + + expect(field.read_value).to eq(nil) + end + end end