Ruby on rails PostgreSQL建模&x27;在Rails中创建大型对象
我需要在rails应用程序的db中保存大型对象。我想我可以在SQL中创建一个表Ruby on rails PostgreSQL建模&x27;在Rails中创建大型对象,ruby-on-rails,postgresql,blob,Ruby On Rails,Postgresql,Blob,我需要在rails应用程序的db中保存大型对象。我想我可以在SQL中创建一个表 CREATE TABLE files ( id serial NOT NULL, name string NOT NULL, blob_oid oid NUT NULL ) 然后将数据存储在Ruby中作为 conn.exec("BEGIN") lo = conn.lo_import(data) conn.exec("COMMIT") file = File.new file.name = file_name; fi
CREATE TABLE files (
id serial NOT NULL,
name string NOT NULL,
blob_oid oid NUT NULL
)
然后将数据存储在Ruby中作为
conn.exec("BEGIN")
lo = conn.lo_import(data)
conn.exec("COMMIT")
file = File.new
file.name = file_name; file.blob_oid = lo.id
file.save
首先,这是正确的吗?其次,我如何描述Rails中的文件模型。Rails中
Friend.blob_oid
的数据类型是什么?我可以在Rails中使用迁移创建文件表吗?如果使用Rails附带的ActiveRecord及其适配器,数据库类型到Rails或Ruby类型的唯一正式映射通常是在适配器中的NATIVE\u database\u TYPES
常量中定义的,该常量通过其NATIVE\u database\u TYPES
方法返回。对于Rails 3.2.x中的PostgreSQL,这是在ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
中,它是。因此,对于该适配器,Rails中的“binary”类型映射到PG中的“bytea”类型。对于某些类型,您可以使用名为。但是,我们想使用大型对象,所以
迁移
正如Jim Deville在注释中指出的,您可以在表中指定自定义类型的列,如下所示:
t.column :some_oid, 'blob_oid', :null => false
如果需要执行更多非标准的操作,还可以使用execute(“SQL转到这里;”)
来使用直接SQL创建表。并且,如果已经存在迁移之外的现有遗留模式或SQL更改,请考虑使用Scheme.sql(<代码> CONTION.ActhViReord.Schema格式=:SQL<代码>选项> <代码> CONFIG/Apvest.Rb<代码>,然后执行:<代码> RAKEDB:结构:转储< /代码>)。
大型对象读取/写入/检查长度/删除
复制并进行一些修改,以澄清,等等,来源:
更新:我们可以但不需要在lo_read/lo_write/lo_lseek和do lo_close前加上begin,因为根据“任何在交易结束时保持打开状态的大型对象描述符都将自动关闭。”(感谢Diogo提供的信息)
使用模型或基础中的原始连接,而不是连接
,例如ActiveRecord::base.connection.raw\u连接
(请参阅)
(…).transaction
正在调用模型或基础上的事务,例如ActiveRecord::base.transaction
(请参阅)
identifier
是您需要传入/设置的oid,或仅通过执行连接即可获得的oid。lou_create
其他示例/信息:
后者和一些答案表明,您可能需要考虑与DB分离的大型文件的存储,例如,这样就可以使用云存储。但是,如果只存储指向不由DB管理的外部文件的路径/ID,则会丢失ACID一致性(一个或多个DB记录可能指向一个或多个不存在的文件,或者可能存在一个或多个数据库中没有一个或多个关联记录的文件)。在文件系统上存储文件的另一个理由是,您可以流式传输文件,但PG large object以postgres管理的方式在文件系统上存储文件,以确保ACID一致性并允许流式传输(这是普通BLOB/Rails二进制类型所无法做到的)。所以,这要视情况而定;有些人认为使用路径引用存储在单独的存储中是更好的选择,有些人更喜欢通过大型对象实现ACID一致性
简单的方法只需使用和。您确定需要大型对象吗?大多数情况下,使用
bytea
来存储“BLOB”数据更合适。@horse\u没有名字,我想我可以使用bytea或text(我正在存储文本文件),但这不会在ActiveRecord对象中加载整个文件吗?我认为这会造成记忆问题。使用pg在Rails中存储此类文件的好方法是什么?您可以将正常迁移与非正常迁移类型一起使用:谢谢,Jim!更新了答案。
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