我正在通过创建带有*_locales
和locale
字段的关联name
表来完成本地化的项目。我正在将其迁移到使用hstore
列(使用Postgres),但我没有正确的语法。
结构现在就像这样
table: thingy_locales
locale :string
name :string
thingy_id : integer
table: thingies
name_translations :hstore
在迁移中,我希望将thingy_locales
表中的所有数据移至name_translations
字段,密钥为'en'
(因为目前只有' en&#39 ; thingy_locales
表中的区域设置。)
所以我试过这个
execute "UPDATE thingies t SET name_translations=(select (\"'en'\" => \"'|name|'\")::hstore from thingy_locales where thingy_id = t.id);"
但是这给了我
PG::UndefinedColumn: ERROR: column "'en'" does not exist
LINE 1: ...ort_categories loc SET name_translations=(select ("'en'" => ...
^
我做错了什么?
答案 0 :(得分:1)
我不知道自动执行SQL命令,但您可能希望进行多次迁移:
thingies
thingy_locales
,将它们读入散列/哈希值。然后做Thingy.create!(name_translations: {'en' => hash})
thingy_locales
Rails中的迁移可以包含任意代码。由于这是一个转换数据的实例,因此在Ruby中执行它可能是最安全的选择。
如果速度是一个问题,那么你可能需要寻求优化的SQL查询,但坦率地说,如果你不担心速度,不要为自己造成麻烦。
答案 1 :(得分:1)
实际上,只要再看一下你的代码,假设你有这种关联:
class Thingy
has_many :thingy_locales
end
class ThingyLocale
belongs_to :thingy
end
看起来你想做的事情就像这样:
Thingy.all.each do |thingy|
name = thingy.thingy_locales.where(locale: 'en').first.select(:name)
thingy.name_translations = {'en' => name}
thingy.save!
end
答案 2 :(得分:1)
好的,我让它上班了。
execute "UPDATE thingies t SET name_translations=hstore('en', (select name from thingy_locales where thingy_id = t.id));"
完美地完成工作
答案 3 :(得分:1)
不要试图通过Ruby研磨大量数据,在数据库中进行。立即想到两种方法:
在UPDATE中使用相关子查询:
connection.execute(%q{
update thingies
set name_translations = (
select hstore(array_agg(locale), array_agg(name))
from thingy_locales
where thingy_id = thingies.id
)
})
加入UPDATE中的派生表:
connection.execute(%q{
update thingies
set name_translations = dt.h
from (
select hstore(array_agg(locale), array_agg(name)) as h, thingy_id
from thingy_locales
group by thingy_id
) as dt
where id = dt.thingy_id
})
两者的核心是使用hstore(text[], text[])
function构建hstore
和array_agg
function来构建hstore(text[], text[])
想要的键和值数组。
不要害怕在迁移中将SQL引入connection.execute
次调用。假装你的数据库太愚蠢而无法做任何有趣的事情在Rails应用程序中可能是纯粹的意识形态,但它是一种非生产性和不专业的态度。从长远来看,通过学习SQL以及数据库的工作方式,您将获得更好的服务。