Сохранение объекта без его ассоциации

#ruby-on-rails

#ruby-on-rails

Вопрос:

Я пытаюсь создать корзину, которую можно использовать, даже если пользователь не входит в систему. В настоящее время я использую сеансы для этого, однако объект cart не будет сохранен, если не будет ассоциации с пользователем. Каков наилучший способ обойти это?

Вот мой код

 class Cart < ApplicationRecord
      belongs_to :user
      has_many :cart_items, dependent: :destroy
      has_many :products, through: :cart_items
      monetize :price_cents
    end


#Application Controller

  def current_customer
    @user = User.find(session[:user_id]) if session[:user_id]
  end

  def current_shopping_cart
    if login?
      @cart = @user.cart
    else
      if session[:cart]
        @cart = Cart.find(session[:cart])
      else
        @cart = Cart.create(delivery: "self-collection")
        session[:cart] = @cart.id
      end
    end
  end

  def login?
    !!current_customer
  end
 

Комментарии:

1. belongs_to займет optional: true .

2. PG:: NotNullViolation: ОШИБКА: значение null в столбце «user_id» нарушает ограничение not-null

3. t.bigint «user_id», null: false <- Должен ли я изменить это тогда?

4. что вам нужно, так это изменить строку belongs_to :user на belongs_to :user, необязательно: true

5. Да, измените user_id столбец в базе данных на not null too .

Ответ №1:

Чтобы сделать ассоциацию необязательной, вам нужно сделать столбец базы данных обнуляемым:

 class ChangeCartsUserId < ActiveRecord::Migration[6.0]
  def change
    change_column_null :carts, :user_id, true
  end
end
 

И сделайте ассоциацию необязательной:

 class Cart < ApplicationRecord
  belongs_to :user, optional: true
  # ...
end
 

Это просто удаляет validates_presence_of проверку, добавленную ассоциациями belongs_to по умолчанию, начиная с Rails 5.

Другой способ решения этой проблемы — создать учетную запись «гостевого пользователя», как только пользователь добавит свой первый товар в корзину, и войти в систему. Вы бы объединили это с повторяющимся заданием для удаления неполных извлечений с течением времени.