Skip to content

Commit

Permalink
rm cached attributes
Browse files Browse the repository at this point in the history
The original patch that added this concept can be found
[here](https://web.archive.org/web/20090601022739/http://dev.rubyonrails.org/ticket/9767).
The current default behavior is to cache everything except serialized
columns, unless the user specified otherwise. If anyone were to specify
otherwise, many types would actually be completely broken. Still, the
method is left in place with a deprecation warning in case anyone is
actually still calling this method.
  • Loading branch information
sgrif committed Jun 11, 2014
1 parent ef4e078 commit 66736c8
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 73 deletions.
4 changes: 4 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
* Remove `cache_attributes` and friends. All attributes are cached.

*Sean Griffin*

* Remove deprecated method `ActiveRecord::Base.quoted_locking_column`.

*Akshay Vishnoi*
Expand Down
49 changes: 11 additions & 38 deletions activerecord/lib/active_record/attribute_methods/read.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,35 +35,22 @@ def #{method_name}

extend ActiveSupport::Concern

ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :time, :date]

included do
class_attribute :attribute_types_cached_by_default, instance_writer: false
self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
end

module ClassMethods
# +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+).
def cache_attributes(*attribute_names)
cached_attributes.merge attribute_names.map { |attr| attr.to_s }
[:cache_attributes, :cached_attributes, :cache_attribute?].each do |method_name|
define_method method_name do |*|
cached_attributes_deprecation_warning(method_name)
true
end
end

# Returns the attributes which are cached. By default time related columns
# with datatype <tt>:datetime, :time, :date</tt> are cached.
def cached_attributes
@cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set
end
protected

# Returns +true+ if the provided attribute is being cached.
def cache_attribute?(attr_name)
cached_attributes.include?(attr_name)
def cached_attributes_deprecation_warning(method_name)
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
Calling `#{method_name}` is no longer necessary. All attributes are cached.
MESSAGE
end

protected

if Module.methods_transplantable?
def define_method_attribute(name)
method = ReaderMethodCache[name]
Expand All @@ -89,16 +76,6 @@ def #{temp_method}
end
end
end

private

def cacheable_column?(column)
if attribute_types_cached_by_default == ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
true
else
attribute_types_cached_by_default.include?(column.type)
end
end
end

# Returns the value of the attribute identified by <tt>attr_name</tt> after
Expand All @@ -122,11 +99,7 @@ def read_attribute(attr_name)
return block_given? ? yield(name) : nil
}

if self.class.cache_attribute?(name)
@attributes[name] = column.type_cast_from_database(value)
else
column.type_cast_from_database value
end
@attributes[name] = column.type_cast_from_database(value)
}
end

Expand Down
44 changes: 9 additions & 35 deletions activerecord/test/cases/attribute_methods_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -517,43 +517,17 @@ def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_m
end
end

def test_only_time_related_columns_are_meant_to_be_cached_by_default
expected = %w(datetime time date).sort
assert_equal expected, ActiveRecord::Base.attribute_types_cached_by_default.map(&:to_s).sort
end

def test_declaring_attributes_as_cached_adds_them_to_the_attributes_cached_by_default
default_attributes = Topic.cached_attributes
Topic.cache_attributes :replies_count
expected = default_attributes + ["replies_count"]
assert_equal expected.sort, Topic.cached_attributes.sort
Topic.instance_variable_set "@cached_attributes", nil
end

def test_cacheable_columns_are_actually_cached
assert_equal cached_columns.sort, Topic.cached_attributes.sort
end

def test_accessing_cached_attributes_caches_the_converted_values_and_nothing_else
t = topics(:first)
cache = t.instance_variable_get "@attributes"

assert_not_nil cache
assert cache.empty?
def test_deprecated_cache_attributes
assert_deprecated do
Topic.cache_attributes :replies_count
end

all_columns = Topic.columns.map(&:name)
uncached_columns = all_columns - cached_columns
assert_deprecated do
Topic.cached_attributes
end

all_columns.each do |attr_name|
attribute_gets_cached = Topic.cache_attribute?(attr_name)
val = t.send attr_name unless attr_name == "type"
if attribute_gets_cached
assert cached_columns.include?(attr_name)
assert_equal val, cache[attr_name]
else
assert uncached_columns.include?(attr_name)
assert !cache.include?(attr_name)
end
assert_deprecated do
Topic.cache_attribute? :replies_count
end
end

Expand Down

0 comments on commit 66736c8

Please sign in to comment.