我的entries
表格带有content
字段,可能包含大量文字。在大多数情况下,我不需要访问该字段,因此每次从数据库加载大量未使用的数据时都会浪费大量资源(从id = 1的条目中选择*)。
我如何指定default_scope,除content
之外的所有字段都将从数据库加载?
答案 0 :(得分:13)
假设Rails 3和一个如下所示的架构:
create_table "entries", :force => true do |t|
t.string "title"
t.text "content"
t.datetime "created_at"
t.datetime "updated_at"
end
您可以使用select
方法限制返回的字段,如下所示:
class Entry < ActiveRecord::Base
default_scope select([:id, :title])
end
在rails控制台中,您应该看到如下内容:
puts Entry.where(:id => 1).to_sql # => SELECT id, title FROM "entries" WHERE "entries"."id" = 1
如果您想要选择所有字段,可以使用unscoped
方法,如下所示:
puts Entry.unscoped.where(:id => 1).to_sql # => SELECT * FROM "entries" WHERE "entries"."id" = 1
答案 1 :(得分:2)
作用域(主要是default_scope)在使用中带来了许多问题,我最好的方法是将大内容(二进制,非常大的文本)移到单独的表中。
create_table "entries", :force => true do |t|
t.string "title"
# ... more small sized attributes of entries
t.timestamps
end
create_table "entry_contents", :force => true do |t|
t.references :entries, foreign_key: true
t.text "content"
t.timestamps
end
class Entry ...
# reference
has_one :entry_content
# build entry_content for every new entry record
after_initialize do |entry|
entry.build_entry_content unless entry.entry_content.present?
end
end
这限制了仅在需要时才加载大数据。
Entry.find(1).entry_content.content
答案 2 :(得分:0)
要建立在@phlipper答案的基础上,如果您只想指定一个或几个列来摆脱:
class Entry < ActiveRecord::Base
default_scope { select(Entry.column_names.map!(&:to_sym) - [:metadata]) }
end
如您所见,从Rails 5+开始,您必须将一个块传递给default_scope
。