Selecting only a subset of columns.

Hi.

In many areas in the AR API you can specify a :select option to select only a subset of columns.

Is there any way to change the default selected columns (which is "*") to a subset of columns for a whole model.

such that when I write Model.find(1) it gives me an instance with only, say 3 (out of 7), columns. and to fetch all columns I have to write Model.find(1, :select => "*")

Thanks in advance.

Jarl

Can you do that in a default_scope for the model? I have not tried it.

Colin

You may try adding a "default_scope :select=>'id, name, etc' " to your model. This would accomplish what you are looking for, but I can't assure it won't give you problems later in your code. Maybe you should add a regular named_scope with parameters and use it instead of 'find'.

Anyway, you should always add the 'id' attribute to that list, just in case you want to reload a particular object you found; if you don't have id, '.reload' won't work.

Thanks Xuan and Colin for your attention.

Xuan <xuanpa@gmail.com> writes:

You may try adding a "default_scope :select=>'id, name, etc' " to your model. This would accomplish what you are looking for,

That was exactly what I was looking for.

My actual implentation looked like this in my AR class

  DEFAULT_SELECT = "#{column_names.reject{|c| c =~ /image/ }.map{|c| "\"orders\".\"#{c}\""}.join(', ')}".freeze   default_scope :select => DEFAULT_SELECT

And the very few places that I need all columns, I have added :select => '*' to the find call

but I can't assure it won't give you problems later in your code. Maybe you should add a regular named_scope with parameters and use it instead of 'find'.

Fortunately I have thousands of tests to asure that :slight_smile:

Jarl

Jarl Friis <jarl@gavia.dk> writes:

Thanks Xuan and Colin for your attention.

Xuan <xuanpa@gmail.com> writes:

You may try adding a "default_scope :select=>'id, name, etc' " to your model. This would accomplish what you are looking for,

That was exactly what I was looking for.

My actual implentation looked like this in my AR class

  DEFAULT_SELECT = "#{column_names.reject{|c| c =~ /image/ }.map{|c| "\"orders\".\"#{c}\""}.join(', ')}".freeze   default_scope :select => DEFAULT_SELECT

Warning to others:

This is not a good solution, it gives problems upon deploying an application at a clean environment. The problem arise when doing rake db:migrate, since column_names tries to get column names from the database at a time where the table does not exist!

I have not found a better way (yet)

Jarl

I think you can avoid the problem in the migration by defining the model class inside the migration, so something like:

class YourMigration < ActiveRecord::Migration   class TheProblematicClass < ActiveRecordBase;   end

  def self.up     ...

This stops your class definition being used by the migration so your default scope is never used. In fact I believe it is good to do this if you ever reference an AR class in the migration as the code for the class may not match the current state of the db during migrations.

Colin

Colin