如果使用带有其中一个适配器的Rails附带的ActiveRecord,那么通常在通过其native_database_types
方法返回的适配器中的NATIVE_DATABASE_TYPES
常量中定义数据库类型到Rails或Ruby类型的唯一正式映射。对于Rails 3.2.x中的PostgreSQL,即ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
即here。因此,对于该适配器,Rails中的“二进制”类型映射到PG中的“bytea”类型。对于某些类型,您可以使用名为activerecord-native_db_types_override的gem覆盖它映射到的数据库类型。但是,我们要使用大型对象,所以......
迁移
吉姆德维尔在评论中指出的那样,你可以在表中指定类型的列,如自定义:
t.column :some_oid, 'blob_oid', :null => false
如果您需要做更多非标准的事情,您还可以使用execute("SQL GOES HERE;")
使用直接SQL来创建表。而且,如果您有现有的遗留模式或SQL迁移之外的更改,请考虑使用structure.sql(config.active_record.schema_format = :sql
选项config/application.rb
,然后执行:rake db:structure:dump
)。
大对象读/写/检查长度/删除
一些修改复制澄清等来自:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb:
更新:我们可以,但不必把在lo_read/lo_write/lo_lseek之前开始并且在lo_close中确保阻止,因为根据PG documentation“在交易结束时保持打开的任何大对象描述符都将自动关闭。” (感谢迪奥戈该信息)
require 'pg'
...
def read
(...).transaction do
lo = connection.lo_open(identifier)
content = connection.lo_read(lo, file_length)
connection.lo_close(lo)
content
end
end
def write(file)
(...).transaction do
lo = connection.lo_open(identifier, ::PG::INV_WRITE)
size = connection.lo_write(lo, file.read)
connection.lo_close(lo)
size
end
end
def delete
connection.lo_unlink(identifier)
end
def file_length
(...).transaction do
lo = connection.lo_open(identifier)
size = connection.lo_lseek(lo, 0, 2)
connection.lo_close(lo)
size
end
end
代替connection
,使用从模型或碱,例如原始连接ActiveRecord::Base.connection.raw_connection
(见this)。
(...).transaction
正在模型或基础上调用交易,例如, ActiveRecord::Base.transaction
(参见this)。
identifier
是您要么通过/设置或从connection.lo_creat
获得的oid。
其他例子/信息:
后者和一些答案here建议你可能要考虑的大文件存储从分离DB,例如以便您可以使用云存储。但是,如果仅将路径/ ID存储到数据库管理的外部文件而不是,则会失去ACID一致性(一个或多个数据库记录可能指向一个或多个不存在的文件或一个或多个文件可能存在数据库中没有一个或多个关联记录)。将文件存储在文件系统上的另一个参数是可以对文件进行流式处理,但PG大对象以postgres管理的方式将文件存储在文件系统中,以确保ACID一致性并允许流式处理(您无法使用正常的BLOB/Rails二进制类型)。所以,这取决于;有些人发现使用路径引用存储在单独的存储中是一个更好的选择,有些更喜欢通过大对象的ACID一致性。
简单的方法
只需使用CarrierWave和carrierwave-postgresql。
您确定您需要大物件吗?大多数时候使用'bytea'来存储“BLOB”数据更合适。 –
@a_horse_with_no_name,我想我可以使用bytea或文本(我正在存储文本文件),但不会加载ActiveRecord对象内的整个文件?我认为这可能会造成记忆问题。用pg在Rails中存储这些文件的好方法是什么? – highBandWidth