Why all columns of joined table get instantiated as String?

Been developing in Rails for about a month and I'm still working on grasping its subtleties. Can someone please shed some light on this simple scenario?

## Schema ##

create_table :books do |t|   t.string :title   t.integer :year end

create_table :pages do |t|   t.integer :no   t.references :book end

## Models ##

Book has_many :pages Page belongs_to :book

Then in Rails' console:

@pages = Page.all(   :select => 'pages.id, pages.no, books.year book_year',   :joins => :book )

@pages.first.no.class #=> Fixnum @pages.first.book_year.class #=> String

What I don't understand is why book_year is a String instead of a Fixnum. Is it possible to get Book's columns correctly instantiated?

Thanks

Not that I know of. The typecasting stuff only knows about the columns of the model itself.

Fred

Thanks, Fred. I suppose I'll stick with views and conversions.

Why not

pages = Page.all(:include => :book)

pages.first.book.year

Rick Denatale wrote:

Why not

pages = Page.all(:include => :book)

I usually need to filter by, let's say, a certain library:

@pages = Page.all(   :select => 'pages.id, pages.no',   :joins => :book,   :conditions => "books.library_id = #{1}" )

AR will generate: SELECT pages.id, pages.no FROM "pages" INNER JOIN "books" ON "books".id = "pages".book_id WHERE (books.library_id = 1)

So the join has already been done. Wouldn't :include make a redundant query?

Then just change the joins to include:

Page.all( :include => :book, :conditions => ["books.library_id = ?", 1] )

Which will both allow you to refer to the books fields in the where clause, and return an collection of object graphs rather than page object corrupted with fields they shouldn't have.

Rick Denatale wrote:

Then just change the joins to include:

Page.all( :include => :book, :conditions => ["books.library_id = ?", 1] )

Which will both allow you to refer to the books fields in the where clause, and return an collection of object graphs rather than page object corrupted with fields they shouldn't have.

That's true, but I lose control over :select

Page.all(   :select => 'pages.id, pages.no',   :include => :book,   :conditions => ["books.library_id = ?", 1] )

...will generate:

SELECT   "pages"."id" AS t0_r0,   "pages"."no" AS t0_r1,   "pages"."book_id" AS t0_r2,   "pages"."created_at" AS t0_r3,   "pages"."updated_at" AS t0_r4,   "books"."id" AS t1_r0,   "books"."title" AS t1_r1,   "books"."year" AS t1_r2,   "books"."library_id" AS t1_r3,   "books"."created_at" AS t1_r4,   "books"."updated_at" AS t1_r5 FROM   "pages"   LEFT OUTER JOIN "books" ON "books".id = "pages".book_id WHERE   (books.library_id = 1)

The real "books" and "pages" have decimal and large text columns that are not always needed.

Could be worth considering extracting those fields into another table and have a 1:1 link... a little messy, but saves you returning lots of data when you only need a small part of it.