【问题标题】:Data structure versioning in railsRails 中的数据结构版本控制
【发布时间】:2025-12-10 04:30:01
【问题描述】:

首先声明:不知道我是否在这里尝试了不可能的事情。

我们的 rails (2.3.12) 应用程序发展得非常快。这个小家伙已经有超过 20 个模型和超过 100 个迁移。此应用程序的任务之一是提供 API。我们目前正在引入 API 版本控制方案,类似于:Best practices for API versioning?

但是,除了拥有不同版本的控制器之外,我们还希望拥有不同版本的模型/数据库表。例如,在 API V1.0 版本中,我们提供了一种获取所有汽车的 JSON 列表的方法,我们可以这样说:

http://we.com/v1.0/cars/

为此,我们有一个看起来像这样的汽车模型(以及相应的迁移):

class car
   attr_accessible :maker, :country
end

现在对于 API 的第 2 版,我们希望我们的 API 调用如下所示:

http://we.com/v2.0/cars

模型看起来像这样:

class car
    attr_accessible :make, :country_code, :country_name
end

我希望你能得到这张照片。我不明白(或还没有正确的想法)是:

我是否必须为此创建两个模型才能使用命名空间?例如

app/models/v1.0/car.rb
app/models/v2.0/car.rb

...或者我可以以某种方式拥有一个尊重 DATA STRUCTURE 版本的模型吗? (注意:我不打算对我的模型实例进行版本控制,vestal_versions 等在这里没有解决方案)

是否可以同时使用这两个模型?我的意思是有一种聪明的方法可以在同一数据上使用模型的两个版本吗?我想到了像“装饰器”或“适配器”这样的模式,我只是没有找到任何例子。但是鉴于我们有一个转换器方法(在我们的示例中)可以转换

[:country] to [:country_code, :country_name]

反之亦然,那不行吗?

这可能吗?你知道处理这个问题的宝石吗?

【问题讨论】:

    标签: ruby-on-rails data-structures migration versioning


    【解决方案1】:

    如果您有像您说的那样转换[:country] to [:country_code, :country_name] 的方法,我认为没有问题。您只需确保每个 API 的控制器都返回正确的内容。

    我不知道您究竟是如何生成 JSON 的,但您可能只需要编写 @car.to_json_1_0@car.to_json_2_0 之类的方法,或者将版本作为参数传递给 JSON 转换方法。

    【讨论】:

    • 我喜欢您实现不同版本的 JSON 序列化程序的想法。你知道任何可以简化这项工作的宝石吗?
    • 我认为不需要单独的 gem,您可以简单地在 Ruby 哈希上调用 to_json
    【解决方案2】:

    我认为此类问题没有现成的解决方案。我认为您维护 api 版本的最佳方法是这样做:

    为所有 API 版本创建可靠的验收测试套件。 (它应该将您的 API 视为黑匣子 - 不应该有任何实现细节,如字段名称等。)这将解决您的问题 - 您将能够更改旧版本的 api 实现细节而不改变行为。因此,在您的示例中,当您决定更改字段名称时 - 您的测试套件会立即向您显示您的 API 已损坏,您必须调整其实现(但不是外部行为!)。我认为这比维护不同的模型版本要容易很多,我认为这几乎是不可能和多余的。

    【讨论】:

    • 对 API 功能进行黑盒测试是理所当然的。我不明白这如何解决我们维护不同版本的问题。