Skip to content

tf/cached_associated_attributes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

About

Not maintained - Easily cache an attribute of an associated model

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages