Skip to content

Commit

Permalink
Fix breaking with has_many and custom primary key. Fixes #1878
Browse files Browse the repository at this point in the history
  • Loading branch information
mshibuya committed Jun 25, 2019
1 parent 4ea4575 commit be7d2f4
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 5 deletions.
2 changes: 1 addition & 1 deletion lib/rails_admin/config/actions/index.rb
Expand Up @@ -49,7 +49,7 @@ class Index < RailsAdmin::Config::Actions::Base
format.json do
output = begin
if params[:compact]
primary_key_method = @association ? @association.associated_primary_key : @model_config.abstract_model.primary_key
primary_key_method = @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
Expand Down
2 changes: 1 addition & 1 deletion lib/rails_admin/config/fields/association.rb
Expand Up @@ -78,7 +78,7 @@ def associated_object_label_method

# Reader for associated primary key
def associated_primary_key
@associated_primary_key ||= association.primary_key
@associated_primary_key ||= associated_model_config.abstract_model.primary_key
end

# Reader for the association's key
Expand Down
7 changes: 4 additions & 3 deletions spec/controllers/rails_admin/main_controller_spec.rb
Expand Up @@ -204,14 +204,15 @@ def get(action, params)
end

describe 'index' do
it "uses source association's primary key with :compact, not target model's default primary key", skip_mongoid: true do
it "uses target model's primary key", skip_mongoid: true do
@player = FactoryBot.create(:player, number: 123)
class TeamWithNumberedPlayers < Team
has_many :numbered_players, class_name: 'Player', primary_key: :number, foreign_key: 'team_id'
end
FactoryBot.create :team
TeamWithNumberedPlayers.first.numbered_players = [FactoryBot.create(:player, number: 123)]
TeamWithNumberedPlayers.first.numbered_players = [@player]
get :index, model_name: 'player', source_object_id: Team.first.id, source_abstract_model: 'team_with_numbered_players', associated_collection: 'numbered_players', current_action: :create, compact: true, format: :json
expect(response.body).to match(/\"id\":\"123\"/)
expect(response.body).to match(/\"id\":\"#{@player.id}\"/)
end

context 'as JSON' do
Expand Down
19 changes: 19 additions & 0 deletions spec/integration/fields/belongs_to_association_spec.rb
Expand Up @@ -40,4 +40,23 @@
is_expected.to have_css("a[href='/admin/team/#{@team.id}']")
end
end

context 'with custom primary_key option', active_record: true do
let(:user) { FactoryBot.create :user }
let!(:teams) { [FactoryBot.create(:team, manager: user.email), FactoryBot.create(:team)] }
before do
class ManagedTeam < Team
belongs_to :user, foreign_key: :manager, primary_key: :email
end
RailsAdmin.config.included_models = [ManagedTeam]
RailsAdmin.config ManagedTeam do
field :user
end
end

it 'picks up associated primary key correctly' 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}\"]")
end
end
end
30 changes: 30 additions & 0 deletions spec/integration/fields/has_many_association_spec.rb
Expand Up @@ -248,4 +248,34 @@
is_expected.to have_selector('a.ra-multiselect-item-remove-all')
end
end

context 'with custom primary_key option', active_record: true do
let(:user) { FactoryBot.create :user }
let!(:teams) { [FactoryBot.create(:team, manager: user.email), FactoryBot.create(:team)] }
before do
class ManagingUser < User
has_many :teams, foreign_key: :manager, primary_key: :email
end
RailsAdmin.config.included_models = [ManagingUser, Team]
RailsAdmin.config ManagingUser do
field(:teams) { associated_collection_cache_all false }
end
end

it "picks up associated model's primary key correctly" 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
click_button 'Save'
expect(ManagingUser.first.teams).to match_array teams
end
end
end

0 comments on commit be7d2f4

Please sign in to comment.