【问题标题】:How do I prevent one partial from hijacking the local variables from another in the same view?如何防止一个局部变量在同一视图中劫持另一个局部变量?
【发布时间】:2016-06-01 08:12:39
【问题描述】:

所以我有一个Question#Show.html.erb,它具有以下内容:

  <% @question.answers.each do |ans| %>
    <%= render partial: "questions/answer", locals: {ans: ans} %>
  <% end %>

  <div class="row">
    <div class="col-lg-8 col-lg-offset-2">
        <div class="ibox">
          <div class="ibox-title">
              <h5>Your Refactor Suggestion</h5>
          </div>

          <div class="ibox-content">
            <%= render partial: "answers/form", locals: {answer: @question.answers.build(user: current_user)} %>
          </div>
        </div>
    </div>
  </div>

这很好用。

但是,一旦我翻转它(即,将当前位于底部的 div.class=row 放在顶部的迭代器上方),我会遇到一些疯狂的错误。

例如,这样做:

  <div class="row">
    <div class="col-lg-8 col-lg-offset-2">
        <div class="ibox">
          <div class="ibox-title">
              <h5>Your Refactor Suggestion</h5>
          </div>

          <div class="ibox-content">
            <%= render partial: "answers/form", locals: {answer: @question.answers.build(user: current_user)} %>
          </div>
        </div>
    </div>
  </div>

  <% @question.answers.each do |ans| %>
    <%= render partial: "questions/answer", locals: {ans: ans} %>
  <% end %>

导致此错误:

ActionController::UrlGenerationError at /questions/42
No route matches {:action=>"vote_up", :controller=>"answers", :id=>nil} missing required keys: [:id]

这是我的questions/_answer.html.erb 部分(为简洁起见被截断):

        <%= link_to vote_up_answer_path(ans), method: :post do %>
            <i class="fa fa-chevron-up"> </i>
        <% end %>
        <%= ans.cached_votes_total %>
        <%= link_to vote_down_answer_path(ans), method: :post do %>
            <i class="fa fa-chevron-down"> </i>
        <% end %>
            <%= ans.body %>
                        <%= link_to ans.user.try(:email), user_path(ans.user) %>

这是我的answers/_form.html.erb 部分(为简洁起见也被截断):

<%= simple_form_for(answer) do |f| %>
  <%= f.error_notification %>
  <%= f.input :question_id, as: :hidden %>
  <%= f.input :user_id, as: :hidden %>
  <div class="form-group">
    <%= f.input_field :body, as: :text, class: "form-control", rows: 8 %>
  </div>
  <div class="form-group">
    <%= f.input_field :language, collection: ["ruby", "python", "php"], as: :select, selected: "ruby", class: "form-control" %>
  </div>

  <div id="new-post-submission-button">
    <%= f.button :submit, class: "btn btn-lg btn-primary pull-right" %>
  </div>
<% end %>

这是我的Questions#Show 控制器:

  def show
    @question = Question.includes(:answers).find(params[:id])
  end

是什么导致了这种奇怪的行为?

【问题讨论】:

  • 这是 Rails 5 的特定问题吗?你在 Rails 4.x 上试过这个吗?
  • @Pavan 我没有在 Rails 4.x 上测试过这个。我正在使用 Rails 5 构建我的应用程序,所以这就是我遇到问题的地方。

标签: ruby-on-rails simple-form erb ruby-on-rails-5


【解决方案1】:

我认为问题在于首先构建相关答案(如在这部分代码中:@question.answers.build(user: current_user))。 build 构造一个新的关联对象(答案),设置指向主对象(问题)的外键链接,并将其添加到关联集合(问题的所有答案中)。但是它还没有保存它,因此它确实还没有ID。

因此,当您为问题答案关联的所有成员呈现部分 next 时,这也包括上面新创建的答案。渲染部分时,您可能应该跳过新创建的答案。 更新:为此,您可以执行以下操作(有很多方法可以实现,这只是一个示例):

@question.answers.select { |ans| ans.persisted? }.each do |ans|
  ...
end

【讨论】:

  • 有趣。如果没有 ID,如何跳过新创建的答案?我不能做Answer.last 或类似的事情,因为记录没有保存......对吗?您是否有代码示例说明我如何做到这一点?谢谢!
  • 在遍历 answers 集合时,您可以简单地跳过新创建的记录。有关示例,请参阅答案更新。
  • 完美。奇迹般有效。谢谢!
猜你喜欢
  • 2017-12-22
  • 2019-10-04
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多