3

I understand the concept of relational databases, primary/foreign keys, etc, however, I'm having trouble seeing the actual result of setting these properties up in my models. Do they generate helper functions or something similar? or do they simply work on a database level?

For example, if I have these two models (other properties omitted)

class Course < ActiveRecord::Base
  has_and_belongs_to_many :schedules
  has_many :sections
end

class Section < ActiveRecord::Base
  belongs_to :course
end

I could simply get all sections for any given course like this:

Section.where(course_id: 1234)

However, I could do this without having set up the relations at all. So my question is: Why do we do this?

tshepang
  • 12,111
  • 21
  • 91
  • 136
flyingtoaster0
  • 159
  • 1
  • 7
  • 2
    So you can get course.sections instead. – Dave Newton Dec 05 '13 at 23:48
  • They are metaprogramming sugar magic stuff. Basically, Rails allows you to use all kinds of other instance methods for a model related to model associations, when you simply write `belongs_to :course`. – Jason Kim Dec 06 '13 at 00:00
  • Thanks everyone! Before, I was manually defining the methods like @course.sections even though they were already being generated by the relations :) – flyingtoaster0 Dec 06 '13 at 00:02

2 Answers2

3

Adding these methods let's you do things like this:

Section.find(5).course  # <== returns a 'Course' model instance

Also it let's you join your queries more easily:

Section.joins(:course).where(course: {name: "English"})  # <== returns sections who have the 'english' course

Neither of these would be possible if you didn't set up the relations in the model.

Similarly:

Course.find(8).sections # returns an array of sections with 'course_id = 8'

It makes your calls more semantic, and makes things easier from a programmatic perspective :)

nzifnab
  • 15,876
  • 3
  • 50
  • 65
  • It also handles the database aspects of this, setting up keys & join tables as necessary. – jm0 Dec 05 '13 at 23:54
  • 1
    Hmm. Defining the `has_many` in the model doesn't itself do anything to the database. You still need a migration in there that creates the `course_id` foreign key on the `sections` table - and same thing for any join table. I suppose if you use one of the model generators to do this you might get this for free, but I've never tried to make one of the generators automatically setup associations for me. Most I've used those for is to create the initial set of properties. – nzifnab Dec 05 '13 at 23:56
  • yes you need migrations to touch DB of course -- http://guides.rubyonrails.org/association_basics.html – jm0 Dec 06 '13 at 00:02
2

Relations are applied on instances of an object. So, these relations allow you to get related objects to an instance of another.

For example, say you have an instance of Section (called @section). You'd be able to get all Course objects for that section by doing:

@section.course if you have belongs_to :course set up.

Similarly, if you have an instance of Course, you can get all Section objects for that Course with:

@course.sections if you have has_many :sections.

TL;DR - these are helper scopes for instance variables of Course and Section.

CDub
  • 13,146
  • 4
  • 51
  • 68