【问题标题】:Rails association form with Ajax updateRails 关联表单与 Ajax 更新
【发布时间】:2015-11-01 20:20:16
【问题描述】:

我有一个模型,书,有一个 has_many 关联,拥有。我已经设置好了,用户可以点击一个按钮将这本书添加到他们的收藏中。控制器如下所示:

def create
    @book.owns.where(user_id: current_user.id).first_or_create
    @own = Own.where(user_id: current_user.id, book_id: @book.id)
    Own.update(@own, :quantity => "1")
    respond_to do |format|
        format.html { redirect_to @book}
        format.js
    end
end

视图如下所示:

<% if user_signed_in? && current_user.owns?(@book) %>
    <%= link_to book_own_path(@book), method: :delete, remote: true, class: "btn btn-danger btn-circle", title: "Remove from collection", data: { toggle: "tooltip", disable_with: "<span class='fa fa-minus'></span>"} do %><span class="fa fa-heart-o"></span><% end %>
<% else %>
    <%= link_to book_own_path(@book), method: :post, remote: true, class: "btn btn-success btn-circle", title: "Add to collection", data: { toggle: "tooltip", disable_with: "<span class='fa fa-plus'></span>"} do %><span class="fa fa-heart"></span><% end %>
<% end %>

因此,当单击该按钮时,它会自动将数量 1 添加到他们的库存中。我想做的是让用户能够从图书展示视图更新他们拥有的数量,所以我添加了这个:

<% if user_signed_in? && current_user.owns?(@book) %>
    <span id="<%= @book.id %>_quantity">
        <% Own.where(:user_id => current_user.id, :book_id => @book.id).each do |z| %>
        <% if z.quantity == 1 %>
            <form>
                You own <input type="text" placeholder="<%= z.quantity %>" id="quantity" name="quantity" size="1" class="text-center" /> copies of this book
                <input type="submit" onclick="<% Own.update(@own, :quantity => params[:quantity]) %>.submit();" hidden />
            <form>
        <% else %>
            <form>
                You own <input type="text" placeholder="<%= z.quantity %>" id="quantity" name="quantity" size="1" class="text-center" /> copies of this book
                <input type="submit" onclick="<% Own.update(@own, :quantity => params[:quantity]) %>.submit();" hidden />
            <form>
        <% end %>
    <% end %>
    <br />
    </span>
<% end %>

当我点击输入时,上面确实会更新自己的数量,但它会将我重定向到相同的 url,并在末尾添加 ?quantity=1(或任何数量值)。除非刷新页面,否则它也不会在输入占位符中显示数量。

我的问题是,有没有更好的方法来解决这个问题,或者有没有办法实际显示占位符的值。另外,如何在后台提交表单而不是刷新页面的位置进行设置?

【问题讨论】:

    标签: javascript jquery ruby-on-rails ajax


    【解决方案1】:

    要在 Rails 中构建表单,您应该使用 Rails 提供的内容: Rails doc for Form helpers

    或者 gems 喜欢 SimpleForm

    本示例假设您使用的是 Rails 4+。

    首先,您要显示您的图书页面,因此加载您的图书并加载您自己的图书(当您操作模型时,最好在控制器中执行此操作):

    # Books Controller
    def show
      @book = Book.find(params[:id])
      @owns = current_user.owns.where(book: @book)
    end
    

    你的观点现在可能是这样的:

    # Book show
    <% @owns.each do |own| %>
      <div> You own <span class="<%= own.id %>_quantity"><%= own.quantity %></span> of this book </div>
      <%= form_for own, remote: true, method: :put do |f| %>
        <%= f.hidden_field :quantity, value: own.quantity + 1 %>
        <%= f.submit "Add One" %>
      <% end %>
      <hr>
    <% end %>
    

    我们遍历我们自己的并创建一个将数量加 1 的表单。由于表单上的 PUT 方法,请求将转到 Own#update。由于属性“remote: true”,表单将通过 AJAX 发送(这是 Rails 在表单中使用 AJAX 的方法之一:Rails doc for AJAX)。

    # Own Controller
    def update
      @own = Own.find(params[:id])
      respond_to do |format|
        if @own.update(own_params)
          format.html do
            redirect_to book_path(@own.book), notice: 'success'
          end
          format.js
        else
          format.html do
            redirect_to book_path(@own.book), alert: 'fail'
          end
        end
      end  
    end
    
    def own_params
      params.require(:own).permit(:quantity)
    end
    

    在这里,我们将加载我们自己的并尝试更新它。如果 JS 被禁用,请求将采用 HTML 部分并将重定向到您想要的位置。如果启用了 JS,那么您可以创建一个“JS 视图”,其呈现方式与 html 完全相同(您必须在操作名称后命名它们)。所以,它可能是这样的:

    # views/owns/update.js.erb
    $(".<%= @own.id %>_quantity").html("<%= @own.quantity %>");
    

    它将用新的数量替换span的内容。

    我没有测试过,但最后你的代码可能是这样的

    【讨论】:

    • 我已经尝试过类似的方法,但它会导致以下错误(正如发布的)未定义的方法 `own_path' for #:0x7e1c8f0>
    • 如果有帮助,在我的 routes.rb 中我确实有 ' 资源 :books do resource :own, module: :books end'
    • 您可以在控制台中使用“rake routes”检查您的路线。错误肯定是由尝试调用 own_path 的“form_for own”发送的。您可以在表单顶部执行以下操作:form_for [own.book, own],因为您的路线是嵌套的,因此您的路线需要一本书和一个自己的工作
    • 新问题,更新记录后出现未知格式。删除 respond_to 块可以解决这个问题,但只会显示未格式化的 html 文本。任何其他操作都没有问题,因为它们都有 respond_to 块,只是在 own.update 操作上。
    • 更新:我可以重定向_book @book 并且一切都按预期工作,但希望异步更新。
    猜你喜欢
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多