Rails关联表与Ajax更新

时间:2015-11-01 20:20:17

标签: javascript jquery ruby-on-rails ajax

我有一个拥有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 %>

当我点击进入时,上面的DOES会更新自己的数量,但是它会将我重定向到相同的网址,其中数量= 1(或数量值不等)添加到结尾。除非刷新页面,否则它也不会在输入占位符中显示数量。

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

1 个答案:

答案 0 :(得分:1)

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

或宝石喜欢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。表单将通过AJAX发送,因为属性“remote:true”(这是在表单中使用AJAX的Rails方法之一: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 %>");

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

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