将HStore列更改为数组

萨沙

我在Rails / Postgres应用程序中有一列想要从Hstore更改为Array。(我将手机存储为哈希,所以可以这样做{default: 123, mobile: 1234},但认为这是不必要的/没用的)

因此,我进行了以下迁移:

class ChangePhonesToArray < ActiveRecord::Migration
  def up
    new_phones = {}
    Place.find_each do |p|
      new_phones[p.id] = p.phones.values.map{ |v| v.gsub(%r!\D!, '') } # get rid of non-number characters while I'm at it
    end

    remove_column :places, :phones

    add_column :places, :phones, :string, array: true, default: []

    new_phones.each do |k, v|
      p = Place.find(k)
      p.update_attributes!(phones: v)
    end
  end
  ...
end

但是,当我这样做时,我得到了这个讨厌的数据库错误,表明那phones仍然是Hstore列!

StandardError: An error has occurred, this and all later migrations canceled:

can't cast Array to hstore/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract/quoting.rb:76:in `type_cast'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql/quoting.rb:111:in `type_cast'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:828:in `block in exec_cache'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:827:in `map'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:827:in `exec_cache'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `exec_delete'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:101:in `update'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `update'

我以为该列未被正确删除,因此我remove_column在第一列之后立即扔了第二列,这引发了以下错误,表明该列已被移除!(但显然并不完全)。

StandardError: An error has occurred, this and all later migrations canceled:

PG::UndefinedColumn: ERROR:  column "phones" of relation "places" does not exist
: ALTER TABLE "places" DROP "phones"/Users/sasha/.rvm/gems/ruby-2.1.2/gems/rack-mini-profiler-0.9.2/lib/patches/sql_patches.rb:160:in `exec'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/rack-mini-profiler-0.9.2/lib/patches/sql_patches.rb:160:in `async_exec'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:128:in `block in execute'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:373:in `block in log'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:367:in `log'
/Users/sasha/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:127:in `execute'

知道这里发生了什么,以及如何解决/解决它吗?

亩太短

仅仅因为您更改了数据库内部的表架构并不意味着您的Place类知道这些更改。ActiveRecord::Base子类仅加载一次列信息,以避免不必要地一遍又一遍地访问数据库。一旦您这样做:

Place.find_each

Place将知道列的类型。然后,您更改背后的模式,Place并尝试编写新值,但Place不知道更改。解决此问题的常用方法是致电reset_column_information

重置所有有关列的缓存信息,这将导致它们在下一个请求时重新加载。

此方法最常见的用法模式可能是在迁移中...

所以你只想说:

#...
remove_column :places, :phones
add_column :places, :phones, :string, array: true, default: []
Place.reset_column_information
#...

顺便说一句,不能保证hstore将保持任何顺序,因此您可能希望p.phones.values_at(:default, :mobile)而不是p.phones.values确保数组中的顺序正确。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

将行数组更改为JavaScript中的列数组

来自分类Dev

将数组的列值更改为列标题

来自分类Dev

将数组更改为ArrayList

来自分类Dev

将数组更改为json

来自分类Dev

尝试将数组数组更改为数组

来自分类Dev

将数组更改为数组列表

来自分类Dev

将列更改为索引

来自分类Dev

将数组键更改为小写

来自分类Dev

将数组更改为SQL查询

来自分类Dev

将DataFrame中的数组更改为值

来自分类Dev

将json值更改为数组

来自分类Dev

将哈希值更改为数组

来自分类Dev

将xml响应更改为数组或对象

来自分类Dev

将数组键更改为小写

来自分类Dev

将一维NumPy数组从(隐式)行主要顺序更改为列主要顺序

来自分类Dev

通过在定界符上分割,将列数据类型从文本更改为数组

来自分类Dev

如何使用一列将数组尺寸从一维更改为二维

来自分类Dev

将 data.frame 的所有数组列更改为列表

来自分类Dev

更改列标签?例如:将“ A”列更改为“名称”列

来自分类Dev

更改列标签?例如:将“ A”列更改为“名称”列

来自分类Dev

将JSON列更改为INTEGER [] ARRAY

来自分类Dev

将列类型从varchar更改为timestamp

来自分类Dev

将熊猫索引更改为列标题

来自分类Dev

将选定的行更改为列

来自分类Dev

将列类型从文本更改为整数

来自分类Dev

将列值从1更改为0

来自分类Dev

将熊猫索引更改为列标题

来自分类Dev

将列更改为唯一

来自分类Dev

将标签更改为datagridview列的总和