Rails/ActiveRecord Nuby question.

H

Harold Hausman

I am kindof assuming that this is something of a newbie question as
far as ActiveRecord goes, but I've looked through the documentation on
ar.rubyonrails.org and can't seem to figure it. Any advice would be
much appreciated.

I'm trying to setup a small stats tracking webapp in an attempt to
teach myself rails. (previously I've done web development with JSasp
and Micro$oft products) and I'm happy to say that I'm pleased as punch
with rails. In fact, I've got the site working but I'm using some
pretty hacky calls to ActiveRecord::Base.connection.select_all to pull
data out of the DB and make on my own collections :(.

I have two tables in my DB, one which keeps track of teams and another
which keeps track of matches. (two teams can play a match and there is
one winner and one loser) The difficult bit seems to be that the
team's id can be stored in either one of two columns in the matches
table.

I feel like I should be able to setup the Team model to have a
collection of the matches which that team has participated in and
here's what I've tried so far:

class Team < ActiveRecord::Base
=09has_many :matchess, :finder_sql =3D>=20
=09=09"select * from matches " +
=09=09"where matches.one =3D #{id} " +
=09=09"or matches.two =3D #{id}"
end

Now this 'works' but it seems that the id that it is inserting into
the SQL string is the ruby unique id for the Team object that is
created. What I want is the id of the team which is stored in the
database. Is this stored in the Team object anywhere? or am I going at
this all backwards?

Is there a resource somewhere that explains when you should use
has_many vs belongs_to or has_and_belongs_to_many?

I'd be happy to clarify if needed, as I wouldn't be supprised if I've
got this basically all wrong. :)

Thanks in advance,
-Harold
 
C

Charles Steinman

Harold said:
I have two tables in my DB, one which keeps track of teams and another
which keeps track of matches. (two teams can play a match and there is
one winner and one loser) The difficult bit seems to be that the
team's id can be stored in either one of two columns in the matches
table.

I feel like I should be able to setup the Team model to have a
collection of the matches which that team has participated in and
here's what I've tried so far:

class Team < ActiveRecord::Base
has_many :matchess, :finder_sql =>
"select * from matches " +
"where matches.one = #{id} " +
"or matches.two = #{id}"
end

Now this 'works' but it seems that the id that it is inserting into
the SQL string is the ruby unique id for the Team object that is
created. What I want is the id of the team which is stored in the
database. Is this stored in the Team object anywhere? or am I going at
this all backwards?

I haven't used this particular feature of Rails, but I think what you
want is to use single quotes around the SQL snippets rather than double
quotes. Double quotes evaluate #{expressions like this} as soon as
they're created, while ActiveRecord wants to evaluate it later once it
has a Team object to get the id from.
Is there a resource somewhere that explains when you should use
has_many vs belongs_to or has_and_belongs_to_many?

I thought there was, but I can't find it. The difference is basically
this:

X belongs_to Ys: Every X record has a y_id entry identifying which Y it
belongs to.

Y has_many Xs: Has a method that will return all Xs with a y_id equal
to its own.

(Basically, objects that belong to another keep track of their owner.
Telling the owner that it owns them gives it the ability to
automatically find them.)

X has_and_belongs_to_many Ys: This one works differently. Every X can
refer to several Ys, and every Y can refer to several Xs. To do this,
you create a join table where each row represents a relationship
between an X and a Y. This might be a good choice for the relationship
between Matches and Teams, because each team can have many matches and
each match has many teams.
 
H

Harold Hausman

=20

=20
I haven't used this particular feature of Rails, but I think what you
want is to use single quotes around the SQL snippets rather than double
quotes. Double quotes evaluate #{expressions like this} as soon as
they're created, while ActiveRecord wants to evaluate it later once it
has a Team object to get the id from.

Perfect! This was exactly the problem, perhaps this should be added to
the activeRecord documentation (or be made more prominent if its
already in there somewhere).

Now another question. ;) Now that each match that the team has
participated in is associated with the team it would be really handy
if the teams involved in each match were associated with that match
(so I can have access to their human readable names and such.) Heres
what I tried:

class Match < ActiveRecord::Base
=09has_one :team_one, :class_name =3D> "Team", :conditions =3D> 'id =3D #{o=
ne}'
=09has_one :team_two, :class_name =3D> "Team", :conditions =3D> 'id =3D #{t=
wo}'
end

*note: 'one' and 'two' are the names of the columns in the matches
table where I store the team ids that participated in the match.

What I was hoping was that each Match object would then have two new
child objects called team_one and team_two which would be Team
objects. This did not work, near as I can tell it formulated some sql
string which contained some match_id gibberish in the where clause and
there is no match_id column in the teams table. (maybe this is how I'm
supposed to know to use has_and_belongs_to_many)

What I've ended up doing is using has_many, and then using :finder_sql
to completely override the sql statement to select just the team I'm
looking for which works and creates a single element array but results
in some slightly hack-ish useage of operator[] passing 0 to get the
first object (i.e. match.team_one[0]["name"] ) which isint a big deal
at all.

But... It seems to me that it might be valuable to have :finder_sql as
an option for has_one for situations like this where I don't want to
bother with another table just to associate teams with matches and use
has_and_belongs_to_many.

Sorry for the rambling post, and thanks kindly for the quick-like and
useful/accurate response on the single vs. double quote thing. Long
live this community and rails and everything else sweet in this world.
:)

-Harold
 
J

Jason Foreman

..
class Match < ActiveRecord::Base
has_one :team_one, :class_name =3D> "Team", :conditions =3D> 'id = =3D #{one}'
has_one :team_two, :class_name =3D> "Team", :conditions =3D> 'id = =3D #{two}'
end
=20
*note: 'one' and 'two' are the names of the columns in the matches
table where I store the team ids that participated in the match.
=20
What I was hoping was that each Match object would then have two new
child objects called team_one and team_two which would be Team
objects. This did not work, near as I can tell it formulated some sql
string which contained some match_id gibberish in the where clause and

You want to have:
class Match < ActiveRecord::Base
belongs_to :team_one, ...
belongs_to :team_two, ...
end

belongs_to signifies that the foreign key column is in THIS table, ie
the table of the same model. has_one signifies that the foreign key
column is in the table of the related model.

Very common mistake. But I believe there is significant documentation
to explain why the relations are named as they are though.

Hope that helps.

BTW, there is a mailing list specifically for Ruby On Rails [1], which
would be more appropriate for these questions than ruby-talk.

Jason


[1] http://lists.rubyonrails.org/mailman/listinfo/rails
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top