【发布时间】:2010-09-10 20:06:59
【问题描述】:
除非明确要求,否则我如何告诉 Activerecord 不加载 blob 列?我的旧数据库中有一些相当大的 blob,必须为“普通”对象排除。
【问题讨论】:
标签: activerecord lazy-loading blob
除非明确要求,否则我如何告诉 Activerecord 不加载 blob 列?我的旧数据库中有一些相当大的 blob,必须为“普通”对象排除。
【问题讨论】:
标签: activerecord lazy-loading blob
我刚刚使用 rail 3 遇到了这个问题。
幸运的是,解决起来并不难。我设置了一个default_scope,它从结果中删除了我不想要的特定列。例如,在我的模型中,有一个可能很长的 xml 文本字段,在大多数视图中都没有使用。
default_scope select((column_names - ['data']).map { |column_name| "`#{table_name}`.`#{column_name}`"})
您将从解决方案中看到,我必须将列映射到完全限定的版本,这样我才能通过关系继续使用模型,而不会在属性中产生歧义。稍后,如果您确实想要该字段,只需添加另一个 .select(:data) 即可将其包含在内。
【讨论】:
lazy_columns。谢谢!
default_scope { where(color: 'red') },而不是default_scope where(color: 'red')。 (或者,您可以重新定义 self.default_scope。)
fd 的回答基本正确,但 ActiveRecord doesn't currently accept an array 作为 :select 参数,因此您需要将所需的列加入逗号分隔的字符串中,如下所示:
desired_columns = (MyModel.column_names - ['column_to_exclude']).join(', ')
MyModel.find(id, :select => desired_columns)
【讨论】:
我相信您可以要求 AR 在您的调用中加载特定列以查找:
MyModel.find(id, :select => 'every, attribute, except, the, blobs')
但是,这需要在您添加列时进行更新,因此并不理想。我认为没有任何方法可以专门排除 rails 中的一列(也没有在单个 SQL 选择中)。
我猜你可以这样写:
MyModel.find(id, :select => (MyModel.column_names - ['column_to_exclude']).join(', '))
在你相信我的话之前先测试一下。 :)
【讨论】:
一种简洁的方法,无需更改您在应用程序中其他位置的编码方式,即不会混淆:select 选项
无论出于何种原因,您需要或选择将 blob 存储在数据库中。 但是,您不希望在同一个表中混合 blob 列作为您的 常规属性。 BinaryColumnTable 可帮助您将所有 blob 存储在 一个单独的表,由 ActiveRecord 模型透明地管理。 或者,它可以帮助您记录 blob 的内容类型。
使用简单
Member.create(:name => "Michael", :photo => IO.read("avatar.png"))
#=> creates a record in "members" table, saving "Michael" into the "name" column
#=> creates a record in "binary_columns" table, saving "avatar.png" binary into "content" column
m = Member.last #=> only columns in "members" table is fetched (no blobs)
m.name #=> "Michael"
m.photo #=> binary content of the "avatar.png" file
【讨论】: