【问题标题】:I am having this error: "You cannot call create unless the parent is saved",我有这个错误:“除非保存父级,否则您不能调用创建”,
【发布时间】:2019-08-30 06:41:32
【问题描述】:

我已经看到了这个错误,我理解这个问题,或者我希望我知道,问题是我的order_items 在创建Order Id 之前正在保存。身为 nube 的问题是对问题有所了解,但不知道如何实施解决方案,感谢您的耐心等待。

我遇到的错误。

ActiveRecord::RecordNotSaved(除非父对象被保存,否则不能调用 create):

app/models/shopping_bag.rb:22:in add_item' app/controllers/order_items_controller.rb:10:increate'

我的OrderItems 控制器

class OrderItemsController < ApplicationController

  def index

    @items = current_bag.order.items

  end

  def create
    current_bag.add_item(
      book_id: params[:book_id],
      quantity: params[:quantity]
    )

    redirect_to bag_path
  end

  def destroy

    current_bag.remove_item(id: params[:id])
    redirect_to bag_path

  end
end

我的订单控制器

class OrdersController < ApplicationController

  before_action :authenticate_user!, except:[:index, :show]

  def index
    @order = Order.all
  end

  def new
    @order = current_bag.order
  end

  def create
    @order = current_bag.order
    if @order.update_attributes(order_params.merge(status: 'open'))
      session[:bag_token] = nil
      redirect_to root_path
    else
      render new
  end
end

private

    def order_params
      params.require(:order).permit(:sub_total, :status, :user_id)
    end

end

我的购物袋模型

class ShoppingBag

  delegate :sub_total, to: :order

  def initialize(token:)
    @token = token
  end

  def order
    @order ||= Order.find_or_create_by(token: @token, status: 'bag') do | order|
      order.sub_total = 0
    end
  end

  def items_count
    order.items.sum(:quantity)
  end

  def add_item(book_id:, quantity: 1)
    book = Book.find(book_id)

    order_item = order.items.find_or_create_by(
      book_id: book_id
    )

    order_item.price = book.price
    order_item.quantity = quantity

    ActiveRecord::Base.transaction do
      order_item.save
      update_sub_total!
    end

  end

  def remove_item(id:)
    ActiveRecord::Base.transaction do
      order.items.destroy(id)
      update_sub_total!
    end
  end

  private

  def update_sub_total!
    order.sub_total = order.items.sum('quantity * price')
    order.save
  end

end

谢谢,感谢您的宝贵时间。

【问题讨论】:

  • 可以添加完整的错误信息吗?
  • @AnshulRiyal 我已添加
  • 什么是current_bag
  • 我建议 order_items 你应该尝试 order.items.find_or_initialize_by() 方法并从 add_item 中删除 order_item.save,find_or_initialize_by 此方法将构建子项,当 order_items 父项的订单将保存时,它将保存它的孩子

标签: ruby-on-rails ruby ruby-on-rails-5


【解决方案1】:

来自关于find_or_create_by的文档:

此方法总是返回一条记录,但如果尝试创建但由于验证错误而失败,则它不会被持久化,你会得到在这种情况下创建返回的内容。

可能是这种情况 - 记录没有保存在数据库中,而只是在内存中创建。查看您的代码,我认为您想使用该方法的 bang 版本 (find_or_create_by!),在这种情况下会引发错误。

【讨论】:

  • 我猜@token 的设置并不总是正确的,比如 nil 或空白,这可能会被“非空白”验证或 unique 验证阻止(如果有已经是一个带有空令牌的包)。这部分代码没有显示,所以只是猜测,但似乎很有可能。
【解决方案2】:

要在使用嵌套属性时在子属性中使用父属性,您可以使用inverse_of。这里是the documentation,它可以帮助你理解为什么需要先创建父母。

更新示例:这将首先创建论坛,然后发布。

class Forum < ActiveRecord::Base
  has_many :posts, :inverse_of => :forum
end

class Post < ActiveRecord::Base
  belongs_to :forum, :inverse_of => :posts
end

【讨论】:

  • 不只是链接到文档,为什么不在你的答案中举个例子呢?
  • 我已添加示例希望对您有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-08
  • 2020-10-19
  • 1970-01-01
  • 2021-05-16
  • 2014-05-28
相关资源
最近更新 更多