4: Rails Models




Learning Rails show

Summary: To listen to the lesson, click the Play button on the left. You can also right-click on the download link to save the mp3 file, or you can subscribe in iTunes (just search for Learning Rails). <p> </p> <p>To read a transcript of the lesson, click the Transcript link on the left.</p> <p><strong>The heart of the lesson is the audio</strong>; these notes are supplementary. So please listen to the audio, or read the transcript, before making use of these notes.</p> <h2>Resources for Further Study</h2> <p>Any Ruby on Rails book will explain how migrations, models, and associations work. The classic Agile Web Development with Rails does a good job explaining them.</p> <p>Note that Rails 2.0 provides a slightly simpler syntax for migrations, which we’ve used in our examples, so in most books you’ll see the Rails 1.2 style.</p> <p>The <a href="http://wiki.rubyonrails.org/rails/pages/UnderstandingMigrations">Rails wiki</a> has an explanation of migrations, but as of this writing it has not been updated for Rails 2.0. The <a href="http://api.rubyonrails.org/classes/ActiveRecord/Migration.html"><span class="caps">API</span> document</a> provides a less readable but more complete and up-to-date description.</p> <p>There’s a <a href="http://www.netbeans.org/kb/60/ruby/model.html">hand-on tutorial using NetBeans 6.0</a> that shows how to create migrations and models using the NetBeans <span class="caps">IDE</span>.</p> <h2>Code Examples</h2> <p>The user requirements for the example we discuss in this podcast are:</p> <ol> <li>A visitor to the site sees a list of podcasts with their title, description, and a link to an MP3 file</li> <li>If there is an associated show note for that podcast, a link appears that goes to a page displaying it.</li> <li>Each podcast is tagged with one or more topic categories which the visitor can see next to the podcast’s other information</li> </ol> <p>Here’s a schematic drawing of the required objects:</p> <p><img alt="" src="/LR_episode_4.jpg"></p> <p>The migration that creates the podcast database table reads something like this:</p> <pre> create_table "podcasts" do |t| t.string "title" t.string "description" t.string "filename" end </pre> <p>The create_table line begins a code block that defines the table. This line provides the shortcut name t, which is referenced in the lines that define the table.</p> <p>To create a new podcast object, you use a very simple Podcast class and simply type:</p> <pre> episode = Podcast.new </pre> <p>And now you have an instance of the Podcast class, which you’ve named episode. Now, to set its attributes, you can simply write:</p> <pre> episode.title = "Learning Ruby on Rails" episode.filename = "learningrails-1.mp3" episode.description = "This episode covers..." </pre> <p>When this code is executed, you’ve created the episode object and filled it with data. Now it takes one more line of code, <code>episode.save</code>, to write the data to the database.</p> <p>To find an episode by name, you can simply write:</p> <pre> episode = Podcast.find_by_title('Learning Ruby on Rails') </pre> <p>and you’ll get back a podcast object, called episode, with all the information about that podcast.</p> <p>What about the show notes? We need another migration to define that table, the core of which is simply:</p> <pre> t.text "body" t.integer "podcast_id" </pre> <p>The body field is where we store the text of the show notes. (The column type of “text” instead of “string” tells the database to allow a potentially large amount of text.)</p> <p>The podcast_id field is how Rails knows what podcast a particular show_notes object is associated with.</p> <p>To set up the association, you add one line of code to each of the associated models’ classes. The podcast class gets a line that reads:</p> <pre> has_one :show_notes </pre> <p>and the show_notes model gets a line that reads:</p> <pre> belongs_to :podcast </pre> <p>With these two simple additions, you can now write episode.show_notes to access the show notes for a particular episode.</p> <p>To associate podcasts with categories, we need a join table, whose field definitions are:</p> <pre> t.integer podcast_id t.integer category_id </pre> <p>With the join table created and the <span class="caps">HABTM</span> declarations in the two model files, you can simply write</p> <pre> episode.categories </pre> <p>and you’ll get back an array of category objects, one for each category that is associated with that particular episode.</p>