【发布时间】:2012-04-01 23:54:45
【问题描述】:
我正在将 Rails 2.3.4 项目升级到 Rails 3.1.1。旧版本使用 ar-extensions 来处理数据导入。我拔出 ar-extensions 并用 activerecord-import 替换它,据我了解,它具有完全相同的接口。
我的代码调用如下所示
Student.import(columns, values)
两个 args 都是保存正确数据的有效数组,但我得到一个大错误!
错误堆栈如下所示:
NoMethodError (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.split):
activerecord (3.1.1) lib/active_record/connection_adapters/postgresql_adapter.rb:828:in 'default_sequence_name'
activerecord (3.1.1) lib/active_record/base.rb:647:in `reset_sequence_name'
activerecord (3.1.1) lib/active_record/base.rb:643:in `sequence_name'
activerecord-import (0.2.9) lib/activerecord-import/import.rb:203:in `import'
查看代码,好像 Activerecord-import 调用了 activerecord,它依次查找 Postgres 序列的名称和下一个值。
所以 activerecord-import 寻找 sequence_name lib/activerecord-import/import.rb:203
# Force the primary key col into the insert if it's not
# on the list and we are using a sequence and stuff a nil
# value for it into each row so the sequencer will fire later
-> if !column_names.include?(primary_key) && sequence_name && connection.prefetch_primary_key?
column_names << primary_key
array_of_attributes.each { |a| a << nil }
end
它调用活动记录... lib/active_record/base.rb:647:in `reset_sequence_name'
# Lazy-set the sequence name to the connection's default. This method
# is only ever called once since set_sequence_name overrides it.
def sequence_name #:nodoc:
-> reset_sequence_name
end
def reset_sequence_name #:nodoc:
-> default = connection.default_sequence_name(table_name, primary_key)
set_sequence_name(default)
default
end
serial_sequence 返回 nil 并且 default_sequence_name 尝试拆分时代码错误。
lib/active_record/connection_adapters/postgresql_adapter.rb
# Returns the sequence name for a table's primary key or some other specified key.
def default_sequence_name(table_name, pk = nil) #:nodoc:
-> serial_sequence(table_name, pk || 'id').split('.').last
rescue ActiveRecord::StatementInvalid
"#{table_name}_#{pk || 'id'}_seq"
end
def serial_sequence(table, column)
result = exec_query(<<-eosql, 'SCHEMA', [[nil, table], [nil, column]])
SELECT pg_get_serial_sequence($1, $2)
eosql
result.rows.first.first
end
当我直接对数据库执行 pg_get_serial_sequence() 时,我没有返回任何值:
SELECT pg_get_serial_sequence('student', 'id')
但是我可以看到在数据库中有一个叫做student_id_seq的序列
我正在使用以下版本的 Ruby、rails PG 等。
- Rails 3.1.1
- Ruby 1.9.2
- Activerecord 导入 0.2.9
- 第 0.12.2 页
- psql(9.0.5,服务器 9.1.3)
我已将数据库从 MySQL 迁移到 PostgreSQL,我认为这与问题没有任何关系,但我认为我最好添加它以确保完整性。
我不知道为什么这不起作用!
【问题讨论】:
标签: postgresql activerecord ruby-on-rails-3.1 auto-increment