用于 has_and_belongs_to_many 关联的 Rails3 缓存清理器
我在 Rails3 应用程序中建模了以下关系:
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
“SkillsUser”模型表示用户和技能之间的多对多关联。这样,当用户添加新技能,并且该技能已存在于“技能”表中(即“Java”)时,我只需在 Skills_users 表中创建现有技能和用户之间的关系。一切都好。
在用户视图中,我显示技能列表。我有一个围绕这些技能的片段缓存块。
<% cache([user,"skills"]) do %>
<div id="skills-grid">
<% user.sorted_skills.each do |s| %>
...
<% end %>
</div>
<% end %>
在单独的编辑页面上,用户可以添加或删除技能。此操作只是创建或删除 Skills_users 记录。当发生这种情况时,我需要使片段缓存无效,以便技能在用户视图上正确呈现。
因此,我创建了一个 CacheSweeper,其生活目的是观察 Skills_Users 关系。这是控制器:
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
这是清理器:
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
问题是,在添加或删除 Skills_users 记录之后(在 SkillsController 上“创建”或“销毁”之后),清理器永远不会被调用。我的项目中有其他清理者在工作,但他们都没有观察到多对多关联。
那么,我的问题是如何创建一个 CacheSweeper 来观察“has_and_belongs_to_many”关联?
I have the following relationships modeled in a Rails3 application:
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
The "SkillsUser" model represents the many-to-many association between users and skills. In this way, when a User adds a new Skill, and said Skill already exists in the "skills" table (i.e "Java"), I simply create the relationship between the existing skill and the user in the skills_users table. All good.
Within the User's view, I display a list of Skills. And I have a fragment caching block wrapped around those skills.
<% cache([user,"skills"]) do %>
<div id="skills-grid">
<% user.sorted_skills.each do |s| %>
...
<% end %>
</div>
<% end %>
On a separate edit page, a User can add or delete a Skill. This action simply creates or removes a skills_users record. And when this happens, I need to invalidate the fragment cache so that the skills render appropriately on the User view.
So I created a CacheSweeper who's purpose in life is to observe the skills_users relationship. Here's the controller:
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
And here's the sweeper:
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
The problem is, after adding or removing a skills_users record (after "create" or "destroy" on the SkillsController), the sweeper is never invoked. I have other sweepers working within my project, but none of them observe many-to-many associations.
My question, then, is how does one create a CacheSweeper to observe a "has_and_belongs_to_many" association?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我会尝试使用 user.id 而不是 user 作为密钥。即更改
为
我还将在回调中添加记录器消息以及在 SkillUserSweeper 类中添加记录器消息以确保它正在加载。
I would try using the user.id rather than user as the key. i.e. change
to
I would also add logger messages inside the callbacks as well as a logger message in the SkillUserSweeper class to make sure it is being loaded.