<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JazzRecord Blog &#187; api</title>
	<atom:link href="http://blog.jazzrecord.org/tag/api/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jazzrecord.org</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Wed, 09 Dec 2009 21:25:54 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>ID Optional in latest JazzRecord 0.7</title>
		<link>http://blog.jazzrecord.org/2009/03/id-optional-in-latest-jazzrecord-07/</link>
		<comments>http://blog.jazzrecord.org/2009/03/id-optional-in-latest-jazzrecord-07/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 04:02:22 +0000</pubDate>
		<dc:creator>thynctank</dc:creator>
				<category><![CDATA[Library]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[migrations]]></category>
		<category><![CDATA[use]]></category>

		<guid isPermaLink="false">http://blog.jazzrecord.org/?p=28</guid>
		<description><![CDATA[As of version 0.07 build 1236659271 (please find on Github), the ID column is now optional once more when using automigrations or in declaring columns on models. In actuality, allcolumns are optional in model declarations, if manual migrations are used. This is somewhat similar to the Hobo project’s automatically-generated migrations, only in reverse. (model fields are determined by migrations rather [...]]]></description>
			<content:encoded><![CDATA[<div style="font-family: 'Lucida Grande', Verdana, sans-serif; padding: 0px; margin: 0px;">As of version 0.07 build 1236659271 (please find on Github), the <strong>ID</strong> column is now <strong>optional</strong> once more when using automigrations or in declaring columns on models. In actuality, <em>all</em>columns are <strong>optional</strong> in model declarations, if manual migrations are used. This is somewhat similar to the Hobo project’s <a style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #336699; font-weight: bold; text-decoration: none; padding: 0px; margin: 0px;" href="http://hobocentral.net/hobofields/">automatically-generated migrations</a>, only in reverse. (model fields are determined by migrations rather than the other way round)</p>
<p>Please note, however, that manual migrations require the explicit inclusion of an <strong>ID</strong> column:</p>
<pre style="font-family: monospace; padding: 0px; margin: 0px;">  <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #003366; font-weight: bold; padding: 0px; margin: 0px;">var</span> BoxContent <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">=</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #003366; font-weight: bold; padding: 0px; margin: 0px;">new</span> <strong>JazzRecord</strong>.<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #660066; padding: 0px; margin: 0px;">Model</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">(</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">{</span>
    table<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">:</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #3366cc; padding: 0px; margin: 0px;">"box_contents"</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">,</span>
    belongsTo<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">:</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">{</span>box<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">:</span> boxes<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">}</span>
  <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">}</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">)</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">;</span>

  <strong>JazzRecord</strong>.<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #660066; padding: 0px; margin: 0px;">createTable</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">(</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #3366cc; padding: 0px; margin: 0px;">"boxes"</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">,</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">{</span>
    <strong>id</strong><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">:</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #3366cc; padding: 0px; margin: 0px;">"int"</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">,</span>
    label<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">:</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #3366cc; padding: 0px; margin: 0px;">"text"</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">,</span>
    volume<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">:</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #3366cc; padding: 0px; margin: 0px;">"float"</span>
  <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">}</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">)</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">;</span>

  <strong>JazzRecord</strong>.<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #660066; padding: 0px; margin: 0px;">createTable</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">(</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #3366cc; padding: 0px; margin: 0px;">"box_contents"</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">,</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">{</span>
    <strong>id</strong><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">:</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #3366cc; padding: 0px; margin: 0px;">"int"</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">,</span>
    <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #000066; padding: 0px; margin: 0px;">name</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">:</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #3366cc; padding: 0px; margin: 0px;">"text"</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">,</span>
    size<span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">:</span> <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #3366cc; padding: 0px; margin: 0px;">"float"</span>
  <span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">}</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #009900; padding: 0px; margin: 0px;">)</span><span style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #339933; padding: 0px; margin: 0px;">;</span></pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">This example shows how a minimal amount of code in the models can set up a 1 to N relationship between a Box and several BoxContent objects. At any time schema operations (like <code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;">createTable()</code> or <code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;">removeColumn()</code>) are called, the model’s definition is updated in memory, so calling <code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;">save()</code> or similar will always be up to date.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.jazzrecord.org/2009/03/id-optional-in-latest-jazzrecord-07/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Features in JazzRecord 0.7: Migrations and isNew()</title>
		<link>http://blog.jazzrecord.org/2009/02/new-features-in-jazzrecord-07-migrations-and-isnew/</link>
		<comments>http://blog.jazzrecord.org/2009/02/new-features-in-jazzrecord-07-migrations-and-isnew/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 07:01:10 +0000</pubDate>
		<dc:creator>thynctank</dc:creator>
				<category><![CDATA[Library]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[behind-the-scenes]]></category>
		<category><![CDATA[contribution]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[localization]]></category>
		<category><![CDATA[migrations]]></category>
		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://blog.jazzrecord.org/?p=20</guid>
		<description><![CDATA[First off, thanks to Khou Suylong of Mango Team for once again providing me with a bug find which led to a fix!
We’ve been busy once more, putting together JazzRecord 0.7, which incorporates manual migrations with all of the major features from Rails’ ActiveRecord migrations. While there are no official updated docs yet, here’s a brief list of changes:
ID must now [...]]]></description>
			<content:encoded><![CDATA[<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">First off, <strong>thanks to Khou Suylong of Mango Team</strong> for once again providing me with a bug find which led to a fix!</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">We’ve been busy once more, putting together <strong><strong>JazzRecord</strong> <strong>0.7</strong></strong>, which incorporates <em>manual <strong>migrations</strong></em> with all of the major <strong>features</strong> from Rails’ ActiveRecord <strong>migrations</strong>. While there are no official updated docs yet, here’s a brief list of changes:</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">ID must now explicitly be listed as a column for a model. If using automigrations, you must list it in the model definition. The explicit requirement for ID column may change going forward, but once we hit Version 1 (another month, perhaps) we will stand firm on the API. <em>If using manual <strong>migrations</strong>, you may now leave out columns from the model definition entirely and rely on <strong>migrations</strong> setting the model’s column knowledge for you.</em></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">What this means is, <em>no matter what changes you make to a db schema using <strong>migrations</strong>, the model is always aware of the current state of the schema</em> and will allow you to create, destroy, and modify properties of records with no problem. The only thing to watch out for is validations if you have any, because they can cause problems if there are requirements which cannot be satisfied given a specific updated schema.</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">The following schema operations are available as of now:</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;"><strong>JazzRecord</strong>.createTable(tableName, cols) &#8211; this creates a table using a columns object, identical the the (now optional) columns object from a model declaration.</p>
<ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; padding: 0px;">
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 15px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;"><code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.dropTable(tableName)</code> &#8211; removes a table from the DB.</li>
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 15px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;"><code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.renameTable(tableName)</code> &#8211; renames a table</li>
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 15px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;"><code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.addColumn(tableName, colName, colType)</code> &#8211; adds a column of given type to a table</li>
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 15px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;"><code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.removeColumn(tableName, colName)</code> &#8211; removes a column from a table</li>
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 15px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;"><code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.renameColumn(tableName, oldName, newName)</code> &#8211; renames a given column in a table</li>
<li style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 15px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;"><code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.changeColumn(tableName, colName, colType)</code> &#8211; changes the type of a column. This can result in data loss, as determined by how the DB converts data types</li>
</ul>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">The last three functions were the trickiest, because <strong>SQLite does not provide inherent capabilities for modifying columns once they exist in a table</strong>. In order to reproduce these<strong>features</strong>, then, we have to go about slurping up all data in a table, dropping the existing table, creating a <strong>new</strong> table with the <strong>new</strong> schema, and spitting the same data back into the database, with data types changed or columns removed or changed in type. To keep this (hopefully) relatively safe, we wrap the destructive DROP operation in a transaction.</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">Did anyone even know <strong>JazzRecord</strong> had a <code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.runTransaction(func, bind)</code> method? I’m not sure! Calling this and passing in a function full of operations will ensure that if something goes wrong and you or some function you call throws an exception, all will revert to its pre-transaction state. Pretty cool, huh?</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">Making use of the schema operations is as simple as calling them anywhere, though typically you’d organize them into <strong>migrations</strong>. <strong>Migrations</strong> are now a bit streamlined, as well.</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">To automigrate, simply call <code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.migrate()</code> with no options, or to refresh the DB to an empty state, pass in an object with refresh property set to true:<code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.migrate({refresh: true})</code>. To optionally load fixture data, assign a fixtures object (same as the old object format) to <em><strong>JazzRecord</strong>.fixtures</em>, and if it exists it will be loaded. To run <strong>migrations</strong>, simply assign to <em><strong>JazzRecord</strong>.<strong>migrations</strong></em> an object literal with numerically-named properties (starting with the number 1) each containing an object literal which has an up function and a down function. These functions should be the reverse of one another, and for an explanation of proper migration usage consult any Rails tutorial or wait for the documentation. Here’s a simple sample migration which creates a couple tables and adds a column to one of them over a few schema versions:</p>
<pre style="font-family: 'Lucida Grande', Verdana, sans-serif; padding: 0px; margin: 0px;"><code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; display: block; padding: 15px; margin: 0px;">  <strong>JazzRecord</strong>.<strong>migrations</strong> = {
    1: {
      up: function() {
        <strong>JazzRecord</strong>.createTable("military_dudes", {
          id: "number",
          name: "text",
          title: "text",
          base_id: "number"
        });

        <strong>JazzRecord</strong>.createTable("bases", {
          id: "number",
          location_name: "text"
        });
      },
      down: function() {
        <strong>JazzRecord</strong>.dropTable("bases");
        <strong>JazzRecord</strong>.dropTable("military_dudes");
      }
    },

    2: {
      up: function() {
        <strong>JazzRecord</strong>.renameColumn("military_dudes", "title", "rank");
        <strong>JazzRecord</strong>.addColumn("bases", "state", "text");
      },
      down: function() {
        <strong>JazzRecord</strong>.removeColumn("bases", "state");
        <strong>JazzRecord</strong>.renameColumn("military_dudes", "rank", "title");
      }
    }
  };
</code></pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">After setting up a <strong>migrations</strong> object like this, you can call <code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.migrate()</code> standalone (to migrate to the latest version), or you can pass in a version number to reach the specified migration number. To reset to pre-migration status, call <code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>JazzRecord</strong>.migrate(0)</code>. In this way, you can evolve an application’s schema over time and can almost effortlessly jump between schema versions to diagnose problems or revert when you’ve introduced more problems than you’ve fixed! You can pretty much use <strong>migrations</strong> exactly as in Rails: changing schema and inserting/removing/updating data for existing, already-deployed applications. Soon we will add additional tools for updating multiple columns and multiple rows simultaneously, which will further add to the usefulness of <strong>migrations</strong>.</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">The smaller, but still useful, function introduced in <strong>JazzRecord</strong> <strong>0.7</strong> is Record’s <code style="font-family: 'Andale Mono', Monaco, 'Courier New', Courier, monospace; background-color: #666666; color: #ffffff; padding: 0px; margin: 0px;"><strong>isNew</strong>()</code> function. This function, when called, will return true if a record has <em>not</em> been saved yet, or false if it <em>has</em>.</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">As a previous blog post stated, we are extremely interested in having our documentation translated into other languages, so please contact me at <a style="font-family: 'Lucida Grande', Verdana, sans-serif; color: #336699; font-weight: bold; text-decoration: none; padding: 0px; margin: 0px;" href="mailto:thynctank@thynctank.com">thynctank@thynctank.com</a> if you can help with that.</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: 'Lucida Grande', Verdana, sans-serif; line-height: 17px; padding: 0px;">Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jazzrecord.org/2009/02/new-features-in-jazzrecord-07-migrations-and-isnew/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JazzRecord: You Have The Power!</title>
		<link>http://blog.jazzrecord.org/2009/01/jazzrecord-you-have-the-power/</link>
		<comments>http://blog.jazzrecord.org/2009/01/jazzrecord-you-have-the-power/#comments</comments>
		<pubDate>Thu, 22 Jan 2009 07:29:01 +0000</pubDate>
		<dc:creator>thynctank</dc:creator>
				<category><![CDATA[Library]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[behind-the-scenes]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[use]]></category>

		<guid isPermaLink="false">http://blog.jazzrecord.org/?p=10</guid>
		<description><![CDATA[Since I recently held a conversation over IRC about some of how JazzRecord&#8217;s association loading and saving works, I thought I&#8217;d share it with the world as well.
The coolest two things about JazzRecord, and likewise Rails&#8217; ActiveRecord:
* the fact they automatically load associated records as objects, based on models&#8217; knowledge of interrelations with other models, [...]]]></description>
			<content:encoded><![CDATA[<p>Since I recently held a conversation over IRC about some of how JazzRecord&#8217;s association loading and saving works, I thought I&#8217;d share it with the world as well.</p>
<p>The coolest two things about JazzRecord, and likewise Rails&#8217; ActiveRecord:</p>
<p>* the fact they automatically load associated records as objects, based on models&#8217; knowledge of interrelations with other models, and that associated records&#8217; linkage is handled transparently to the user in such a way as to make total sense. The *databaseness* of working with things melts away to pure OO code.<br />
* the fact the built in validations lend so much power and usefulness when it comes to business logic, without sacrificing readability of code.</p>
<p>In order to maintain the ease of use that ActiveRecord affords, I had to put JazzRecord together carefully. One thing I really wanted to maintain, which I&#8217;ve seen fall by the wayside in similar JavaScript ORMs, is the ability to simply assign new values to properties of a record object and have them be validated at save time, saved down as appropriate column/field data in the database, and even reload appropriate associated records from different tables. This requires that record objects have knowledge, or rather the ability to communicate with objects that *do* have knowledge (models), of interrelations between tables and knowledge of how to validate the properties.</p>
<p>Even knowledge of a record&#8217;s model and its associations is not enough to overcome the language barriers faced when porting a Ruby-language project to JavaScript: JavaScript function calls require the use of parenthesis, and because of this field name getters/setters cannot be treated as simple properties the way ActiveRecord field names are. To avoid having to unnecessarily clutter up API code with function calls for simple setting and getting of field data, JazzRecord introduces the idea that fields are simply properties of record objects &#8211; it just doesn&#8217;t care about any extraneous properties not defined within a record&#8217;s model declaration. At the time of save, and partially at the time a record is validated, a record&#8217;s data are examined in the context of those fields defined on the record&#8217;s model, and those associations defined in the same place. Any additional properties are simply ignored by JazzRecord. This stresses the importance of tying the record object to its basis, a model. Without the knowledge inherent in this connection, the record would have no way of loading associated data, and no means for validating field data. Without this connection, each record object would have to carry around its own set of validation rules and association-loading methods. And that would be slow.</p>
<p>An example may help to illustrate the ease of use/power combo better: Say we&#8217;re dealing with a *Home* model and a *Person* model. The relationship is 1 to N, where Person is the N end. Let&#8217;s say we also have a *Vehicle* model, which has a relationship of 1 to 1, with Vehicle belonging to Person. We&#8217;ve set up some nominal validation setup for ensuring a person&#8217;s age is an integer. Setup code will follow the usage examples.</p>
<p>Here&#8217;s a few things JazzRecord does or lets you do:</p>
<p>* Everyone knows finders: `var p = Person.findBy(&#8221;name&#8221;, &#8220;Nick&#8221;)`<br />
* And getting and setting local column properties of the record is simple: `p.age //returns 28`, `p.age = &#8220;29yrs&#8221; //it&#8217;s my birthday!`<br />
* Calling `isValid()` on a record object will return a boolean, as well as populating the error object with appropriate error information.<br />
* Calling `p.save()` will also cause validation methods to run. Since this is an existing record, any *validatesAtUpdate* or *validatesAtSave* methods defined on the model will run.</p>
<p>  Our record will fail to save because we&#8217;ve got errors: p.errors.age is an array of all errors relating to the *age* field, and it contains the helpful default string &#8220;age is not an integer&#8221;. This error message could easily be customized for use as actual presentational text to be used in an application to show users entering invalid data.</p>
<p>  Correcting the age to a simple number and saving again will fix this and clear out the errors arrays: `p.age = 29; p.save()` This now succeeds, and indeed our p.errors object is re-initialized to an empty state.</p>
<p>Did you know JazzRecord will also reload all associated records? Didja even know it loaded them to begin with? Associations are easy to use. As soon as a finder returns a record, or as soon as a save finishes, your new record has not only the immediate field properties defined on its own model, but the associated data of any immediately-related records are loaded automatically. Here&#8217;s what this means:</p>
<p>* `p.vehicle` is an actual vehicle record. It has all the capabilities p has, such as retrieving/editing immediate fields and saving them back down. `p.vehicle.model` returns the string &#8220;Forenza&#8221;, and setting it `p.vehicle.model = &#8220;Corvette&#8221;` and saving `p.save()` will update the record accordingly. This is quite useful.<br />
* if validations were defined for the vehicle record, they would be run prior to actually updating it.<br />
* Records can be loaded more than 1 level deep by calling the `load(colname)` method of a record with unloaded subordinate records: `p.vehicle.load(&#8221;dealership&#8221;)`, perhaps, if a dealership association was defined and such data existed.</p>
<p>  Upon loading the new data, all of the newly-loaded record&#8217;s immediate data is available for tinkering with, just as with the automatically-loaded association data.</p>
<p>  Be careful! Loading associated records which are already present earlier in the scope chain may lead to unpredictable and undesirable results. Never do `p.vehicle.load(&#8221;owner&#8221;)`, for instance, as this will load a *second* instance of the same person record stored in *p*, and these two objects cannot be kept in sync. This is a language limitation and is unavoidable. **Do NOT load redundant records from earlier in the scope chain!**</p>
<p>The last piece of the powerful parts of JazzRecord puzzle (say that three times fast!) is auto-linking and unlinking of associations in the database based on logical user interaction in the API. </p>
<p>* A user can add or change a foreign-key reference manually: `vehic.person_id = 1`, or she can change it through the association property itself: `vehic.owner = Person.last()`. After calling `vehic.save()`, the association and the ID are both set correctly, no matter which was the triggering mechanism. Note that trying to assign both the key manually and the association can lead to confusion and is best avoided. If one has been set and you want to reset before setting the other, feel free to call the record&#8217;s *revert()* method. It will return to the state it was in after the last find or save operation.</p>
<p>* Likewise, deleting a foreign-key manually or deleting an association both work: `delete vehic.person_id` and `delete vehic.owner` work equally well. After calling `vehic.save()`, both association and foreign key will be deleted.</p>
<p>This is a useful concept. It allows the user to think in more abstract terms than setting keys all over the place. It works on all supported association types, even N to N. (it will delete and add records to mapping tables automatically) It *also* works from either side of an association. More on that in a second.</p>
<p>We&#8217;ve seen that deleting a record&#8217;s association when it &#8220;belongs to&#8221; another record is easy. But we can also link or unlink a record from the other side: `p.vehicle = Vehicle.find(3)` followed by a save will cause the original vehicle&#8217;s foreign key reference to disappear and the foreign key on the new vehicle (#3) to be set to the person&#8217;s ID. Again, powerful stuff. Deleting an association works the same: `h = Home.first(); delete h.people[0]; h.save()` causes the first Home record to be loaded, and removes the association of the first person object from the equation. The person object&#8217;s `home_id` will now be gone.</p>
<p>As for the models which were used in this article&#8230;</p>
<p>    var Home = new JazzRecord.Model({<br />
      table: &#8220;homes&#8221;,<br />
      foreignKey: &#8220;home_id&#8221;,<br />
      hasMany: { people: &#8220;people&#8221;},<br />
      columns: {<br />
        address: &#8220;text&#8221;,<br />
      }<br />
    });</p>
<p>    var Person = new JazzRecord.Model({<br />
      table: &#8220;people&#8221;,<br />
      foreignKey: &#8220;person_id&#8221;,<br />
      belongsTo: { home: &#8220;homes&#8221;},<br />
      hasOne: { vehicle: &#8220;vehicles&#8221;},<br />
      columns: {<br />
        name: &#8220;text&#8221;,<br />
        age: &#8220;number&#8221;,<br />
        home_id: &#8220;number&#8221;,<br />
      },</p>
<p>      validate: {<br />
        atSave: function() {<br />
          this.validatesIsInt(&#8221;age&#8221;);<br />
        }<br />
      }<br />
    });</p>
<p>    var Vehicle = new JazzRecord.Model({<br />
      table: &#8220;vehicles&#8221;,<br />
      foreignKey: &#8220;vehicle_id&#8221;,<br />
      belongsTo: { owner: &#8220;people&#8221;},<br />
      columns: {<br />
        make: &#8220;text&#8221;,<br />
        model: &#8220;text&#8221;,<br />
        person_id: &#8220;number&#8221;<br />
      }<br />
    });</p>
<p>More complex versions of these models are in the *example_models.js* file which comes in the zip file of source code for JazzRecord.</p>
<p>Working with the library functions almost identically to most general usage of Rails&#8217; ActiveRecord, and this ease of use/identical behavior was a driving goal in its development. Because of its scope and methodology, actually sitting down to use JazzRecord may be the easiest way to learn it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jazzrecord.org/2009/01/jazzrecord-you-have-the-power/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
