From 17a8becfd73eeff26c8710296ed0be7ac0390823 Mon Sep 17 00:00:00 2001 From: Ivanov-Anton Date: Wed, 3 Feb 2021 20:41:42 +0200 Subject: [PATCH 1/4] Improve build path for ajax request To prevent error in build path for ajax request when we have namespaced classes solves #29 issue --- .../select_input_extension.rb | 12 +- spec/features/end_to_end_spec.rb | 114 ++++++++++++------ spec/internal/db/schema.rb | 11 ++ spec/support/models.rb | 14 +++ 4 files changed, 113 insertions(+), 38 deletions(-) diff --git a/lib/activeadmin/searchable_select/select_input_extension.rb b/lib/activeadmin/searchable_select/select_input_extension.rb index 203a0fb..cf9aff7 100644 --- a/lib/activeadmin/searchable_select/select_input_extension.rb +++ b/lib/activeadmin/searchable_select/select_input_extension.rb @@ -45,11 +45,21 @@ def collection_from_options def ajax_url return unless options[:ajax] - template.polymorphic_path([template.active_admin_namespace.route_prefix, ajax_resource_class], + template.polymorphic_path([active_admin_prefix, resource_route_name || ajax_resource_class], action: option_collection.collection_action_name, **ajax_params) end + def active_admin_prefix + template.active_admin_namespace.route_prefix + end + + def resource_route_name + active_admin_namespace = template.active_admin_namespace + str = active_admin_namespace.resource_for(ajax_resource_class)&.route_collection_path + str&.split('/')&.last + end + def all_options_collection option_collection_scope.all.map do |record| option_for_record(record) diff --git a/spec/features/end_to_end_spec.rb b/spec/features/end_to_end_spec.rb index 4d61d49..3bfdb3f 100644 --- a/spec/features/end_to_end_spec.rb +++ b/spec/features/end_to_end_spec.rb @@ -5,60 +5,100 @@ require 'support/active_admin_helpers' RSpec.describe 'end to end', type: :feature, js: true do - before(:each) do - ActiveAdminHelpers.setup do - ActiveAdmin.register(Category) do - searchable_select_options(scope: Category, text_attribute: :name) - end + context 'class name without namespaces' do + before(:each) do + ActiveAdminHelpers.setup do + ActiveAdmin.register(Category) do + searchable_select_options(scope: Category, text_attribute: :name) + end - ActiveAdmin.register(Post) do - filter(:category, as: :searchable_select, ajax: true) + ActiveAdmin.register(Post) do + filter(:category, as: :searchable_select, ajax: true) - form do |f| - f.input(:category, as: :searchable_select, ajax: true) + form do |f| + f.input(:category, as: :searchable_select, ajax: true) + end end - end - ActiveAdmin.setup {} + ActiveAdmin.setup {} + end end - end - describe 'index page with searchable select filter' do - it 'loads filter input options' do - Category.create(name: 'Music') - Category.create(name: 'Travel') + describe 'index page with searchable select filter' do + it 'loads filter input options' do + Category.create(name: 'Music') + Category.create(name: 'Travel') - visit '/admin/posts' + visit '/admin/posts' - expand_select_box - wait_for_ajax + expand_select_box + wait_for_ajax - expect(select_box_items).to eq(%w(Music Travel)) - end + expect(select_box_items).to eq(%w(Music Travel)) + end - it 'allows filtering options by term' do - Category.create(name: 'Music') - Category.create(name: 'Travel') + it 'allows filtering options by term' do + Category.create(name: 'Music') + Category.create(name: 'Travel') - visit '/admin/posts' + visit '/admin/posts' - expand_select_box - enter_search_term('T') - wait_for_ajax + expand_select_box + enter_search_term('T') + wait_for_ajax - expect(select_box_items).to eq(%w(Travel)) + expect(select_box_items).to eq(%w(Travel)) + end + + it 'loads more items when scrolling down' do + 15.times { |i| Category.create(name: "Category #{i}") } + visit '/admin/posts' + + expand_select_box + wait_for_ajax + scroll_select_box_list + wait_for_ajax + + expect(select_box_items.size).to eq(15) + end end + end - it 'loads more items when scrolling down' do - 15.times { |i| Category.create(name: "Category #{i}") } - visit '/admin/posts' + context 'class name with namespace' do + before(:each) do + ActiveAdminHelpers.setup do + ActiveAdmin.register RGB::Color, as: 'color' do + searchable_select_options scope: RGB::Color, text_attribute: :code + end + + ActiveAdmin.register Internal::TagName, as: 'Tag Name' do + filter :color, as: :searchable_select, ajax: { resource: 'RGB::Color' } + end + + ActiveAdmin::SearchableSelect.inline_ajax_options = true + ActiveAdmin.setup {} + end + end - expand_select_box - wait_for_ajax - scroll_select_box_list - wait_for_ajax + describe 'index page with searchable select filter' do + let!(:orange) { RGB::Color.create(code: '#eac112', description: 'Orange') } + let(:filters_options) { %w(Any #19bf25 #eac112) } - expect(select_box_items.size).to eq(15) + let!(:other_records) do + RGB::Color.create(code: '#19bf25', description: 'Green') + Internal::TagName.create(name: 'Important Guest', color: orange) + end + + before { visit '/admin/tag_names' } + + it 'should have all created colors in filter' do + expect(page).to have_select :Color, options: filters_options + end + + it 'should have selected option' do + select orange.code, from: :Color + expect(page).to have_select :Color, selected: orange.code + end end end diff --git a/spec/internal/db/schema.rb b/spec/internal/db/schema.rb index dc9624b..05ae8c3 100644 --- a/spec/internal/db/schema.rb +++ b/spec/internal/db/schema.rb @@ -20,6 +20,17 @@ t.boolean :published end + create_table(:rgb_colors, force: true) do |t| + t.string :code + t.text :description + end + + create_table(:internal_tag_names, force: true) do |t| + t.string :name + t.text :description + t.integer :color_id + end + create_table(:users, force: true) do |t| t.string :name end diff --git a/spec/support/models.rb b/spec/support/models.rb index d061aee..d15b378 100644 --- a/spec/support/models.rb +++ b/spec/support/models.rb @@ -13,6 +13,20 @@ class Post < ActiveRecord::Base scope(:published, -> { where(published: true) }) end +module RGB + class Color < ActiveRecord::Base + self.table_name = :rgb_colors + has_many :tags, class_name: 'Internal::TagName' + end +end + +module Internal + class TagName < ActiveRecord::Base + self.table_name = :internal_tag_names + belongs_to :color, class_name: 'RGB::Color', foreign_key: :color_id + end +end + RSpec.configure do |config| config.after do DatabaseCleaner.strategy = :truncation From fac26c85a890daae42702c29aebc7868cf99c7eb Mon Sep 17 00:00:00 2001 From: Ivanov-Anton Date: Thu, 4 Feb 2021 02:38:37 +0200 Subject: [PATCH 2/4] add bin/ folder in ignore section --- .rubocop.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.rubocop.yml b/.rubocop.yml index e3c8e31..729b845 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,7 @@ AllCops: TargetRubyVersion: 2.3 + Exclude: + - 'bin/**/*' # The default of 80 characters is a little to narrow. Metrics/LineLength: From d1eb35a858cf7e2775317af2a240f9e3bd03ee2c Mon Sep 17 00:00:00 2001 From: Tim Fischbach Date: Thu, 4 Feb 2021 12:59:02 +0100 Subject: [PATCH 3/4] Ensure end to end test makes ajax request Adapt test case for namespaced module to actually fetch the options to ensure that the constructed route actually works. --- spec/features/end_to_end_spec.rb | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/spec/features/end_to_end_spec.rb b/spec/features/end_to_end_spec.rb index 3bfdb3f..aeea510 100644 --- a/spec/features/end_to_end_spec.rb +++ b/spec/features/end_to_end_spec.rb @@ -72,32 +72,24 @@ end ActiveAdmin.register Internal::TagName, as: 'Tag Name' do - filter :color, as: :searchable_select, ajax: { resource: 'RGB::Color' } + filter :color, as: :searchable_select, ajax: { resource: RGB::Color } end - ActiveAdmin::SearchableSelect.inline_ajax_options = true ActiveAdmin.setup {} end end describe 'index page with searchable select filter' do - let!(:orange) { RGB::Color.create(code: '#eac112', description: 'Orange') } - let(:filters_options) { %w(Any #19bf25 #eac112) } - - let!(:other_records) do + it 'loads filter input options' do + RGB::Color.create(code: '#eac112', description: 'Orange') RGB::Color.create(code: '#19bf25', description: 'Green') - Internal::TagName.create(name: 'Important Guest', color: orange) - end - before { visit '/admin/tag_names' } + visit '/admin/tag_names' - it 'should have all created colors in filter' do - expect(page).to have_select :Color, options: filters_options - end + expand_select_box + wait_for_ajax - it 'should have selected option' do - select orange.code, from: :Color - expect(page).to have_select :Color, selected: orange.code + expect(select_box_items).to eq(%w(#eac112 #19bf25)) end end end From 07bf49f13b0dbd27750808f4e1c99034460d88bf Mon Sep 17 00:00:00 2001 From: Tim Fischbach Date: Thu, 4 Feb 2021 13:00:38 +0100 Subject: [PATCH 4/4] Always construct ajax url based on resource collection path No need to fall back to constructing it via `polymorphic_path` since if we cannot fine the admin resource to get `route_collection_path`, we will also not be able to use to determine `ajax_resource_class`. --- .../select_input_extension.rb | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/lib/activeadmin/searchable_select/select_input_extension.rb b/lib/activeadmin/searchable_select/select_input_extension.rb index cf9aff7..464adc4 100644 --- a/lib/activeadmin/searchable_select/select_input_extension.rb +++ b/lib/activeadmin/searchable_select/select_input_extension.rb @@ -45,19 +45,11 @@ def collection_from_options def ajax_url return unless options[:ajax] - template.polymorphic_path([active_admin_prefix, resource_route_name || ajax_resource_class], - action: option_collection.collection_action_name, - **ajax_params) - end - - def active_admin_prefix - template.active_admin_namespace.route_prefix - end - - def resource_route_name - active_admin_namespace = template.active_admin_namespace - str = active_admin_namespace.resource_for(ajax_resource_class)&.route_collection_path - str&.split('/')&.last + [ajax_resource.route_collection_path, + '/', + option_collection.collection_action_name, + '?', + ajax_params.to_query].join end def all_options_collection