通过Ajax请求和部分访问实例变量

时间:2016-01-04 10:55:32

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

在我的应用程序中,我可以在我的CartItem模型中添加一个对象,但在销毁记录并通过Ajax渲染我的视图时会得到undefined method 'id' for nil:NilClass

因此,在页面加载/images/7时,我有

<div id="cart_form">
  <% if @cart_item_collection.include?(@image.id) %>
    <%= render 'shared/forms/remove_from_cart', locals: { image: @image } %>
  <% else %>
    <%= render 'shared/forms/add_to_cart', locals: { image: @image } %>
  <% end %>
</div>

class ImagesController < ApplicationController
  def show
    @image = Image.find(params[:id])
    @cart_item_collection = CartItem.where(user_id: current_or_guest_user).pluck(:image_id)
  end
end

_add_to_cart.html.erb

<%= form_for(@cart_item, url: cart_item_path, :remote => true do |f| %>
   <%= f.hidden_field :image_id, value: @image.id %>
   <%= f.submit "Add To Cart" %>
<% end %>

_remove_from_cart.html.erb

<%=button_to cart_item_path(id: @cart_item), method: :delete, :remote => true, class: "icon di_darckblue extra-large button fill", name: 'images' do %>
<i class="di-shopping-cart-up"></i>
Remove From Cart

如前所述,我可以创建一个CartItem,我渲染这个js.erb文件

$("#cart_form").html("<%= j render partial: 'shared/forms/remove_from_cart', locals: { image: @image } %>");

但是当我在收到错误时尝试销毁CartItem时

$("#cart_form").html('<%= j render partial: "shared/forms/add_to_cart", locals: { image: @image } %>');

如何在每次通话中保持@image保持不变?

由于

1 个答案:

答案 0 :(得分:1)

我们需要在进行AJAX调用时传递图像id,这样当部分在AJAX完成时呈现时,可以在视图中获得@image对象。

因此我们使用image_id参数获取@image

<强> show.html.erb

<div id="cart_form">
  <% if @cart_item_collection.include?(@image.id) %>
    <%= render 'shared/forms/remove_from_cart', locals: { image: @image } %>
  <% else %>
    <%= render 'shared/forms/add_to_cart', locals: { image: @image } %>
  <% end %>
  <p class="error"></p>
</div>

<强> images_controller.rb

class ImagesController < ApplicationController
  def show
    @image = Image.find(params[:id])
    @cart_item_collection = CartItem.where(user_id: current_or_guest_user).pluck(:image_id)
  end
end

<强> _add_to_cart.html.erb

<%= form_for(@cart_item, url: cart_item_path, :remote => true do |f| %>
   <%= f.hidden_field :image_id, value: @image.id %>
   <%= f.submit "Add To Cart" %>
<% end %>

<强> _remove_from_cart.html.erb

<%=button_to cart_item_path(id: @cart_item, image_id: @image.id), method: :delete, :remote => true, class: "icon di_darckblue extra-large button fill", name: 'images' do %>
<i class="di-shopping-cart-up"></i>
Remove From Cart

添加到购物车

def add_to_cart
    @image = Image.find(params[:cart_item][:image_id])
    #if @image is present
      #your code
    #else
       #@error= "Item could not be added to cart."
    #end
end

create.js.erb

<% if !@error %>
    $("#cart_form").html("<%= j render partial: 'shared/forms/remove_from_cart', locals: { image: @image } %>");
    $('.error').html('');
<% else %>
    $('.error').html(<%= @error %>);
<% end %>

从购物车中删除

def destroy
    @image = Image.find(params[:image_id])
    #if @image
      #destroying @cart_item
      #rendering destroy.js.erb
      #@cart_item = CartItem.new
    #else
      @error="Item could not be removed from cart"
    #end 
end

destroy.js.erb:

<% if !@error %>
    $("#cart_form").html('<%= j render partial: "shared/forms/add_to_cart", locals: { image: @image } %>');
    $('.error').html('');
<% else %>
    $('.error').html(<%= @error %>);
<% end %>

另一种方式: 因为你只是在partials中使用image id: 这里我们只是在控制器中传递image_id并将其发送回前端。

但我们唯一需要检查的是检查传递给控制器​​的image_id是否存在图像,因为用户可能会更改前端的值。

要检查我们是否必须在每次调用AJAX时检查是否存在图像,这使第一种方法更安全。但如果这对你不重要,那么你可以采用这种方法。

<div id="cart_form">
  <% if @cart_item_collection.include?(@image.id) %>
    <%= render 'shared/forms/remove_from_cart', locals: { image_id: @image.id } %>
  <% else %>
    <%= render 'shared/forms/add_to_cart', locals: { image_id: @image.id } %>
  <% end %>
</div>

class ImagesController < ApplicationController
  def show
    @image = Image.find(params[:id])
    @cart_item_collection = CartItem.where(user_id: current_or_guest_user).pluck(:image_id)
  end
end

_add_to_cart.html.erb

<%= form_for(@cart_item, url: cart_item_path, :remote => true do |f| %>
   <%= f.hidden_field :image_id, value: image_id %>
   <%= f.submit "Add To Cart" %>
<% end %>

_remove_from_cart.html.erb

<%=button_to cart_item_path(id: @cart_item, image_id: image_id), method: :delete, :remote => true, class: "icon di_darckblue extra-large button fill", name: 'images' do %>
<i class="di-shopping-cart-up"></i>
Remove From Cart

添加到购物车,我渲染此js.erb文件

def add_to_cart
    @image_id = params[:cart_item][:image_id]
    #your code

end

<强> create.js.erb

$("#cart_form").html("<%= j render partial: 'shared/forms/remove_from_cart', locals: { image_id: @image_id } %>");

从购物车中删除

def destroy
    @image = params[:image_id]
    #destroying @cart_item
    #rendering destroy.js.erb
end

<强> destroy.js.erb:

$("#cart_form").html('<%= j render partial: "shared/forms/add_to_cart", locals: { image_id: @image_id } %>');