Ruby on Rails:默认情况下阻止选择列

时间:2011-06-16 09:55:55

标签: ruby-on-rails activerecord

我的entries表格带有content字段,可能包含大量文字。在大多数情况下,我不需要访问该字段,因此每次从数据库加载大量未使用的数据时都会浪费大量资源(从id = 1的条目中选择*)。

我如何指定default_scope,除content之外的所有字段都将从数据库加载?

3 个答案:

答案 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

还有you should consider not using default scope