<?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>Cappuccino Blog &#187; Tutorials</title>
	<atom:link href="http://cappuccino.org/discuss/category/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://cappuccino.org/discuss</link>
	<description>Home of Cappuccino and Objective-J</description>
	<lastBuildDate>Wed, 25 Apr 2012 05:40:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Cappuccino Training Course: iDeveloper TV</title>
		<link>http://cappuccino.org/discuss/2011/10/19/cappuccino-training-course-ideveloper-tv/</link>
		<comments>http://cappuccino.org/discuss/2011/10/19/cappuccino-training-course-ideveloper-tv/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 22:01:20 +0000</pubDate>
		<dc:creator>me1000</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Community Highlights]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=1194</guid>
		<description><![CDATA[I&#8217;ve been a big fan of Cappuccino since late 2009 and have written and spoken about it pretty extensively. This past July I went to sunny Tetbury, UK to record a video course entitled “Cappuccino for Cocoa Developers.” Here&#8217;s some background on how the course came into being&#8230; In addition to being a tony little [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been a big fan of Cappuccino since late 2009 and have <a href="http://www.memoryminer.com/blog/?cat=6"  target="_blank">written</a> and <a href="http://feeds.ideveloper.tv/ideveloperlive/files/ideveloperlive027.m4a" target="_blank">spoken</a> about it pretty extensively. This past July I went to sunny Tetbury, UK to record a video course entitled “Cappuccino for Cocoa Developers.” Here&#8217;s some background on how the course came into being&#8230;</p>
<p>In addition to being a tony little country village where Prince Charles has one of his castles, Tetbury is famous for being the home town of <a href="http://ideveloper.tv"  target="_blank">iDeveloperTV</a>, a company much loved by indie Mac and iOS developers for putting on NSConference, along with the extensive library of video courses and podcasts it has produced over the years. This past Spring, Steve &#8220;Scotty&#8221; Scotty invited me to give a presentation on Cappuccino at NSConference in the UK. It was extremely well-received, so I reprised the talk at the first CappCon in San Francisco this past Summer. </p>
<p>My goal for both talks was to show existing Cocoa developers how they can leverage their existing skills to craft desktop-caliber web-apps. In the course of preparing for these presentations, I ended up developing a series of carefully-designed tutorial apps, designed to feel comfortable to Cocoa developers while highlighting some web-specific architectural considerations.</p>
<p>These tutorial applications thus formed the basis of the 4 hour course. We shot the video against a white background so that the &#8220;talking-head&#8221; video could be mixed-in with the screen capture from my laptop as you see here:</p>
<p><a href="http://cappuccino.org/discuss/wp-content/uploads/2011/10/Cappuccino-Tutorial-App.png"><img src="http://cappuccino.org/discuss/wp-content/uploads/2011/10/Cappuccino-Tutorial-App.png" alt="" title="Cappuccino-Tutorial-App" width="600"  class="alignnone size-full wp-image-1195" /></a></p>
<p>The net effect is quite like having your own personal trainer. Scotty&#8217;s role is to make sure that I highlighted the points that may not be obvious to first-time learners.</p>
<p><a href="http://cappuccino.org/discuss/wp-content/uploads/2011/10/Looking-At-Cappuccino-Code.png"><br />
<img src="http://cappuccino.org/discuss/wp-content/uploads/2011/10/Looking-At-Cappuccino-Code.png" alt="" title="Looking-At-Cappuccino-Code" width="600" class="alignnone size-full wp-image-1196" /></a></p>
<p>The video is delivered in high-quality, DRM-free H.264 video that you download to your machine. Sync it to your iPad if you wish, then watch it in bed before dreaming of Cappuccino. The resolution lets you clearly read the code while listening to the discussion. Work along with the same source code shown in the video, adapt it to your needs, then build something meaningful to you. Since data persistence in web-apps is a major consideration, I&#8217;ve even included the source code for a simple RESTful Web Service written in Ruby on Rails so you can see how things work end-to-end.</p>
<p>I&#8217;m extremely proud of the work I did in creating this course, and I think Dave at iDeveloper TV did a bang-up job with the editing. Scotty has been kind enough to release the course at the exceptional price of US $29.99 in order to put in reach of everyone. Complete details can be found here:</p>
<p><a href="http://ideveloper.tv/video/cappuccinocourse.html" target="blank">http://ideveloper.tv/video/cappuccinocourse.html</a></p>
<p>I hope you enjoy the course. Feedback is greatly appreciated. Hopefully, I&#8217;ll have the chance to make some additional courseware in the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2011/10/19/cappuccino-training-course-ideveloper-tv/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
<enclosure url="http://feeds.ideveloper.tv/ideveloperlive/files/ideveloperlive027.m4a" length="22563576" type="audio/mpeg" />
		</item>
		<item>
		<title>Cappuccino Casts</title>
		<link>http://cappuccino.org/discuss/2009/02/07/cappuccino-casts/</link>
		<comments>http://cappuccino.org/discuss/2009/02/07/cappuccino-casts/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 01:19:52 +0000</pubDate>
		<dc:creator>ross</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Objective-J]]></category>
		<category><![CDATA[Screencasts]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=291</guid>
		<description><![CDATA[Thomas Balthazar, who&#8217;s been doing the recent &#8220;This Week in Edge Cappuccino&#8221; series (read this week&#8217;s post), also started a new site to host screencasts of Cappuccino &#38; Objective-J tutorials. So far he&#8217;s created a screencast for the starter tutorial.  We&#8217;re all looking forward to seeing more screencasts on the site, and if you want [...]]]></description>
			<content:encoded><![CDATA[<p>Thomas Balthazar, who&#8217;s been doing the recent &#8220;This Week in Edge Cappuccino&#8221; series (read <a href="http://suitmymind.com/2009/02/05/this-week-in-edge-cappuccino-3/">this week&#8217;s post</a>), also started a new site to host <a href="http://cappuccinocasts.com">screencasts of Cappuccino &amp; Objective-J tutorials</a>. So far he&#8217;s created a screencast for the <a href="http://suitmymind.com.s3.amazonaws.com/screencasts/cappuccinocasts.com/001/001_cappuccino_sample_application.mov">starter tutorial</a>. </p>
<p>We&#8217;re all looking forward to seeing more screencasts on the site, and if you want to contribute your own screencast, get in touch with Thomas and he&#8217;ll add it to the site. Thanks Thomas!</p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2009/02/07/cappuccino-casts/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
<enclosure url="http://suitmymind.com.s3.amazonaws.com/screencasts/cappuccinocasts.com/001/001_cappuccino_sample_application.mov" length="33887284" type="video/quicktime" />
		</item>
		<item>
		<title>Tutorial on Adding Undo to Your Cappuccino Application Published on ThinkVitamin</title>
		<link>http://cappuccino.org/discuss/2008/11/13/thinkvitamin/</link>
		<comments>http://cappuccino.org/discuss/2008/11/13/thinkvitamin/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 20:49:17 +0000</pubDate>
		<dc:creator>ross</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=153</guid>
		<description><![CDATA[ThinkVitamin.com is featuring an article by Francisco that goes through the process of adding undo/redo support to an existing application. It uses a &#8220;furniture layout&#8221; application as the model, and goes through all the steps necessary to make user actions undoable. This is a great demonstration of one of the powerful built-in features in Cappuccino, [...]]]></description>
			<content:encoded><![CDATA[<p>ThinkVitamin.com is featuring <a href="http://www.thinkvitamin.com/features/ajax/add-undo-and-redo-to-your-web-application-with-cappuccino">an article</a> by Francisco that goes through the process of adding undo/redo support to an existing application. It uses a &#8220;furniture layout&#8221; application as the model, and goes through all the steps necessary to make user actions undoable. </p>
<p>This is a great demonstration of one of the powerful built-in features in Cappuccino, and a good read for anyone building an application in Cappuccino. Undo support is one of those features that goes a long way in making your application more enjoyable to use, and customers will love you for it.</p>
<p>So go <a href="http://www.thinkvitamin.com/features/ajax/add-undo-and-redo-to-your-web-application-with-cappuccino">checkout the tutorial</a>, then get started adding undo support to your own applications!</p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2008/11/13/thinkvitamin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Started With Cappuccino and Ruby on Rails</title>
		<link>http://cappuccino.org/discuss/2008/11/11/cappuccino-and-ruby-on-rails/</link>
		<comments>http://cappuccino.org/discuss/2008/11/11/cappuccino-and-ruby-on-rails/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 09:52:14 +0000</pubDate>
		<dc:creator>tlrobinson</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=139</guid>
		<description><![CDATA[Cappuccino is completely server agnostic, meaning Cappuccino applications can be served using any HTTP server (for example Apache, lighttpd, Microsoft IIS, etc) and can communicate with any server side technology over HTTP (Ruby on Rails, Django, PHP, ASP, Java, CouchDB, etc). This lets you choose your server-side components based on whatever criteria is important to [...]]]></description>
			<content:encoded><![CDATA[<p>Cappuccino is completely server agnostic, meaning Cappuccino applications can be served using any HTTP server (for example Apache, lighttpd, Microsoft IIS, etc) and can communicate with any server side technology over HTTP (Ruby on Rails, Django, PHP, ASP, Java, CouchDB, etc). This lets you choose your server-side components based on whatever criteria is important to you (experience, existing infrastructure, etc).</p>
<p>That said, many people have asked for examples of using Cappuccino with various server side technologies, especially Ruby on Rails. Since Cappuccino is server agnostic, it turns out to be very simple to get started.</p>
<h3>Setting Up a Project</h3>
<p>The first step is to create your Rails project using the standard &#8220;rails <em>appname</em>&#8221; command:</p>
<pre>rails appname
cd appname</pre>
<p>Then create a new Cappuccino project in a temporary directory, either using the &#8220;steam create&#8221; command, or by downloading the <a href="http://cappuccino.org/download/">&#8220;Starter Package&#8221;</a>. Move the contents of the Cappuccino project to the Rails application&#8217;s &#8220;public&#8221; directory. Here&#8217;s an example using &#8220;steam create&#8221; (which will overwrite the default index.html):</p>
<pre>steam create temp
mv temp/* public/.
rmdir temp</pre>
<p>That&#8217;s it! Start the Rails webserver using &#8220;script/server&#8221;. Point your browser to http://localhost:3000/ and you should see the &#8220;hello world&#8221; Cappuccino application.</p>
<h3>Exposing the Data</h3>
<p>This alone isn&#8217;t particularly interesting. For Rails to be useful in conjunction with Cappuccino you&#8217;ll want to be able to transfer data between them. Rails makes this very easy.</p>
<p>Rails offers built in support for two common data exchange formats: JSON and XML. Of the two, JSON is typically prefered in Cappuccino. To output a Ruby data structure as JSON, simply call &#8220;render :json => object&#8221; in the controller action:</p>
<pre class="enscript" ><!--BEGIN enscript-->
<B><span style="color:#A020F0">class</span></B> TestController &lt; ApplicationController
  <B><span style="color:#A020F0">def</span></B> <B><span style="color:#0000FF">movies
</span></B>    <span style="color:#B8860B">@movies</span> = Movie.find(:all)
    render :json =&gt; <span style="color:#B8860B">@movies</span>
  <B><span style="color:#A020F0">end</span></B>
<B><span style="color:#A020F0">end</span></B><!--END enscript--></pre>
<p>This is getting all the &#8220;Movie&#8221; model objects, and simply serializing the array into JSON.</p>
<p>You can also filter or process the array before serializing it. When an ActiveRecord instance is converted to JSON it is wrapped in an extra object that&#8217;s usually uneccessary (i.e. { &#8220;movie&#8221; : { &#8220;title&#8221; : &#8220;something&#8221;, &#8220;description&#8221; : &#8220;a description&#8221; }}). Creating a plain Ruby object from each ActiveRecord object prevents this. Additionally, it allows you to perform other processing, such as excluding certain properties. Here we use &#8220;map&#8221; to convert each ActiveRecord object to a plain Ruby object:</p>
<pre class="enscript" ><!--BEGIN enscript-->
<B><span style="color:#A020F0">def</span></B> <B><span style="color:#0000FF">movies
</span></B>  <span style="color:#B8860B">@movies</span> = Movie.find(:all).map {|m| { :title =&gt; m.title, :description =&gt; m.description } }
  render :json =&gt; <span style="color:#B8860B">@movies</span>
<B><span style="color:#A020F0">end</span></B><!--END enscript--></pre>
<p>Finally, if for some reason you need to use <a href="http://cappuccino.org/discuss/2008/10/08/xmlhttprequest-jsonp-cappuccino/">JSONP</a> (be sure you understand why you need it, and the security implications!), Rails makes it very easy to wrap the JSON in callback:</p>
<pre class="enscript" ><!--BEGIN enscript-->
<B><span style="color:#A020F0">def</span></B> <B><span style="color:#0000FF">hello
</span></B>	render :json =&gt; { :hello =&gt; <B><span style="color:#BC8F8F">&quot;world&quot;</span></B> }, :callback =&gt; params[:jsoncallback]
<B><span style="color:#A020F0">end</span></B><!--END enscript--></pre>
<p>This example also demonstrates accessing parameters that were passed in, namely the &#8220;jsoncallback&#8221; parameter.</p>
<h3>Getting and Submitting Data From Cappuccino</h3>
<p>The typical way to retrieve or submit data from a Cappuccino application is to use <a href="http://cappuccino.org/learn/documentation/classes/CPURLConnection.html">CPURLConnection</a>. This is discussed extensively in <a href="http://cappuccino.org/discuss/2008/10/08/xmlhttprequest-jsonp-cappuccino/">a previous blog post</a>, and all of it applies to using Cappuccino with Rails.</p>
<h3>Scaffolding</h3>
<p>In addition to HTML views Rails &#8220;scaffolding&#8221; also provides simple XML web services. You can also easily add JSON versions similar to the following:</p>
<pre class="enscript" ><!--BEGIN enscript-->
<B><span style="color:#A020F0">def</span></B> <B><span style="color:#0000FF">index
</span></B>  <span style="color:#B8860B">@movies</span> = Movie.find(:all)

  respond_to <B><span style="color:#A020F0">do</span></B> |format|
    format.html <I><span style="color:#B22222"># index.html.erb
</span></I>    format.xml  { render &lt;img src=<B><span style="color:#BC8F8F">'http://cappuccino.org/discuss/wp-includes/images/smilies/icon_mad.gif'</span></B> alt=<B><span style="color:#BC8F8F">':x'</span></B> <B><span style="color:#A020F0">class</span></B>=<B><span style="color:#BC8F8F">'wp-smiley'</span></B> /&gt; ml =&gt; <span style="color:#B8860B">@movies</span> }
    format.json  { render :json =&gt; <span style="color:#B8860B">@movies</span> }
  <B><span style="color:#A020F0">end</span></B>
<B><span style="color:#A020F0">end</span></B><!--END enscript--></pre>
<h3>Conclusion</h3>
<p>This covers the bare essentials of integrating a Cappuccino application with Rails. There is lots of potential for better Cappuccino integration with ActiveRecord and other server-side data technologies. Please feel free to make suggestions, or implement something and contribute it back!</p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2008/11/11/cappuccino-and-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>New Cappuccino Automatic Layout Tutorial</title>
		<link>http://cappuccino.org/discuss/2008/11/07/new-cappuccino-automatic-layout-tutorial/</link>
		<comments>http://cappuccino.org/discuss/2008/11/07/new-cappuccino-automatic-layout-tutorial/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 10:50:19 +0000</pubDate>
		<dc:creator>tolmasky</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=144</guid>
		<description><![CDATA[This new tutorial covers Cappuccino&#8217;s powerful system of automatic resizing and repositioning support for creating dynamic layouts easily and quickly.  Proper resizing behavior is an important part of polishing any application, so make sure to check it out!]]></description>
			<content:encoded><![CDATA[<p>This new tutorial covers Cappuccino&#8217;s powerful system of automatic resizing and repositioning support for creating dynamic layouts easily and quickly.  Proper resizing behavior is an important part of polishing any application, so make sure to <a href="http://cappuccino.org/learn/tutorials/automatic-layout">check it out!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2008/11/07/new-cappuccino-automatic-layout-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cappuccino Tools: &#8220;bake&#8221;</title>
		<link>http://cappuccino.org/discuss/2008/10/29/cappuccino-tools-bak/</link>
		<comments>http://cappuccino.org/discuss/2008/10/29/cappuccino-tools-bak/#comments</comments>
		<pubDate>Wed, 29 Oct 2008 10:06:21 +0000</pubDate>
		<dc:creator>tlrobinson</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=135</guid>
		<description><![CDATA[Note: please check the tools page on the wiki for the latest information on Cappuccino&#8217;s tools. In the final installment of the Cappuccino Tool article series (for now), we cover &#8220;bake&#8221;, an automatic deployment tool. Writing a Cappuccino application does not require using &#8220;bake&#8221;, but can help with more advanced deployments. Introduction &#8220;bake&#8221; is somewhat [...]]]></description>
			<content:encoded><![CDATA[<p><i>Note: please check the <a href="http://wiki.github.com/280north/cappuccino/tools">tools page</a> on the wiki for the latest information on Cappuccino&#8217;s tools.</i></p>
<p>In the final installment of the Cappuccino Tool article series (for now), we cover &#8220;bake&#8221;, an automatic deployment tool. Writing a Cappuccino application does not require using &#8220;bake&#8221;, but can help with more advanced deployments.</p>
<h3>Introduction</h3>
<p>&#8220;bake&#8221; is somewhat analogous to <a href="http://www.capify.org/">Capistrano</a>, a deployment tool often used for deploying Ruby on Rails and other applications, but &#8220;bake&#8221; has several features specifically for deploying Cappuccino applications.</p>
<p>The basic idea behind &#8220;bake&#8221; is to assemble a complete deployable copy of your application by pulling the pieces from various places (Git, Subversion, and local or remote directories via rsync), building it, packing it up, and deploying it to your server(s).</p>
<p>One key feature of bake is the management of multiple deployments over time, which allows three things: <a href="http://en.wikipedia.org/wiki/Atomic_operation">atomic</a> deployments, keeping your client side code (the Cappuccino application) synchronized with your server side code, and enabling aggressive caching on all your static resources (code, images, etc). We&#8217;ll see later this is done by putting all the new resources in place, then &#8220;swinging&#8221; a single file, the index.html with a &lt;base&gt; tag.</p>
<p>&#8220;Atomic deployments&#8221; means that the deployment is updated to the new version in a single operation, which is either successful or not, nothing in between. Every client loading your application receives either the previous deployment, or the new deployment, but never a mixture of the two.</p>
<p>Keeping client code synchronized with server code is (sometimes) important for making sure users who have already loaded the application can continue using it even after you deploy a new version of the server side code that is incompatible with older versions of the client side code.</p>
<p>Aggressive caching of static resources reduces the load time of Cappuccino applications for repeat useres. This is possible because every resources URL is unique in each deployment, so we can set the &#8220;Expires&#8221; header far in the future (e.x. &#8216;Expires &#8220;Thu, 15 Apr 2010 20:00:00 GMT&#8221;&#8216;). While the actual file name is not unique (for example Objective-J/Objective-J.js), in the deployed application the <em>path</em> will be unique (www.yourserver.com/YourApp/1225273279/Objective-J/Objective-J.js where the version number changes for each deployment)</p>
<h3>Summary</h3>
<p>The configuration for a bake deployment is specified in a &#8220;bakefile&#8221;, which is in the JSON format with a structure like the following:</p>
<pre>
{
	"sources" : [
	    {
	        "type"    : "git",
	        "path"    : "git://github.com/280north/cappuccino.git",
	        "parts"   : [
    	        {
    	            "src"       :   "Objective-J",
    	            "dst"       :   "Frameworks/Objective-J",
    	            "build"     :   "ant -DBuild=BUILD_PATH",
    	            "copyFrom"  :   "Release/Objective-J"
    	        },
	            {
    	            "src"       :   "Foundation",
    	            "dst"       :   "Frameworks/Foundation",
    	            "build"     :   "steam build -c Release -b BUILD_PATH",
    	            "copyFrom"  :   "Release/Foundation"
	            },
        	    {
    	            "src"       :   "AppKit",
    	            "dst"       :   "Frameworks/AppKit",
    	            "build"     :   "steam build -c Release -b BUILD_PATH",
    	            "copyFrom"  :   "Release/AppKit"
        	    }
	        ]
	    },
	    {
	        "type"    : "rsync",
	        "path"    : "/Users/username/projects/NewApplication",
	        "parts"   : [
	            {
    	            "src"       :   "",
    	            "dst"       :   "Blah"
	            }
	        ]
	    },
	    {
	        "type"    : "svn",
	        "path"    : "https://svn.youserver.com/Project/trunk",
	        "parts"   : [
	            {
    	            "src"       :   "subdirectory",
    	            "dst"       :   "Something"
	            }
	        ]
	    }
	],
	"deployments" : [
	    { "host" : "deploy@myserver.com", "path" : "/var/www/mysite/public" }
	],
	"templateVars" : {
        "APPLICATION_NAME" : "My Application",
        "BACKGROUND_COLOR" : "black",
        "TEXT_COLOR" : "black"
	}
}
</pre>
<p>This bakefile contains three &#8220;sources&#8221;: a git repository, a local directory, and a svn repository. The git repository is the main <a href="http://github.com/280north/cappuccino/">Cappuccino git repository</a>, hosted on GitHub. You could replace this with a different branch if you needed a specific version, or even your own if you have one. This source contains three &#8220;parts&#8221;, Objective-J, AppKit, and Foundation. The &#8220;src&#8221; specifies where in the checkout the part is located, while &#8220;dst&#8221; specified where in the final built application it should be placed. You can optionally specify a &#8220;build&#8221; command, which is run from the specified &#8220;src&#8221; directory. This command should include the placeholder &#8220;BUILD_PATH&#8221;, which will be filled in by &#8220;bake&#8221; with the temporary directory where the build results are placed (equivalent to $STEAM_BUILD for any &#8220;steam&#8221; commands). Additionally, if you specify a &#8220;build&#8221; command you also need to specify a &#8220;copyFrom&#8221; parameter, which tells build the subdirectory of the build directory it should copy the built part from.</p>
<p>Once each piece of the application has been built it is copied to the appropriate subdirectory of a uniquely named (using the current Unix timestamp) &#8220;versioned&#8221; directory. Rather than deploying this versioned directory directly, it is placed within another directory which contains a special index.html file. This file includes a &lt;base&gt; tag that points to the versioned directory, which causes the browser to treat it as the base for all relative URLs, thus loading the correct version of all resources without requiring the application be located at a unique URL. &#8220;bake&#8221; will fill in &#8220;$VERSION&#8221; template variable in the base tag of the template with the correct</p>
<p>Additionally, &#8220;bake&#8221; will calculate the size of all code which needs to be loaded, in order to provide an accurate loading progress bar. The calculated size is inserted into the template variable &#8220;$FILES_TOTAL&#8221;. You can also specify other template variables such as &#8220;$APPLICATION_NAME&#8221;, &#8220;$BACKGROUND_COLOR&#8221;, and &#8220;$TEXT_COLOR&#8221; in the bakefile.</p>
<p>If you use your own template, the only required variable is the &#8220;$VERSION&#8221; one, but you can specify as many custom variables as you wish.</p>
<p>Finally, once the application has been built and assembled, it is optionally run through <a href="http://cappuccino.org/discuss/2008/10/21/cappuccino-tools-“press”/">&#8220;press&#8221;</a>, then gzipped. If the &#8220;&#8211;deploy&#8221; command line parameter was given then the gzipped application is transmitted to the deployment servers, un-gzipped, and copied to the deployment path using a specific sequence of command to ensure the deployment is atomic:</p>
<pre>
tar xzf 1225273279.tar.gz
mkdir -p /path/to/deployment
mv 1225273279/1225273279/ /path/to/deployment/1225273279
mv 1225273279/index.html path/to/deployment/index.html
rm "1225273279.tar.gz
rmdir 1225273279
cd /path/to/deployment
ln -nsf 1225273279 Current
</pre>
<p>(version &#8220;1225273279&#8243;, deplyoment directory &#8220;/path/to/deployment&#8221;)</p>
<p>One important thing to note about &#8220;bake&#8221; is that since the old deployment remains live (but hidden) if you deploy a fix for a security vulnerability you should manually purge all the old deployments from your server. If the change doesn&#8217;t introduce any incompatibilities between the server and client, you could set up a <a href="http://en.wikipedia.org/wiki/Rewrite_engine">rewrite rule</a> to direct all requests to the purged deployments to the latest, which is always symlinked to &#8220;Current&#8221;.</p>
<h3>Conclusion</h3>
<p>Once again I should stress that this tool is by no means required for writing a Cappuccino application. It was written to help deploy our production application, <a href="http://280slides.com">280 Slides</a>, but we have made it available for anyone who has similar deployment requirements. If it doesn&#8217;t quite fit your requirements, please feel free to suggest improvements, or even better, make improvements yourself and contribute them back!</p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2008/10/29/cappuccino-tools-bak/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Scrapbook Tutorial</title>
		<link>http://cappuccino.org/discuss/2008/10/22/new-scrapbook-tutorial/</link>
		<comments>http://cappuccino.org/discuss/2008/10/22/new-scrapbook-tutorial/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 19:13:40 +0000</pubDate>
		<dc:creator>tolmasky</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[draganddrop]]></category>
		<category><![CDATA[scrapbook]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=109</guid>
		<description><![CDATA[We&#8217;ve just finished the latest installment in the Scrapbook Tutorial Series.  In Part II, we cover adding drag and drop to the application so that can begin allowing the user to start generating content.  In the process we cover a number of other Cappuccino topics, including creating and setting up collection views, panels, and scroll [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve just finished the latest installment in the Scrapbook Tutorial Series.  In Part II, we cover adding drag and drop to the application so that can begin allowing the user to start generating content.  In the process we cover a number of other Cappuccino topics, including creating and setting up collection views, panels, and scroll views.  We also briefly touch on the topic of serialization through Cappuccino&#8217;s keyed archiving API.  Make sure to <a href="http://cappuccino.org/learn/tutorials/scrapbook-tutorial-2">check it out</a> and give us your feedback!</p>
<p style="text-align: center;"><a href="http://cappuccino.org/discuss/wp-content/uploads/2008/10/overview.png"><img class="alignnone size-medium wp-image-110" title="overview" src="http://cappuccino.org/discuss/wp-content/uploads/2008/10/overview-300x214.png" alt="" width="300" height="214" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2008/10/22/new-scrapbook-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cappuccino Tools: “press”</title>
		<link>http://cappuccino.org/discuss/2008/10/21/cappuccino-tools-%e2%80%9cpress%e2%80%9d/</link>
		<comments>http://cappuccino.org/discuss/2008/10/21/cappuccino-tools-%e2%80%9cpress%e2%80%9d/#comments</comments>
		<pubDate>Tue, 21 Oct 2008 11:16:45 +0000</pubDate>
		<dc:creator>tlrobinson</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[build tool]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=104</guid>
		<description><![CDATA[Note: please check the tools page on the wiki for the latest information on Cappuccino&#8217;s tools. In the third installment of the build tools series we tackle one of the most advanced build tools: &#8220;press&#8221;. Recall from the overview that &#8220;press&#8221; is a tool for stripping code and other optimizations. Additionally, it can convert an [...]]]></description>
			<content:encoded><![CDATA[<p><i>Note: please check the <a href="http://wiki.github.com/280north/cappuccino/tools">tools page</a> on the wiki for the latest information on Cappuccino&#8217;s tools.</i></p>
<p>In the third installment of the build tools series we tackle one of the most advanced build tools: &#8220;press&#8221;. Recall from the <a href="http://cappuccino.org/discuss/2008/10/06/the-cappuccino-build-tools/">overview</a> that &#8220;press&#8221; is a tool for stripping code and other optimizations. Additionally, it can convert an entire Objective-J application into a single pure JavaScript file, which we&#8217;ll see can be useful.</p>
<h3>press</h3>
<p>The primary goal of &#8220;press&#8221; is to strip unused code from your application and frameworks and perform other optimizations. It needs to know about the entire application, including your application code and the Cappuccino frameworks, in order to determine the dependencies and remove unused files. It is called with two parameters, the path to your application, and the output directory:</p>
<p><code>press root_directory output_directory</code></p>
<p>This will run &#8220;press&#8221; on your application located at root_directory, and output a similar but smaller version (with unused files stripped) at output_directory.</p>
<p>Additionally, there are several useful options:</p>
<ul>
<li><em>&#8208;&#8208;main path</em>: The relative path (from root_directory) to the main file (default: &#8216;main.j&#8217;)</li>
<li><em>&#8208&#8208frameworks path</em>: The relative path (from root_directory) to the frameworks directory (default: &#8216;Frameworks&#8217;)</li>
<li><em>&#8208&#8208png</em>: Run pngcrush on all PNGs (pngcrush must be installed!)</li>
<li><em>&#8208&#8208flatten</em>: Flatten all code into a single Application.js file and attempt to add script tag to index.html (useful for Adobe AIR and CDN deployment)</li>
<li><em>&#8208&#8208nostrip</em>: Don&#8217;t strip any files. Mostly useful for debugging.</li>
</ul>
<h3>&#8208&#8208flatten</h3>
<p>The most interesting of these options is &#8220;&#8208&#8208flatten&#8221;, which converts your application into a single pure JavaScript file that can be imported with a standard &#8220;script&#8221; tag. While the Objective-J load system is great in most scenarios, there are currently a few limitations that a pure JavaScript file helps overcome. Namely that the load system doesn&#8217;t work in Adobe AIR due to strict security restrictions, and the load system doesn&#8217;t work across domains, such as with a CDN, also due to browser security restrictions. By flattening all Objective-J code into a JavaScript file, we can use a standard script tag to load our application, which works cross-domain and in Adobe AIR.</p>
<h3>Internals</h3>
<p>If you&#8217;re interested in how &#8220;press&#8221; works, read on. It starts by loading your application while noting which global variables are defined in each file. It then &#8220;walks&#8221; along the dependency &#8220;graph&#8221;, including every imported file, with one important exception: framework imports like &#8220;import &lt;AppKit/AppKit.j&gt;&#8221; and &#8220;import &lt;Foundation/Foundation.j&gt;&#8221; are ignored since these types of imports would result in the entire framework (including unused files) being imported. Instead, press looks at the global dependencies, and only keeps the files that are referenced by any other file that has been imported.</p>
<h3>Conclusion</h3>
<p>&#8220;press&#8221; is a already a great tool, but there is much room for improvement. In the future we would like to add finer-granularity code stripping, such as method-level rather than file-level. Additionally, we&#8217;re working on an automatic <a href="http://www.alistapart.com/articles/sprites">image spriting</a> and optimization feature which determines exactly which images are required for your application and includes them in a single image, vastly reducing the number of HTTP requests to load your application.</p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2008/10/21/cappuccino-tools-%e2%80%9cpress%e2%80%9d/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Cappuccino Tools: &#8220;objjc&#8221; and &#8220;steam&#8221;</title>
		<link>http://cappuccino.org/discuss/2008/10/14/objjc-and-steam/</link>
		<comments>http://cappuccino.org/discuss/2008/10/14/objjc-and-steam/#comments</comments>
		<pubDate>Tue, 14 Oct 2008 06:42:38 +0000</pubDate>
		<dc:creator>tlrobinson</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[build tool]]></category>
		<category><![CDATA[Objective-J]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=93</guid>
		<description><![CDATA[Note: please check the tools page on the wiki for the latest information on Cappuccino&#8217;s tools. In our previous post on the Cappuccino build tools we summarized the purpose of four of the tools. In this article we&#8217;ll dive deeper into two of them, objjc and steam. To review, the purpose of these tools is [...]]]></description>
			<content:encoded><![CDATA[<p><i>Note: please check the <a href="http://wiki.github.com/280north/cappuccino/tools">tools page</a> on the wiki for the latest information on Cappuccino&#8217;s tools.</i></p>
<p>In our previous post on the <a href="http://cappuccino.org/discuss/2008/10/06/the-cappuccino-build-tools/">Cappuccino build tools</a> we summarized the purpose of four of the tools. In this article we&#8217;ll dive deeper into two of them, objjc and steam.</p>
<p>To review, the purpose of these tools is to prepare your application for deployment by pre-compiling all application Objective-J code into JavaScript, thereby reducing the load time for clients. Additionally, since most developers won&#8217;t need to modify Cappuccino itself, we always compile Cappuccino&#8217;s AppKit and Foundation frameworks to further reduce load time.</p>
<p>The only time you&#8217;ll need to run steam (which handles running objjc for you) is when you&#8217;re deploying your application, or if you&#8217;re making changes to the Cappuccino frameworks themselves. In the latter case, the easiest way to recompile the frameworks is to run the default ant task in the Cappuccino source tree:</p>
<pre><code>cd /path/to/cappuccino
ant</code></pre>
<p>To use the freshly built frameworks simply replace the &#8220;Frameworks&#8221; directory in your application with a symbolic link to the Release directory in the directory pointed to by your $STEAM_BUILD environment variable:</p>
<pre><code>cd /path/to/your_application
mv Frameworks Frameworks-Original
ln -s $STEAM_BUILD/Release Frameworks</code></pre>
<p>(if you&#8217;re loading your project through a webserver like Apache make sure to <a href="http://tlrobinson.net/blog/?p=40">enable the FollowSymLinks option</a>)</p>
<h3>objjc</h3>
<p>objjc, the Objective-J compiler, is the most important of the build tools, but you&#8217;ll likely never invoke it directly. objj can take any number of parameters as input filenames and output filenames (preceded by the &#8220;-o&#8221; flag). For example:</p>
<pre><code>objj Class1.j -o Class1.o Class2.j -o Class2.o</code></pre>
<p style="text-align: center;"><img src="http://cappuccino.org/discuss/wp-content/uploads/2008/10/objjc1.png" alt="" title="objjc" width="338" height="76" class="aligncenter size-full wp-image-49" /></p>
<p>This will invoke the Objective-J compiler (which is identical to the one used by Objective-J in the browser) on each input file, outputting JavaScript plus some metadata to each specified output file. Next we need to combine all of these individual output files into a single &#8220;.sj&#8221; archive that contains the JavaScript and import dependency metadata for the entire framework. It would be possible to do this by hand, but steam takes care of it for you.</p>
<h3>steam</h3>
<p>steam is the general Cappuccino build tool that manages the creation and compilation of your Cappuccino applications.</p>
<p>To create a basic Cappuccino application, simply run steam with the &#8220;create&#8221; command:</p>
<pre><code>steam create ApplicationName</code></pre>
<p>This will create a new Cappuccino application in the directory &#8220;ApplicationName&#8221;. This application can be modified and run (by opening index.html in the browser) without any further usage of the build tools.</p>
<p>When you&#8217;re ready to compile the application code for deployment, add a .steam file to your application, like the following:</p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; "><span style="color:#236e25;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br />
<span style="color:#236e25;">&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;</span><br />
<span style="color:#881280;">&lt;plist </span><span style="color:#994500;">version</span><span style="color:#881280;">=</span><span style="color:#1a1aa6;">&quot;1.0&quot;</span><span style="color:#881280;">&gt;</span><br />
<span style="color:#881280;">&lt;dict&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>Name<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;string&gt;</span>YourApplication<span style="color:#881280;">&lt;/string&gt;</span><br />
&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>Targets<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;<span style="color:#881280;">&lt;array&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;dict&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>Name<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;string&gt;</span>YourApplication<span style="color:#881280;">&lt;/string&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;/dict&gt;</span><br />
&nbsp;&nbsp;<span style="color:#881280;">&lt;/array&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>Configurations<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;<span style="color:#881280;">&lt;array&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;dict&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>Name<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;string&gt;</span>Debug<span style="color:#881280;">&lt;/string&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>Settings<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;dict&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>PREPROCESS<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;true/&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>FLAGS<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;string&gt;</span>-DDEBUG<span style="color:#881280;">&lt;/string&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;/dict&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;/dict&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;dict&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>Name<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;string&gt;</span>Release<span style="color:#881280;">&lt;/string&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>Settings<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;dict&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>PREPROCESS<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;true/&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;key&gt;</span>PREINTERPRET<span style="color:#881280;">&lt;/key&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;true/&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;/dict&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881280;">&lt;/dict&gt;</span><br />
&nbsp;&nbsp;<span style="color:#881280;">&lt;/array&gt;</span><br />
<span style="color:#881280;">&lt;/dict&gt;</span><br />
<span style="color:#881280;">&lt;/plist&gt;</span></div>
<p>This file defines the targets and configurations for your project. This one defines a single target, YourApplication, and two configurations, Release and Debug. To compile your application, simply execute steam with the build command, the .steam filename, and the configuration name:</p>
<pre><code>steam build -f MyApp.steam -c Release</code></pre>
<p>If a .steam filename is not provided it will look for a file with the extension &#8220;.steam&#8221;. Likewise, if a configuration name is not provided, it will use the first one defined in the file. The following will run the &#8220;Debug&#8221; configuration in your .steam file:</p>
<pre><code>steam build</code></pre>
<p>steam gathers all &#8220;.j&#8221; files in your application, compiles them, and combines them into a single &#8220;.sj&#8221; file (&#8220;static Objective-J&#8221;), along with a new &#8220;Info.plist&#8221; which tell Objective-J which files are contained in the &#8220;.sj&#8221;.</p>
<p style="text-align: center;"><img src="http://cappuccino.org/discuss/wp-content/uploads/2008/10/steam1.png" alt="" title="steam" width="356" height="100" class="aligncenter size-full wp-image-50" /></p>
<p>The results are placed in a subdirectory of $STEAM_BUILD named the same as the configuration, i.e. Debug or Release. Alternatively, pass the &#8220;-b&#8221; flag and a build directory to specify where it should be built.</p>
<p>The compiled application or framework can then be used in place of the original uncompiled collection of .j files. If it was an application, copy or symlink your Frameworks directory to it&#8217;s directory. If it was a framework, copy it to your application&#8217;s Frameworks directory.</p>
<h3>Conclusion</h3>
<p>This article covered the core Cappuccino build tools, objjc and steam. Remember that you will probably never want to call objjc directly, but rather rely on the &#8220;steam build&#8221; command to manage the build process for you. Additionally, remember the build process is entirely optional (except if you&#8217;re editing the Cappuccino frameworks themselves), and is only necessary as a deploy-time optimization.</p>
<p>In subsequent articles we&#8217;ll cover the remaining more advanced build tools, press and bake, as well as further deployment optimizations.</p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2008/10/14/objjc-and-steam/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>XMLHTTPRequest, JSONP &amp; Cappuccino</title>
		<link>http://cappuccino.org/discuss/2008/10/08/xmlhttprequest-jsonp-cappuccino/</link>
		<comments>http://cappuccino.org/discuss/2008/10/08/xmlhttprequest-jsonp-cappuccino/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 07:53:08 +0000</pubDate>
		<dc:creator>ross</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[CPURLConnection]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[XMLHTTPRequest]]></category>

		<guid isPermaLink="false">http://cappuccino.org/discuss/?p=56</guid>
		<description><![CDATA[If you&#8217;re a veteran web developer, you&#8217;re probably familiar with the XMLHTTPRequest (XHR for short), the bread and butter of &#8220;AJAX&#8221;. XHRs are what make dynamic applications that don&#8217;t reload the page possible. For an application framework like Cappuccino this is critical, since Cappuccino applications are designed to never reload the page &#8212; so it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re a veteran web developer, you&#8217;re probably familiar with the XMLHTTPRequest (XHR for short), the bread and butter of &#8220;AJAX&#8221;. XHRs are what make dynamic applications that don&#8217;t reload the page possible. For an application framework like Cappuccino this is critical, since Cappuccino applications are designed to never reload the page &#8212; so it&#8217;s important to understand exactly how Cappuccino deals with these requests.</p>
<p>Before we get in too deep, a quick primer on exactly what I&#8217;m talking about. If you&#8217;re comfortable with XMLHTTPRequests already, feel free to skip this paragraph. <a href="http://en.wikipedia.org/wiki/XMLHttpRequest">XMLHTTPRequest</a> was introduced by Microsoft in Internet Exporer 5 as a way for scripts within a web page to send a remote request to another server without reloading the entire page. Although it started as a propriety Microsoft technology, it was later adopted by Mozilla, and eventually all the other major browsers. The term AJAX, which stands for Asynchronous JavaScript and XML, is essentially synonymous with the use of XMLHTTPRequests on a website. A website creates an XHR object with a specific URL, gives it a function to execute when the status of the request changes, and then executes the request. With this mechanism, your script can use most of the HTTP verbs, and can respond to specific HTTP response codes, which makes it a flexible and powerful API. If you&#8217;re coming from Cocoa, or another desktop programming environment, you may be used to classes that perform similar functions like NSURLConnection or maybe even (approximately) curl and wget. There are, however, important limitations introduced by the browser security model that we&#8217;ll discuss shortly.</p>
<h3>XMLHTTPRequest</h3>
<p>In Objective-J and Cappuccino, asynchronous http requests are instrumental for creating a working app, beginning with the import statement. As you&#8217;ve probably noticed by now, Objective-J introduces the <strong class="keyword">import</strong> keyword to JavaScript. Import statements pull in and execute Objective-J code at runtime, which lets us maintain dependency relationships across classes in Cappuccino, much like code in C or Java. These statements are actually asynchronous, and are implemented using XHRs. This means we only have to include one script tag in our <em>index.html</em> file for Objective-J only, while the rest of Cappuccino is bootstrapped with these asynchronous requests. This is a fairly low level detail, but it illustrates the importance of the XHR when writing complex javascript based applications.</p>
<p>When writing a Cappuccino applications, XHRs are the primary way to communicate with your backend server. While most of your application logic may be running in the client, certain tasks will still need to run on a webserver.  For example, consider an authentication system; in order for authentication to be meaningful, it will need to present credentials to a server for verification. Similarly, features like persistent data storage require server communication to actually store the data, otherwise it would dissappear when the user navigated away from the page. To put it another way, if your app doesn&#8217;t talk to an outside server, it may be of limited utility.</p>
<h3>CPURLConnection</h3>
<p>Like most things in Cappuccino, XMLHTTPRequests are abstracted at a higher level. In this case, the CPURLConnection class manages the communication. If we look at the <a href="http://cappuccino.org/learn/documentation/class_c_p_u_r_l_connection.html">API Reference</a>, we&#8217;ll find a few different ways to create an instance. The easiest way is the class method <strong class="keyword">connectionWithRequest:delegate:</strong>, which takes a CPURLRequest object and a delegate. CPURLRequest objects wrap a single request, including the URL, HTTP method, request body, and request headers. Like everywhere in Cappuccino, the delegate provides for the ability to customize the request&#8217;s behavior. Let&#8217;s look at the process of creating a CPURLConnection.</p>
<pre class="enscript" ><!--BEGIN enscript-->var request = [CPURLRequest requestWithURL:<B><span style="color:#BC8F8F">&quot;list.txt&quot;</span></B>];
var connection = [CPURLConnection connectionWithRequest:request delegate:<B><span style="color:#A020F0">self</span></B>];<!--END enscript--></pre>
<p>As you can see, it&#8217;s a simple process. Connections created with this class method fire immediately, without needing to explicitly call any additional methods.  By default, the request object will be a GET request, with no additional data. Like any URL on a webpage, the URL will be treated as relative to your <em>index.html</em> file unless you specify an absolute path or URL (e.g. preceding the URL with http://). To handle the response, we can implement these two optional delegate methods:</p>
<pre class="enscript" ><!--BEGIN enscript-->
- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">connection</span></B>:(<B><span style="color:#228B22">CPURLConnection</span></B>) <span style="color:#B8860B">connection</span> <B><span style="color:#0000FF">didReceiveData</span></B>:(<B><span style="color:#228B22">CPString</span></B>)<span style="color:#B8860B">data</span>
{
    <I><span style="color:#B22222">//This method is called when a connection receives a response. in a
</span></I>    <I><span style="color:#B22222">//multi-part request, this method will (eventually) be called multiple times,
</span></I>    <I><span style="color:#B22222">//once for each part in the response.
</span></I>}

- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">connection</span></B>:(<B><span style="color:#228B22">CPURLConnection</span></B>)<span style="color:#B8860B">connection</span> <B><span style="color:#0000FF">didFailWithError</span></B>:(<B><span style="color:#228B22">CPString</span></B>)<span style="color:#B8860B">error</span>
{
    <I><span style="color:#B22222">//This method is called if the request fails for any reason.
</span></I>}<!--END enscript--></pre>
<p>After your request is created it will be fired, and later CPURLConnection will call the methods above on the connection&#8217;s delegate. These methods are both optional, but are the minimum that you should implement in order to interact with your AJAX requests. The first is essential in processing any response, and the second is necessary for correctly dealing with errors, which is an important part of a well written application. Let&#8217;s look at a real world implementation of these two methods, as well as the creation of a request, to get a sense for how all this works.</p>
<p>The following code is taken from 280 Slides. It deletes a photo from your library. In this first chunk, we&#8217;ll construct and start our connection:</p>
<pre class="enscript" ><!--BEGIN enscript-->
<I><span style="color:#B22222">//BASE_URL is a 280 Slides global, which points to the base directory of our server structure
</span></I>var request = [CPURLRequest requestWithURL: BASE_URL+<B><span style="color:#BC8F8F">&quot;Media/photo.php?id=&quot;</span></B>+itemID];

<I><span style="color:#B22222">//we're using HTTP verbs to keep our backend as RESTful as possible
</span></I>[request setHTTPMethod: <B><span style="color:#BC8F8F">&quot;DELETE&quot;</span></B>];

<I><span style="color:#B22222">//create the CPURLConnection and store it. the connection fires immediately
</span></I>_deletePhotoConnection = [CPURLConnection connectionWithRequest: request delegate: <B><span style="color:#A020F0">self</span></B>];<!--END enscript--></pre>
<p>Notice that we store a reference to the connection in the ivar <em>_deletePhotoConnection</em>. This is so, if we have multiple connections, we can check to ensure we&#8217;re responding to the right one. Now let&#8217;s look at the delegate method implementations:</p>
<pre class="enscript" ><!--BEGIN enscript-->
- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">connection</span></B>:(<B><span style="color:#228B22">CPURLConnection</span></B>)<span style="color:#B8860B">aConnection</span> <B><span style="color:#0000FF">didReceiveData</span></B>:(<B><span style="color:#228B22">CPString</span></B>)<span style="color:#B8860B">data</span>
{
    <I><span style="color:#B22222">//get a javascript object from the json response
</span></I>    var result = CPJSObjectCreateWithJSON(data);

    <I><span style="color:#B22222">//check if we're talking about the delete connection
</span></I>    <B><span style="color:#A020F0">if</span></B> (aConnection == _deletePhotoConnection)
        [<B><span style="color:#A020F0">self</span></B> deletePhoto:result.<B><span style="color:#A020F0">id</span></B>];   <I><span style="color:#B22222">//deletes the specified photo
</span></I>
    <I><span style="color:#B22222">//clear out this connection's reference
</span></I>    [<B><span style="color:#A020F0">self</span></B> clearConnection:aConnection];
}

- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">connection</span></B>:(<B><span style="color:#228B22">CPURLConnection</span></B>)<span style="color:#B8860B">aConnection</span> <B><span style="color:#0000FF">didFailWithError</span></B>:(<B><span style="color:#228B22">CPError</span></B>)<span style="color:#B8860B">anError</span>
{
    <B><span style="color:#A020F0">if</span></B> (aConnection == _deletePhotoConnection)
        alert(<B><span style="color:#BC8F8F">&quot;There was an error deleting this photo. Please try again in a moment.&quot;</span></B>);

    [<B><span style="color:#A020F0">self</span></B> clearConnection:aConnection];
}

- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">clearConnection</span></B>:(<B><span style="color:#228B22">CPURLConnection</span></B>)<span style="color:#B8860B">aConnection</span>
{
    <I><span style="color:#B22222">//we no longer need to hold on to a reference to this connection
</span></I>    <B><span style="color:#A020F0">if</span></B> (aConnection == _deletePhotoConnection)
        _deletePhotoConnection = <B><span style="color:#A020F0">nil</span></B>;
}<!--END enscript--></pre>
<p>Again, the code is very simple. Since we send and receive data using JSON, the first call in our <strong>connection:didReceiveData:</strong> implementation turns that text response (<em>data</em>) into a javascript object using the JSON helper function <strong>CPJSObjectCreateWithJSON()</strong>. For the reverse operation, you can use the reverse function, <strong>CPJSObjectCreateJSON()</strong>. With the resulting object in hand, we check if the resulting connection is in fact our _deletePhotoConnection, and if it is, we proceed to delete the photo referenced in the object. In the alternate case, where our request is unsuccessful, we prompt the user to inform them that the request failed and do not delete the photo.</p>
<p>You&#8217;ll notice that both methods call <strong>clearConnection:</strong>. This is a convenience method we&#8217;ve written to nil out our reference to the connection object once we&#8217;ve finished using it. Although not strictly necessary, keeping a pointer to the object means it won&#8217;t be collected by the garbage collector. Removing the reference from our instance variable is the best practice since we know we will not be using it again. </p>
<p>Although it&#8217;s not shown here, the reason we store a reference to the specific connection is that we use other connections in the same class, so we need a simple way to tell them apart. If you&#8217;re only using one connection with your delegate, you may not need to use this technique or store a reference to the connection at all.</p>
<p>Finally, there are two additional CPURLConnection delegate methods we chose not to implement, but which you may be interested in for your own application. There&#8217;s also a class delegate for handling request authentication at the application level. You can read more about these methods in the <a href="http://cappuccino.org/learn/documentation/class_c_p_u_r_l_connection.html">API documentation</a>. </p>
<h3>CPJSONPConnection</h3>
<p>One of the limitations of the XHR is that it must follow what is known in the web security world as the <a href="http://en.wikipedia.org/wiki/Same_origin_policy">same origin policy</a>. The model requires that requests can only be sent to URLs with the same protocol, domain, and port number as the web page. This policy makes it difficult to interact with third party web services without having to proxy requests first through your own webserver.  Several people developed their own workarounds to the limitation, but eventually <a href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/">JSONP</a> emerged as the standard mechanism. </p>
<p>JSONP stands for JSON with Padding, and it comprises two components. The first part deals with getting around the same origin policy itself. XMLHTTPRequests may not work across multiple domains, but &lt;script&gt; tags have no such limitation. JSONP takes advantage of this by  dynamically generating a &lt;script&gt; tag and appending it to the page. The script&#8217;s src property is set to the URL of the remote API, including all request parameters in the query string. The second component of JSONP deals with what to do once the API returns a response.</p>
<p>As the name suggests, JSONP APIs return their data in the JSON format, but instead of returning a plain JSON string, they wrap the JSON response in a function call. This extra function call is the &#8220;padding&#8221; in JSONP, and it effectively works around the browser&#8217;s security policy. Typically, function name is a parameter of the request, which you can see demonstrated in the Flickr API.  This API allows you to specify <em>format=json</em> to get a JSON response, and <em>jsoncallback=myfunctionname</em> to specify your custom function wrapper for the response. An example request might look something like this:</p>
<pre class="enscript" ><!--BEGIN enscript-->
<B><span style="color:#A020F0">var</span></B> url = <B><span style="color:#BC8F8F">&quot;http://www.flickr.com/services/rest/&quot;</span></B>+
          <B><span style="color:#BC8F8F">&quot;?method=flickr.interestingness.getList&quot;</span></B>+
          <B><span style="color:#BC8F8F">&quot;&amp;format=json&amp;jsoncallback=flickResponse&amp;api_key=YOUR_KEY&quot;</span></B>;<!--END enscript--></pre>
<p>As you can imagine, generating your own dynamic script tags and managing global callback methods would be a serious hassle, which is why Cappuccino has built in support in the form of <a href="http://cappuccino.org/learn/documentation/class_c_p_j_s_o_n_p_connection.html">CPJSONPConnection</a>. You may have encountered this class in the source of our <a href="http://cappuccino.org/learn/demos/FlickrPhotoDemo/">Flickr Demo</a>. Creating an instance should look familiar:</p>
<pre class="enscript" ><!--BEGIN enscript-->
var connection = [CPJSONPConnection sendRequest:aRequest callback:aCallbackParameter delegate:<B><span style="color:#A020F0">self</span></B>];<!--END enscript--></pre>
<p>The additional parameter, <strong>callback:</strong>, is a string that specifies the name of the parameter that allows us to specify the callback function&#8217;s name in the JSONP API we&#8217;re talking to. Similar to CPURLConnection, these two delegate methods are defined:</p>
<pre class="enscript" ><!--BEGIN enscript-->
- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">connection</span></B>:(<B><span style="color:#228B22">CPJSONPConnection</span></B>)<span style="color:#B8860B">aConnection</span> <B><span style="color:#0000FF">didReceiveData</span></B>:(<B><span style="color:#228B22">Object</span></B>)<span style="color:#B8860B">data</span>
{
    <I><span style="color:#B22222">//called by the &quot;padding&quot; function when the request is complete
</span></I>
    <I><span style="color:#B22222">//depending on the third part API, data may be the native javascript object,
</span></I>    <I><span style="color:#B22222">//or it may be a string. usually a js object is used, but if a string
</span></I>    <I><span style="color:#B22222">//is passed, you can create a js object with CPJSObjectCreateWithJSON()
</span></I>}

- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">connection</span></B>:(<B><span style="color:#228B22">CPJSONPConnection</span></B>)<span style="color:#B8860B">aConnection</span> <B><span style="color:#0000FF">didFailWithError</span></B>:(<B><span style="color:#228B22">CPString</span></B>)<span style="color:#B8860B">error</span>
{
    <I><span style="color:#B22222">//will be called if the connection fails
</span></I>    <I><span style="color:#B22222">//will see improvements in an upcoming release
</span></I>}<!--END enscript--></pre>
<p>Let&#8217;s take a look at the actual implementation in our Flickr Demo:</p>
<pre class="enscript" ><!--BEGIN enscript-->
- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">applicationDidFinishLaunching</span></B>
{
    ...

    <I><span style="color:#B22222">//Create the request, which contains all of our query parameters,
</span></I>    <I><span style="color:#B22222">//except the jsoncallback parameter
</span></I>
    var req = [CPURLRequest requestWithURL:
                    <B><span style="color:#BC8F8F">&quot;http://www.flickr.com/services/rest/&quot;</span></B>+
                    <B><span style="color:#BC8F8F">&quot;?method=flickr.interestingness.getList&quot;</span></B>+
                    <B><span style="color:#BC8F8F">&quot;&amp;per_page=20&amp;format=json&amp;api_key=&quot;</span></B>+API_KEY];

    <I><span style="color:#B22222">//Create the connection, set the callback, and make ourselves the delegate.
</span></I>    <I><span style="color:#B22222">//the connection fires immediately
</span></I>
    var connection = [CPJSONPConnection sendRequest:req callback:<B><span style="color:#BC8F8F">&quot;jsoncallback&quot;</span></B> delegate:<B><span style="color:#A020F0">self</span></B>];
}

- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">connection</span></B>:(<B><span style="color:#228B22">CPJSONPConnection</span></B>)<span style="color:#B8860B">aConnection</span> <B><span style="color:#0000FF">didReceiveData</span></B>:(<B><span style="color:#228B22">Object</span></B>)<span style="color:#B8860B">data</span>
{
    <I><span style="color:#B22222">//the response from Flickr is the actual JS Object, which has an
</span></I>    <I><span style="color:#B22222">//array of photos that we pass to our collection view
</span></I>    [<B><span style="color:#A020F0">self</span></B> addImageList:data.photos.photo withIdentifier: lastIdentifier];
}

- (<B><span style="color:#228B22">void</span></B>)<B><span style="color:#0000FF">connection</span></B>:(<B><span style="color:#228B22">CPJSONPConnection</span></B>)<span style="color:#B8860B">aConnection</span> <B><span style="color:#0000FF">didFailWithError</span></B>:(<B><span style="color:#228B22">CPString</span></B>)<span style="color:#B8860B">error</span>
{
    <I><span style="color:#B22222">//Ideally, we would do something smarter here.
</span></I>    alert(error);
}<!--END enscript--></pre>
<p>Due to the use of the script tag injection, as opposed to a traditional XHR object, we don&#8217;t have any fine grained information about the response. We cannot detect status codes, and cannot natively access the response. Thankfully, CPJSONPConnection does a good job of managing the additional complexity, and massaging it into a familiar API. There is still some work to be done on generating more reliable errors, but it should be completed in the near future.</p>
<p>JSONP does have it&#8217;s own security implications. Because you&#8217;re essentially allowing arbitrary third party code to execute within the context of your own application, you should only use JSONP with providers you trust. It&#8217;s also important to note that because these requests are sent to different domains, cookies from your own site will not be sent along with the request. This prevents third parties from stealing your sessions, but it also means that authenticating requests is significantly more complex.</p>
<h3>Conclusion</h3>
<p>There&#8217;s been some confusion about when to use CPURLConnection versus CPJSONPConnection, due largely in part to the lack of documentation or discussion on the issue. In general, you should only use JSONP with third-party services that you trust, and only when doing so doesn&#8217;t involve sensitive information. For example, getting public Flickr photos, or performing a Google search using Google&#8217;s AJAX search API. If you&#8217;re communicating with your own service, even if you use JSON as the transmission format, you should use CPURLConnection. Their are numerous advantages to this approach, especially the additional security. </p>
<p>I hope this has illustrated both when and how to use CPURLConnection and CPJSONPConnection. As we continue to develop Cappuccino, we&#8217;ll be improving both of these classes, and introducing new communication methods as well. If you have questions, sound off in the comments, or try the <a href="http://cappuccino.org/discuss/list.php">mailing list or irc channel</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://cappuccino.org/discuss/2008/10/08/xmlhttprequest-jsonp-cappuccino/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
	</channel>
</rss>

