Last active
April 20, 2023 01:18
-
-
Save leehericks/4f05b83acae8b188b1693220cd8663ce to your computer and use it in GitHub Desktop.
Alias delegated types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module DelegatedTypeAliasing | |
extend ActiveSupport::Concern | |
class_methods do | |
def delegated_type(role, types:, **options) | |
if types.is_a?(Hash) | |
aliases = types.stringify_keys! | |
types = types.keys | |
elsif options.delete(:demodulized_aliases) | |
aliases = generate_delegated_type_demodulized_aliases(types) | |
else | |
raise "#{self.model_name}.delegated_type(:#{role}) supplied invalid types:" unless types.is_a?(Array) | |
aliases = {} | |
end | |
super | |
alias_delegated_types(aliases) | |
define_singleton_method("#{role}_types") { types.freeze } | |
define_singleton_method("#{role}_type_aliases") { aliases.freeze } | |
end | |
def has_many_delegated_type(role, through:, prefix: nil) | |
role = role.to_s.singularize | |
klass = reflect_on_association(through).klass | |
types = klass.public_send("#{role}_types") | |
aliases = klass.public_send("#{role}_type_aliases") | |
types.each do |type| | |
scope_name = (aliases[type] || type).tableize.gsub("/", "_") | |
assoc_name = prefix.present? ? "#{prefix}_#{scope_name}" : scope_name | |
has_many assoc_name.to_sym, through: through, source: role, source_type: type | |
end | |
end | |
private | |
def generate_delegated_type_demodulized_aliases(types) | |
types.map do |type| | |
type_alias = type.demodulize | |
[type, type_alias] unless type == type_alias | |
end.compact.to_h | |
end | |
def alias_delegated_types(aliases) | |
aliases.each do |type, type_alias| | |
scope_name = type.tableize.gsub("/", "_") | |
singular = scope_name.singularize | |
query = "#{singular}?" | |
scope_name_alias = type_alias.tableize.gsub("/", "_") | |
singular_alias = scope_name_alias.singularize | |
query_alias = "#{singular_alias}?" | |
singleton_class.send(:alias_method, :"#{scope_name_alias}", :"#{scope_name}") | |
alias_method :"#{query_alias}", :"#{query}" | |
alias_method :"#{singular_alias}", :"#{singular}" | |
alias_method :"#{singular_alias}_id", :"#{singular}_id" | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Lms::Program::Membership < ApplicationRecord | |
include DelegatedTypeAliasing | |
belongs_to :program | |
belongs_to :user | |
delegated_type :membershipable, types: %w[ Lms::Program::Staffing Lms::Program::Enrollment ], demodulized_aliases: true, inverse_of: :membership, dependent: :destroy | |
scope :active, -> { where(ends_at: nil) } | |
validates :user, uniqueness: { scope: [:program, :ends_at] } | |
def self.create_staffing(program:, user:, manages: false, teaches: false) | |
create! program: program, user: user, membershipable: Lms::Program::Staffing.new(manages: manages, teaches: teaches) | |
end | |
def self.create_enrollment(program:, user:) | |
create! program: program, user: user, membershipable: Lms::Program::Enrollment.new | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment