Skip to content

Commit 049fb60

Browse files
feature: array adapter (#3469)
* feature: array adapter * update ovei list * wip: hide unsupported actions, implement show view * some lint * revert indentation * lint * lint * rm `ActiveRecordResource` for now * wip * rm ostruct requirement * make it work with array of active records * has_many field array option * lint * fix * fix flaky test * fix flaky test * prepare dummy for tests * lint * index tests * lint & flaky test * lint * more tests * lint * wait_for_loaded on associations * rm copyable * rm comments * array resource check * using_wait_time capybara * . * fix test * . * fix test * fix test * wip * wip * wip * wip * wip * fix test * refactor wip * refactor still wip * fix test * wip refactor * lint * Revert "wip refactor" This reverts commit 431435d. * re-try * Revert "Revert "wip refactor"" This reverts commit c4884bc. * re-add display * rm display * add description * fix habtm * fix attach_fields on has one * is_searchable? * add attach_scope to has one field * rbac changes * lint * lint * minor tweaks --------- Co-authored-by: Paul Bob <[email protected]> Co-authored-by: Paul Bob <[email protected]>
1 parent 36b510f commit 049fb60

39 files changed

+751
-98
lines changed

app/components/avo/index/resource_controls_component.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ def can_detach?
1616
end
1717

1818
def can_edit?
19+
# Disable edit for ArrayResources
20+
return false if @resource.resource_type_array?
21+
1922
return authorize_association_for(:edit) if @reflection.present?
2023

2124
@resource.authorization.authorize_action(:edit, raise_exception: false)

app/components/avo/index/table_row_component.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
parent_resource: @parent_resource
4242
) %>
4343
<% else %>
44-
<td class="text-center"></td>
44+
<td class="px-3"></td>
4545
<% end %>
4646
<% end %>
4747
<% if @resource.resource_controls_render_on_the_right? %>

app/components/avo/resource_component.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ def detach_path
4040
end
4141

4242
def can_see_the_edit_button?
43+
# Disable edit for ArrayResources
44+
return false if @resource.resource_type_array?
45+
4346
return authorize_association_for(:edit) if @reflection.present?
4447

4548
@resource.authorization.authorize_action(:edit, raise_exception: false)
4649
end
4750

4851
def can_see_the_destroy_button?
52+
# Disable destroy for ArrayResources
53+
return false if @resource.resource_type_array?
54+
4955
@resource.authorization.authorize_action(:destroy, raise_exception: false)
5056
end
5157

app/components/avo/views/resource_index_component.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
description: description,
1212
cover_photo: resource.cover_photo,
1313
data: {component: "resources-index"},
14-
display_breadcrumbs: @reflection.blank? || (@reflection.present? && !helpers.turbo_frame_request?)
14+
display_breadcrumbs: (@reflection.blank? && @parent_resource.blank?) || (@reflection.present? && !helpers.turbo_frame_request?)
1515
) do |c| %>
1616
<% c.with_name_slot do %>
1717
<%= render Avo::PanelNameComponent.new name: title, url: (params[:turbo_frame].present? && linkable?) ? field.frame_url(add_turbo_frame: false) : nil, target: :_blank do |panel_name_component| %>

app/components/avo/views/resource_index_component.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ def available_view_types
4040
# The Create button is dependent on the new? policy method.
4141
# The create? should be called only when the user clicks the Save button so the developers gets access to the params from the form.
4242
def can_see_the_create_button?
43+
# Disable creation for ArrayResources
44+
return false if @resource.resource_type_array?
45+
4346
return authorize_association_for(:create) if @reflection.present?
4447

4548
@resource.authorization.authorize_action(:new, raise_exception: false) && !has_reflection_and_is_read_only
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Avo
2+
class ArrayController < BaseController
3+
def set_query
4+
@query ||= @resource.fetch_records
5+
end
6+
end
7+
end

app/controllers/avo/associations_controller.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,20 @@ def index
2424
@resource = @related_resource
2525
@parent_record = @parent_resource.find_record(params[:id], params: params)
2626
@parent_resource.hydrate(record: @parent_record)
27-
association_name = BaseResource.valid_association_name(@parent_record, association_from_params)
28-
@query = @related_authorization.apply_policy @parent_record.send(association_name)
27+
28+
# When array field the records are fetched from the field block, from the parent record or from the resource def records
29+
# When other field type, like has_many the @query is directly fetched from the parent record
30+
# Don't apply policy on array type since it can return an array of hashes where `.all` and other methods used on policy will fail.
31+
@query = if @field.type == "array"
32+
@resource.fetch_records(Avo::ExecutionContext.new(target: @field.block).handle || @parent_record.try(@field.id))
33+
else
34+
@related_authorization.apply_policy(
35+
@parent_record.send(
36+
BaseResource.valid_association_name(@parent_record, association_from_params)
37+
)
38+
)
39+
end
40+
2941
@association_field = find_association_field(resource: @parent_resource, association: params[:related_name])
3042

