Module | Cms::Behaviors::DynamicAttributes::MacroMethods |
In: |
lib/cms/behaviors/dynamic_attributes.rb
|
Will make the current class have dynamic attributes.
# File lib/cms/behaviors/dynamic_attributes.rb, line 125 125: def has_dynamic_attributes(options={}) 126: @has_dynamic_attributes = true 127: include InstanceMethods 128: 129: # Provide default options 130: options[:class_name] ||= self.class_name + 'Attribute' 131: options[:table_name] ||= options[:class_name].tableize 132: options[:relationship_name] ||= options[:class_name].tableize.to_sym 133: options[:foreign_key] ||= self.class_name.foreign_key 134: options[:base_foreign_key] ||= self.name.underscore.foreign_key 135: options[:name_field] ||= 'name' 136: options[:value_field] ||= 'value' 137: options[:fields].collect! {|f| f.to_s} unless options[:fields].nil? 138: 139: # Init option storage if necessary 140: cattr_accessor :dynamic_options 141: self.dynamic_options ||= Hash.new 142: 143: # Return if already processed. 144: return if self.dynamic_options.keys.include? options[:class_name] 145: 146: # Attempt to load related class. If not create it 147: begin 148: options[:class_name].constantize 149: rescue 150: Object.const_set(options[:class_name], 151: Class.new(ActiveRecord::Base)).class_eval do 152: def self.reloadable? #:nodoc: 153: false 154: end 155: end 156: end 157: 158: # Store options 159: self.dynamic_options[options[:class_name]] = options 160: 161: # Modify attribute class 162: attribute_class = options[:class_name].constantize 163: base_class = self.name.underscore.to_sym 164: attribute_class.class_eval do 165: belongs_to base_class, :foreign_key => options[:base_foreign_key] 166: alias_method :base, base_class # For generic access 167: end 168: 169: # Modify main class 170: class_eval do 171: has_many options[:relationship_name], 172: :class_name => options[:class_name], 173: :table_name => options[:table_name], 174: :foreign_key => options[:foreign_key], 175: :dependent => :destroy 176: 177: # The following is only setup once 178: unless private_method_defined? :method_missing_without_dynamic_attributes 179: 180: # Carry out delayed actions before save 181: after_validation_on_update :save_modified_dynamic_attributes 182: 183: # Make attributes seem real 184: alias_method :method_missing_without_dynamic_attributes, :method_missing 185: alias_method :method_missing, :method_missing_with_dynamic_attributes 186: 187: private 188: 189: alias_method :read_attribute_without_dynamic_attributes, :read_attribute 190: alias_method :read_attribute, :read_attribute_with_dynamic_attributes 191: alias_method :write_attribute_without_dynamic_attributes, :write_attribute 192: alias_method :write_attribute, :write_attribute_with_dynamic_attributes 193: 194: end 195: end 196: end