【问题标题】:How to update json column in Rails?如何更新 Rails 中的 json 列?
【发布时间】:2020-02-23 00:34:48
【问题描述】:

我的Categories 表中有一个json 列,我想使用来自json 文件的翻译来更新每个类别记录。我已经构建了 json 文件,使其包含一个类别数组,每个类别都有一个名称和一个翻译,如下所示:

{
  "categories": [
    {
        "name": "starter",
        "message": "Abs/Анти блокираща система (система против боксуване)"
    },
    {
        "name": "alternator",
        "message": "Алтернатор"
    }
    ...
  ]
}

我希望使用语言键以及文件中的翻译来更新每个类别记录,如下所示:

{ bg: 'translation from file' }

我有这个代码

file = File.read('app/services/translations/files/bg.json')
data = JSON.parse(file)
language = File.basename(file, '.json')
Translations::CategoriesMigrator.call(file: data, language: language)

module Translations
  class CategoriesMigrator < Service
    def initialize(category_repo: Category)
      @category_repo = category_repo
    end

    def call(file:, language:)
      file['categories'].each do |category|
        found_category = @category_repo.find_by(name: category['name'])
        found_category.translated_categories[language] = category['message']
        found_category.save
      end
    end
  end
end

现在我最终将所有类别都包含在一个类别记录中。我做错了什么?

更新

我的数据库迁移如下所示:

class AddTranslatedCategoriesToCategories < ActiveRecord::Migration[5.1]
  def change
    add_column :categories, :translated_categories, :jsonb, null: false, default: {}
    add_index :categories, :translated_categories, using: :gin
  end
end

【问题讨论】:

  • 你在使用 PosgreSQL 对吗?什么版本?什么 Rails 版本?
  • 是的,Postgres,Rails 5.1.7
  • 该 JSON 列中存储的数据的结构是什么?该表的迁移情况如何?
  • 没关系,我在language = File.basename(file, '.json') 中有一个错误。 File.basename 需要一个文件路径,而不是文件本身。对此感到抱歉。
  • 很抱歉扮演魔鬼的拥护者,但为什么不将翻译添加到单独的表格中呢?它会更容易查询。这似乎是另一种情况,您应该正确使用关系模型。

标签: ruby-on-rails json ruby


【解决方案1】:

当您的数据不适合关系模型时,JSON/JSONB 是一个不错的选择。在大多数其他情况下,它是一种反模式,因为它使查询数据变得更加困难,并且不提供数据完整性或规范化。

这种情况肯定是后者,因为底层结构不是动态的。要跟踪翻译,我们只需要知道主题、语言和翻译。

class Category
  has_many :category_translations
end

# rails g model category_translation category:belongs_to locale:string text:string
class CategoryTranslation
  belongs_to :category
end

您可以在 category_id 和 locale 上添加复合索引以强制唯一性。

见:

【讨论】:

  • 欢迎您。我有一种感觉,这在以前已经做过了,您也许可以找到一些将 I18n 模块与自定义后端(您的数据库)一起使用的示例。
猜你喜欢
  • 2021-11-07
  • 2014-03-17
  • 1970-01-01
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-07
  • 1970-01-01
相关资源
最近更新 更多