Skip to content

Commit

Permalink
fix: search association field by type and id
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul-Bob committed Sep 10, 2024
1 parent b87693c commit aaaab9a
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 5 deletions.
4 changes: 2 additions & 2 deletions app/components/avo/base_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
class Avo::BaseComponent < ViewComponent::Base
extend Literal::Properties
include Turbo::FramesHelper
include Avo::Concerns::FindAssociationField

def has_with_trial(ability)
Avo.license.has_with_trial(ability)
Expand All @@ -12,8 +13,7 @@ def has_with_trial(ability)

# Use the @parent_resource to fetch the field using the @reflection name.
def field
reflection_name = params[:related_name]&.to_sym || @reflection.name
@parent_resource.get_field(reflection_name)
find_association_field(resource: @parent_resource, association: params[:related_name] || @reflection.name)
rescue
nil
end
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/avo/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ApplicationController < ::ActionController::Base
include Avo::ApplicationHelper
include Avo::UrlHelpers
include Avo::Concerns::Breadcrumbs
include Avo::Concerns::FindAssociationField

protect_from_forgery with: :exception
around_action :set_avo_locale
Expand Down Expand Up @@ -85,7 +86,7 @@ def resource

def related_resource
# Find the field from the parent resource
field = @resource.get_field params[:related_name]
field = find_association_field(resource: @resource, association: params[:related_name])

return field.use_resource if field&.use_resource.present?

Expand Down
4 changes: 2 additions & 2 deletions app/controllers/avo/associations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def index
@parent_resource.hydrate(record: @parent_record)
association_name = BaseResource.valid_association_name(@parent_record, association_from_params)
@query = @related_authorization.apply_policy @parent_record.send(association_name)
@association_field = @parent_resource.get_field params[:related_name]
@association_field = find_association_field(resource: @parent_resource, association: params[:related_name])

if @association_field.present? && @association_field.scope.present?
@query = Avo::ExecutionContext.new(target: @association_field.scope, query: @query, parent: @parent_record).handle
Expand Down Expand Up @@ -126,7 +126,7 @@ def set_attachment_record
end

def set_reflection_field
@field = @resource.get_field(@related_resource_name.to_sym)
@field = find_association_field(resource: @resource, association: @related_resource_name)
@field.hydrate(resource: @resource, record: @record, view: Avo::ViewInquirer.new(:new))
rescue
end
Expand Down
21 changes: 21 additions & 0 deletions lib/avo/concerns/find_association_field.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Avo
module Concerns
module FindAssociationField
# The supported association types are defined in the ASSOCIATIONS constant.
unless defined?(ASSOCIATIONS)
ASSOCIATIONS = ["belongs_to", "has_one", "has_many", "has_and_belongs_to_many"]
end

# This method is used to find an association field for a given resource.
# Ideally, the exact type of the association should be known in advance.
# However, there are cases where the type is unknown
# and the method will return the first matching association field
# based on the provided association name.
def find_association_field(resource:, association:)
resource.get_field_definitions.find do |field|
(field.id == association.to_sym) && field.type.in?(ASSOCIATIONS)
end
end
end
end
end
6 changes: 6 additions & 0 deletions spec/dummy/app/avo/resources/store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ def fields
field :location, as: :has_one
end

# Use the same id as the :has_many field intentinally to test if correct association field is fetched when rendering
# the association
field :patrons, as: :tags do
record.patrons.map(&:name)
end

field :patrons,
as: :has_many,
through: :patronships,
Expand Down

0 comments on commit aaaab9a

Please sign in to comment.