Skip to content

Commit 42f0a5f

Browse files
committed
Provide has_one id setters/getters, eliminating the need for explicitly defining them
Closes #2625
1 parent af88091 commit 42f0a5f

7 files changed

Lines changed: 81 additions & 20 deletions

File tree

lib/rails_admin/adapters/active_record/object_extension.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@ module RailsAdmin
22
module Adapters
33
module ActiveRecord
44
module ObjectExtension
5+
def self.extended(object)
6+
object.class.reflect_on_all_associations.each do |association|
7+
association = Association.new(association, object.class)
8+
case association.type
9+
when :has_one
10+
object.instance_eval <<-RUBY, __FILE__, __LINE__ + 1
11+
def #{association.name}_id
12+
self.#{association.name}&.id
13+
end
14+
15+
def #{association.name}_id=(item_id)
16+
self.#{association.name} = #{association.klass}.find_by_id(item_id)
17+
end
18+
RUBY
19+
end
20+
end
21+
end
22+
523
def assign_attributes(attributes)
624
super if attributes
725
end

lib/rails_admin/adapters/mongoid/object_extension.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ def self.extended(object)
1818
send(name)&.save
1919
end
2020
end
21+
object.instance_eval <<-RUBY, __FILE__, __LINE__ + 1
22+
def #{name}_id=(item_id)
23+
self.#{name} = (#{association.klass}.find(item_id) rescue nil)
24+
end
25+
RUBY
2126
end
2227
end
2328
end

lib/rails_admin/config/fields/types/has_one_association.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ class HasOneAssociation < RailsAdmin::Config::Fields::Association
1717
(o = value) && o.send(associated_model_config.object_label_method)
1818
end
1919

20-
def editable?
21-
(nested_form || abstract_model.model.new.respond_to?("#{name}_id=")) && super
22-
end
23-
2420
def selected_id
2521
value.try :id
2622
end

spec/dummy_app/app/active_record/player.rb

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,4 @@ class Player < ActiveRecord::Base
1717
scope :rails_admin_search, ->(query) { where(name: query.reverse) }
1818

1919
def destroy_hook; end
20-
21-
def draft_id
22-
draft.try :id
23-
end
24-
25-
def draft_id=(id)
26-
self.draft = Draft.find_by_id(id)
27-
end
2820
end

spec/dummy_app/app/mongoid/player.rb

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,4 @@ class Player
3131
scope :rails_admin_search, ->(query) { where(name: query.reverse) }
3232

3333
def destroy_hook; end
34-
35-
def draft_id
36-
draft.try :id
37-
end
38-
39-
def draft_id=(id)
40-
self.draft = Draft.where(_id: id).first
41-
end
4234
end

spec/rails_admin/adapters/active_record/object_extension_spec.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,52 @@
99
expect(object.assign_attributes(nil)).to be nil
1010
end
1111
end
12+
13+
describe 'has_one association' do
14+
let(:draft) { FactoryBot.create(:draft) }
15+
let(:player) { FactoryBot.build(:player).extend(RailsAdmin::Adapters::ActiveRecord::ObjectExtension) }
16+
before do
17+
class PlayerWithAutoSave < Player
18+
has_one :draft, inverse_of: :player, foreign_key: :player_id, autosave: true
19+
end
20+
end
21+
22+
it 'provides id getter' do
23+
player.draft = draft
24+
expect(player.draft_id).to eq draft.id
25+
end
26+
27+
context 'on create' do
28+
before do
29+
player.draft_id = draft.id
30+
expect(player.draft).to receive(:save).once.and_call_original
31+
player.save
32+
end
33+
34+
it 'persists associated documents changes on save' do
35+
expect(player.reload.draft).to eq draft
36+
end
37+
end
38+
39+
context 'on update' do
40+
let(:player) { FactoryBot.create(:player).extend(RailsAdmin::Adapters::ActiveRecord::ObjectExtension) }
41+
before do
42+
player.draft_id = draft.id
43+
end
44+
45+
it 'persists associated documents changes on assignment' do
46+
expect(player.reload.draft).to eq draft
47+
end
48+
end
49+
50+
context 'with explicit id setter' do
51+
let(:user) { ManagingUser.create(FactoryBot.attributes_for(:user)) }
52+
let(:team) { ManagedTeam.create(FactoryBot.attributes_for(:team)) }
53+
54+
it 'works without issues' do
55+
user.team_id = team.id
56+
expect(user.reload.team).to eq team
57+
end
58+
end
59+
end
1260
end

spec/rails_admin/adapters/mongoid/object_extension_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,15 @@ class PlayerWithAutoSave < Player
110110
end
111111
end
112112
end
113+
114+
context 'with explicit id setter' do
115+
let(:user) { ManagingUser.create(FactoryBot.attributes_for(:user)) }
116+
let(:team) { ManagedTeam.create(FactoryBot.attributes_for(:team)) }
117+
118+
it 'works without issues' do
119+
user.team_id = team.id
120+
expect(user.reload.team).to eq team
121+
end
122+
end
113123
end
114124
end

0 commit comments

Comments
 (0)