我有一个控制器,我正在缓存show动作.show动作有许多安全过滤器,用于执行和重定向,如果用户没有登录,不是当前组的成员等.这些过滤器在我没有打开缓存时工作正常,但是当我打开开关以转换缓存之前,不再执行过滤器(我的调试器调用未被命中).
我一直认为,在为缓存操作调用过滤器之前,这是页面缓存和操作缓存之间的主要区别.这由操作缓存的Rails缓存教程部分支持,其中包括:
操作缓存的工作方式类似于页面缓存,除了传入的Web请求确实从Web服务器传递到Rails堆栈和Action Pack,以便在提供缓存之前可以在其上运行过滤器.这允许在仍然提供缓存副本的输出结果的同时运行身份验证和其他限制.
那么为什么我的前过滤器不会被调用?
关于我的设置:Rails 3.1使用Devise进行身份验证.我正在使用dalli gem作为memcached商店.
这里有一些代码总结了我的代码(很多琐事):
class GroupsController < ApplicationController
caches_action :show
cache_sweeper :group_sweeper
before_filter :authenticate_user!, :except => [:index]
before_filter :init_group, :except => [:new, :create, :index]
before_filter :requires_group_membership, :except => [:new, :create, :index]
def show
end
private
def requires_group_membership
if current_user and !@group.users_active.index(current_user).nil?
return true
else
redirect_to :root
return false
end
end
def init_group
@group = current_user.active_groups.find_by_id(params[:id])
if @group.nil?
redirect_to :root
return false
end
end
Run Code Online (Sandbox Code Playgroud)
那么,有没有人见过这种行为呢?在理解过滤器和动作缓存应该如何工作之前,我是否有一个漏洞?或者也许我有一些奇怪的voodo发生与奇怪的宝石版本组合?
[编辑]
有趣的是,我刚刚了解到返回值对是否运行链中的方法没有影响,而是调用重定向还是渲染.
[编辑2]
我将我的应用程序升级到rails 3.2.3以查看它是否有效,但没有解决问题.我发现的东西是在ApplicationController中定义的before过滤器被调用,但是我的GroupsController中的过滤器却没有被调用.
注意:我在这里提出一个逻辑我在做什么.
我在做什么:
考虑我们列出产品和分页的基本索引操作.现在使用remote-true选项我启用了基于ajax的分页.到目前为止,事情完美无缺.看看示例代码.
产品控制器:
def index
@products = Product.paginate(:order =>"name ASC" ,:page => params[:page], :per_page => 14)
respond_to do |format|
format.html # index.html.erb
format.json { render json: @products }
format.js
end
end
Run Code Online (Sandbox Code Playgroud)
Index.html.erb
<h1>Products</h1>
<div id="products">
<%= render "products/products" %> // products partial is just basic html rendering
</div>
<script>
$(function(){
$('.pagination a').attr('data-remote', 'true')
});
</script>
Run Code Online (Sandbox Code Playgroud)
index.js.erb的
jQuery('#products').html("<%= escape_javascript (render :partial => 'products/products' ) %>");
$('.pagination a').attr('data-remote', 'true');
Run Code Online (Sandbox Code Playgroud)
所以有什么问题:
现在我想在此上启用动作缓存.但是index.js.erb文件不是在操纵DOM.如果我删除了remote-true功能,那么缓存就可以正常工作了.
对于动作缓存,我在控制器的顶部添加了这一行:
caches_action :index, :cache_path => Proc.new { |c| c.params } …Run Code Online (Sandbox Code Playgroud) 我有一个控制器索引操作,它返回json输出.
render :json => my_array.to_json
Run Code Online (Sandbox Code Playgroud)
我必须在这里使用什么类型的缓存."页面缓存"对此有意义吗?
或者我必须像下面那样进行动作缓存
caches_action :index
Run Code Online (Sandbox Code Playgroud) 我的应用程序中的操作缓存到期时遇到了一些问题.
这是我的控制器:
class ToplistsController < ApplicationController
caches_action :songs, cache_path: :custom_cache_path.to_proc
def custom_cache_path
"#{params[:when]}-#{params[:what]}-#{params[:controller]}-#{params[:action]}"
end
def songs
# ...
end
end
Run Code Online (Sandbox Code Playgroud)
我不知何故需要能够重置自定义缓存路径,但我无法弄清楚如何.
我已经尝试过使用这种技术,但没有成功.它看起来像我的缓存引擎Dalli,不支持regexp匹配器.
我在尝试使用此代码时遇到此错误:
expire_fragment(/songs/)
ActiveSupport::Cache::DalliStore does not support delete_matched
我试图使用这行代码进行调试,但它被忽略了.
before_filter only: [:songs]
expire_fragment(custom_cache_path)
end
Run Code Online (Sandbox Code Playgroud)
我正在使用Rails 3.1.0.rc6,Dalli 1.0.5和Ruby 1.9.2.
我是一个铁杆新手试图为我的应用程序实现缓存.我安装了memcached并在我的development.rb中配置它,如下所示:
config.action_controller.perform_caching = true
config.cache_store = :mem_cache_store
Run Code Online (Sandbox Code Playgroud)
我有一个控制器ProductsController,它在登录时显示用户特定的产品.
class ProductsController < ApplicationController
caches_action :index, :layout => false
before_filter :require_user
def index
@user.products
end
end
The route for index action is: /products
Run Code Online (Sandbox Code Playgroud)
问题是,当我登录时
1)用户A第一次,rails命中我的控制器并缓存产品动作.
2)我注销并以用户B身份登录,它仍以用户A身份登录并显示用户A而非用户B的产品.它甚至没有打到我的控制器.
关键可能是路由,在我的memcached控制台中,我看到它是基于相同的密钥获取的.
20 get views/localhost:3000/products
20 sending key views/localhost:3000/products
Run Code Online (Sandbox Code Playgroud)
动作缓存不是我应该使用的吗?我如何缓存和显示用户特定的产品?
谢谢你的帮助.
我一直在Heroku上玩不同的缓存策略,并添加了他们的memcached插件,旨在为我的应用添加动作缓存.
当我在当前应用程序上查看Rails.cache.stats时(安装了memcached并使用dalli gem),在执行应缓存的操作后,我将current和total_items设置为0.
在我想要缓存的操作的控制器顶部,我有:
caches_action :show
Run Code Online (Sandbox Code Playgroud)
另外,我修改了我的环境配置(对于在Heroku上运行的配置)
config.cache_store = :dalli_store
Run Code Online (Sandbox Code Playgroud)
是否有一些其他的统计数据,我可以看看它是否有效或我做错了什么?
我有一个规范,用于在禁用缓存和启用缓存时测试操作缓存。看起来测试执行的顺序会影响它们是否通过。
it "should not cache the index page when we're not caching" do
ActionController::Base.perform_caching = false
HomeController.caches_action :index
Rails.cache.clear
ActionController::Base.cache_store.exist?(:index_cache_path).should be_false
get :index
ActionController::Base.cache_store.exist?(:index_cache_path).should be_false
end
it "should cache the index page when we're caching" do
ActionController::Base.perform_caching = true
HomeController.caches_action :index
Rails.cache.clear
ActionController::Base.cache_store.exist?(:index_cache_path).should be_false
get :index
ActionController::Base.cache_store.exist?(:index_cache_path).should be_true
end
Run Code Online (Sandbox Code Playgroud)
当按上述顺序运行测试时,最后一个测试会失败,因为最后一个期望中不存在cache_store。我很困惑为什么无缓存测试会影响缓存测试。有谁知道出了什么问题吗?
我不太确定如何确保我的缓存工作,但我很确定它不是.我有一个带有索引操作的用户控制器,我在操作缓存,直到创建新用户.这是代码:
UsersController < ApplicationController
caches_action :index
def index
@users = User.all
end
def create
expires_action :index
...
end
end
Run Code Online (Sandbox Code Playgroud)
现在,在我访问index操作的日志中,我看到:
Cached fragment hit: views/localhost:3000/users (0.0ms)
Filter chain halted as [#<ActionController::Filters::AroundFilter:0xe2fbd3 @identifier=nil, @kind=:filter, @options={:only=>#<Set: {"index", "new"}>, :if=>nil, :unless=>nil}, @method=#<Proc:0x186cb11@/Users/bradrobertson/.rvm/gems/jruby-1.5.3/gems/actionpack-2.3.10/lib/action_controller/caching/actions.rb:64>>] did_not_yield.
Run Code Online (Sandbox Code Playgroud)
我不确定这filter chain halted ... did_not_yield是什么,我也看到select * from users......每次都会被调用,这不是我所期待的.
有人可以告诉我这里发生了什么以及为什么这不符合我的预期?即.当整个动作的输出应该被缓存时,为什么User.all会运行?