2011-08-11 2 views
1

J'ai les relations suivantes modelées dans une application Rails3:Rails3 Cache Sweeper pour l'association has_and_belongs_to_many

class User < ActiveRecord::Base 
    has_and_belongs_to_many :skills 
end 

class SkillsUser < ActiveRecord::Base 
end 

class Skill < ActiveRecord::Base 
    has_and_belongs_to_many :users 
end 

Le modèle « SkillsUser » représente le nombre à plusieurs entre les utilisateurs et les compétences. De cette manière, lorsqu'un utilisateur ajoute une nouvelle compétence et que cette compétence existe déjà dans le tableau "compétences" (par exemple "Java"), je crée simplement la relation entre la compétence existante et l'utilisateur dans la table skills_users. Tout bon.

Dans la vue de l'utilisateur, j'affiche une liste de compétences. Et j'ai un bloc de mise en cache fragmenté autour de ces compétences.

<% cache([user,"skills"]) do %> 
<div id="skills-grid"> 
     <% user.sorted_skills.each do |s| %> 
     ... 
    <% end %> 
</div> 
<% end %> 

Sur une page d'édition distincte, un utilisateur peut ajouter ou supprimer une compétence. Cette action crée ou supprime simplement un enregistrement skills_users. Et lorsque cela se produit, je dois invalider le cache de fragments afin que les compétences soient correctement affichées dans la vue utilisateur. J'ai donc créé un CacheSweeper dont le but dans la vie est d'observer la relation skills_users. Voici le contrôleur:

class SkillsController < ApplicationController 
    autocomplete :skill, :name 
    cache_sweeper :skill_user_sweeper 

    def create 
    @user = User.find(params[:user_id]) 
    #Make sure the current user has access to 
    #associate a skill to the user in the request 
    if(@user.id = current_user.id) 
     SkillsHelper.associate_skill(@user,params[:skill][:name]) 
     @skill = Skill.find_by_name(params[:skill][:name]) 
    end 
    respond_to do |format| 
     format.js 
    end 
    end 

    def destroy 
    @skill = Skill.find_by_id(params[:id]) 
    @user = User.find_by_id(params[:user_id]) 
    #Destroy the relationship, not the skill 
    @user.skills.delete(@skill) if(@skill.can_be_tweaked_by?(current_user)) 

    respond_to do |format| 
     format.js 
    end 
    end 
end 

Et voici la balayeuse:

class SkillUserSweeper < ActionController::Caching::Sweeper 
    observe SkillsUser 

    def after_create(skill_user) 
    expire_cache_for(skill_user) 
    end 

    def after_update(skill_user) 
    expire_cache_for(skill_user) 
    end 

    def after_destroy(skill_user) 
    expire_cache_for(skill_user) 
    end 

    private 
    def expire_cache_for(skill_user) 
    expire_fragment([skill_user.user,"skills"]) 
    end 
end 

Le problème est, après l'ajout ou la suppression d'un skills_users enregistrement (après « créer » ou « détruire » sur le SkillsController), la balayeuse n'est jamais invoqué. J'ai d'autres balayeurs travaillant dans mon projet, mais aucun d'entre eux n'observe des associations plusieurs-à-plusieurs.

Ma question est donc comment créer un CacheSweeper pour observer une association "has_and_belongs_to_many"?

Répondre

2

Je ne peux pas laisser des commentaires - désolé

Je voudrais essayer d'utiliser la user.id plutôt que l'utilisateur comme clé. dire changer

<% cache([user,"skills"]) do %> 

à

<% cache([user.id,"skills"]) do %> 

Je voudrais aussi ajouter des messages de l'enregistreur à l'intérieur des callbacks ainsi qu'un message d'enregistreur dans la classe SkillUserSweeper pour vous assurer qu'il est en cours de chargement.

+0

Merci. J'ai essayé ceux-ci, et le SkillsUserSweeper n'est pas chargé. Cela est probablement dû au fait que je n'interagis pas explicitement avec un objet SkillsUserSweeper dans mon contrôleur et qu'en tant que tel, Rails ne déclenche pas d'actions de balayage. –

Questions connexes