【问题标题】:Rails is rendering partial view, when it should only be updating the partial view in an existing pageRails 正在渲染局部视图,而它应该只更新现有页面中的局部视图
【发布时间】:2014-08-21 08:41:57
【问题描述】:

我正在尝试通过 AJAX 对帖子进行上/下投票,以便用户不必刷新页面即可查看更新后的分数。但是,当点击投票链接时,用户会被重定向到仅显示部分视图的页面。甚至不显示父视图。如何在不刷新整个页面的情况下更新索引页面中的部分内容?我怀疑问题出在我的“投票”控制器动作上。到目前为止,这是我的代码:

/app/controllers/posts_controllers.rb

def vote
  value = params[:type] == "up" ? 1 : -1
  @post = Post.find(params[:id])
  @post.add_or_update_evaluation(:votes, value, current_user)
  respond_to do |format|
    #I'm guessing the problem lies here.
    format.html { render partial: 'score', locals: {post: @post} }
    format.js
  end
end

/app/views/posts/_score.html.erb

<td id="score_<%= post.id %>"><%= post.reputation_for(:votes).to_i %></td>
<% if user_signed_in? %>
<td>
  <%= button_to "Upvote", vote_post_path(post, type: "up"), method: "post", class: "btn btn-success", remote: true %>
</td>
<td>
  <%= button_to "Downvote", vote_post_path(post, type: "down"), method: "post", class: "btn btn-danger", remote: true %>
</td>
<% end %>

/app/views/posts/score.js.erb

$('#score_<%= post.id %>').html("<%= escape_javaScript render partial: 'score', locals: {post: @post} %>");

/app/views/posts/index.html.erb

<% @posts.each do |post| %>
  <%= render partial: 'score', locals: {post: post} %>
  ...
<% end %>

/app/assets/javascripts/application.js

//= require jquery
//= require jquery_ujs
//= require bootstrap.min
//= require turbolinks
//= require_tree .

【问题讨论】:

  • 我猜它没有通过javascript,链接只是一个普通的锚。
  • “链接”是 Rails button_to。请注意,我向按钮添加了remote: true 属性。任何想法如何解决这个问题?

标签: javascript ajax ruby-on-rails-4 partials


【解决方案1】:

您响应的js 分支错过了说明应呈现哪个视图的块:

respond_to do |format|
  format.html { render partial: 'score', locals: {post: @post} }
  format.js { render partial: 'score', locals: {post: @post} }
end

否则,rails 默认会渲染vote.js,因为这是您的控制器方法名称。也许这只是一个错字,但您的文件应该命名为 _score.js.erb(部分),就像 HTML 版本一样。

更新

再次查看您的代码后,可能只需将score.js.erb 重命名为vote.js.erb 就足够了,因为您在其中呈现了_score 部分。

从设计的角度来看,最干净和最干燥的解决方案是跳过 format 调用的块并拥有如下文件:

# posts_controllers.rb
def vote
  value = params[:type] == "up" ? 1 : -1
  @post = Post.find(params[:id])
  @post.add_or_update_evaluation(:votes, value, current_user)

  respond_to do |format|
    format.html  # this renders vote.html.erb
    format.js    # this renders vote.js.erb
  end
end


# vote.html.erb
<%= render 'score', locals: { post: @post } %>


# vote.js.erb
$('#score_<%= @post.id %>').html("<%= escape_javaScript render partial: 'score', locals: { post: @post } %>");


# _score.html.haml
<td id="score_<%= post.id %>"><%= post.reputation_for(:votes).to_i %></td>
<% if user_signed_in? %>
<td>
  <%= button_to "Upvote", vote_post_path(post, type: "up"), method: "post", class: "btn btn-success", remote: true %>
</td>
<td>
  <%= button_to "Downvote", vote_post_path(post, type: "down"), method: "post", class: "btn btn-danger", remote: true %>
</td>


# index.html.erb
<%= render 'score', collection: @posts, as: :post %>

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多