Skip to content

Instantly share code, notes, and snippets.

@tjbarker
Created August 27, 2021 05:59
Show Gist options
  • Save tjbarker/daeb4ee12012b52a79aeaaacb3801a13 to your computer and use it in GitHub Desktop.
Save tjbarker/daeb4ee12012b52a79aeaaacb3801a13 to your computer and use it in GitHub Desktop.
active admin, polymorphic drop down
# this is a helper method to provide setters for polymorphic relationships in active admin forms
# attribute_name: name that record knows polymorphic relationship as
# actions: the active record actions that should use this setter, defaults to setter being implemented before create and update
def polymorphic_attribute_set(attribute_name, actions: [:before_create, :before_update])
klass = config.resource_class
foreign_key = klass.reflect_on_all_associations.find { |ref| ref.name == attribute_name }.association_foreign_key
setter = lambda do |rec|
record = ApplicationRecord.identifier_to_record(params[klass.name.snakecase][foreign_key])
resource.send("#{attribute_name}=", record)
end
actions.each { |action| send(action, &setter) }
end
# this is a helper to provide a polymorphic dropdown that will interact with the above polymorphic attribute setter
# f: is the form in which the select is to be placed
# key: is the name of the polymorphic attribute on the record
# options: are the records to be selected from
# selected: is the record to prefill selection with
# display: is the method to call on each option to display in the dropdown
# other options for the select can also be appended as named params
def polymorphic_select(f, key, options, selected: nil, display: :to_s, **opts)
options_list = options.flatten.map { |opt| [opt.send(display), ApplicationRecord.record_to_identifier(opt)] }
f.input key, as: :select, collection: options_for_select(options_list, selected&.identifier), **opts
end
ActiveAdmin.register Foo do
permit_params :bar
# will set bar on record before create and update
polymorphic_attribute_set :bar
form do |f|
# adds drop down with list of all Baz and Buzz instances for selection as resource's bar
polymorphic_select(f, :bar, [Baz.all, Buzz.all], selected: resource.bar)
end
end
IDENTIFICATION_JOINER = '>><<'.freeze
def record_to_identifier(record)
[record.class.name, record.id].join(IDENTIFICATION_JOINER)
end
# WARNING: may raise NameError if identifier cannot be constantized
def self.identifier_to_record(identifier)
return if identifier.blank?
record_klass_string, record_id = identifier.split(IDENTIFICATION_JOINER)
record_klass = record_klass_string.constantize
record_klass.find_by(record_klass.primary_key => record_id)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment