简体   繁体   English

如何在Rails 4中缓存个性化片段?

[英]How do I cache a personalised fragment in Rails 4?

My app (Rails 4) allows users to vote on posts. 我的应用程序(Rails 4)允许用户对帖子进行投票。 Is it possible to cache the post, but personalise the vote cache so it shows one personalised for current_user? 是否可以缓存帖子,但个性化投票缓存,以便显示一个针对current_user的个性化? For example, whether the user voted or not. 例如,用户是否投票。

I would rather not change the html structure to achieve this. 我宁愿不改变html结构来实现这一点。

# posts/_post.html.slim
- cache post do
  h1 = post.title
  = post.text
  = render 'votes/form', post: post

# votes/_form.html.slim
- if signed_in? && current_user.voted?(post)
  = form_for current_user.votes.find_by(post: post), method: :delete do |f|
    = f.submit
- else
  = form_for Vote.new do |f|
    = f.submit

You have two options here: 你有两个选择:

Option 1: don't cache the votes 选项1:不要缓存投票

This is the simplest solution and the one i personally recommends. 这是最简单的解决方案,也是我个人推荐的解决方案。 You just don't cache the dynamic user dependent part so you have something like this: 您只是不缓存动态用户相关部分,因此您有这样的事情:

# posts/_post.html.slim
- cache post do
  h1 = post.title
  = post.text
= render 'votes/form', post: post # not cached

Option 2: use javascript 选项2:使用javascript

This solution is more complex, but is actually how basecamp do it (however mostly with more simple examples). 这个解决方案更复杂,但实际上是basecamp如何做到这一点(但主要是用更简单的例子)。 You have both part rendered on the page but remove one of them with javascript. 您在页面上呈现了两个部分,但使用javascript删除其中一个部分。 Here is a example using jQuery and CoffeeScript: 以下是使用jQuery和CoffeeScript的示例:

# posts/_post.html.slim
- cache post do
  h1 = post.title
  = post.text
  = render 'votes/form', post: post

# votes/_form.html.slim
div#votes{"data-id" => post.id}
  .not_voted
    = form_for current_user.votes.find_by(post: post), method: :delete do |f|
      = f.submit
  .voted
    = form_for Vote.new do |f|
      = f.submit

# css
.not_voted {
  display:none;
}

# javascript (coffeescript)
jQuery ->
  if $('#votes').length
    $.getScript('/posts/current/' + $('#votes').data('id'))

# posts_controller.b
def current
  @post = Post.find(params[:id])
end

# users/current.js.erb
<% signed_in? && current_user.voted?(@post) %>
  $('.voted').hide();
  $('.not_voted').show();
<% end %>

I would however properly change voted? 然而,我会适当改变voted? method to accept a id, so you don't need to make a new query. 接受id的方法,因此您不需要进行新的查询。 You can learn more about this approach in this railscasts: http://railscasts.com/episodes/169-dynamic-page-caching-revised?view=asciicast 您可以在此railscast中了解有关此方法的更多信息: http: //railscasts.com/episodes/169-dynamic-page-caching-revised?view=asciicast

Try the following, this will create 2 different fragments for both voted and not voted for each post. 尝试以下操作,这将为每个帖子创建两个不同的片段,用于投票和未投票。 It will be read by according to its status. 它将根据其状态进行阅读。

# posts/_post.html.slim
- cache [post, current_user.votes.find_by(post: post)]do
  h1 = post.title
  = post.text
  = render 'votes/form', post: post

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM