复制记录,它是 children - 但 children 从旧记录中删除
Duplicating record and it's children - but children get deleted from old record
我的问题类似于:
但我似乎无法找到适用于我的解决方案。我正在尝试创建一个订单交换表单,其中涉及用旧记录详细信息填充表单。因此,当我保存表单时,它会创建一个新的订单记录,但 children 似乎已从旧订单记录中删除并转移到新订单记录中。
代码如下:
def new
@old_order = Order.includes(:line_items).find(params[:id])
@order = Order.new @old_order.attributes
@order.line_items = []
@old_order.line_items.each do |old|
new = old.dup # the line_item id is set before creation.
new.order_id = @order.id
new.save!
@order.line_items << new
@old_order.line_items << old # this was to see if the old line_items would reappend to the old order. Didn't help...
end
end
def create
@order = Order.new(exchange_order_params)
if @order.save
@order.update_attributes!(stage: 2, ordered_at: Date.today)
redirect_to admin_returns_url, notice: "Order moved to 'accepted' for processing"
else
flash.now[:alert] = "Please try again"
render :action => "new"
end
end
private
def exchange_order_params
params.require(:order).permit(:id, :user_id,
line_items_attributes: [:id, :order_id, :cart_id, :quantity, :_destroy,
product_attributes: [:id, :sku, :euro_price, :sterling_price, :product_group_id, :product_size_id, :product_waistband_id]])
end
Schema.rb
create_table "orders", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "returned", default: false
t.date "date_sent"
t.date "ordered_at"
t.integer "user_id"
t.boolean "return_requested", default: false
t.integer "stage", default: 0
t.decimal "order_total", default: 0.0
t.string "transaction_secret"
t.string "token"
t.string "uuid"
t.string "currency"
t.float "discounted_by", default: 0.0
end
add_index "line_items", ["cart_id"], name: "index_line_items_on_cart_id", using: :btree
add_index "line_items", ["order_id"], name: "index_line_items_on_order_id", using: :btree
add_index "line_items", ["product_id"], name: "index_line_items_on_product_id", using: :btree
create_table "line_items", force: :cascade do |t|
t.integer "quantity"
t.integer "order_id"
t.integer "cart_id"
t.integer "product_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "unit_price"
t.string "currency"
end
create_table "product_groups", force: :cascade do |t|
t.string "name"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "product_sizes", force: :cascade do |t|
t.string "specification"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "product_waistbands", force: :cascade do |t|
t.string "specification"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "products", force: :cascade do |t|
t.integer "sku"
t.integer "product_group_id"
t.integer "product_size_id"
t.integer "product_waistband_id"
t.decimal "euro_price"
t.decimal "sterling_price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "stock_level", default: 0
end
add_index "products", ["product_group_id"], name: "index_products_on_product_group_id", using: :btree
add_index "products", ["product_size_id"], name: "index_products_on_product_size_id", using: :btree
add_index "products", ["product_waistband_id"], name: "index_products_on_product_waistband_id", using: :btree
同样在 Order 模型中,我将 id before_create 随机化,这样当用户提交表单时,它会创建一个具有不同 Order id 的复制副本。这与 LineItems 相同。
Order.rb(LineItem.rb中相同)
before_create :randomize_id
private
def randomize_id
begin
self.id = SecureRandom.random_number(1_000_000)
end while Order.where(id: self.id).exists?
end
我的方法是重写 Order 模型中的 ActiveRecord::Base#dup 方法,使其递归,这意味着它也复制 LineItem 集合:
class Order < ActiveRecord::Base
def dup
duped_order = super
duped_order.line_items = line_items.map(&:dup)
duped_order
end
end
这样做很容易测试。现在控制器变为:
class OrderController < ApplicationController
def new
@order = Order.find(params[:id]).dup
end
def create
# not sure how your form populates the params hash
# here you need to new-up and then save the order and the line items
# with the attributes from the form
end
end
编写测试以确认这是否符合您的预期。这是应该应用旧 "fat model skinny controller" 范例的完美示例。
我的问题类似于:
但我似乎无法找到适用于我的解决方案。我正在尝试创建一个订单交换表单,其中涉及用旧记录详细信息填充表单。因此,当我保存表单时,它会创建一个新的订单记录,但 children 似乎已从旧订单记录中删除并转移到新订单记录中。
代码如下:
def new
@old_order = Order.includes(:line_items).find(params[:id])
@order = Order.new @old_order.attributes
@order.line_items = []
@old_order.line_items.each do |old|
new = old.dup # the line_item id is set before creation.
new.order_id = @order.id
new.save!
@order.line_items << new
@old_order.line_items << old # this was to see if the old line_items would reappend to the old order. Didn't help...
end
end
def create
@order = Order.new(exchange_order_params)
if @order.save
@order.update_attributes!(stage: 2, ordered_at: Date.today)
redirect_to admin_returns_url, notice: "Order moved to 'accepted' for processing"
else
flash.now[:alert] = "Please try again"
render :action => "new"
end
end
private
def exchange_order_params
params.require(:order).permit(:id, :user_id,
line_items_attributes: [:id, :order_id, :cart_id, :quantity, :_destroy,
product_attributes: [:id, :sku, :euro_price, :sterling_price, :product_group_id, :product_size_id, :product_waistband_id]])
end
Schema.rb
create_table "orders", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "returned", default: false
t.date "date_sent"
t.date "ordered_at"
t.integer "user_id"
t.boolean "return_requested", default: false
t.integer "stage", default: 0
t.decimal "order_total", default: 0.0
t.string "transaction_secret"
t.string "token"
t.string "uuid"
t.string "currency"
t.float "discounted_by", default: 0.0
end
add_index "line_items", ["cart_id"], name: "index_line_items_on_cart_id", using: :btree
add_index "line_items", ["order_id"], name: "index_line_items_on_order_id", using: :btree
add_index "line_items", ["product_id"], name: "index_line_items_on_product_id", using: :btree
create_table "line_items", force: :cascade do |t|
t.integer "quantity"
t.integer "order_id"
t.integer "cart_id"
t.integer "product_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "unit_price"
t.string "currency"
end
create_table "product_groups", force: :cascade do |t|
t.string "name"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "product_sizes", force: :cascade do |t|
t.string "specification"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "product_waistbands", force: :cascade do |t|
t.string "specification"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "products", force: :cascade do |t|
t.integer "sku"
t.integer "product_group_id"
t.integer "product_size_id"
t.integer "product_waistband_id"
t.decimal "euro_price"
t.decimal "sterling_price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "stock_level", default: 0
end
add_index "products", ["product_group_id"], name: "index_products_on_product_group_id", using: :btree
add_index "products", ["product_size_id"], name: "index_products_on_product_size_id", using: :btree
add_index "products", ["product_waistband_id"], name: "index_products_on_product_waistband_id", using: :btree
同样在 Order 模型中,我将 id before_create 随机化,这样当用户提交表单时,它会创建一个具有不同 Order id 的复制副本。这与 LineItems 相同。
Order.rb(LineItem.rb中相同)
before_create :randomize_id
private
def randomize_id
begin
self.id = SecureRandom.random_number(1_000_000)
end while Order.where(id: self.id).exists?
end
我的方法是重写 Order 模型中的 ActiveRecord::Base#dup 方法,使其递归,这意味着它也复制 LineItem 集合:
class Order < ActiveRecord::Base
def dup
duped_order = super
duped_order.line_items = line_items.map(&:dup)
duped_order
end
end
这样做很容易测试。现在控制器变为:
class OrderController < ApplicationController
def new
@order = Order.find(params[:id]).dup
end
def create
# not sure how your form populates the params hash
# here you need to new-up and then save the order and the line items
# with the attributes from the form
end
end
编写测试以确认这是否符合您的预期。这是应该应用旧 "fat model skinny controller" 范例的完美示例。