Rails 从数据库中转换变量名和值

Rails transform variable name and value from database

我想在 class 的 属性 中使用一个转换后的 name/value,而不是我们从数据库中获取的 class。我需要这个的原因是我有两个版本的应用程序指向同一个数据库,但较新的版本最近更新了列名称。因此,对于所有使用旧版本的应用程序,都必须使其兼容。

Environment: Rails version: 6.0.3.3 & Ruby version: ruby 2.7.1p83

假设有一个叫做 Sprinter 的 class。 短跑运动员 table 看起来像:

id name m s
1 Mr. Bolt 100 9.58

sprinter 实例看起来像:

sprinter = {
   "id" => 1,
   "name" => "Mr. Bolt",
   "m" => 100,
   "s" => 9.58
}

旧版本需要不同的格式。现在我想要这样的东西:

sprinter = {
   "id" => 1,
   "name" => "Mr. Bolt",
   "cm" => 10000, # transformed from `m`
   "ms" => 9580   # transformed from `s`
}

m 列名称已转换为 cm,值也已转换。 sms 的情况相同。值转换没什么大不了的,但是变量名好像是。

我希望在获取对象时进行内部更新。但是,如果不支持,作为基本级别的解决方案,我更愿意更改我发送给客户端的 json 表示。作为参考,我将它用作嵌套 include 的一部分,例如:

render status: :ok, json: {races: races}.as_json(
            {:include => [:sprinters] }
)

谢谢。

您可以将 keys/values 从 Sprinter 转换为 select:

Sprinter.select(:id, :name, 'm * 100 AS cm', 's * 1000 AS ms')

但不确定如何将其与 as_json

结合使用

您可以使用序列化层来处理 JSON.

中模型的不同表示,而不是研究 .as_json 的内部结构或您的模型如何进行序列化。

例如,您可以使用 ActiveModel::Serializers 或 JBuilder,如果您愿意,甚至可以自己动手。

module API
  module V2
    class SprinterAdapter
      def intialize(sprinter)
        @sprinter = sprinter
      end

      def to_json
        @sprinter.to_json.except("m", "s").merge(
          "cm" => @sprinter.m * 100,
          "ms" => @sprinter.s * 1000
        )
      end
    end
  end
end

并且在您的控制器中,您将使用序列化程序来呈现资源:

module API
  module V2
    class SprintersController < ApplicationController
      def show
        @sprinter = Sprinter.find(params[:id])
        render json: SprinterAdapter.new(@sprinter)
      end
    end
  end
end

参见: