Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails PostgreSQL建模&x27;在Rails中创建大型对象_Ruby On Rails_Postgresql_Blob - Fatal编程技术网

Ruby on rails PostgreSQL建模&x27;在Rails中创建大型对象

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

我需要在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; 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