active_record-acts_as多次更新created_as

时间:2018-07-26 03:45:03

标签: ruby-on-rails ruby-on-rails-5.2

我正在创建Rails 5.2电子商务应用程序。我正在使用active_record-acts_as gem来模拟多表继承,该继承具有一个名为Product的父类和多个子类(BookClothingElectronic。 .etc)作为Product(它们继承了Product的所有属性和方法)。

每个产品只能在Category的上下文中创建,该上下文与Product子类的名称相对应。为了直观起见,这是我当前的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  

目前一切正常。但是,我不得不将其添加到每个this SOF question的产品模型中,尽管我修改了它以使用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方法,则创建动作有效,但更新动作无效。当我尝试更新产品(产品的子类)时,没有build_actable的错误是...

Cannot build association actable. Are you trying to build a polymorphic one-to-one association?

主要问题

尽管我当前的控制器和build_actable方法是“有效的”,但每次我更新Product属性时,它都会更新updated_at 3次...这是日志输出...

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 3次?

注意:我已经尝试过直接调用build_actable而不是在控制器中进行更新...但是它做同样的事情。我还从Product的子类中删除了时间戳。 我觉得我缺少明显的东西。...

1 个答案:

答案 0 :(得分:0)

通过将touch: false添加到Product的子类中的关联行为,我能够纠正两次更新时间戳的问题...

acts_as :product, touch: false