summaryrefslogtreecommitdiff
path: root/_posts/2009-04-30-relationships-in-rails-2-3.html
blob: aba204d5ad4840402ecca05586c811c22c2d8fa8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
---
layout: post
title: Relationships in Rails 2.3
tags:
- Development
- rails
status: publish
type: post
published: true
meta:
  _edit_last: '1'
---
Ruby on Rails is becoming quite a piece of software. I've been learning how to work with its latest version to date, 2.3, for a series of workshops on web development. It has surprised me how easy it is now to accomplish a simple task such as multi-model form processing. Let me show what I've been doing lately.

<!--more-->
<h3>Case study: a school</h3>
The example I am going to show my attendees resembles a typical school situation. In a nutsheel:
<ul>
	<li>Students have Subjects.</li>
	<li>Subjects have Students.</li>
	<li>Students have Grades to Subjects.</li>
</ul>
[caption id="attachment_78" align="alignnone" width="442" caption="Rails relationships — student"]<a href="/wp-content/uploads/2009/07/rails-relationships-student.png"><img class="size-full wp-image-78" title="Rails relationships — student" src="/wp-content/uploads/2009/07/rails-relationships-student.png" alt="Rails relationships — student" width="442" height="98" /></a>[/caption]
<h3>The Models</h3>
<h4>Student</h4>
<pre class='brush:rails'>class Student < ActiveRecord::Base
   has_many :grades
   has_many :subjects, :through => :grades, :uniq => true
   accepts_nested_attributes_for :grades, :allow_destroy => true
end</pre>
<h4>Subject</h4>
<pre class='brush:rails'>class Subject < ActiveRecord::Base
  validates_uniqueness_of :shortname
  has_many :grades
  has_many :students, :through => :grades, :uniq => true
end
</pre>
<h4>Grade</h4>
<pre class='brush:rails'>class Grade < ActiveRecord::Base
  belongs_to :subject
  belongs_to :student
  validates_presence_of :value
end
</pre>
<h3>And the magic trick!</h3>
Through <em>accepts_nested_attributes_for</em>, the student's <em>form_for</em> can now accept nested fields through <em>fields_for</em> for setting Grades' data.

Everytime a student is created, subjects are not directly associated to him. You need to create a form in which you allow to assign a student the subjects you want.

[image missing]

This tells you that a student can have an array of subject id's. You even get to see what subjects are already assigned and dissociate them just like that! When the associations are done, a new Grade record is created to associate the first two modules. Unfortunately, when the associations are dismantled, the Grade association is gone too.

If you know Railscasts, the <a href="http://railscasts.com/episodes?search=complex+forms">Complex Forms series</a> explain this task for Rails &lt; 2.3. But now it has become easier and easier to associate models and worrying less about your structure.