Returns true if the provided attribute is being cached.
# File lib/active_record/attribute_methods/read.rb, line 28 28: def cache_attribute?(attr_name) 29: cached_attributes.include?(attr_name) 30: end
cache_attributes allows you to declare which converted attribute values should be cached. Usually caching only pays off for attributes with expensive conversion methods, like time related columns (e.g. created_at, updated_at).
# File lib/active_record/attribute_methods/read.rb, line 17 17: def cache_attributes(*attribute_names) 18: cached_attributes.merge attribute_names.map { |attr| attr.to_s } 19: end
Returns the attributes which are cached. By default time related columns with datatype :datetime, :timestamp, :time, :date are cached.
# File lib/active_record/attribute_methods/read.rb, line 23 23: def cached_attributes 24: @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set 25: end
We want to generate the methods via module_eval rather than define_method, because define_method is slower on dispatch and uses more memory (because it creates a closure).
But sometimes the database might return columns with characters that are not allowed in normal method names (like ‘my_column(omg)’. So to work around this we first define with the temp identifier, and then use alias method to rename it to what we want.
# File lib/active_record/attribute_methods/read.rb, line 69 69: def define_method_attribute(attr_name) 70: generated_attribute_methods.module_eval def __temp__ #{internal_attribute_access_code(attr_name, attribute_cast_code(attr_name))} end alias_method '#{attr_name}', :__temp__ undef_method :__temp__, __FILE__, __LINE__ + 1 71: end
# File lib/active_record/attribute_methods/read.rb, line 119 119: def attribute_cast_code(attr_name) 120: columns_hash[attr_name].type_cast_code('v') 121: end
# File lib/active_record/attribute_methods/read.rb, line 91 91: def cacheable_column?(column) 92: attribute_types_cached_by_default.include?(column.type) 93: end
# File lib/active_record/attribute_methods/read.rb, line 81 81: def define_external_attribute_method(attr_name) 82: generated_external_attribute_methods.module_eval def __temp__(v, attributes, attributes_cache, attr_name) #{external_attribute_access_code(attr_name, attribute_cast_code(attr_name))} end alias_method '#{attr_name}', :__temp__ undef_method :__temp__, __FILE__, __LINE__ + 1 83: end
# File lib/active_record/attribute_methods/read.rb, line 109 109: def external_attribute_access_code(attr_name, cast_code) 110: access_code = "v && #{cast_code}" 111: 112: if cache_attribute?(attr_name) 113: access_code = "attributes_cache[attr_name] ||= (#{access_code})" 114: end 115: 116: access_code 117: end
# File lib/active_record/attribute_methods/read.rb, line 95 95: def internal_attribute_access_code(attr_name, cast_code) 96: access_code = "(v=@attributes[attr_name]) && #{cast_code}" 97: 98: unless attr_name == primary_key 99: access_code.insert(0, "missing_attribute(attr_name, caller) unless @attributes.has_key?(attr_name); ") 100: end 101: 102: if cache_attribute?(attr_name) 103: access_code = "@attributes_cache[attr_name] ||= (#{access_code})" 104: end 105: 106: "attr_name = '#{attr_name}'; #{access_code}" 107: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.