Обновление драгоценного камня active_record-actions_as созданного несколько раз
Я создаю приложение электронной коммерции Rails 5.2. Я использую гем active_record-acts_as для имитации наследования нескольких таблиц, родительский класс которого называется Product
и несколько подклассов (Book
, Clothing
, Electronic
... и т. д.), что все действуют как Product
(они наследуют все атрибуты и методы Продукта).
Каждый продукт может быть создан только в контексте Category
, что соответствует названиям подклассов Продукта. Для наглядности вот мой текущий ProductsController...
class ProductsController < ApplicationController
before_action :set_category, only: [:new, :create]
before_action :set_product_type, only: [:new, :create]
before_action :set_product, only: [:show, :edit, :destroy]
def show
authorize @product
end
def new
@product = Product.new(actable: @product_type.new)
authorize @product
end
def create
@product = @product_type.new product_params
authorize @product
@product.category = @category
@product.user = current_user
if @product.save
redirect_to product_path @product.slug
else
render :new
end
end
def edit
@product = Product.friendly.find(params[:id])
authorize @product
@category = @product.category
set_product_type
end
def update
@product = Product.friendly.find(params[:id])
authorize @product
@category = @product.category
set_product_type
if @product.update product_params
redirect_to product_path @product.slug
else
render :edit
end
end
def destroy
authorize @product
@category = @product.category
if @product.destroy
redirect_to category_path(@category)
else
redirect_to request.referrer
end
end
private
def set_category
@category = Category.friendly.find(params[:category_id])
end
def set_product
# specific comes from active_record_acts-as gem
@product = Product.friendly.find(params[:id]).specific
end
def set_product_type
@product_type = @category.name.singularize.capitalize.constantize
end
def product_params
params.require(:product).permit(:name, :description, :price_cents, :main_image, actable_attributes: (@product_type.permitted_params))
end
end
В настоящее время все работает. Тем не менее, я должен был добавить это к модели продукта в соответствии с этим вопросом SOF, хотя я изменил его, чтобы использовать update
вместо new
, чтобы исправить мою конкретную проблему.
ACTABLE_TYPES = %w(Book Supply Electronic etc...)
def build_actable(params)
raise "Unknown actable_type: #{actable_type}" unless ACTABLE_TYPES.include?(actable_type)
self.actable.update(params)
end
Если build_actable
метод не включен, действие create работает, а действие update - нет. Ошибка, без build_actable
когда я пытаюсь обновить продукт (подкласс продукта)...
Cannot build association actable. Are you trying to build a polymorphic one-to-one association?
Главный вопрос
Хотя мой текущий контроллер и build_actable
метод "работает", каждый раз, когда я обновляю атрибут Product, он обновляется updated_at
три раза... вот вывод журнала...
Book Load (0.7ms) SELECT "books".* FROM "books" WHERE "books"."id" = $1 LIMIT $2 [["id", 13], ["LIMIT", 1]]
↳ app/controllers/products_controller.rb:45
Product Update (1.0ms) UPDATE "products" SET "name" = $1, "updated_at" = $2 WHERE "products"."id" = $3 [["name", "Where Angels Fear to Tread something else "], ["updated_at", "2018-07-26 03:28:30.414635"], ["id", 13]]
↳ app/models/product.rb:22
Product Update (0.7ms) UPDATE "products" SET "updated_at" = $1 WHERE "products"."id" = $2 [["updated_at", "2018-07-26 03:28:30.417622"], ["id", 13]]
↳ app/models/product.rb:22
Product Update (0.5ms) UPDATE "products" SET "updated_at" = $1 WHERE "products"."id" = $2 [["updated_at", "2018-07-26 03:28:30.420007"], ["id", 13]]
↳ app/models/product.rb:22
(5.0ms) COMMIT
Мой контроллер, конечно, должен быть реорганизован... но почему он обновляется updated_at
три раза???
Примечание: я попытался вызвать build_actable напрямую вместо обновления в контроллере... но он делает то же самое. Я также удалил временные метки из подклассов продукта. Я чувствую, что упускаю что-то очевидное....
1 ответ
Мне удалось исправить проблему обновления временных меток дважды, добавив touch: false
к актам как объединение в подклассах Продукта...
acts_as :product, touch: false