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

On Mar 4, 2:58 pm, Jack S. [email protected] wrote:

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?

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.

On Fri, Mar 5, 2010 at 9:07 AM, Jack S. [email protected]
wrote:

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

Why not

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

pages.first.book.year


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

On Fri, Mar 5, 2010 at 2:12 PM, Jack S. [email protected]
wrote:

: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

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

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.

On 6 March 2010 17:49, Jack S. [email protected] wrote:

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.

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?