【问题标题】:Rails transform variable name and value from databaseRails 从数据库中转换变量名称和值
【发布时间】:2021-06-07 00:16:06
【问题描述】:

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

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

假设有一个名为 Sprinter 的类。 Sprinter 表如下所示:

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] }
)

谢谢。

【问题讨论】:

  • 如何检查API调用是否来自使用旧版本或新版本的应用程序?
  • 好吧,url 将有 /api/v100/... 和 /api/v101/... 基于此,请求将路由到可以处理该请求的特定服务器。
  • 很好,这意味着有单独的控制器吗?对吗?
  • 是的,你可以这么说。我计划仅在几周内支持 v100(旧),因此将在不同的服务器上运行它,并在新服务器中完全放弃它。

标签: ruby-on-rails json activerecord ruby-on-rails-6 backwards-compatibility


【解决方案1】:

您可以使用序列化层代替处理模型在 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

见:

【讨论】:

  • 请注意,这并不是真正意义上的复制粘贴解决方案——它更多的是朝着正确的方向推动。
  • 是的,对于一个简单的对象代表来说,这看起来像是一个优雅的解决方案。但是,当我生成 json 时,sprinter 对象是一个嵌套属性。它通过:include 与父级连接。我觉得这不会解决这个问题。
  • 这就是像 AMS 这样的 gem 的用武之地。它也将使用序列化器进行关联。
  • 这看起来像一个方便的工具。谢谢。
【解决方案2】:

您可以通过 selectSprinter 转换键/值:

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

但不确定如何与as_json结合使用

【讨论】:

  • 这看起来像是一个开始。当我们做一些事情时,有没有办法修改默认行为..race.sprinter。我希望模型始终返回转换后的版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 2020-08-01
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多