Rails 正在为每次点击创建多个购物车记录

Rails is creating multiple shopping cart records per click

我正在按照本指南创建购物车模型: https://richonrails.com/articles/building-a-shopping-cart-in-ruby-on-rails

我让它工作成功,但仍然有问题。当我加载页面并添加一个项目时,如果我转到另一个页面,然后再次加载主页,通过我拥有的侧边栏菜单,我单击一个产品,然后添加相同的产品 3次到购物车。我转到另一个页面并 return,每次点击 5 个项目,再次每次点击 7 个项目。 我不知道为什么会这样,我什至不知道要显示代码的哪一部分,所以有人可以帮助我。 如果我重新加载页面(通过单击地址栏并输入),它将返回到每次单击添加一个项目。

提前致谢

编辑:在第一次评论建议后,这里是控制器代码。

def create
    @invoice = current_invoice
    @invoice_product = @invoice.invoice_products.new(invoice_product_params)
    @invoice.save
    session[:invoice_id] = @invoice.id
end

def update
    @invoice = current_invoice 
    @invoice_product = @invoice.invoice_products.find(params[:id])
    @invoice_product.update.attributes(order_item_params)
    @invoice_products = @invoice.invoice_products
end

def destroy
    @invoice = current_invoice 
    @invoice_product = @invoice.invoice_products.find(params[:id])
    @invoice_product.destroy
    @invoice_products = @invoice.invoice_products
end

private
def invoice_product_params
    params.require(:invoice_product).permit(:id, :invoice_id, :product_id, :price, :tax, :value)
end

that same product gets added 3 times to the shopping cart. I go to another page and return, 5 items per click, again 7 items per click

这具有 Turbolinks 和糟糕的 JS 绑定的所有特征。

--

让我解释一下...

Turbolinks makes following links in your web application faster. Instead of letting the browser recompile the JavaScript and CSS between each page change, it keeps the current page instance alive and replaces only the body (or parts of) and the title in the head. Think CGI vs persistent process.

简而言之,Turbolinks 使用 "Ajax" 加载下一页的 <body>,替换您当前的 <body> 内容。虽然这确实加快了处理速度(通过消除重新编译的需要 CSS/images),但它会对 JS 绑定造成严重破坏。

JS "binds" 到 DOM:

中的元素

它希望有 个元素 供它绑定。这在大多数情况下效果很好:

element = document.getElementById("your_element").addEventListener('click', function() {
   console.log('anchor');
});

但是,使用 Turbolinks(尤其是 JQuery)的问题是绑定可能会发生多次,具体取决于 Turbolinks 将新数据加载到 DOM 的次数。

这个问题是因为你的 Javascript 没有刷新 ,但是你的 DOM 元素刷新了,JS 把它们当作 new 个元素,因此每次点击都会触发 x 次函数。我想有点像 n+1

--

在回答您的问题时,问题出在您的 JS 绑定上:

#app/assets/javascripts/application.js
bind = function() {
    $("#shopping_cart").on("click", function(){
        //payload
    });
};
$(document).on("ready page:load", bind);

以上将为您选择 "local" 元素,并使用 page:load Turbolinks hook,确保每次请求 Turbolinks 时都会刷新。

如果您想在每次调用 Turbolinks 时不必重新声明,只需 delegate from the document:

#app/assets/javascripts/application.js
$(document).on("click", "#shopping_cart", function(){
   //payload
});