Skip to content

Commit 53b89c9

Browse files
committed
ActiveRecord 7.1 composite primary keys support
1 parent 5245d5b commit 53b89c9

37 files changed

+281
-191
lines changed

.rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ Metrics/BlockNesting:
109109

110110
Metrics/ClassLength:
111111
CountComments: false
112-
Max: 200 # TODO: Lower to 100
112+
Max: 201 # TODO: Lower to 100
113113

114114
Metrics/CyclomaticComplexity:
115115
Max: 15 # TODO: Lower to 6

.rubocop_todo.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Lint/ReturnInVoidContext:
2121
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
2222
# IgnoredMethods: refine
2323
Metrics/BlockLength:
24-
Max: 1119
24+
Max: 1135
2525

2626
# Offense count: 1
2727
# Configuration parameters: Max, CountKeywordArgs.

app/helpers/rails_admin/form_builder.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ def dom_name(field)
108108
end
109109

110110
def hidden_field(method, options = {})
111-
if method == :id
112-
super method, {value: object.id.to_s}
111+
if method == :id && object.id.is_a?(Array)
112+
super method, {value: RailsAdmin.config.composite_keys_serializer.serialize(object.id)}
113113
else
114114
super
115115
end

config/initializers/active_record_extensions.rb

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,4 @@ def safe_send(value)
2020
end
2121
end
2222
end
23-
24-
if defined?(CompositePrimaryKeys)
25-
# Apply patch until the fix is released:
26-
# https://github.com/composite-primary-keys/composite_primary_keys/pull/572
27-
CompositePrimaryKeys::CompositeKeys.class_eval do
28-
alias_method :to_param, :to_s
29-
end
30-
31-
CompositePrimaryKeys::CollectionAssociation.prepend(Module.new do
32-
def ids_writer(ids)
33-
if reflection.association_primary_key.is_a? Array
34-
ids = CompositePrimaryKeys.normalize(Array(ids).reject(&:blank?), reflection.association_primary_key.size)
35-
reflection.association_primary_key.each_with_index do |primary_key, i|
36-
pk_type = klass.type_for_attribute(primary_key)
37-
ids.each do |id|
38-
id[i] = pk_type.cast(id[i]) if id.is_a? Array
39-
end
40-
end
41-
end
42-
super ids
43-
end
44-
end)
45-
end
4623
end

lib/rails_admin/abstract_model.rb

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,17 +105,20 @@ def each_associated_children(object)
105105
end
106106
end
107107

108+
def format_id(id)
109+
id
110+
end
111+
112+
def parse_id(id)
113+
id
114+
end
115+
108116
private
109117

110118
def initialize_active_record
111119
@adapter = :active_record
112-
if defined?(::CompositePrimaryKeys)
113-
require 'rails_admin/adapters/composite_primary_keys'
114-
extend Adapters::CompositePrimaryKeys
115-
else
116-
require 'rails_admin/adapters/active_record'
117-
extend Adapters::ActiveRecord
118-
end
120+
require 'rails_admin/adapters/active_record'
121+
extend Adapters::ActiveRecord
119122
end
120123

121124
def initialize_mongoid

lib/rails_admin/adapters/active_record.rb

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def new(params = {})
1515
end
1616

1717
def get(id, scope = scoped)
18-
object = scope.where(primary_key => id).first
18+
object = primary_key_scope(scope, id).first
1919
return unless object
2020

2121
object.extend(ObjectExtension)
@@ -115,10 +115,42 @@ def adapter_supports_joins?
115115
true
116116
end
117117

118+
def format_id(id)
119+
if primary_key.is_a? Array
120+
RailsAdmin.config.composite_keys_serializer.serialize(id)
121+
else
122+
id
123+
end
124+
end
125+
126+
def parse_id(id)
127+
if primary_key.is_a?(Array)
128+
ids = RailsAdmin.config.composite_keys_serializer.deserialize(id)
129+
primary_key.each_with_index do |key, i|
130+
ids[i] = model.type_for_attribute(key).cast(ids[i])
131+
end
132+
ids
133+
else
134+
id
135+
end
136+
end
137+
118138
private
119139

140+
def primary_key_scope(scope, id)
141+
if primary_key.is_a? Array
142+
scope.where(primary_key.zip(parse_id(id)).to_h)
143+
else
144+
scope.where(primary_key => id)
145+
end
146+
end
147+
120148
def bulk_scope(scope, options)
121-
scope.where(primary_key => options[:bulk_ids])
149+
if primary_key.is_a? Array
150+
options[:bulk_ids].map { |id| primary_key_scope(scope, id) }.reduce(&:or)
151+
else
152+
scope.where(primary_key => options[:bulk_ids])
153+
end
122154
end
123155

124156
def sort_scope(scope, options)

lib/rails_admin/adapters/active_record/association.rb

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,29 @@ def klass
4242
def primary_key
4343
return nil if polymorphic?
4444

45-
case type
46-
when :has_one
47-
association.klass.primary_key
45+
value =
46+
case type
47+
when :has_one
48+
association.klass.primary_key
49+
else
50+
association.association_primary_key
51+
end
52+
53+
if value.is_a? Array
54+
:id
4855
else
49-
association.association_primary_key
50-
end.try(:to_sym)
56+
value.to_sym
57+
end
5158
end
5259

5360
def foreign_key
54-
association.foreign_key.to_sym
61+
if association.options[:query_constraints].present?
62+
association.options[:query_constraints].map(&:to_sym)
63+
elsif association.foreign_key.is_a?(Array)
64+
association.foreign_key.map(&:to_sym)
65+
else
66+
association.foreign_key.to_sym
67+
end
5568
end
5669

5770
def foreign_key_nullable?
@@ -75,7 +88,11 @@ def key_accessor
7588
when :has_one
7689
:"#{name}_id"
7790
else
78-
foreign_key
91+
if foreign_key.is_a?(Array)
92+
:"#{name}_id"
93+
else
94+
foreign_key
95+
end
7996
end
8097
end
8198

lib/rails_admin/adapters/composite_primary_keys.rb

Lines changed: 0 additions & 40 deletions
This file was deleted.

lib/rails_admin/adapters/composite_primary_keys/association.rb

Lines changed: 0 additions & 45 deletions
This file was deleted.

lib/rails_admin/config.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require 'rails_admin/config/lazy_model'
44
require 'rails_admin/config/sections/list'
5+
require 'rails_admin/support/composite_keys_serializer'
56
require 'active_support/core_ext/module/attribute_accessors'
67

78
module RailsAdmin
@@ -84,6 +85,9 @@ class << self
8485
# Set where RailsAdmin fetches JS/CSS from, defaults to :sprockets
8586
attr_writer :asset_source
8687

88+
# For customization of composite keys representation
89+
attr_accessor :composite_keys_serializer
90+
8791
# Setup authentication to be run as a before filter
8892
# This is run inside the controller instance so you can setup any authentication you need to
8993
#
@@ -329,6 +333,7 @@ def reset
329333
@navigation_static_links = {}
330334
@navigation_static_label = nil
331335
@asset_source = nil
336+
@composite_keys_serializer = RailsAdmin::Support::CompositeKeysSerializer
332337
@parent_controller = '::ActionController::Base'
333338
@forgery_protection_settings = {with: :exception}
334339
RailsAdmin::Config::Actions.reset

0 commit comments

Comments
 (0)