From 0e92ca43fe7782a8d62ae9285a8d3de7857c9853 Mon Sep 17 00:00:00 2001 From: "M.Shibuya" Date: Wed, 14 Aug 2019 23:20:00 +0900 Subject: [PATCH] Fix be7d2f4a broke belongs_to with custom primary key Fixes #3184 --- .../adapters/mongoid/association.rb | 2 +- lib/rails_admin/config/actions/index.rb | 2 +- .../fields/types/belongs_to_association.rb | 4 ++ .../app/active_record/managing_user.rb | 5 +++ spec/dummy_app/app/mongoid/managing_user.rb | 5 +++ .../fields/belongs_to_association_spec.rb | 34 ++++++++++++++--- .../fields/has_many_association_spec.rb | 33 +++++++++++------ .../fields/has_one_assosiation_spec.rb | 37 +++++++++++++++++++ 8 files changed, 104 insertions(+), 18 deletions(-) diff --git a/lib/rails_admin/adapters/mongoid/association.rb b/lib/rails_admin/adapters/mongoid/association.rb index 9ebfca47f6..be35b677c3 100644 --- a/lib/rails_admin/adapters/mongoid/association.rb +++ b/lib/rails_admin/adapters/mongoid/association.rb @@ -41,7 +41,7 @@ def klass end def primary_key - :_id + association.primary_key.to_sym rescue :_id end def foreign_key diff --git a/lib/rails_admin/config/actions/index.rb b/lib/rails_admin/config/actions/index.rb index 7c48ba57e0..131ad1784a 100644 --- a/lib/rails_admin/config/actions/index.rb +++ b/lib/rails_admin/config/actions/index.rb @@ -49,7 +49,7 @@ class Index < RailsAdmin::Config::Actions::Base format.json do output = begin if params[:compact] - primary_key_method = @model_config.abstract_model.primary_key + primary_key_method = @association ? @association.associated_primary_key : @model_config.abstract_model.primary_key label_method = @model_config.object_label_method @objects.collect { |o| {id: o.send(primary_key_method).to_s, label: o.send(label_method).to_s} } else diff --git a/lib/rails_admin/config/fields/types/belongs_to_association.rb b/lib/rails_admin/config/fields/types/belongs_to_association.rb index 5719c6d3a5..ab24df509d 100644 --- a/lib/rails_admin/config/fields/types/belongs_to_association.rb +++ b/lib/rails_admin/config/fields/types/belongs_to_association.rb @@ -35,6 +35,10 @@ class BelongsToAssociation < RailsAdmin::Config::Fields::Association true end + def associated_primary_key + @associated_primary_key ||= association.primary_key + end + def selected_id bindings[:object].send(foreign_key) end diff --git a/spec/dummy_app/app/active_record/managing_user.rb b/spec/dummy_app/app/active_record/managing_user.rb index 29be614937..87d36a90f8 100644 --- a/spec/dummy_app/app/active_record/managing_user.rb +++ b/spec/dummy_app/app/active_record/managing_user.rb @@ -1,3 +1,8 @@ class ManagingUser < User + has_one :team, class_name: 'ManagedTeam', foreign_key: :manager, primary_key: :email, inverse_of: :user has_many :teams, class_name: 'ManagedTeam', foreign_key: :manager, primary_key: :email, inverse_of: :user + + def team_id=(id) + self.team = ManagedTeam.find_by_id(id) + end end diff --git a/spec/dummy_app/app/mongoid/managing_user.rb b/spec/dummy_app/app/mongoid/managing_user.rb index 29be614937..9bba8f3d79 100644 --- a/spec/dummy_app/app/mongoid/managing_user.rb +++ b/spec/dummy_app/app/mongoid/managing_user.rb @@ -1,3 +1,8 @@ class ManagingUser < User + has_one :team, class_name: 'ManagedTeam', foreign_key: :manager, primary_key: :email, inverse_of: :user has_many :teams, class_name: 'ManagedTeam', foreign_key: :manager, primary_key: :email, inverse_of: :user + + def team_id=(id) + self.team = ManagedTeam.where(_id: id).first + end end diff --git a/spec/integration/fields/belongs_to_association_spec.rb b/spec/integration/fields/belongs_to_association_spec.rb index ef09941b8a..e81b199698 100644 --- a/spec/integration/fields/belongs_to_association_spec.rb +++ b/spec/integration/fields/belongs_to_association_spec.rb @@ -42,18 +42,42 @@ end context 'with custom primary_key option' do - let(:user) { FactoryBot.create :managing_user } - let!(:teams) { [FactoryBot.create(:managed_team, manager: user.email), FactoryBot.create(:managed_team)] } + let(:users) { FactoryBot.create_list :managing_user, 2 } + let!(:teams) { [FactoryBot.create(:managed_team, manager: users[0].email), FactoryBot.create(:managed_team)] } before do - RailsAdmin.config.included_models = [ManagedTeam] + RailsAdmin.config.included_models = [ManagedTeam, ManagingUser] RailsAdmin.config ManagedTeam do field :user end end - it 'picks up associated primary key correctly' do + it 'allows update' do visit edit_path(model_name: 'managed_team', id: teams[0].id) - expect(page).to have_css("select#managed_team_manager option[value=\"#{user.id}\"]") + expect(page).to have_css("select#managed_team_manager option[value=\"#{users[0].email}\"]") + select("ManagingUser ##{users[1].id}", from: 'User') + click_button 'Save' + teams[0].reload + expect(teams[0].user).to eq users[1] + end + + context 'when fetching associated objects via xhr' do + before do + RailsAdmin.config ManagedTeam do + field(:user) { associated_collection_cache_all false } + end + end + + it 'allows update', js: true do + visit edit_path(model_name: 'managed_team', id: teams[0].id) + find('input.ra-filtering-select-input').set('M') + page.execute_script("$('input.ra-filtering-select-input').trigger('focus')") + page.execute_script("$('input.ra-filtering-select-input').trigger('keydown')") + expect(page).to have_selector('ul.ui-autocomplete li.ui-menu-item a') + page.execute_script %{$('ul.ui-autocomplete li.ui-menu-item a:contains("ManagingUser ##{users[1].id}")').trigger('mouseenter').click()} + click_button 'Save' + teams[0].reload + expect(teams[0].user).to eq users[1] + end end end end diff --git a/spec/integration/fields/has_many_association_spec.rb b/spec/integration/fields/has_many_association_spec.rb index 2f474d8402..432790575b 100644 --- a/spec/integration/fields/has_many_association_spec.rb +++ b/spec/integration/fields/has_many_association_spec.rb @@ -255,24 +255,35 @@ before do RailsAdmin.config.included_models = [ManagingUser, ManagedTeam] RailsAdmin.config ManagingUser do - field(:teams) { associated_collection_cache_all false } + field :teams end end - it "picks up associated model's primary key correctly" do + it "allows update" do visit edit_path(model_name: 'managing_user', id: user.id) expect(find("select#managing_user_team_ids option[value=\"#{teams[0].id}\"]")).to have_content teams[0].name - end - - it "allows update with fetching associated objects via xhr", js: true do - visit edit_path(model_name: 'managing_user', id: user.id) - find('input.ra-multiselect-search').set('T') - page.execute_script("$('input.ra-multiselect-search').trigger('focus')") - page.execute_script("$('input.ra-multiselect-search').trigger('keydown')") - find('.ra-multiselect-collection option', text: teams[1].name).select_option - find('.ra-multiselect-item-add').click + select(teams[1].name, from: 'Teams') click_button 'Save' expect(ManagingUser.first.teams).to match_array teams end + + context 'when fetching associated objects via xhr' do + before do + RailsAdmin.config ManagingUser do + field(:teams) { associated_collection_cache_all false } + end + end + + it "allows update", js: true do + visit edit_path(model_name: 'managing_user', id: user.id) + find('input.ra-multiselect-search').set('T') + page.execute_script("$('input.ra-multiselect-search').trigger('focus')") + page.execute_script("$('input.ra-multiselect-search').trigger('keydown')") + find('.ra-multiselect-collection option', text: teams[1].name).select_option + find('.ra-multiselect-item-add').click + click_button 'Save' + expect(ManagingUser.first.teams).to match_array teams + end + end end end diff --git a/spec/integration/fields/has_one_assosiation_spec.rb b/spec/integration/fields/has_one_assosiation_spec.rb index f17cdcffdf..ef681f9e9e 100644 --- a/spec/integration/fields/has_one_assosiation_spec.rb +++ b/spec/integration/fields/has_one_assosiation_spec.rb @@ -92,4 +92,41 @@ expect(@record.comment).to be_nil end end + + context 'with custom primary_key option' do + let(:user) { FactoryBot.create :managing_user } + let!(:team) { FactoryBot.create(:managed_team) } + before do + RailsAdmin.config.included_models = [ManagingUser, ManagedTeam] + RailsAdmin.config ManagingUser do + field :team + end + end + + it "allows update" do + visit edit_path(model_name: 'managing_user', id: user.id) + select(team.name, from: 'Team') + click_button 'Save' + expect(ManagingUser.first.team).to eq team + end + + context 'when fetching associated objects via xhr' do + before do + RailsAdmin.config ManagingUser do + field(:team) { associated_collection_cache_all false } + end + end + + it "allows update", js: true do + visit edit_path(model_name: 'managing_user', id: user.id) + find('input.ra-filtering-select-input').set('T') + page.execute_script("$('input.ra-filtering-select-input').trigger('focus')") + page.execute_script("$('input.ra-filtering-select-input').trigger('keydown')") + expect(page).to have_selector('ul.ui-autocomplete li.ui-menu-item a') + page.execute_script %{$('ul.ui-autocomplete li.ui-menu-item a:contains("#{team.name}")').trigger('mouseenter').click()} + click_button 'Save' + expect(ManagingUser.first.team).to eq team + end + end + end end