3143
if @association_field.present? && @association_field.scope.present?
@@ -125,7 +137,8 @@ def set_reflection
125137
end
126138

127139
def set_attachment_class
128-
@attachment_class = @reflection.klass
140+
# @reflection is nil whe using an Array field.
141+
@attachment_class = @reflection&.klass
129142
end
130143

131144
def set_attachment_resource

app/controllers/avo/base_application_controller.rb

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,6 @@ def resource
8484
Avo.resource_manager.get_resource_by_controller_name @resource_name
8585
end
8686

87-
def related_resource
88-
# Find the field from the parent resource
89-
field = find_association_field(resource: @resource, association: params[:related_name])
90-
91-
return field.use_resource if field&.use_resource.present?
92-
93-
reflection = @record.class.reflect_on_association(field&.for_attribute || params[:related_name])
94-
95-
reflected_model = reflection.klass
96-
97-
Avo.resource_manager.get_resource_by_model_class reflected_model
98-
end
99-
10087
def set_resource_name
10188
@resource_name = resource_name
10289
end
@@ -118,6 +105,11 @@ def detect_fields
118105
end
119106

120107
def set_related_resource
108+
# Find the field from the parent resource
109+
related_resource = find_association_field(resource: @resource, association: params[:related_name])
110+
.hydrate(record: @record)
111+
.resource_class(params)
112+
121113
raise Avo::MissingResourceError.new(related_resource_name) if related_resource.nil?
122114

123115
action_view = action_name.to_sym

app/controllers/avo/base_controller.rb

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,7 @@ def index
2828
set_index_params
2929
set_filters
3030
set_actions
31-
32-
# If we don't get a query object predefined from a child controller like associations, just spin one up
33-
unless defined? @query
34-
@query = @resource.class.query_scope
35-
end
31+
set_query
3632

3733
# Eager load the associations
3834
if @resource.includes.present?
@@ -46,7 +42,7 @@ def index
4642
end
4743
end
4844

49-
apply_sorting
45+
apply_sorting if @index_params[:sort_by]
5046

5147
# Apply filters to the current query
5248
filters_to_be_applied.each do |filter_class, filter_value|
@@ -310,18 +306,7 @@ def set_index_params
310306
set_pagination_params
311307

312308
# Sorting
313-
if params[:sort_by].present?
314-
@index_params[:sort_by] = params[:sort_by]
315-
elsif @resource.model_class.present?
316-
available_columns = @resource.model_class.column_names
317-
default_sort_column = @resource.default_sort_column
318-
319-
if available_columns.include?(default_sort_column.to_s)
320-
@index_params[:sort_by] = default_sort_column
321-
elsif available_columns.include?("created_at")
322-
@index_params[:sort_by] = :created_at
323-
end
324-
end
309+
@index_params[:sort_by] = params[:sort_by] || @resource.sort_by_param
325310

326311
@index_params[:sort_direction] = params[:sort_direction] || @resource.default_sort_direction
327312

@@ -608,8 +593,6 @@ def apply_pagination
608593
end
609594

610595
def apply_sorting
611-
return if @index_params[:sort_by].nil?
612-
613596
sort_by = @index_params[:sort_by].to_sym
614597
if sort_by != :created_at
615598
@query = @query.unscope(:order)
@@ -650,5 +633,10 @@ def set_pagination_params
650633

651634
@index_params[:per_page] = cookies[:per_page] || Avo.configuration.per_page
652635
end
636+
637+
# If we don't get a query object predefined from a child controller like associations, just spin one up
638+
def set_query
639+
@query ||= @resource.class.query_scope
640+
end
653641
end
654642
end

app/views/avo/partials/_table_header.html.erb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
<% fields.each_with_index do |field, index| %>
2929
<%
3030
first_option = Avo.configuration.first_sorting_option.to_s
31-
second_option = first_option == "desc" ? "asc" : "desc"
3231

3332
if params[:sort_by] == field.id.to_s
33+
second_option = first_option == "desc" ? "asc" : "desc"
34+
3435
if params[:sort_direction] == second_option
3536
sort_by = nil
3637
else
@@ -65,7 +66,7 @@
6566
} do %>
6667
<%= content_tag :div,
6768
class: "relative flex items-center justify-between w-full" do %>
68-
<% if field.sortable %>
69+
<% if field.sortable && @resource.sorting_supported? %>
6970
<%= link_to params.permit!.merge(sort_by: sort_by, sort_direction: sort_direction),
7071
class: class_names("flex-1 flex justify-between", text_classes),
7172
'data-turbo-frame': params[:turbo_frame] do %>

0 commit comments

Comments
 (0)