module ActiveRecord::Mti::ClassMethods
Public Class Methods
as_base_instance() { || ... }
click to toggle source
Thread safe execution of a block in a “base instance mode”
# File lib/mti.rb, line 55 def self.as_base_instance @@base_instance_mode_lock.synchronize do @@base_instance_mode = true result = yield @@base_instance_mode = false result end end
instantiate(*_)
click to toggle source
Override ActiveRecord's instantiation method which builds an object from a record Return the base class object when in “base instance mode” and the implementation object otherwise
Calls superclass method
# File lib/mti.rb, line 46 def self.instantiate(*_) if @@base_instance_mode super else super.public_send(mti_name) end end
Public Instance Methods
mti_base()
click to toggle source
# File lib/mti.rb, line 27 def mti_base class_attribute :mti_name self.mti_name = self.to_s.underscore.to_sym @@base_instance_mode = false @@base_instance_mode_lock = Mutex.new # Always fetch with the implementation default_scope lambda { includes(mti_name) } # Implementation model association belongs_to mti_name, polymorphic: true, inverse_of: mti_name # Override ActiveRecord's instantiation method # which builds an object from a record # Return the base class object when in "base instance mode" # and the implementation object otherwise def self.instantiate(*_) if @@base_instance_mode super else super.public_send(mti_name) end end # Thread safe execution of a block in a "base instance mode" def self.as_base_instance @@base_instance_mode_lock.synchronize do @@base_instance_mode = true result = yield @@base_instance_mode = false result end end end
mti_implementation_of(mti_base_name)
click to toggle source
# File lib/mti.rb, line 65 def mti_implementation_of(mti_base_name) class_attribute :mti_base self.mti_base = mti_base_name.to_s.classify.constantize # Base model association has_one mti_base_name.to_sym, :as => mti_base_name.to_sym, :autosave => true, :dependent => :destroy, :validate => true, :inverse_of => mti_base_name.to_sym # When calling the base object from the implementation # switch the base's class to the "base instance mode" # to receive the base class object instead of another # implementation object and avoid an infinite loop define_method "#{mti_base_name}_with_reverse" do # def role_with_reverse mti_base.as_base_instance do # Role.as_base_instance do send("#{mti_base_name}_without_reverse") # role_without_reverse end # end end # end alias_method_chain mti_base_name, :reverse # alias_method_chain :role, :reverse # Auto build base model define_method "#{mti_base_name}_with_autobuild" do # def role_with_autobuild public_send("#{mti_base_name}_without_autobuild") || # role_without_autobuild || public_send("build_#{mti_base_name}") # build_role end # end alias_method_chain mti_base_name, :autobuild # alias_method_chain :role, :autobuild # Delegate attributes mti_base.content_columns.map(&:name).each do |attr| delegate attr, "#{attr}=", "#{attr}?", :to => mti_base_name.to_sym end # Delegate associations mti_base.reflections.keys .tap { |k| k.delete(mti_base_name.to_sym) } .each do |association| delegate association, "#{association}=", :to => mti_base_name.to_sym end delegate_missing_to mti_base_name accepts_nested_attributes_for mti_base_name define_method "#{mti_base_name}_id" do public_send(mti_base_name).id end end