Моя корзина не будет увеличивать количество на 1. Говорит "NoMethodError (неопределенный метод" + "для nil: NilClass) - PullRequest
1 голос
/ 08 мая 2020

Я слежу за книгой Agile Веб-разработка с Rails 6 и в Главе 10: Умная тележка , мы должны построить тележку, которая будет принимать все ваши предметы в вашей тележке и объединяет их вместе, если у вас есть несколько одинаковых предметов, и показывает, сколько их у вас есть.

Мы создаем метод в классе Cart:

class Cart < ApplicationRecord
  has_many :line_items, dependent: :destroy

  def add_product(product)
    current_item = line_items.find_by(product_id: product.id)
    if current_item
      current_item.quantity += 1
    else
      current_item = line_items.build(product_id: product.id)
    end
    current_item
  end
end

, который дает ошибку:

NoMethodError (undefined method `+' for nil:NilClass):

У нас есть класс, который создает line_items и позволяет нам добавить количество в LineItems:

class AddQuantityToLineItems < ActiveRecord::Migration[6.0]
  def change
    add_column :line_items, :quantity, :integer, default: 1
  end
end

Вместе с классом для объединения элементов:

class CombineItemsInCart < ActiveRecord::Migration[6.0]
  def up
    # replace multiple items a single product in a cart with
    # a single item
    Cart.all.each do |cart|
      #count products in the cart
      sums = cart.line_items.group(:product_id).sum(:quantity)
      sums.each do |product_id, quantity|
        if quantity > 1
          # remove individual items
          cart.line_items.where(product_id: product_id).delete_all

          # replace with a single item
          item = cart.line_items.build(product_id: product_id)
          item.quantity = quantity
          item.save!
        end
      end
    end
  end

  def down
    LineItem.where("quantity>1").each do |line_item|
      line_item.quantity.times do
        LineItem.create(
          cart_id: line_item.cart_id,
          product_id: line_item.product_id,
          quantity: 1,
        )
      end
      line_item.destroy
    end
  end
end

Я сбит с толку, почему моя корзина не может взять количество и добавить к нему 1 , и он не будет отображаться в моем представлении, а это просто:

    <% @cart.line_items.each do |item| %>
        <li> <%= item.quantity %> &times; <%= item.product.title %></li>
    <% end %>

Как лучше всего отображать и увеличивать количество элементов?

Ответы [ 2 ]

0 голосов
/ 08 мая 2020

В чем проблема?

  current_item = line_items.find_by(product_id: product.id)

Вышеупомянутое вернет пустой объект ActiveRecord :: Relation. И это не будет ноль.

Попробуйте следующее:

LineItem.where(id: 1231231231293214082340).nil? # => false

Если у вас нет существующей записи с этим идентификатором, она должна вернуть false. На самом деле вам нужно что-то вроде этого:

current_items = line_items.find_by(product_id: product.id).exists?

И затем вы можете продолжить в своем операторе if, учитывая, что эти элементы действительно существуют.

Обратите внимание, что вы вернете line_items множественное число : вы можете перебрать их или выбрать свой первый.

Окончательный код:

def add_product(product)
    current_items = line_items.find_by(product_id: product.id)
    if current_items.exists?
      current_item = current_items.first
      current_item.quantity += 1
    else
      current_item = line_items.build(product_id: product.id)
    end
    current_item
  end

Мой предыдущий комментарий был неверным: find_by просто использует where под крышками - это одно и то же.

Если у вас есть другие проблемы

Тогда, как предложил Джо sh Броуди, количество может быть равно нулю. Возможно, вам придется обновить все количество элементов в вашей базе данных до: 0. Возможно, вы могли бы сделать это при миграции, учитывая, что эта база данных очень мала.

0 голосов
/ 08 мая 2020

При миграции вы обновляете только line_item с количеством больше 1. Следовательно, любые позиции с количеством, равным 1, по-прежнему имеют quantity столбец, равный нулю.

Измените эту строку

if quantity > 1

К этому

if quantity == 1

И вы должны переместить эту часть кода в задачу с граблями.

...