【问题标题】:Access Instance Variable through Ajax Requests and Partials通过 Ajax 请求和部分访问实例变量
【发布时间】:2016-01-04 10:55:31
【问题描述】:

在我的应用程序中,我可以向我的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 的持久性?

谢谢

【问题讨论】:

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


    【解决方案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 %>
    

    另一种方式: 因为您只是在部分中使用图像 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 } %>');
    

    【讨论】:

    • 我在@image 上获得undefined method 'id' for nil:NilClass 是否意味着@image inst 可用或不存在?
    • 这个检查会在 _add_to_cart.html.erb 上进行吗?
    • 如果一个商品从购物车中移除,图片会发生什么变化?你是从def remove_from_cart 方法传递的吗?
    • 您正在传递,image 在两个部分中,但您正在尝试访问 @image。在一般页面加载时,由于实例存在,它不会给出任何错误,但是当通过 AJAX 执行此操作时,该对象将不再存在。
    • 所以我需要引用image.id 而不是@image.id 吗?我需要@image 在创建和销毁时可用。我有点困惑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    相关资源
    最近更新 更多