Skip to content

Commit

Permalink
Support for virtual fields
Browse files Browse the repository at this point in the history
  • Loading branch information
goosys committed Sep 13, 2024
1 parent 31ed271 commit f377679
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 6 deletions.
13 changes: 13 additions & 0 deletions lib/administrate/field/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
8 changes: 8 additions & 0 deletions lib/administrate/field/deferred.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ def ==(other)
options == other.options
end

def getter
options.fetch(:getter, nil)
end

def associative?
deferred_class.associative?
end
Expand Down Expand Up @@ -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
Expand Down
7 changes: 1 addition & 6 deletions lib/administrate/page/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions spec/example_app/app/dashboards/customer_dashboard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ 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? },
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,
Expand Down
30 changes: 30 additions & 0 deletions spec/lib/fields/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit f377679

Please sign in to comment.