Module: EnterpriseMti::ClassMethods
- Defined in:
- lib/enterprise_mti/class_methods/class_methods.rb
Instance Method Summary collapse
- #has_one_superclass(superclass_symbol, options = {}) ⇒ Object
- #has_subclass(subclass_symbol, options = {}) ⇒ Object
- #is_a_superclass ⇒ Object
Instance Method Details
#has_one_superclass(superclass_symbol, options = {}) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/enterprise_mti/class_methods/class_methods.rb', line 82 def has_one_superclass(superclass_symbol, ={}) superclass_name = superclass_symbol.to_s.camelize superclass_qualified_name = ([:module] || '') + '::' + superclass_name superclass = superclass_qualified_name.constantize container_class = self container_class_camel_name = self.name.demodulize container_class_underscore_name = self.name.demodulize.underscore superclass_relation_name = superclass_symbol.to_s + "_superclass" superclass_relation_symbol = superclass_relation_name.to_sym has_one superclass_relation_symbol, class_name: superclass_qualified_name # Create build and create methods for each subclass superclass.descendants.each do |subclass| subclass_underscore_name = subclass.name.demodulize.underscore actions = [:build, :create, :create!] actions.each do |action| action_suffix = nil action_name = action.to_s if action.to_s.last(1) == '!' action_suffix = '!' action_name = action.to_s[0..-2] end subclass.define_singleton_method "#{action_name}_with_superclass_instance#{action_suffix}" do |*args, &block| self.send("#{action_name}#{action_suffix}", *args, &block).superclass_instance = args.last[:superclass_instance] end superclass.class_eval do define_method "#{action_name}_#{subclass_underscore_name}_subclass#{action_suffix}" do |*args, &block| args.last[:superclass_instance] = self subclass.send "#{action_name}_with_superclass_instance#{action_suffix}", *args, &block end define_method "#{subclass_underscore_name}_with_superclass_instance=" do |value| value.superclass_instance = self self.send "#{subclass_underscore_name}=", value end end container_class.class_eval do define_method "#{action_name}_#{subclass_underscore_name}#{action_suffix}" do |*args, &block| unless superclass_instance = self.send(superclass_relation_symbol) superclass_instance = self.send("build_#{superclass_relation_name}") end superclass_instance.instance_eval do send "#{action_name}_#{subclass_underscore_name}_subclass#{action_suffix}", *args, &block end end end end end # Create getter define_method superclass_symbol do association_methods = superclass.descendants.collect { |subclass| reflection_symbol = subclass.to_s.demodulize.underscore.to_sym assoc = superclass.reflect_on_association(reflection_symbol) assoc ? assoc.name : nil }.compact if superclass_model_instance = self.send(superclass_relation_symbol) association_methods.collect{ |a| superclass_model_instance.send a }.inject do |a, b| a || b end end end # Create setter define_method "#{superclass_symbol.to_s}=" do |value| reflection_symbol = value.class.name.demodulize.underscore.to_sym unless superclass_instance = self.send(superclass_relation_symbol) superclass_instance = self.send("build_#{superclass_relation_name}") end reflection_assignment_method = superclass.reflect_on_association(reflection_symbol).name.to_s + '_with_superclass_instance=' superclass_instance.send reflection_assignment_method, value end end |
#has_subclass(subclass_symbol, options = {}) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/enterprise_mti/class_methods/class_methods.rb', line 3 def has_subclass(subclass_symbol, ={}) subclass_name = subclass_symbol.to_s.camelize subclass = nil subclass_qualified_name = ([:module] || '') + '::' + subclass_name superclass = self superclass_name = self.name.demodulize.underscore superclass_symbol = self.name.demodulize.underscore.to_sym table_name = [:table_name] || subclass_symbol.to_s.pluralize # Get subclass Kernel.const_get([:module] || 'Kernel').module_eval { subclass = const_get subclass_name } subclass.class_eval do # Set table name on subclass to prevent it from inheriting # superclass' attributes, etc. self.table_name = table_name has_one superclass_symbol attr_accessor :superclass_instance validates :superclass_instance, presence: true define_method "#{superclass_name}_transaction" do superclass_instance.send "#{subclass_symbol.to_s}_id=", self.id superclass_instance.save end after_save "#{superclass_name}_transaction".to_sym, on: :create end # Superclass belongs to subclass self.belongs_to subclass_symbol, :class_name => subclass_qualified_name end |
#is_a_superclass ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/enterprise_mti/class_methods/class_methods.rb', line 36 def is_a_superclass # Require subclasses' files as dependencies, otherwise we get circular # dependency errors (see https://github.com/rails/rails/issues/3364) if descendants.empty? module_path_tokens = self.name.underscore.split('/') module_path_tokens[-1] += '_subclasses' Dir[Rails.root.join('app', 'models', File.join(module_path_tokens), "*.rb")].each do |file| require_dependency file end end # Call has_sublcass on the superclass for each subclass descendants.each do |subclass| name_tokens = subclass.to_s.split('::') subclass_name = name_tokens.last module_name = name_tokens[0...-1].join('::') if name_tokens.count > 1 self.send :has_subclass, subclass_name.underscore.to_sym, :module => module_name end # Populate container_classes, an array that contains classes that "have" # the superclass (and thus have foreign key constraints on the # superclass) reflection_class = Proc.new do |r| if r.[:class_name] r.[:class_name].constantize else prefix = self.name.deconstantize || '' "#{prefix}::#{r.name.to_s.camelize}".constantize end end @container_classes = self.reflect_on_all_associations.keep_if { |r| r.macro == :belongs_to && #self.column_names.include?(r.association_foreign_key) && !self.descendants.include?(reflection_class.call(r)) }.collect { |r| reflection_class.call(r) } # Add read-only access to container_classes class << self def container_classes @container_classes end end end |