在模型中确定哪个控制器触发保存操作?

Determine in model that which controller is trigger the save action?

正在为 api 和前端开发 rails 应用程序。所以我们有 api 的产品控制器和前面的产品控制器,产品模型是两者的一个。

像那样

class Api::V1::ProductsController < ActionController::API
  def create
    @product.save
  end
end

class ProductsController < ActionController::Base
  def create
    @product.save
    render @product
  end
end

class Product < ActiveRecord::Base
  def weight=(value)
    weight = convert_to_lb
    super(weight)
  end
end

基本上在产品中我们有 'weight field',这个字段基本上是从仓库中捕获重量。对于用户来说,这将是不同的单位。所以我将保存按单位捕获的任何重量,它的 lb、g 或 stone 但它会转换为 lb 并存储到数据库中。

所以我为对话编写了覆盖方法。但我希望这个覆盖方法应该只调用前端应用程序而不是 api。因为 api 总是 post 以磅为单位的重量(需要在客户端进行转换)

你们有谁能提出解决方案吗?对于这种 scenario.suggest 我应该使用什么或者我应该做什么,如果它也适用于这种情况的任何其他解决方案。提前致谢。

最好保持 Product 模型尽可能简单 (Single-responsibility principle) 并将重量转换放在外面。

我认为使用 Decorator 模式会很棒。想象一下 class 是这样工作的:

@product = ProductInKilogram.new(Product.find(params[:id]))
@product.update product_params
@product.weight # => kg weight here

因此,您应该只使用来自 Api::V1::ProductsController 的新 ProductInKilogram

您可以选择实现它。

继承

class ProductInKilogram < Product
  def weight=(value)
    weight = convert_to_lb
    super(weight)
  end
end

product = ProductInKilogram.find(1)
product.weight = 1

很简单,但是 ProductInKilogram 的复杂度很高。例如,您无法在没有数据库的情况下在隔离环境中测试此类 class。

简单委托人

class ProductInKilogram < SimpleDelegator
  def weight=(value)
    __getobj__.weight = convert_to_lb(value)
  end
end

ProductInKilogram.new(Product.find(1))

普通 Ruby(我的最爱)

class ProductInKilogram
  def initialize(obj)
    @obj = obj
  end

  def weight=(value)
    @obj.weight = convert_to_lb(value)
  end

  def weight
    convert_to_kg @obj.weight
  end

  def save
    @obj.save
  end
 
  # All other required methods
end

看起来有点冗长,其实很简单。测试这样的 class 非常容易,因为它对持久性没有任何影响。

链接