Skip to content
Not maintained - Easily cache an attribute of an associated model
Ruby
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
lib
tasks
test
.autotest
.gitignore
MIT-LICENSE
README.rdoc
Rakefile
init.rb
install.rb
uninstall.rb

README.rdoc

CachedAssociationAttributes

STATUS: No longer maintained / bad idea


Easily cache an attribute of an associated model.

Imagine you have a Post model that belongs_to a User model. Assume the User name changes almost never. If you want to display a lot of posts along with their user's names and you do not always want to :include the User model, then this plugin gives you an alternative.

This plugin keeps a copy of the User.name in a column user_name on the posts table. When the user_id changes user_name is updated. In the rare case where the user.name changes all posts are updated automatically. All of this happens with half a line of extra code.

Example

class Post < ActiveRecord::Base
  belongs_to :user, :cached_attributes => [:name, :email]
end

class User < ActiveRecord::Base
  has_many :users
end

This automatically adds the needed before_save and after_save callbacks to the Post and User model resp to sync the user_name and user_email attributes in Post:

user = User.create(:name => 'Bob', :email => 'bob@example.com')
post = user.posts.create

post.user_name  # => 'Bob'
post.user_email # => 'bob@example.com'

user.update_attribute(:name, 'Joe')
post.user_name  # => 'Joe'

In the above situation you probably could just use :joins. But calculated attributes are where the plugin comes in really handy:

class Post < ActiveRecord::Base
  belongs_to :user, :cached_attributes => :full_name
end

class User < ActiveRecord::Base
  has_many :users

  def full_name
    if first_name.blank?
      "#{title} #{name}"
    else
      "#{first_name} #{last_name}"
    end
  end
end

user = User.create(:title => 'Mr', :name => 'Doe', :first_name => 'John)
post = user.posts.create

post.user_full_name  # => 'John Doe'

user.update_attribute(:first_name, '')
post.user_full_name  # => 'Mr Doe'

Now you can show the user_full_name along with your posts without having to include the user association. If you add a *_changed? method Post.update_all will only be triggered if really needed:

class User < ActiveRecord::Base
  has_many :users

  def full_name
    if first_name.blank?
      "#{title} #{name}"
    else
      "#{first_name} #{last_name}"
    end
  end

  def full_name_changed?
    name_changed? || first_name_changed? || title_changed?
  end
end

# Post.update_all *will not* be called:
user.update_attribute(:role, 'admin')

# Post.update_all *will* be called:
user.update_attribute(:name, 'Jim')

Disclaimer

You might not want to overuse this feature. Keep in mind that it introduces a lot of duplication in your database. This plugin is quite new. Familiarize yourself with its internals if you want to use it (though you should probably do that with any plugin you use anyway).

Copyright © 2008 Tim Fischbach, released under the MIT license

Something went wrong with that request. Please try again.