如何使用 change_column 在 rails 迁移 postgres 中生成使用 hstore 的权利 sql
How to generate right sql for using hstore in rails migration postgres using change_column
我需要让 hstore 在 rails 迁移中工作。我已经通过迁移启用了 hstore,现在,我正在尝试生成正确的 sql 以使其正常工作,但是当我 运行 db:migrate 我收到此错误;
C:\Sites\Peoples_Profiles>rails db:migrate
rails aborted!
SyntaxError: C:/Sites/Peoples_Profiles/db/migrate/20180407073155_add_hstore_hash_to_urls.rb:4: syntax error, unexpected '\n', expecting =>
C:/Sites/Peoples_Profiles/db/migrate/20180407073155_add_hstore_hash_to_urls.rb:10: syntax error, unexpected end-of-input, expecting keyword_end
bin/rails:4:in `require'
bin/rails:4:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
迁移看起来像这样。
class AddHstoreHashToUrls < ActiveRecord::Migration[5.0]
def self.up
change_column :users, :urls, default: {}, "hstore USING urls::hstore"
end
def self.down
change_column :users, :urls, :text
end
end
获取该列的类型集的正确 sql 是什么?为什么我会收到换行符错误?
更新
我的网址在 db
中像这样存储
urls: {"url1"=>"", "url2"=>"", "url3"=>"", "url4"=>"", "url5"=>""}
所以我认为 postgres 正在抱怨,因为它正在尝试转换此代码..
所以在检查 rails 实际引入参数后,它看起来像这样
["urls", "--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\nurl1: http://hello\nurl2: http://jack\nurl3: http://boo\nurl4: ''\nurl5: ''\n"]
不幸的是,不确定它在数据库中是否看起来像这样,但我说在某些地方有一个 \n 导致了这个错误。将不得不进一步追求这一点。
...我现在意识到 \n 将来自序列化哈希到 YAML 的转换。
尝试将 SELF.DOWN 更改为 SELF.ANNUAL
我认为它会解决
大概您是从:
开始的
serialize :urls
在您的模型中,因此您的散列将作为 YAML 存储在数据库中。没有从 YAML 文本到 hstore
的类型转换,因此您的 USING:
USING urls::hstore
行不通。没有简单的方法可以在 PostgreSQL 中可靠地解析 YAML,所以最好的选择是:
- 将
users.urls
列重命名为 users.yaml_urls
。
- 添加一个新的
urls
列(最好) jsonb
类型,但如有必要,您可以使用 hstore
。 jsonb
是未来,未来会得到更好的支持。
- 将数据库中的每个
yaml_urls
值读入 Ruby。
- 将该 YAML 字符串转换为具有
h = YAML.load(yaml_from_db)
的散列。
- 将哈希编码为 JSON (
h.to_json
) 并将其放回数据库中。
- 如果需要,使
urls
NOT NULL 并删除 yaml_urls
列。
我建议为此使用低级别 pg interface,因为您不希望 ActiveRecord 东西妨碍您,您能在 ApplicationRecord.connection.raw_connection
中找到这样的连接吗?我这样说是因为您不希望数据迁移以任何方式与模型交互,并且低级接口支持占位符,因此您可以避免转义和引用问题。
该过程假定您没有那么多数据,或者等同地,您的应用程序可以在您修复数据库时脱机。如果不是这种情况,那么您需要维护这两种格式(添加一个新的 jsonb
列,在调用 urls
和 urls=
时在模型内部写入和读取两者)同时您修复数据,稍后再清理。
我需要让 hstore 在 rails 迁移中工作。我已经通过迁移启用了 hstore,现在,我正在尝试生成正确的 sql 以使其正常工作,但是当我 运行 db:migrate 我收到此错误;
C:\Sites\Peoples_Profiles>rails db:migrate
rails aborted!
SyntaxError: C:/Sites/Peoples_Profiles/db/migrate/20180407073155_add_hstore_hash_to_urls.rb:4: syntax error, unexpected '\n', expecting =>
C:/Sites/Peoples_Profiles/db/migrate/20180407073155_add_hstore_hash_to_urls.rb:10: syntax error, unexpected end-of-input, expecting keyword_end
bin/rails:4:in `require'
bin/rails:4:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
迁移看起来像这样。
class AddHstoreHashToUrls < ActiveRecord::Migration[5.0]
def self.up
change_column :users, :urls, default: {}, "hstore USING urls::hstore"
end
def self.down
change_column :users, :urls, :text
end
end
获取该列的类型集的正确 sql 是什么?为什么我会收到换行符错误?
更新 我的网址在 db
中像这样存储 urls: {"url1"=>"", "url2"=>"", "url3"=>"", "url4"=>"", "url5"=>""}
所以我认为 postgres 正在抱怨,因为它正在尝试转换此代码..
所以在检查 rails 实际引入参数后,它看起来像这样
["urls", "--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\nurl1: http://hello\nurl2: http://jack\nurl3: http://boo\nurl4: ''\nurl5: ''\n"]
不幸的是,不确定它在数据库中是否看起来像这样,但我说在某些地方有一个 \n 导致了这个错误。将不得不进一步追求这一点。
...我现在意识到 \n 将来自序列化哈希到 YAML 的转换。
尝试将 SELF.DOWN 更改为 SELF.ANNUAL 我认为它会解决
大概您是从:
开始的serialize :urls
在您的模型中,因此您的散列将作为 YAML 存储在数据库中。没有从 YAML 文本到 hstore
的类型转换,因此您的 USING:
USING urls::hstore
行不通。没有简单的方法可以在 PostgreSQL 中可靠地解析 YAML,所以最好的选择是:
- 将
users.urls
列重命名为users.yaml_urls
。 - 添加一个新的
urls
列(最好)jsonb
类型,但如有必要,您可以使用hstore
。jsonb
是未来,未来会得到更好的支持。 - 将数据库中的每个
yaml_urls
值读入 Ruby。 - 将该 YAML 字符串转换为具有
h = YAML.load(yaml_from_db)
的散列。 - 将哈希编码为 JSON (
h.to_json
) 并将其放回数据库中。 - 如果需要,使
urls
NOT NULL 并删除yaml_urls
列。
我建议为此使用低级别 pg interface,因为您不希望 ActiveRecord 东西妨碍您,您能在 ApplicationRecord.connection.raw_connection
中找到这样的连接吗?我这样说是因为您不希望数据迁移以任何方式与模型交互,并且低级接口支持占位符,因此您可以避免转义和引用问题。
该过程假定您没有那么多数据,或者等同地,您的应用程序可以在您修复数据库时脱机。如果不是这种情况,那么您需要维护这两种格式(添加一个新的 jsonb
列,在调用 urls
和 urls=
时在模型内部写入和读取两者)同时您修复数据,稍后再清理。