onrails.org2014-02-28T16:36:33-08:00http://onrails.org/Daniel Wanjad@n-so.comArchiving OnRails.org2012-11-26T00:00:00-08:00http://onrails.org/2012/11/26/archiving-onrails-dot-org<p>Since I started blogging on my <a href="http://n-so.com/blog">corporate blog</a> I neglected this blog. It is a little ironic as I’m doing more Rails work than ever and I have a few blog posts comming up. I contacted <a href="http://twitter.com/lmarlow">Lee Marlow</a> and <a href="http://twitter.com/rubysolo">Solomon White</a>, my long time cohosts of this blog and authors of some of the most famous blog entries of this blog, and we decided to put it in <em>archival</em> mode. We won’t add new entries but thought that as there was some good and now historical material we could just keep around.</p>
<p>Enjoy!</p>
<p>- Daniel.</p>I'm leaving Flex and it's not because of HTML5.2012-06-01T00:00:00-07:00http://onrails.org/2012/06/01/im-leaving-flex-and-its-not-because-of-html5<p>Note I cross posted this entry on my <a href="http://n-so.com/blog/2012/06/01/im-leaving-flex-and-its-not-because-of-html5/">new blog</a>.</p>
<p>Flex has been really good to me for many years. In fact I moved to the US in 2002 and started working on a Flash project and we jumped on Flex before it was 1.0 with Royal which was the beta code name of Flex. Flex had a long road since and I delivered many fun and successful customer projects. Many of which were internal enterprise projects and I also worked on a few pretty visible public ones like the <a href="http://vault.australianopentv.com">Australian Open Tennis Vault</a>, the <a href="http://vault.ncaa.com"><span class="caps">NCAA</span> Vault</a>. I even co-authored a <a href="http://flexonrails.com">Flex on Rails"</a> book.</p>
<p>You would think I would leave Flex based on the flux it is in right now after the catastrophic public relation announcement from Adobe in November. That’s not it, as I actually believe Flex has a bright future and is in great hands with the Apache Flex Team. My realization happened a couple of weeks ago with the announcement of <a href="http://www.rubymotion.com">Rubymotion</a>. The cheer fact of being able to build iOS apps with the iOS <span class="caps">SDK</span> in Ruby was that moment for me and it opened my eyes and pointed to a turning point in my career. I’m going mobile full steam ahead. This is the future. Note just RubyMotion, just the mobile sector in general. And many mobile apps need to be backed by great server side services. So mobile and the cloud are really an exciting combination.</p>
<p>So what do I mean by “I leave Flex”. Actually it already started, I’m not taking on new Flex Desktop Project, I cancelled of few customer Flex projects that where on my radar and I’m canceling several internal project I was working on. In addition I will not attend Flex user groups or conferences and I’m not giving Flex speaking engagements or trainings. That’s it, done!</p>
<p>So what about my current engagements with Flex? I currently have two great customer for which I provide product development, mentoring and consulting services and I would like to continue working with them for the foreseeable future. In fact these two customers have many Ruby on Rails projects and will start doing more mobile development. So it seems to be a good match.</p>
<p>And what about Flex mobile which is pretty awesome and is a great way to build iOS and Android apps for the enterprise? You may not know this, but I have been an Objective-C developer in the mid-90 on NeXTStep and followed the <span class="caps">WWDC</span> conference since many years before the iOS <span class="caps">SDK</span> was announced. Again I love Ruby and the iOS <span class="caps">SDK</span>, I just wasn’t very fond of Objective-C anymore as Ruby spoiled me. RubyMotion is my gateway drug to iOS and I’m just ready to dive fully into iOS. Mentally I don’t want to master two different environments and the iOS ecosystem is large enough to sustain me professionally.</p>
<p>Now will I still recommend Flex to anyone? The answer is clearly yes as there are still many situations and projects where Flex is a great match. At least until a good HTML5/JavaScript framework can provide the same productivity than with the Flex <span class="caps">SDK</span>. All the current <span class="caps">HTML</span> frameworks will evolve and morph drastically over the coming years. Which is a good reason to choose Flex if you want stability. These <span class="caps">HTML</span> frameworks will take several years to mature. This said I really enjoy Backbonejs, Spinejs, Ember-js and how they try to make development of Rich <span class="caps">HTML</span> Applications easier.</p>
<p>So, here we go. Good bye Flex!</p>
<p>- Daniel Wanja</p>UndoManager for ActionScript2012-02-27T00:00:00-08:00http://onrails.org/2012/02/27/undomanager-for-actionscript<p>UndoManager is A simple ActionScript library to add undo/redo functionality to your Flex/ActionScript projects. I just extracted this library from one of the project I’m working on.</p>
<p><a href="http://n-so.com/blog/2012/02/27/undomanager-for-actionscript/">Read more on my new blog</a></p>
<p>Enjoy!<br />
Daniel</p>Dentaku a calculator for Ruby2012-01-26T00:00:00-08:00http://onrails.org/2012/01/26/dentaku-a-calculator-for-ruby<p>I’m currently working on a project that requires the use of formulas or expressions to implement business rules (the original system is an Excel workbook), and I needed a way to implement some of the same functionality. My first thought was to model the formulas in ActiveRecord, clause by clause, using something like `acts_as_nested_set` to handle hierarchies and grouping. However, I’ve done something similar before, and was never quite satisfied with the result — it always felt “heavy” — so I decided to try a different approach this time.</p>
<p>The result is Dentaku, a gem that parses and evaluates Excel-like formulas, allowing the use of named variables that will be substituted for real values at run time. So far, the result values will be either boolean or numeric, but strings will probably be added soon.</p>
<p>To illustrate how it works, let me set up the following (quite contrived) hypothetical situation: You’re building an upvote system for a Reddit-type site, but the customers do not want to encode all the logic for the system in Ruby — they need to be able to manage all the rules on the fly. However, they are willing to be limited to only using a few predefined attributes of the user as all variable inputs to the rules.</p>
<p>The initial ruleset is something like this: A vote from a “normal” user is worth one point for each week the user has been with the site. A vote from an “admin” user is worth 100 points. A vote from a “limited” user is worth one point, and a vote from a “blacklisted” user is worth zero points. However, users can earn achievements, which update a “bonus” number for the user, and any normal or limited user’s vote points are augmented with the bonus, but only after the user has been with the site for at least five weeks. (Hey, I promised contrived, right?) So how could we accomplish this with Dentaku?</p>
<p>We could create the following rules:</p>
<pre><code>
+-------------------------------+----------------------+
| conditions | points |
+-------------------------------+----------------------+
| admin | 100 |
| normal and age_in_weeks < 5 | age_in_weeks |
| limited and age_in_weeks < 5 | 1 |
| normal and age_in_weeks >= 5 | age_in_weeks + bonus |
| limited and age_in_weeks >= 5 | 1 + bonus |
| blacklisted | 0 |
+-------------------------------+----------------------+
</code></pre>
<p>Then, given a hash representing the user like:</p>
<typo:code lang="ruby">
user = {
:admin => false,
:normal => true,
:limited => false,
:blacklisted => false,
:age_in_weeks => 10,
:bonus => 8
}
</typo:code>
<p>we could calculate the points for a vote by the represented user like so:</p>
<typo:code lang="ruby">
def calculate_points_for(user, rules)
calculator = Dentaku::Calculator.new
rules.each do |rule|
if calculator.evaluate(rule.conditions, user)
return calculator.evaluate(rule.points, user)
end
end
<ol>
<li>no rules matched, default to zero<br />
0<br />
end<br />
</typo:code></li>
</ol>
<p>So that’s what Dentaku is about — I hope someone else finds it useful. You can check it out, fork it, etc at the <a href="http://github.com/rubysolo/dentaku">Dentaku</a> Github page, or just `gem install dentaku` and start playing!</p>Adobe's Announcement on Flash: visually!2011-11-21T00:00:00-08:00http://onrails.org/2011/11/21/adobes-announcement-on-flash-visually<p>I’ve received so much feedback from many of my friends on Flex projects being cancelled or scheduled to be rewritten in another technology than Flex. Great Job Adobe, you did it!</p><p>So what was really announced last week is the following:<br /> <img src="http://www.onrails.org/files/FlasAnnouncement.png" alt="" /></p><p>Yes, Adobe will stop development on the Flash Player in the Browser.<br /> Flash Player on the mobile will continue.<br /> Adobe <span class="caps">AIR</span> will continue, on the desktop and mobile.<br /> Captive runtime of <span class="caps">AIR</span> allows to create “native” apps on mobile and tablets (Android, iOS and more) and desktop WIndows and <span class="caps">OSX</span> apps that don’t need <span class="caps">AIR</span> to be distributed. Yep, that continues too.</p><p>Of course Adobe tried to clarify their statements after the fact saying the transition to HTML5 will take 3 to 5 years. The following is from Adobe’s website from Andrew Shorten & Deepa Subramaniam, see: <a href="http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html">http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html</a></p><p><strong>You said that you believe <span class="caps">HTML</span> is the “long-term solution for enterprise applications” – can you clarify this statement?</strong></p><p>HTML5 related technologies (comprising <span class="caps">HTML</span>, JavaScript and <span class="caps">CSS</span>) are becoming increasingly capable, such that we have every reason to believe that advances in expressiveness (e.g. Canvas), performance (e.g. VM and <span class="caps">GPU</span> acceleration in many browsers) and application-related capabilities (e.g. offline storage, web workers) will continue at a rapid pace. In time (and depending upon your application,<strong><span style="color: #ff0000;"> it could be 3-5 years from now</span></strong>), we believe HTML5 could support the majority of use cases where Flex is used today.</p><p>However, Flex has now, and for many years will continue to have, advantages over HTML5 for enterprise application development – in particular:</p><ul><li>Flex offers complete feature-level consistency across multiple platforms</li><li>The Flex component set and programming model makes it extremely productive when building complex application user interfaces</li><li>ActionScript is a mature language, suitable for large application development</li><li>Supporting tools (both Adobe’s and third-party) offer a productive environment with respect to code editing, debugging and profiling</li><p></ul><p> </p><p>I guess Adobe’s communication just accelerated that 3 to 5 year timeframe by quite a bit.</p><p>Enjoy!</p><p>Daniel</p></p>The Future of Flex. 2011-11-15T00:00:00-08:00http://onrails.org/2011/11/15/the-future-of-flex<p>At first I thought “Wow, Adobe really messed up their communication”. They could have focused on what they are adding, strong support for HTML5 and CSS4, Adobe <span class="caps">AIR</span> for Mobile, and not on what they are removing, the Flash Player in the Browser. But then they also announced that they opened sourced Flex via the Apache Foundation. And the main stream media, the blogosphere, and many developers I know went crazy and said Flex is dead, it’s over, time to convert all your projects to HTML5.</p>
<p>At a second thought I think it’s pretty smart what Adobe did. The saying goes “If you can’t beat them, join them”. In fact the Flex against <span class="caps">HTML</span> fight wasn’t one where Adobe had anything to win from. So they just made it loud and clear and now they are saying “We are HTML5”. In fact detaching themselves from Flex in appearance allows them to ride the new HTML5 technowave and get in the news when they upgrade their tool, bring out new HTML5 component framework or acquire hot companies like PhoneGap and TypeKit. We are HTML5!!</p>
<p>Adobe has already two great tools for HTML5, Muse and Edge and needs to push them way further and also needs to create or acquire a great <span class="caps">HTML</span> component framework such as Sencha so they call build and sell new development tools as well as design tools for the new growing crowd of HTML5 developers.</p>
<p>So where does that leave Flash and Flex. I use a lot Flex in the enterprise, and that’s where Adobe just did the most damage in my eyes. Go now try to convince any <span class="caps">CTO</span> that Flex is a good idea. Flex is a mature framework and Adobe has a great enterprise offering, but it will be hard to convince anyone that Adobe is still behind that technology after the way they managed their communication. This said I think the move of Flex to the Apache open source foundation is a great one and if managed right will give Flex a good run for years to come. Flex is still a great choice for many enterprise projects and will remain so until a solid and widely adopted <span class="caps">HTML</span> component framework emerges. If Adobe is smart they could provide that offering.</p>
<p>Flex is also a great environment to develop “native” mobile applications that can run on iOS and Android. The forthcoming Flex <span class="caps">SDK</span> 4.6 will show that potential and it’s a great way to create cross platform mobile and tablet applications. Adobe will not kill Adobe <span class="caps">AIR</span> for the mobile as it’s a too appealing growth market. But that message didn’t get through to the main stream media.</p>
<p>As Adobe said Flash for the desktop for games and Adobe <span class="caps">AIR</span> for mobile will be here for a while. But Adobe has the most to gain if they become the major player in the HTML5 field by providing tools, framework and making the web standards evolve. And they are in a good position to get there. To achieve this goal it also means that they will refocus many of their development teams and this will impact Flash and Flex. Moving the Flex <span class="caps">SDK</span> and some of the key developers to the Apache Foundation will allow to continue to evolve the <span class="caps">SDK</span> regardless of Adobe’s new focus. The move a few years ago to the Flex Sparks components and the recent addition of the new mobile components provide a great and mature framework basis for a real open source effort which I believe will have a long life even if it will become a niche environment over the long run. Note I consider Ruby on Rails a niche market, a really great one to be in. Adobe has something great with Adobe <span class="caps">AIR</span> for mobile and this is the one area where they could even grow their developers basis if they get their message right. For me <span class="caps">AIR</span> for mobile/tablets and the Flex <span class="caps">SDK</span> 4.6 is one solution where I can build mobile apps faster than in any other environment and this will be a great business to be in, especially for the enterprise market.</p>
<p>The smart enterprises will realize that Flex is stable and here to stay for the long run, even if it’s not in the spotlight. They will start <span class="caps">HTML</span> projects in parallel to gradually improve their developer workforce and experience in this area. They will also realize that the HTML5 frameworks and coding technics are evolving so rapidly that it will be time consuming just to keep up. Also these frameworks are not as mature and complete as in the Flex ecosystem. Finding Flex developers is difficult, but finding great <span class="caps">HTML</span>/Javascript developers is even harder. This said, there is no denying that pretty quickly the HTML5 tools and frameworks will catchup with what Flex offers today in ease of development for enterprise applications.</p>
<p>Personally I’m looking forward to see how these HTML5/Javascript tools/libraries will evolve and will play with many of them.</p>
<p>So where does all this leaves you, the developer. Well, it’s for sure time to jump on the new <span class="caps">HTML</span>/Javascript bandwagon if you haven’t yet. I cannot see many companies starting new enterprise projects with Flex. If you are into mobile or tablet development give the new Flex <span class="caps">SDK</span> 4.6 a try, I believe there is a great potential for Flex to become a major player in the mobile development arena…targeting “native” applications and not the browser. Yep, your heard it here first ;-)</p>
<p>Enjoy,<br />
Daniel</p>Flex With Ruby on Rails talk - An AdobeMax preview2011-09-19T00:00:00-07:00http://onrails.org/2011/09/19/flex-with-ruby-on-rails-talk-an-adobemax-preview<p><iframe src="http://player.vimeo.com/video/29279457" width="400" height="300" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe></p>
<p>This is a presentation I gave in September 2011 at the <a href="http://ria5280.org">Denver <span class="caps">RIA</span> Developers Group</a> showing how to create a Flex application that interacts with a Ruby on Rails server. In fact it was schedule for the Flash Builder track of Adobe Max but was bumped to the the <a href="http://www.360flex.com/about/360max/">360Flex Unconference</a> as it was deemed too specialized for the general track. In this presentation I will show you how to interact with Rails using <span class="caps">REST</span>, nested resources, nested attributes and the newest kid on the block, the bulk-api allowing to transfer complex data structures between your rich client application and your Rails server. You will get a good overview on how Rails works and how to quickly build a Flex application on top of Ruby on Rails.</p>Writing tests is not fun. Anyone who tells you otherwise is a liar....2011-08-30T00:00:00-07:00http://onrails.org/2011/08/30/writing-tests-is-not-fun-anyone-who-tells-you-otherwise-is-a-liar<p>At least so says my good friend Sean Voisen in his latest blog entry <a href="http://sean.voisen.org/blog/2011/08/thoughts-on-test-driven-development">Thoughts on test-driven development</a>.</p>
<p>What, you are calling me a liar? :-) I must respectfully disagree with Sean. Not on the fact that he may think it’s not fun, that’s his opinion like many other Flex developers that don’t do testing. I disagree because I see many developers, in other communities, that actually really enjoy testing. If you look at the Ruby community you will see many developpers enjoying doing test driven development, enjoying writing tests, and even expanding the way you can write tests. Check out rspec, Cucumber, and the many of books and screencast on the subject. Checkout all the ruby libraries, they are all pretty well tested. There are many training classes on people that really want to improve doing testing. Many Rails projects are extremly well tested. Many Ruby developers cannot even code without writing tests first.</p>
<p>This said as they are many examples on how to test Ruby and Rails code it’s easier to get going on with testing in that environment. On the other hand, there are not many example of tested Flex applications and libraries. Not many toturoials on how to test your Flex application.<br />
I happend to do a lot of unit testing for my Flex apps, but I do not test everything, I use tests for more difficult aspects, when I’m not sure how to design something, when it’s slow to access a part of the application just to verify that my new code works. Then I write tests and it’s fun. How many times do you manually repeat a sequence on the UI like start the application, perform a search, click on the grid, open a record, click the calculate button…Oh no, that not right…go change some code and do it again. Well that’s not fun. Every developer I know does that thousands a time a day. Well, write a test and your workflow becomes more fun.</p>
<p>So why are Flex developers not testing? As I mentioned above, there is not much peer pressure to do so as not many Flex developers do testing. Also they are not many examples. In addition it’s not obvious how to test applications in many case. Often they are not written in a testable manner. Flex/ActionScript is asynchronous and event driven, that’s harder too.</p>
<p>They are solutions for that and Flex applications are very well suited to testing…but the sweet spot must be found. And you should start by testing the simple things that have lots of added value. Anywhere you have logic in your code that does filtering, calculation, transform data, write a test…You gonna like it. FlexUnit 4 as great support for asynchronous or event driven programming, but I agree, at first it’s not obvious how to best us that support. So again, start with the simple thing, refactor your code so that you can test it in a non-asynchronous way, that will already be helpfull.</p>
<p>So I came to the conclusion that I won’t be able to convince Flex developers that testing is needed and even fun. I can only hope that as a Flex developer you will start using FlexUnit 4 and try to add tests to your application and persevere and find the sweet spot on where testing is fun and makes you more productive. If you persevere you will like many Ruby developers become a better developer, write better code and faster.</p>
<p>I finally like Sean’s balanced view on test driven development: “But would I use <span class="caps">TDD</span> for every project I work on? Probably not. For personal “one-off†projects or projects I know will not see much future maintenance, the slower development time is simply not worth it. For serious, long-term projects however, <span class="caps">TDD</span> is now a must.”</p>
<p>Testing remains hard, but it’s just essential if you want to become a great, agile, developer.</p>
<p>Persevere and testing will become your friend!</p>
<p>Enjoy!<br />
Daniel</p>Termistat : a status bar for your terminal2011-08-26T00:00:00-07:00http://onrails.org/2011/08/26/termistat-a-status-bar-for-your-terminal<p>When running background processes that produce detail logging, it’s often difficult to strike the right balance between providing overall status information and details about the current step in the process. It’s helpful to be able to see “tail-like” information at the detail level to monitor and debug your processes; however, it’s also helpful to be able to know summary information, such as the overall progress through the entire task. You can intersperse “record 1 of n” lines in your output, but they are easy to miss in all the noise.</p>
<p>In order to be able to display both types of information concurrently, I built a simple gem called <a href="http://github.com/rubysolo/termistat">termistat</a>, which allows you to display a status bar for summary information at the top of your terminal in addition to the original detailed output. It was meant to be a whyday contribution, but I didn’t quite finish it in time to be released on whyday…oh well.</p>
<p>Here’s a screenshot of termistat in action:<br />
<img src="http://www.onrails.org/files/file_copy.png" alt="termistat screenshot" /></p>
<p>Termistat requires the ffi-ncurses gem (which requires the ncurses library to be on your system), and has a configuration <span class="caps">DSL</span> to customize the appearance somewhat. Check it out and let me know if you have any ideas for improvement!</p>Redis-Flex: An ActionScript Library to integrate with Redis2011-06-13T00:00:00-07:00http://onrails.org/2011/06/13/an-actionscript-library-to-integrate-with-redis<p>Announcing <a href="https://github.com/danielwanja/redis_flex">redis flex</a> An ActionScript Library to integrate with Redis.</p>
<p>A while back I looked into accessing Redis directly from Flex and I found an existing library, <a href="https://github.com/claus/as3redis">as3redis</a> that however didn’t support the new unified request protocol. So I wrote a minimalist wrapper that now allows to send commands to a redis server.</p>
<p>To access the Redis server from Flex just instantiate a Redis instance:</p>
<typo:code lang="XML">
<redis:Redis id="server"
connected="server_connectedHandler(event)"
result="server_resultHandler(event)" />
</typo:code>
<p>Then you can send commands:</p>
<typo:code lang="Javascript">
server.send(“<span class="caps">SET</span> A 123”);
server.send(“<span class="caps">GET</span> A”);
server.send([“rpush”, “messages”, “message one”]);
</typo:code>
<p>Note it’s not a good idea to connect a Flex application directly to Redis. Redis is usually used in the context of an application server that protects it’s access in the same way that Flex doesn’t connect directly to a database. However they may be cases that this could be useful.</p>
<p>Enjoy!</p>
<p>Daniel</p>To Infinity and... no beyond - An ActionScript bug...I mean, feature.2011-05-27T00:00:00-07:00http://onrails.org/2011/05/27/to-infinity-and-no-beyond-an-actionscript-bug-i-mean-feature<p>So yesterday I was asked about a bug in a legacy Rails and Flex application. There was one company name that wasn’t displayed correctly on the front-end. “Infinity Corp Name” was just displayed as “Infinity”, so nothing beyond infinity. First I thought it was a joke, but not, a real bug that could cause issues.</p>
<p>So I looked at the code and the service call was a plain HttpService call with the resultFormat set to object. The server returns <span class="caps">XML</span> but the Flash Player converts the <span class="caps">XML</span> to a tree of objects. This is where it get’s funny. In fact when the player converts your hash to Objects it checks if a value is a number or a string…Hey guess what “Infinity followed by something” is a number.</p>
<p>Here are some conversion examples:</p>
<table border="0">
<tr>
<td>String</td>
<td>Is Number</td>
<td>Converted Number</td>
</tr>
<tr>
<td>“123”</td>
<td>true</td>
<td>123</td>
</tr>
<tr>
<td>“123 Abc”</td>
<td>false</td>
<td>NaN</td>
</tr>
<tr>
<td>“Infinity”</td>
<td>true</td>
<td>Infinity</td>
</tr>
<tr>
<td>“Infinity Abc”</td>
<td>true</td>
<td>Infinity</td>
</tr>
</table>
<p>It’s the last conversion which is the root of the problem as “Infinity Abc” is a number that when casted translates to Infinity!</p>
<p>So we found the problem but the solution is really don’t use the Flash Player to do the conversion for you using the return type “object”. Use “e4x” which would turn your object in <span class="caps">XML</span> or use <span class="caps">JSON</span> and do the conversion yourself.</p>
<p>To Infinity… and beyond!</p>
<p>Daniel</p>Building Rails Apps for Rich Client - Using the bulk_api from Flex.2011-05-27T00:00:00-07:00http://onrails.org/2011/05/27/building-rails-apps-for-rich-client-using-the-bulk_api-from-flex<p>In this screencast we are going to show how to build a Rails app in a couple of minutes that is optimized for Rich Client. The application is a todo application build in Flex connecting using the <a href="https://github.com/drogus/bulk_api">bulk_api</a> to the Rails server using my new <a href="https://github.com/danielwanja/bulk_data_source_flex">bulk data source Flex framework</a>.</p>
<p><iframe src="http://player.vimeo.com/video/24299809" width="400" height="300" frameborder="0"></iframe></p>
<p>Enjoy!</p>
<p>Daniel</p>Sitting is killing you2011-05-24T00:00:00-07:00http://onrails.org/2011/05/24/sitting-is-killing-you<p>I started working standing, what seems now ages ago, after a chat with <a href="http://thillerson.blogspot.com/">Tony Hilerson</a> when I thought…why not try it. I spend most days of the week working at a customer site and they where not just eager when I asked if I could work standing, they just went ahead and changed my work desk to a standing desk. The first few hours I felt weird…standing and coding. But after a day it felt pretty fun. During the first few weeks it was hard to go through the day without wanting to sit down, but after that period I was just feeling great after height hours of work. I felt not only that I coded hard but also that I physically did something. Another benefit it that it’s really easy when someone comes by my desk to talk that I don’t have to get up, I’m just standing there and ready to welcome them to my desk. It’s funny when you do peer programing, as after one hour anyone that is not used to work standing complains, and the we switch station. Another issue is when you work with someone of different height, I’m 6.2", then they have to look up or can even not reach the keyboard. My friend <a href="http://voisen.org/">Sean</a> tweeted about the following review on working while sitting…and I thought I share. Although I don’t know the source of that information, I can tell you that working standing is pretty fun.</p>
<p><a href="http://www.medicalbillingandcoding.org/sitting-kills"><img src="http://images.medicalbillingandcoding.org.s3.amazonaws.com/sitting-is-killing-you.jpg" alt="Sitting is Killing You" width="500" border="0" /></a><br /></p>railsconf - Day 32011-05-19T00:00:00-07:00http://onrails.org/2011/05/19/railsconf-day-3<p>Speaker Slides<br /> <a href="http://railsconf.com/slides">http://railsconf.com/slides</a></p><p>Official Photos<br /> <a href="../../">http://www.flickr.com/photos/oreillyconf/sets/72157626743161970</a></p><p>Keynote Video and Other Interviews<br /> <a href="../../">http://www.youtube.com/playlist?p=PL379EA9290474C86C</a></p><p>News and Coverage:<br /> <a href="../../">http://en.oreilly.com/rails2011/public/content/news-coverage</a></p><h3>Sproutcore with Yehuda Katz</h3><p><em>This are some notes I took at the Sproutcore <span class="caps">BOF</span> tonight…</em></p><p>He started working around 9 month ago. Started working on it full time at the beginning of the year. First thing he did was to evaluate how to make the getting started experience better. They switched over to a template model doing views. The biggest thing he will say in regards with template, they automatically update the html when the underlying objects update. Sprout core today do two things, one is to handle event and two, to update the dom. So they will split this in two objects. They are changing the render and update. They will have a plugable UI with a widget layer. A separate layer for Desktop and Mobile. Currently Checkbox, Textbox, and Button are widgets that use templates.</p><p>Today they announce Sproutcore 2.0 alpha. It’s a 20k single file with contains the core abstraction. They have a separate library to access the database store that is also 20k, that will provide ActiveRecord like functionality.</p><p>Will release a dropin plugin for Rails and Sproutcore to connect automatically to a Rails application to do basic crud.</p><p>To install Sproutcore in a rails app you can use a generator which will do the following changes:</p><p>In your Gemfile</p><p> gem ‘bulk_api’</p><p>In the routes file</p><p> mount Bulk::Spourcore.new => “/_sproutcore”<br /> builk_routes “/api/build/”</p><p>It then created the app/sproutcore folder.</p><p>These are a few javascript classes that allow to deal with the Rails integration:</p><ul><li>SC.Application</li><li>SC.Store</li><li>SC.Record </li><p></ul><p>The generator can be used as follows for example to add a ‘projects’ resource:</p><p> rails g bulk:resource projects</p><p>Which adds the app/builk/projects_resource.rb. This class manages automatically all the crud operations from javascript. So the client side can auto commit some of the changes and can send multiple statements as one html requests.</p><p>Every Tuesday, starting in 2 weeks, at 10am <span class="caps">PST</span> they will have a one hour training session. </p><p> </p></p>RailsConf 2011 - Thank you!2011-05-19T00:00:00-07:00http://onrails.org/2011/05/19/railsconf-2011-thank-you<div>It’s a wrap. Wow, that was fun and a great conference. It didn’t hurt that a party was planned every night. Engineyard, Bluebox, Github had open bars in a different places every night. Free beer for everyone. If that doesn’t feel like a tech bubble. But what fun it was. It wasn’t just the partying, lots of coding, people networking, awesome keynotes and tons of great talks that made this Railsconf the best in my view. RailsConf is a well oiled machine, but it takes lots of effort and planing to make it such a successful event. So thank you to everyone that works behind the scenes to get this event going. What impresses me the most is that the Rails core team manages to make Rails better – release after release, year over year. Better not with more features, but removing all the stuff that is not needed anymore and adding features that keeps the Rails community engaged and enthusiast. Rails 3.0 was a big refactoring that allowed this all and was released about this time last year. Rails 3.1 was announced at DHH’s keynote where he showed the way of where this can lead us and this will certainly trigger a new generations of mobile and desktop Rich Internet Applications powered by Rails. Rails 3.1 will be released this week, you can use the beta by doing a ‘gem install rails —pre’, and I’m actually excited to use CoffeScript. <span class="caps">CSS</span> and JavaScript are now first class citizen in Rails. This was the year of JavaScript at RailsConf, and if as usual Rails is right, it’s a showcase of where the industry is going. So now is the time to jump on board, Backbone.js, SproutCore , CoffeScript and Rails 3.1 here we come! </div><div></div><div></div><div>I was really excited by Yehuda Katz’s talk “Bridging The Gap – Using Rails To Write Dry Rich Client Applications” as this is was I am evangelizing since years, use Rails as an <span class="caps">API</span> with all the goodies it has to offer and create “fatter” client applications that are more compelling to use. Yehuda made a compelling presentation on what’s great about Rails beyond the view layer and pointed out that just saying use <span class="caps">REST</span> wasn’t enough to build the new style of apps that are starting to show up. Hence he described a new protocol built on top of <span class="caps">REST</span> to allow bulk updates. He and his team created a first implementation that can be used with Rails, <a href="https://github.com/drogus/bulk_api">the bulk_api gem</a>. Of course I have still a foot in the Flex world and will leverage this work to Flex and will be cranking out a <a href="https://github.com/danielwanja/bulk_data_source_flex">BulkDataStore for Flex framework</a> over the next few weeks. Yea, Flex has still a few miles left :-) </div><div></div><div></div><div>Again, the biggest kudos goes to the presenters where, beside one talk that was ultra light, all talks where just awesome. I enjoyed the html5 tutorial the first day during which I had time code html5. This was followed by Bruce Williams and Jonh Athayde talk on Building Bulletproof Views. As usual Bruce loving code design and sense of esthetics managed to convey on how to be a better programmer through example. Really enjoyed it. There where just so many practical sessions, like how to scale your application, how to integrate diverse databases, how Saas works, a talk on CoffeScript, on testing the impossible, intense lightning talks, talks on HBase, and an ultra fun talk on Backbone.js.</div><div></div><div></div><div>The vendors area was also great fun and the usual suspect where present, Heroku, Engineyard, New Relics and others. Thanks for the pingpong ball gun and all the T-shirts. My wife can wait to see me in them!</div><div></div><div></div><div>Rails is the community. I was amazed on how many newcomers where here and how they are welcomed. This was not only apparent at the Ignite Rails event where presenters showed their enthusiasms of sharing knowledge but also apparent in all the discussions that where going on between sessions. Speaking of Ignite Rails, this was just awesome. 16 presenters, 5 minutes each = high energy. That Rocked. Another parallel event was BohConf, with many sessions and local Ruby and Rails developers hanging out just next to RailsConf and having many really cool sessions.</div><div></div><div>Finally it was great to meet again with the usual Denver crew. Now back to coding!</div><div></div><div><div>So if you didn’t make this year, make sure to put it on your calendar for next year!</div><p></div><div></div><div>Enjoy!</div><div>Daniel Wanja</div><div><a href="http://twitter.com/danielwanja">@danielwanja</a></div></p>RailsConf 2011 - Day 22011-05-17T00:00:00-07:00http://onrails.org/2011/05/17/railsconf-2011-day-2<p>Today is really the first day of the conference, yesterday was the tutorial day for which you had to pay extra. So I wonder how much more crowded it will be. The tutorials where great this year. In the evening the second Ignite Rails was held and was just awesome. All the talks just rocked! After Ignite, Engineyard invited everyone to an open tap at Max’s Taphouse. Not everyone will function at full capacity today.Don’t miss today’s <a href="http://en.oreilly.com/rails2011/public/content/video">livestreamd keynote by David Heinemeier Hansson</a> starting at 9:15am Baltimore time.There will be ton’s of great sessions. I’ll update this blog entry with the information I gather as the day goes along.I’m looking forward tonight’s <span class="caps">BOF</span>:</p><p><img src="http://onrails.org/files/20110517_bof.JPG" alt="" width="450" /></p><p> </p><p>Keynote: the <span class="caps">ASSET</span> <span class="caps">PIPELINE</span> and our <span class="caps">POST</span>-<span class="caps">MODERN</span>, <span class="caps">HYBRID</span>, Javascript <span class="caps">FUTURE</span>:</p><p><img src="http://www.onrails.org/files/20110517_dhh_keynote.png" alt="" width="564" height="411" /></p><p>Peter Cooper did a great job <a href="http://www.rubyinside.com/dhh-keynote-streaming-live-from-railsconf-2011-right-here-right-now-4769.html">covering the Keynote</a> on the <a href="http://www.rubyinside.com/">rubyinside</a> website.</p><p>All the slides from today (via<a href="http://joeloliveira.com/2011/05/17/slides-available-from-railsconf-2011/"> Joel Oliveira</a>)</p><ul><li><a href="http://zachholman.com/talk/2011/railsconf">Zach Holman – Double-Shipping Software for Profit</a></li><li><a href="http://dl.dropbox.com/u/69001/Fat%20Models%20Aren%27t%20Enough%20-%20RailsConf.pdf">Jeff Casimir – Fat Models Aren’t Enough</a></li><li><a href="http://www.slideshare.net/moonmaster9000/readme-driven-development">Matt Parker – Readme Driven Development</a></li><li><a href="http://speakerdeck.com/u/jnunemaker/p/why-you-should-never-use-an-orm">John Nunemaker – Why You Should Never Use an <span class="caps">ORM</span></a></li><li><a href="http://assets.en.oreilly.com/1/event/59/Building%20Bulletproof%20Views%20Presentation.pdf">John Athayde and Bruce Williams – Building Bulletproof Views</a></li><li><a href="http://assets.en.oreilly.com/1/event/59/Cloud%20Foundry%20%E2%80%93%20The%20Rails%20Developer%E2%80%99s%20Perspective%20Presentation.pdf">Derek Collison – Cloud Foundry – The Rails Developer’s Perspective</a></li><li><a href="http://knowsql.heroku.com/">Nick Gauthier – KnowSQL: Database Tricks To Make Your Life Easier</a></li><li><a href="http://assets.en.oreilly.com/1/event/59/Upgrading%20Legacy%20Rails%20Applications%20to%20Rails%203%20Presentation.pdf">Clinton R. Nixon – Upgrading Legacy Rails Applications to Rails 3</a></li><li><a href="http://www.slideshare.net/raasdnil/keeping-rails-on-the-tracks">Mikel Lindsaar – Keeping Rails on the Tracks</a></li><li><a href="http://speakerdeck.com/u/therealadam/p/mixing-a-persistence-cocktail-1">Adam Keys – Mixing a Persistence Cocktail</a></li><li><a href="http://dl.dropbox.com/u/1788208/ProductivityTips.pdf">Hiro Asari – 20 Productivity Tips (pdf)</a> <a onclick="javascript:pageTracker._trackPageview('/outgoing/bit.ly/mqlGxi');" href="http://bit.ly/mqlGxi">(and keynote)</a></li><li><a href="http://therailsview.com/building-bulletproof-views-rc2011.pdf">Matteo Latini – Building Bulletproof Views</a></li><li><a href="http://smartic.us/doodads/presentations/railsconf2011/#1">Bryan Liles – Active Support</a></li><li><a href="https://github.com/coderoshi/holy-grail-dbs">Eric Redmond – The Holy Grail of Databases</a></li></ul>RailsConf 2011 - Day 12011-05-16T00:00:00-07:00http://onrails.org/2011/05/16/railsconf-2011-day-1RailsConf 2011 - Day 1
Today is the tutorial days.
<h2>Tutorial 1 : html5tutorial</h2>
I started RailsConf with the "Building Web Apps with HTML5: Beyond the Buzzword" by Mike Subelsky (<a href="https://twitter.com/#!/subelsky">@subelsky</a>).<br/>
He prepared twelve html5 exercises that walked the about 250 attendees through various features of html5 over a 2.5 hour session. It's fun to have time to work on these features. The high point was having about 200 computers using Websockets to send data back and forth with his server. He created a small ruby program that used EventMachine::WebSocket and it was holding up quite well all these connections.<br/>
You can download his tutorial and all files from https://github.com/subelsky/html5tutorial. Look at the tutorial.html file for instructions.<br/>
Here are a few highlights of his talk:<br/>
<h4>1 - Feature Detection</h4>
By using the <a href="http://www.modernizr.com/">Modernizr</a> library, we used modernizr-1.7.js, you can detect difference html5 of your browser. <br/>
For example:<br/>
<ul>
<li>Modernizr.canvas</li>
<li>Modernizr.websockets</li>
</ul>
<h4>2 - Basic Canvas Drawing</h4>
You can get a 2d context and draw on the canvas via that context. You can use <i>fillRect</i> and other primitives like <i>moveTo</i> and <i>lineTo</i> to draw.<br/>
<pre>
var canvas = document.getElementById("main");
var context = canvas.getContext("2d");
context.fillRect(0,0,20,20);
</pre>
<br/>
<canvas id="canvas_ex2_1" width="450" height="40"></canvas>
<script>
var canvas = document.getElementById("canvas_ex2_1");
var context = canvas.getContext("2d");
context.fillStyle = "red";
context.fillRect(0,0,20,20);
</script>
<p>Here I just created a loop to generate 180 rectangles. Note they are clipped due to the width of the canvas.</p>
<p/>
<canvas id="canvas_ex2_2" width="450" height="40"></canvas>
<script>
var canvas = document.getElementById("canvas_ex2_2");
var context = canvas.getContext("2d");
for (var i=0;i<180;i++) {
context.fillStyle = i % 2 == 0 ? "red" : "blue";
var w = 5
context.fillRect(i*w+1,0,w-1,19);
}
</script>
<h4>3 - Canvas Image Manipulation</h4>
<pre>
var img = new Image();
img.src = "http://www.flickr.com/photos/50183640@N05/5616041841/";
img.onload = function() {
context.drawImage(img,0,110);
};
</pre>
<br/>
<canvas id="canvas_ex3" width="200" height="150"></canvas>
<script>
var canvas = document.getElementById("canvas_ex3");
var context = canvas.getContext("2d");
var img = new Image();
img.src = "http://onrails.org/files/20110516_water.jpg";
img.onload = function() {
context.drawImage(img,0,0);
};
</script>
<br/>
<h4>4 - Basic Animation</h4>
In this exercise we first load a new image then trap the keystroke and call the up method. Note we use jquery:<br/>
<pre>
var characters = new Image();
characters.src = "http://onrails.org/files/20110516_characters.gif";
characters.onload = function() {
$(window).keyup(move);
};
</pre>
In the move the x+y coordinates are updated accordingly and is cleared and redrawn.<br/>
<pre>
context.clearRect(0,0,width,height);
context.drawImage(characters,33,0,32,32,x,y,32,32);
</pre>
Use the left and right arrow keys<br/>
<p>
<canvas id="canvas_ex4" width="450" height="150"></canvas>
<script src="http://onrails.org/files/jquery-1.5.2.js" ></script>
<script>
function Exercise4() {}
Exercise4.prototype.run = function() {
var canvas = document.getElementById("canvas_ex4");
var context = canvas.getContext("2d");
var characters = new Image();
characters.src = "http://onrails.org/files/20110516_characters.gif";
characters.onload = function() {
$(window).keyup(move);
};
var x, y;
x = y = 0;
var height = $(canvas).height();
var width = $(canvas).width();
function move(event) {
switch (event.which) {
case 38:
if (y > 0) { y -= 10; }
break;
case 40:
if (y < height) { y += 10; }
break;
case 37:
if (x > 0) { x -= 10; }
break;
case 39:
if (x < width) { x += 10; }
break;
default:
break;
}
context.clearRect(0,0,width,height);
context.drawImage(characters,33,0,32,32,x,y,32,32);
}
}
var ex4 = new Exercise4();
ex4.run();
</script>
<h4>5 - Fun With Forms</h4>
In this exercise we look at few attributes of the <i>input</i> tag like the <i>placeholder</i> and <i>autofocus</i> attributes.
<pre>
<input id="username" placeholder="Your name" autofocus>
<input id="fn" placeholder="First name">
</pre>
Use the slider below to scale the image:<br/>
<table border="0">
<tr>
<td>
<input id="username" placeholder="Your name"><br/>
<input id="fn" placeholder="First name"><br/>
<input id="ls" placeholder="Last name"><br/>
<input id="ad" placeholder="Address" ><br/>
<input id="size" type="range" min="4" max="320" step="8" value="60">
</td>
<td>
<canvas id="canvas_ex5" width="250" height="250"></canvas>
</td>
</tr>
</table>
<br/>
We listen to the change event of the size input and call the draw() function. Note the last two of the drawImage below is the new width and height which will give us the scaling effect.<br/>
<pre>
<input id="size" type="range" min="4" max="320" step="8" value="60">
</pre>
<pre>
function draw() {
context.clearRect(0,0,width,height);
context.drawImage(characters,33,0,32,32,0,0,sizeAmt,sizeAmt);
}
</pre>
<script>
function Exercise5() {}
Exercise5.prototype.run = function() {
var canvas = document.getElementById("canvas_ex5");
var context = canvas.getContext("2d");
var characters = new Image();
characters.src = "http://onrails.org/files/20110516_characters.gif";
var x, y;
x = y = 0;
var sizeAmt = 60;
var height = $(canvas).height();
var width = $(canvas).width();
var sizeEl = $('#size');
sizeEl.change(function() {
sizeAmt = Number(sizeEl.val());
$('#ad').val(sizeEl.val())
draw5();
});
function draw5() {
context.clearRect(0,0,width,height);
context.drawImage(characters,33,0,32,32,0,0,sizeAmt,sizeAmt);
}
draw5();
}
var ex5 = new Exercise5();
ex5.run();
</script>
<h4>6 - Local Storage</h4>
If you are in Google Chrome press option-command-j to bring up the javascript console. The you can enter key-values pair associated with the page. It's like a client side cookie.<br/>
<pre>
localStorage.setItem('shaz','bot')
localStorage.getItem('shaz')
localStorage.length // return 1
localStorage.clear()
</pre>
<h4>7 - Canvas Cleanup</h4>
The canvas itself can be styled like any element. Here we set a black background:
<p>
<canvas id="canvas_ex4" class="dark-canvas" width="450" height="50"></canvas>
<pre>
canvas {
background-color: black;
}
input { display: block; }
</pre>
<style>
.dark-canvas {
background-color: black;
}
canvas {
background-color: #ccc;
}
input { display: block; }
</style>
<h4>8 - Web Sockets</h4>
That was the fun part of the presentation, mike created the a small <a href="https://github.com/subelsky/html5tutorial/blob/master/server/server.rb">ruby application</a> and had over 200 clients connecting to it. <br/>
Here is an extract of the ruby program:<br/>
<typo:code lang="ruby">
class TutorialServer
def run
EventMachine.run do
EventMachine::WebSocket.start(:host => @host, :port => @port) do |socket|
socket.onmessage do |msg|
@logger.info "received: #{msg}"
broadcast(msg)
end
end
EventMachine::add_periodic_timer(10) { broadcast(JSON.generate({ :type => "ping" })) }
end
end
def broadcast(msg)
@sockets.keys.each { |socket| socket.send(msg) }
end
end
TutorialServer.new('0.0.0.0',8011).run
</typo:code>
Then when the users moved the character image using the keyboard each keystroke was sent to his server.<br/>
<typo:code lang="javascript">
// create the socket
var ws = new WebSocket("ws://exp.subelsky.com:8011");
// sent to position+name to server
ws.send(JSON.stringify({ name: name, x: x, y: y, type: "move" }));
</typo:code>
Ultimately he wanted to drive multiple clients from his server...but we ran out of time to dive into this. <br/>
<h4>And much more..</h4>
Mike covered additionally these topics: Embedded Media, Geolocation, Web Workers, Offline App<br/><br/>
Well that was a couple of hours well spent! Go check out his material on github.<br/>
<h2>Tutorial 2 : Building Bulletproof Views</h2>
Now I'm at a great presentation from John Athayde & Bruce Williams on how to make elegant html, css and javascript. The slides will be posted online. <br/>
Here are some of the topics:<br/>
<ul>
<li>The Art of Template Writing</li>
<li>Nailing Navigation</li>
<li>Maintainable Forms</li>
<li>Don't Fear the Object</li>
<li>Going Mobile</li>
<li>packaging Assets</li>
<li>Questions & Discussion</li>
</ul>
<p/>
And the day is not over...Ignite Rails tonight.<br/>
Enjoy!<br/>
Daniel Wanja
Unboxing Sifteo cubes2011-04-28T00:00:00-07:00http://onrails.org/2011/04/28/unboxing-sifteo-cubes<p>A good friend in Switzerland wanted the sifteo cubs, so I order a started kit for him which I just received. He told me I should check them out, now I want to keep them :-)<br />
They come with a bunch of games but they can also be used as controls for your computer. I’m looking forward to see what new interaction people create with these. I would love to control my home automation with these cubes.</p>
<p>For the very curious (and patient) out there, here is the Uboxing video and the initial setup walk through:</p>
<p><iframe src="http://player.vimeo.com/video/22978760" width="400" height="300" frameborder="0"></iframe></p>
<p>For something more exiting here is David Merrill demo at Ted:</p>
<p><a href="http://www.ted.com/talks/david_merrill_demos_siftables_the_smart_blocks.html">http://www.ted.com/talks/david_merrill_demos_siftables_the_smart_blocks.html</a></p>
<p><object width="446" height="326"><param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"></param><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always"/><param name="wmode" value="transparent"></param><param name="bgColor" value="#ffffff"></param> <param name="flashvars" value="vu=http://video.ted.com/talks/dynamic/DavidMerrill_2009-medium.flv&su=http://images.ted.com/images/ted/tedindex/embed-posters/DavidMerrill-2009.embed_thumbnail.jpg&vw=432&vh=240&ap=0&ti=457&lang=eng&introDuration=15330&adDuration=4000&postAdDuration=830&adKeys=talk=david_merrill_demos_siftables_the_smart_blocks;year=2009;theme=what_makes_us_happy;theme=design_like_you_give_a_damn;theme=the_creative_spark;theme=tales_of_invention;theme=speaking_at_ted2009;theme=what_s_next_in_tech;event=What%27s+Next+in+Tech;tag=Business;tag=Design;tag=TED2009;tag=Technology;tag=art;tag=children;tag=computers;tag=education;tag=invention;tag=music;&preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /><embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="446" height="326" allowFullScreen="true" allowScriptAccess="always" flashvars="vu=http://video.ted.com/talks/dynamic/DavidMerrill_2009-medium.flv&su=http://images.ted.com/images/ted/tedindex/embed-posters/DavidMerrill-2009.embed_thumbnail.jpg&vw=432&vh=240&ap=0&ti=457&lang=eng&introDuration=15330&adDuration=4000&postAdDuration=830&adKeys=talk=david_merrill_demos_siftables_the_smart_blocks;year=2009;theme=what_makes_us_happy;theme=design_like_you_give_a_damn;theme=the_creative_spark;theme=tales_of_invention;theme=speaking_at_ted2009;theme=what_s_next_in_tech;event=What%27s+Next+in+Tech;tag=Business;tag=Design;tag=TED2009;tag=Technology;tag=art;tag=children;tag=computers;tag=education;tag=invention;tag=music;"></embed></object></p>
<p>Check out their Websites <a href="http://www.sifteo.com">www.sifteo.com</a></p>Fuzzy Clock 1.3 for iPad - 9 designer clocks at an awesome price - FREE2011-04-13T00:00:00-07:00http://onrails.org/2011/04/13/fuzzy-clock-1-3-for-ipad-9-designer-clocks-at-an-awesome-price-free<p>Fuzzy Clock is now free. I’ve added three new clocks, a Polar clock from from the <a href="http://raphaeljs.com">Raphaël javascript library</a>, and two others are based on <a href="https://github.com/simonbaird/CoolClock">CoolClock</a>. In addition to three new clocks Fuzzy Clock now has a option to disable the Auto-Lock allowing the clock to run forever on a stand without having the lock screen appear.</p>
<p>Check out this video to see the new features.</p>
<p><iframe src="http://player.vimeo.com/video/22325813?portrait=0" width="400" height="280" frameborder="0"></iframe></p>
<p>Enjoy!<br />
Daniel</p>Journey into Android Development - Part 3 : Flex Development (Adobe AIR for Android)2011-04-10T00:00:00-07:00http://onrails.org/2011/04/10/journey-into-android-development-part-3-flex-development-adobe-air-for-android<p>Ok, today I’m at the 360Flex conference following Brent Arnold’s <span class="caps">AIR</span> for Android presentation. We are playing with the Flex <span class="caps">SDK</span> 4.5 to build an Android app however we had to sign an <span class="caps">NDA</span>, so I cannot say some of the detail unless it’s already on the internet. This said I assume that tomorrow Adobe will announce the official release of Flash Builder 4.5. And a ton’s of information was already published:</p>
<ul>
<li>http://labs.adobe.com/technologies/flex/mobile/</li>
<li>http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+Hero</li>
<li>http://corlan.org/2011/01/12/understanding-flex-mobile-views-and-viewnavigator/</li>
</ul>
<p>Here is TourDeFlex that shows all the capabilities of the Adobe <span class="caps">AIR</span> runtime. <a href="http://www.onrails.org/files/TourDeMobileFlex.apk">Download TourDeFlex</a>. The source code can be found at https://github.com/jamesward/TourDeMobileFlex</p>
<p>In the training we created a small application that checks the capabilities of your device: <a href="http://www.onrails.org/files/DeviceCapabilities.apk">Download DeviceCapabiliites</a> <br />
The application uses the Capabilities api that checks various parameters of your device., such as multi-touch, camera, location. Here is the source code:</p>
<script src="https://gist.github.com/912777.js?file=DeviceCapabilities.mxml"></script><script src="https://gist.github.com/912777.js?file=DeviceCapabilitiesHomeView.mxml"></script><p>Within Flash Builder in the properties of your project you can go to the Flex Build Packaging | Google Android and create a self-signed certificate.<br />
Then you can use the Project | Export Release Build… option to create an .apk file for your project.</p>
<p>The application itself is not that exicting but allowed us to discover how to create <span class="caps">AIR</span> apps for Android using Flex and Flash Builder.</p>
<p>Enjoy!</p>
<p>Daniel.</p>
<p><b><span class="caps">UPDATE</span> (4/10/11):</b> Et voilà Flex 4.5 is <a href="http://www.adobe.com/devnet/flex/articles/introducing-flex45sdk.html">announced</a>, but the final version will only be downloadable early May. Here is a good <a href="http://www.adobe.com/devnet/flex/articles/mobile-development-flex-flashbuilder.html">article on mobile development.</a></p>T3 Metadata Editor - A cool Flex App2011-04-09T00:00:00-07:00http://onrails.org/2011/04/09/t3-metadata-editor-a-cool-flex-app<div style="text-align: center;"><img src="http://www.onrails.org/files/T3ME_ss.png" alt="" width="386" height="458" /></div><p>A lot of my work is for enterprises for software that is hidden behind closed doors but since I started helping out Thought Equity I have a few visible apps under my belt. Just in time for March madness they released a new version of the http://vault.ncca.com, see my last year’s entry on <a href="http://www.onrails.org/2010/03/05/vault-ncaa-com-under-the-hood-of-a-cool-flex-project">“under the hood of a cool flex project.”</a></p><p>And to capture all that meta data regarding games and movies they created a whole server side infrastructure but they also needed a pretty face for all that power and I got lucky to be one of the main coder on the T3 Metadata Editor.</p><p>It’s fun to work on software that ends up in the press, here are a few extracts found on the web:</p><p><a href="http://www.msnbc.msn.com/id/42355987">http://www.msnbc.msn.com/id/42355987</a></p><p>Sony Pictures is utilizing the T3 Metadata Editor to:<br /> • Search by actor, line of dialogue, location, and a range of other parameters so that they can create interactive features that enable fans to search for words within the script and share their favorite moments<br /> • Manage restrictions around product placements, talent clearances, and music in order to dynamically create trailers, clips, and other edits for online promotion, social linking, and targeted ads</p><p>From <a href="http://videonuze.com/blogs/?2011-04-08/Sony-Pictures-Taps-Value-of-Archive-With-Thought-Equity-s-Metadata-Editor/&id=3025">http://videonuze.com/blogs/?2011-04-08/Sony-Pictures-Taps-Value-of-Archive-With-Thought-Equity-s-Metadata-Editor/&id=3025</a></p><p>As Dan Weiner, VP of Marketing and Products at Thought Equity explained, Sony will turn what has been a non-scalable, highly manual process for understanding a film’s music clearances, product placements and talent clearances, among other things, into a technology-driven process. Ellen Goodridge, VP, Global Digital Strategy and Operations at Sony Pictures said frame-level metadata will let it create innovative digital movie extras like search and music playlists that add to the value and relevance of our digital offerings and make digital movie purchases more collectable for consumers. The deal again shows that in the digital age metadata is the coin of the realm.</p><p>You can find out more on the <a href="http://platform.thoughtequity.com/video/home/metadata_services.do">products home’s page</a> :</p><p>A Flex App? Yea, Flex is really cool and allowed us to create a nice visualization of the meta data. For this end I created a custom component that allows to show thousands of entries and annotations visually. The new version in the works support hierarchies and drag and drop editing. As a framework when <a href="http://theaboutbox.com">Cameron</a> started the project he used the Parsley framework as one of the component was developed in pure Actionscript and we thought that Parsley could simplify integration. I still prefer Swiz, but Parsley is working out for this project.</p><p>Thanks again to the awesome team at Thought Equity, this is a fun project!</p><p>Enjoy!</p><p>Daniel Wanja.</p>Journey into Android Development - Part 2 : rooting the gTablet2011-04-07T00:00:00-07:00http://onrails.org/2011/04/07/journey-into-android-development-part-2-rooting-the-gtablet<p class="p1">Before continuing development I want to update the tablet. The cyanogenmod wiki seems a good resource <a href="http://wiki.cyanogenmod.com/index.php?title=Viewsonic_G_Tablet:_Full_Update_Guide">http://wiki.cyanogenmod.com/index.php?title=Viewsonic_G_Tablet:_Full_Update_Guide</a></p><p class="p1">A colleague received a 7" Galaxy Tab today and I must admit it seems a way nicer tablet than the gTablet…but then again I can now hack around. Let’s hope that updating the tablet won’t brick it…Then I couldn’t report much progress on the Android front as my “accountant” wouldn’t let me get another one before a while.</p><p class="p1">Note the wiki mentions to put the files on the root of the device, I did that via <span class="caps">USB</span> transfer.</p><p class="p1">So step 1) download ClockworkMod_Gtab_v08.zip, unzip and copy the recovery folder and update.zip to the root of the internal memory.</p><p class="p1">That worked, also I tried yesterday and push the power button and the volume up button, but that didn’t put me in the recovery mode. But pushing the volume up and power button works</p><p class="p1">Step 2) Flashing CyanogenMod via the Recovery. Note I should try via RomManager.</p><p class="p1"><a href="http://android.d3xt3r01.tk/cyanogen/harmony/update-cm-7.0.0-Beta1-Harmony-signed.zip">http://android.d3xt3r01.tk/cyanogen/harmony/update-cm-7.0.0-Beta1-Harmony-signed.zip<br /></a><a href="http://android.d3xt3r01.tk/cyanogen/gapps/gapps-gb-20110307-signed.zip">http://android.d3xt3r01.tk/cyanogen/gapps/gapps-gb-20110307-signed.zip</a></p><p class="p1">I moved the previous update.zip to a backup folder and just moved the above two files to root of the internal sd card. Then renamed update-cm-7.0.0-Beta1-Harmony-signed.zip to update.zip and rebooted in recovery mode. Selected “apply sdcard:update.zip” from the menu and pressed the home button and selected yes. The install is underway and takes longer than step 1. Rebooting…shoold have booted in recovery mode. Will do it next. Yea the startup logo is already different and show “cyanogen 7”…and loops…and booted. Ok, shutting down once more and restart in recovery mode to “Wipe data/factory reset” and then “Wipe cache partition”. </p><p class="p1">Now I select “Install zip from sdcard” and select the google apps: gapps-gb-20110307-signed.zip.</p><p class="p1">Press the back button and select “reboot system now”. </p><p class="p1">I like it, in the apps there is Terminal Emulator app. Managed to get the wifi connect…and again problems with the security certificate. Is that an android issue, or maybe there is something wrong with my network…I don’t think so. So the OS look way nicer, but still cannot access the Android Market place…the app starts and shutdowns.</p><p class="p1">After a reboot the tablet is stuck in startup mode, shows “<span class="caps">ANDROID</span>” and that’s it. <span class="caps">USB</span> doesn’t connect, so now I have to find another way to get the next update on the tablet. Ok Wiping the data and cache as in step 2 put the tablet back in business.</p><p class="p1">All right that’s it for tonight, I shall check if I can’t find a better rom next.</p>
<p><b><span class="caps">UPDATE</span></b>: (4/10/11) Actually after playing with the Cyanogen I must say it works quite well. I have no problem accessing the drive when connecting the table via <span class="caps">USB</span>. The device is very responsife and I had no issue installing the <a href="http://www.amazon.com/gp/mas/get-appstore/android/ref=mas_em_dl?dl=1">Amazon AppStore</a>. Just download the .apk and moved it to the tablet and Angry Bird here I come.</p>Journey into Android Development - Part 1: the gTablet2011-04-06T00:00:00-07:00http://onrails.org/2011/04/06/journey-into-android-development-part-1-the-gtablet<p>I dabbled a while back with the Android <span class="caps">SDK</span> 1.5 but didn’t pursue that platform back then. With the advent of Amazon’s App Store, a bunch of cool tablets and Honeycomb, I thought it was time to take a Journey into Android land again. </p><p class="p1">Over the next couple of weeks I will report my findings on this blog. I didn’t just want to explore the Android ecosystem from the emulator I wanted a real device. But I also didn’t want to spend $800 or signup for a two year contract, so I went for the cheap gTablet. So here is my first impression.</p><p class="p1">I must admit that I’m an Apple fan boy. I’ve had numerous MacBook, Macs, iPhones, iPads over the years and I will compare exploring the gTablet to my experience with the iPad (one).</p><p class="p1"><strong>First stop, opening the box and starting the gTablet</strong></p><p class="p1">The packaging wasn’t that bad, nothing exciting, just a box. But then starting the gTablet didn’t work, the battery must be empty. So I had to plug it in. It’s a small detail, but let’s move on. I plugged it in and behold, it’s starts. The hardware looks and feels not too bad for the price. The screen get’s smudged with fingers prints pretty fast.</p><p class="p1"><strong>The software</strong></p><p class="p1">Well it runs Android 2.2 and that will be the target of my first application. However the stock software they provide is real crap. Even for a cheap table, the browser is just ridiculous and presents Security Warning for every https page, they don’t even have a proper certificate authority. I won’t go on and tear the rest of the applications to pieces, as I was aware from reading many reviews that the stock software isn’t great and I will try to find a good upgrade. I’ll hilight the process in this column. Ok, just one more critic…when I started the tablet my kids where standing next to me and got really excited as they saw the Angry Birds icon on the desktop. But the app doesn’t start…how disappointing. So my recommendation so far, don’t spend a penny on this tablet <span style="text-decoration: underline;">unless</span> your are ready to update it. It’s not worth the $200 or more dollars like that. </p><p class="p1">Now this said before upgrading I want to see how I can create a simple app and move it onto the tablet. Note I won’t describe the development process, the <span class="caps">SDK</span> and other tools I will use as I will mainly focus on the eco system, like how to move the app on the device, how to get the app into the Amazon app store, can I get apps from the Amazon AppStore onto the device at all? So I’m a total newbie and will share my experience, the ups and downs, the excitement, the hacking, on these pages. So stay tuned…</p><p class="p1"><strong><span class="caps">USB</span> Connection</strong></p><p class="p1">Now onto the fun stuff. I connected the usb call and can see the whole disk system right away…Note sure it’s the whole file system but it’s fun that you can add easily stuff on the tablet:</p><p class="p1"><img src="http://www.onrails.org/files/01_usb_connection.png" alt="usb connection" width="450" /></p><p class="p1">Well, it’s fun to see some of the iPhone restrictions not beeing there. I wonder if the applications must be signed. Also I think to install a new system you can just find a different update.zip file and load it during the boot process…I will try that later. For now let’s see if I can copy a new .apk file directly to the device.</p><p class="p1"><strong>Installing the Android <span class="caps">SDK</span> on my Mac.</strong></p><p class="p1">Before I can install an app, I need to build one. A quick google search and onto http://developer.android.com/sdk/android-2.2.html. The page says "If you are new to Android, <a style="color: #006699;" href="http://developer.android.com/sdk/index.html">download the <span class="caps">SDK</span> Starter Package</a> first.". Let’s do that…<span style="color: #333333; font-family: arial, sans-serif; font-size: 13px; line-height: 16px;"> http://dl.google.com/android/android-sdk_r10-mac_x86.zip. </span>After unziping it create the android-sdk-mac_x86 folder which I move to my /Developer folder.</p><p class="p1"><span style="color: #333333; font-family: arial, sans-serif; font-size: 13px; line-height: 16px;"><span style="font-family: Helvetica, Arial, sans-serif; font-size: 14px; color: #000000; line-height: normal;">Then onto </span></span><span style="color: #333333; font-family: arial, sans-serif; font-size: 13px; line-height: 16px;"><a style="color: #006699;" href="http://developer.android.com/sdk/installing.html">Installing the <span class="caps">SDK</span></a>. </span></p><p class="p1">Well, the instructions says to “On Mac or Linux, open a terminal and navigate to the tools/ directory in the Android <span class="caps">SDK</span>, then execute: android”<span style="color: #333333; font-family: arial, sans-serif; line-height: 17px;">, let’s do that. Well I had to execute “sh android” as the script didn’t have the +x flag set. Ok that opens a ui and I select the <span class="caps">SDK</span> Platform for Android 2.2, <span class="caps">API</span> 8, revision. Later if rooting the gTablet works I will have to get another version, but as the stock software says it’s a 2.2 OS, let try with that <span class="caps">SDK</span>, so I just the the “Install Selected” from the UI. The UI shows the following log:</span><span style="color: #333333; font-family: arial, sans-serif; line-height: 17px;"> </span></p><blockquote><p class="p1">Downloading Android <span class="caps">SDK</span> Platform-tools, revision 3<br /> Installing Android <span class="caps">SDK</span> Platform-tools, revision 3<br /> ‘adb kill-server’ failed — run manually if necessary.<br /> Installed Android <span class="caps">SDK</span> Platform-tools, revision 3<br /> Downloading <span class="caps">SDK</span> Platform Android 2.2, <span class="caps">API</span> 8, revision 2<br /> Installing <span class="caps">SDK</span> Platform Android 2.2, <span class="caps">API</span> 8, revision 2<br /> Installed <span class="caps">SDK</span> Platform Android 2.2, <span class="caps">API</span> 8, revision 2<br /> ‘adb kill-server’ succeeded.<br /> <span class="caps">ADB</span>: * daemon not running. starting it now on port 5037 *<br /> ‘adb start-server’ succeeded.<br /> <span class="caps">ADB</span>: * daemon started successfully *</p><p></blockquote><p class="p1">And mentions that “Done, 2 packages installed”. </p><p class="p1"><strong>Building a first app using Appcelerator’s Titanium</strong></p><p class="p1">Well, I’ve an app that I wrote for the iPhone, I would like to see if Titanium’s cross platform premise holds. Let see what I need to sweat to get it running on the gTablet…First step let’s add the <span class="caps">SDK</span> to Titanium. My app was an “iPad” app to Titanium doesn’t even want to know about the Android <span class="caps">SDK</span>. So let’s create a new “Mobile” <span class="caps">SDK</span>…Hey, it finds an Android 1.6 <span class="caps">SDK</span>…I must have dabbled with that a while back. Finnally found the following on Appcelerator’s support pages "I<span style="color: #1d1d1d; font-family: 'Trebuchet MS', Tahoma, Arial, sans-serif; line-height: 20px;">f you’re installing the Android <span class="caps">SDK</span>, make sure to install the Platform-tools package, and as usual you will need the Google APIs Add-on". Ok, then let’s try that.</span></p><p class="p1">10pm and the kids go swiming early in the morning, so I’ll wrap up this experiment and continue over the next few days. </p><p class="p1">… to be continued</p><p> </p><p class="p1"> </p><p class="p1"><span style="color: #333333; font-family: arial, sans-serif; line-height: 17px;"><br /> </span></p><p class="p1"> </p><p class="p1"> </p><p class="p1"> </p></p>iPhone App: Mi-Fi 1.2 now with iOS 4.x support. A must have if you have an Mifi card.2010-10-13T00:00:00-07:00http://onrails.org/2010/10/13/iphone-app-mi-fi-1-2-now-with-ios-4-x-support-a-must-have-if-you-have-an-mifi-card<div style="float:left; padding: 15px;">
<p><img src="http://www.onrails.org/files/mifi12.jpg" alt="mifi12.jpg" border="0" height="250" align="left" /><br />
<a href="http://itunes.apple.com/app/mi-fi/id333601535?mt=8"><br />
<img src="http://www.onrails.org/files/marketing_badge.png" alt="marketing_badge.png" border="0" width="121" height="61" align="left" /><br />
</a></p>
</div>
<p>I created the MiFi app during the 360iDev conference on September 29th 2009 and submitted the app the same day. I released a fix a month later and didn’t touch the application since. I wasn’t using my Mifi card much until recently when I realized that the app wasn’t working on iOS 4.1. Then I checked the comments for the Mi-Fi app on the AppStore and realized that there where hundreds of comments of people that have the same issue. Sorry for being so late to realize that. Once I found that out I had to decide wether to remove the application from the store or fix it. So I reopened the project and realized that the way it was written wouldn’t work in the new Titanium <span class="caps">SDK</span>. Despite of the work I decided to rewrite/reorganized the code and voila…Mi-Fi 1.2 for iOS 4.1 should now work better than ever. I did not restyle the application, it could look better but it’s still functional. I also didn’t add any feature but at least you should get the battery and reception levels that are the most important features. Another feature I should add soon is to be able to set the ip address of your Mi-Fi card in case you changed from the default address.</p>
<p>What is stranger to me is how many people downloaded the application, knowing that it didn’t work on iOS4. About 400 downloads a week…man.. many people must be wondering what this application does and in fact did, as the reviews show. Well, that should be fixed. Sorry for the delay! Here is the weekly sales trend:</p>
<p><br/>
<div style="text-align:center;"><img src="http://www.onrails.org/files/20101012MiFiWeeklySales.png" alt="20101012MiFiWeeklySales.png" border="0" width="450" /></div></p>
<p>I also saw someone created a $2.99 version of the same app called MyMiFi it does the same thing but it has a nicer design I would say. Maybe I should give “paid” a try and will release this one for $.99 cents….or should I? The fact is that I really don’t care about selling 10 apps or even 100 apps at $.99…I maybe wouldn’t say the say if I sold 1000…So free it stays.</p>
<p>Now internally I had to rewrite the application as somehow the Titanium <span class="caps">SDK</span> changed enough that I couldn’t get it to work. So the new code is also a lot cleaner, so maybe I could add a few features soon:</p>
<p>In short this is the app.js</p>
<typo:code lang="javascript" title="app.js">
<p>Titanium.include(‘resource.js’);<br />
Titanium.include(‘parser.js’);<br />
Titanium.include(‘controller.js’);</p>
<p>var controller = new Controller();<br />
controller.start();</p>
<p>var webview = Titanium.UI.createWebView({url:‘index.html’, controller:controller});<br />
var window = Titanium.UI.createWindow({fullscreen: true });<br />
window.add(webview);<br />
window.open();</p>
</typo:code>
<p>As you see it loads the index.html which renders the main view. Index.html loads index.js which declares a listener to the update_view event.</p>
<typo:code lang="javascript">
<p>Ti.App.addEventListener(‘update_view’,function(e) {<br />
//..update the view using jquery based on e.state and e.info<br />
})</p>
</typo:code>
<p>The controller class checks every two seconds the state of the mifi card by getting the mifi status on the following url: “http://192.168.1.1/getStatus.cgi?dataType=<span class="caps">TEXT</span>”. It then parse the data (different for each version of the card) and creates a unified javascript structure and fire the update_view event:</p>
<typo:code lang="javascript">
Titanium.App.fireEvent(‘update_view’, {state:this.currentState, info:info});
</typo:code>
<p>To make the calls to the mifi card I wrote a Resource class that abstracts the xhr request</p>
<typo:code lang="javascript">
this.mifi = new Resource(“http://192.168.1.1/getStatus.cgi?dataType=<span class="caps">TEXT</span>”);
this.mifi.index(this.mifiResult.bind(this));
</typo:code>
<p>Internally the resource uses the createHTTPClient and makes a standard ajax get call. I haven’t tried to use jquery’s .get function directly but assume it may not work with Titanium without some hacking…</p>
<typo:code lang="javascript">
var xhr = Titanium.Network.createHTTPClient();
xhr.open(“<span class="caps">GET</span>”, url);
xhr.send();
</typo:code>
<p>So Titanium rocks and works pretty well, at least for many iPhone apps. Now let’s see how long it takes for the approval of another app that I submitted yesterday….</p>
<p>Enjoy!<br />
Daniel Wanja</p>Making CRUD less "Cruddy", one step at a time 2010-10-04T00:00:00-07:00http://onrails.org/2010/10/04/making-crud-less-cruddy-one-step-at-a-time<p>One of the great “new” features of Rails (as of 2.3) is <code>accepts_nested_attributes_for</code>, allowing you to build cross-model <span class="caps">CRUD</span> forms without “cruddying” your controller. There are some great examples out there about <a href="http://weblogs.manas.com.ar/spalladino/2010/03/03/handling-children-with-accepts_nested_attributes_for-in-rails/">how to</a> <a href="http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes">do</a> <a href="http://github.com/alloy/complex-form-examples">this</a>, but I’d like to walk thorough a particular use case — managing the “join” records in a <code>has_many :through</code> relationship.</p>
<p>Consider the following database schema:</p>
<typo:code lang="ruby">
<p>class Villain < ActiveRecord::Base<br />
has_many :gifts<br />
has_many :super_powers, :through => :gifts<br />
end</p>
<p>class Gift < ActiveRecord::Base<br />
belongs_to :villain<br />
belongs_to :super_power</p>
validates_uniqueness_of :super_power, :scope => :villain_id
<p>end</p>
<p>class SuperPower < ActiveRecord::Base<br />
has_many :gifts<br />
has_many :villains, :through => :gifts<br />
end</p>
</typo:code>
<p>In our dataset, there are a relatively small number of super powers which we wish to present as a list of checkboxes on the villain management form. Checking/unchecking the boxes will manage the gift records for that villain, effectively managing the list of super powers available to the baddy.</p>
<p>To get started, we need to add <code>accepts_nested_attributes_for :gifts</code> to the Villain class — piece of cake. To complete the implementation, we need to change the <code>params</code> hash that our form generates. Let’s review the cases that we need to support and the associated <code>params</code> hash format needed to implement the correct functionality.</p>
<p>The first case is a super power record that is not currently associated with the villain. Here, the UI should display an unchecked checkbox. If we check it and submit the form, a gift record should be created linking the villain with the super power, making this bad guy that much badder. Here is an example of the <code>params</code> hash we should be sending to accomplish this:</p>
<typo:code>
{
‘villain’ => {
‘name’ => ‘Lex Luthor’,
…
‘gifts_attributes’ => {
1 => { ‘super_power_id’ => 5 },
2 => { ‘super_power_id’ => 7 },
…
}
}
}
</typo:code>
<p>The alternate case is a super power this villain already possesses. In this instance, the UI should display a checked checkbox, and if we uncheck it, the existing <code>gift</code> record should be deleted, diminishing the villain’s capacity for evil. And our <code>params</code> hash needs to look like:</p>
<typo:code>
{
‘villain’ => {
‘name’ => ‘Two-Face’,
…
‘gifts_attributes’ => {
1 => { ‘id’ => 101, ‘_delete’ => true },
…
}
}
}
</typo:code>
<p>Note that the keys for the <code>gifts_attributes</code> hash are arbitrary; we can use any scheme to generate unique keys for the hash.</p>
<p>So how can we craft a form that sends the <code>params</code> hash that Rails wants to see? Here’s my implementation:</p>
<typo:code lang="ruby">
<%- SuperPower.all.each_with_index do |super_power, index| -%>
<label>
<%- if gift = @villain.gifts.find_by_super_power_id(super_power.id) -%>
<%= hidden_field_tag “villain[gifts_attributes][#{ index }][id]”, gift.id %>
<%= check_box_tag “villain[gifts_attributes][#{ index }][_delete]”, false, true %>
<%= hidden_field_tag “villain[gifts_attributes][#{ index }][_delete]”, true %>
<%- else -%>
<%= check_box_tag “villain[gifts_attributes][#{ index }][super_power_id]”, super_power.id %>
<%- end -%>
<%= super_power.name %>
</label><br />
<%- end -%>
</typo:code>
<p>If the gift is detected, the villain has the super power, and we handle our second case from above, using the checkbox / hidden field hack Rails employs in the <code>check_box</code> helper method to make sure a value is sent whether or not the checkbox is checked. The else block handles the other case, setting up our <code>params</code> hash to create the gift if the checkbox is checked.</p>
<p>This works, but we probably don’t want to copy and paste that code everywhere we use this pattern. How can we reuse this in a <span class="caps">DRY</span> fashion? Here’s a helper method that encapsulates the logic:</p>
<typo:code lang="ruby">
def has_join_relationship(model, join_collection_name, related_item, collection_index, options={})
returning "" do |output|
relationship_name = options[:relationship_name] || related_item.class.table_name.singularize + “_id”
tag_prefix = “#{ model.class.class_name.underscore }[#{ join_collection_name }_attributes][#{ collection_index }]”
if join_item = model.send(join_collection_name).find(:first, :conditions => { relationship_name => related_item.id })
output << hidden_field_tag(“#{ tag_prefix }[id]”, join_item.id)
output << hidden_field_tag(“#{ tag_prefix }[_delete]”, true)
output << check_box_tag(“#{ tag_prefix }[_delete]”, false, true)
else
output << check_box_tag(“#{ tag_prefix }[#{ relationship_name }]”, related_item.id, false)
end
end
end
</typo:code>
<p>Drop that in a helper, and then your form code becomes:</p>
<typo:code lang="ruby">
<%- SuperPower.all.each_with_index do |super_power, index| -%>
<label>
<%= has_join_relationship(@villain, :gifts, super_power, index) %>
<%= super_power.name %>
</label><br />
<%- end -%>
</typo:code>
<p>Much nicer … although I’m not sold on the name <code>has_join_relationship</code>. Any suggestions?</p>
<p><strong><span class="caps">UPDATE</span>:</strong> There was a problem with the published code, which I corrected — sorry about that.</p>
<p><strong><span class="caps">RAILS</span> 3 <span class="caps">UPDATE</span>:</strong> To get the code above to work with Rails 3 / Ruby 1.9.2, I had to change <code>class.class_name</code> to <code>class.name</code>, and call <code>.html_safe</code> on the initial string so that it would not get escaped.</p>Good RobotLeg presentation at 360Flex2010-09-28T00:00:00-07:00http://onrails.org/2010/09/28/robotleg-keypoints<p>Paul Robertson gave a RobotLeg presentation at 360Flex and put his slides online. I had to dive into a RobotLeg application the other and wanted a refresher and found his slides really great so I’ve extracted for your (and my) convenience some useful bullets points:</p>
<ul>
<li>View
<ul>
<li>the View is represented by your view components and their Mediators</li>
<li>Mediators provide <span class="caps">API</span> for view components</li>
<li>Mediators listen for view component events</li>
<li>Mediators listen for framework events</li>
<li>Mediators dispatch framework events</li>
<li>view components are not coupled to their Mediators</li>
<li>Mediators are coupled to their view components</li>
<li>Mediators can access Service and Model classes directly</li>
</ul></li>
</ul>
<ul>
<li>Actor
<ul>
<li>Actor is the base class for Model and Service classes</li>
<li>eventDispatcher is injected into Actor</li>
<li>Actor provides a dispatch(event) method</li>
<li>Actor is for your convenience</li>
</ul></li>
</ul>
<ul>
<li>Model
<ul>
<li>Models extend Actor</li>
<li>Models provide an <span class="caps">API</span> for data</li>
<li>Models sit between application data and other actors</li>
<li>Models should not listen for framework events</li>
<li>Models dispatch framework events</li>
</ul></li>
</ul>
<ul>
<li>Service
<ul>
<li>Services extend Actor</li>
<li>Services usually implement an interface</li>
<li>Services communicate with the outside world and provide an <span class="caps">API</span> to external services</li>
<li>Services can parse results from external services</li>
<li>Services do not store data</li>
<li>Services do not receive framework events</li>
<li>Services dispatch framework events</li>
</ul></li>
</ul>
<ul>
<li>Controller
<ul>
<li>represented by the Command class</li>
<li>Commands are executed in response to framework events</li>
<li>Commands are stateless</li>
<li>Commands perform work on Service and Model classes and dispatch events (call other commands)</li>
<li>Commands receive data from the events that trigger them</li>
<li>Commands dispatch framework events</li>
<li>Commands do not receive framework events</li>
</ul></li>
</ul>
<p>You can get the slides <a href="http://probertson.com/resources/2010/09/21/Robotlegs_360Flex_2010_DC.pdf">here</a> and also checkout <a href="http://probertson.com/articles/2010/09/21/robotlegs-hands-on-training-slides-and-examples/">his blog entry</a> for more info.</p>
<p>These days everyone has his preferred Flex framework. Mine is still <a href="http://swizframework.org/">Swiz</a> as it doesn’t impose a structure like Cairgorm or RobotLeg. I’ve also just started on a new project that uses <a href="http://www.spicefactory.org/parsley/">Parsley</a>, so I’ve soon done them all!</p>
<p>Enjoy!<br />
Daniel</p>Moving (again) http://onrails.org from Heroku to EC22010-09-20T00:00:00-07:00http://onrails.org/2010/09/20/moving-again-http-onrails-org-from-heroku-to-ec2<p>If you read this then this blog is now running Typo 5.5 on Rails 2.3.9 on EC2.</p>
<p>I really love the ease of deployment to heroku and the fact that they manage the whole stack. However I receive regularly emails from Heroku stating that I get a specific number of “backlog too deep errors” indicating the app is receiving more requests than it is capable of responding to, or in other words that that my blog is outgrowing their developer instance. So I have the option to increment the number of requests my application can handle, which is easy thanks to the the heroku command line: heroku dynos +1 —app onrails. So I can increase the <span class="caps">HTTP</span> performance by cranking up the “dynos” to 2 which would be an additional $36 a month. I still think it’s a good deal for a managed environment.</p>
<p>However you also saw on my <a href="http://onrails.org/2010/07/12/moving-http-onrails-org-to-typo-5-4-x-rails-2-3-8-on-heroku">last blog entry</a> that there are other issues with running Typo on Heroku and therefore I started playing with running Rails on EC2. And I like what I see and now that Amazon has an official and secured Amazon Linux <span class="caps">AMI</span>, I’ll be using that. Here are a few notes on how I did set it up.</p>
<p>I started with the new Basic 32-bit Amazon Linux <span class="caps">AMI</span> 1.0 (http://aws.amazon.com/amazon-linux-ami/). I take basically only a few clicks to get a server started. You can use the ec2 console (https://console.aws.amazon.com/ec2) to create and connect to the server, however you need to use ec2-user instead of root to connect due to the way the Amazon Linux <span class="caps">AMI</span> is setup.</p>
<p>Note Lee is right that if I continue to moving host I should create a Chef recipe for this.</p>
<p><strong>Install dev tools</strong></p>
<p>$ sudo yum install git<br />
$ sudo yum install make gcc-c++ zlib-devel openssl-devel<br />
$ sudo yum install ruby-devel ruby-libs ruby-mode ruby-rdoc ruby-irb ruby-ri ruby-docs</p>
<p><strong>Install MySQL</strong></p>
<p>$ sudo yum install mysql mysql-server<br />
$ sudo /etc/init.d/mysqld restart<br />
$ mysql_secure_installation<br />
$ sudo yum install mysql-libs mysql-devel</p>
<p><strong>Install ruby-mysql</strong></p>
<p>$ sudo gem install mysql —no-ri —no-rdoc</p>
<p><strong>Install rubygems</strong></p>
<p>$ wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.7.zip <br />
$ tar xzvf rubygems-1.3.7.tgz<br />
$ cd rubygems-1.3.7<br />
$ sudo ruby setup.rb<br />
$ cd ..</p>
<p><strong>Install Rails (note I use 2.3.9 for Typo )</strong></p>
<p>$ sudo gem install rails —no-ri —no-rdoc<br />
$ sudo gem install rails —no-ri —no-rdoc -v=2.3.9</p>
<p><strong>Install Apache (2.2.15</strong>)</p>
<p>$ sudo yum install httpd</p>
<p><strong>Install Passenger</strong></p>
<p>$ sudo gem install passenger —no-ri —no-rdoc <br />
$ sudo yum install httpd-devel<br />
$ passenger-install-apache2-module</p>
<p><strong>Configure Passenger</strong></p>
<p>nano /etc/httpd/conf/httpd.conf</p>
<typo:code lang="ruby">
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15
PassengerRuby /usr/bin/ruby
</typo:code>
<p>Suppose you have a Rails application in /somewhere. Add a virtual host to your<br />
Apache configuration file and set its DocumentRoot to /somewhere/public:</p>
<typo:code lang="xml">
<VirtualHost *:80>
ServerName www.yourhost.com
DocumentRoot /somewhere/public
<Directory /somewhere/public>
AllowOverride all
Options -MultiViews
</Directory>
</VirtualHost>
</typo:code>
<p><strong>Installing Typo (from source)</strong></p>
<p>see http://wiki.github.com/fdv/typo/install-typo-from-sources</p>
<p>$ wget http://rubyforge.org/frs/download.php/71779/typo-5.5.zip</p>
<p>then unzip, that’s it. That’s your typo instance, now let’s configure it’s database.<br />
Note I moved it to /var/www/typo/</p>
<p>Create config/database.yml i.e.<br />
<code>production
adapter: mysql
host: localhost
username: yourusername
password: secret
database: onrails_prod</code></p>
<p>Change the Rails version in config/environment.rb, replace 2.3.8 with 2.3.9</p>
<p>RAILS_GEM_VERSION = ‘2.3.8’ unless defined? RAILS_GEM_VERSION</p>
<p>setups gems required for Typo:<br />
$ sudo rake gems:install</p>
<p><strong>Creating/Copying database:</strong></p>
<p>Note I migrated my blog so I need to copy the database to the new server.</p>
<p>$ scp -i .ssh/linux_ami.pem onrails_org.sql ec2-user@ec2-184-73-20-188.compute-1.amazonaws.com:onrails_org.sql<br />
$ mysql -u yourusername -p<br />
create database onrails_prod;<br />
exit<br />
$ mysql -u yourusername -p onrails_prod < onrails_org.sql</p>
<p>As I also update Typo to a new version I had to run a migration:</p>
<p>$ rake db:migrate RAILS_ENV=production</p>
<p>Note if you want a clean install you can just to a rake db:create and rake db:migrate.</p>
<p>Et voila! Well Heroku made it simpler but I always have fun playing with EC2.</p>
<p>Enjoy!<br />
Daniel</p>Moving onrails.org to Typo 5.4.x, Rails 2.3.8 on Heroku2010-07-12T00:00:00-07:00http://onrails.org/2010/07/12/moving-http-onrails-org-to-typo-5-4-x-rails-2-3-8-on-heroku<p>
<p>So why Heroku and why not leave my server on slicehost? I don't have any issue with the slice but I want to upgrade the version of Typo just to stay uptodate and while at it wanted to explore a little. So of course I found an article on <a href="http://joelgreutman.com/2010/05/21/getting-typo-5-4-running-on-heroku">Getting Typo 5.4 running on Heroku</a> So I gave it a try. The interesting part is that <a href="http://onrails.org">onrails.org</a> has been around since forever and I also had tomigrate the database. Onrails.org was running on a version of Typo 4. h2. setting the blog up locally First I've downloaded my older typo MySQL database and restored it locally. I've copied Typo from <a href="http://rubyforge.org/frs/download.php/70057/typo-5.4.4.zip">here</a> or you can clone the Typo git repository.</p><br />
<pre>$ git clone http://github.com/fdv/typo.git <br />
</pre><br />
<p><br />
I changed the database.yml to point to my database. Did a rake gems:install, followed by a rake d:migrate and had now a local install of my blog. h2. creating a heroku app The goal was to try to deploy the blog to heroku. So here you can create an empty</p><br />
<pre>$ heroku create onrails<br />
git@heroku.com:onrails.git<br />
$ git init<br />
$ git add .<br />
$ git commit -m "Adding onrails.org using typo 5.4.4"<br />
</pre><br />
<p><br />
I then followed joels' <a href="http://joelgreutman.com/2010/05/21/getting-typo-5-4-running-on-heroku"> article</a> to "heroku"fy Typo. So I basically created afew empty folders and replaced FileUtils by FileUtils::NoWrite. Note sure if that last change would cripple Typo but things seems to work fine. Then I created a .gems files that is used by heroku instead of Bundler.</p><br />
<pre>.gems<br />
rails = 2.3.8<br />
htmlentities <br />
json <br />
calendar_date_select <br />
bluecloth ~> 2.0.5<br />
coderay ~> 0.8<br />
mislav-will_paginate ~> 2.3.11 —source gems.github.com<br />
RedCloth ~> 4.2.2<br />
panztel-actionwebservice = 2.3.5<br />
addressable ~> 2.1.0<br />
mini_magick ~> 1.2.5<br />
</pre><br />
<p><br />
Finally I deployed the app with an empty database:</p><br />
<pre>$ git remote add heroku git@heroku.com:onrails.git<br />
$ git push heroku master<br />
$ heroku rake db:migrate # with empty db<br />
</pre><br />
<p><br />
That's it that gets you an install of Typo on Heroku. Note, keep reading for a few gotcha's I found in regards to Rails 2.3.8. h2. Rails 2.3.8 on heroku At the time of this writing Rails 2.3.8 wasn't the default on Heroku, but fortunaely they support a different stack with Rails 2.3.8. To switch I just had to do the following:</p><br />
<pre>$ heroku stack:migrate bamboo-ree-1.8.7<br />
</pre><br />
<p><br />
h2. Migrating the local MySQL database to Heroku's Postgres database. It's a rather straight forward process…just do</p><br />
<pre>$ heroku db:push<br />
</pre><br />
<p><br />
This converted the database and replaced the remote database with my local data on Heroku. It converts my MySQL database to a Postgress database without having to speify anything…But there was on gotcha. The Sidebar table id column turned out as "text" instead of an "integer". And this caused some of the admin functionality to fail, i.e. reconfiguring the sidebar. The other tables where converted correctly and I saw that the local Sidebar id column was slightly different than the other id columns. For some reasons the sidebar table id column type was a "signed int' and that translated to a text field when doing the db:push. So I just unchecked the signed flag ad the db:push went smoothly. h2. legacy permalinks Somehow the articles and category links are all prefixed with "/articles" on onrails.org. I don't know if that was due to some default setting in Typo 4 or due to the fact that I started with a way earlier version of Typo. In any case I preferred to use the new links formats that just drops the "/articles", but that would also mean breaking a lot of incoming links. So I just configured Typo to support the legacy permalinks via these addd routes <typo:code> # Legacy permalink format support map.connect '/articles/:year/:month', :controller => 'articles', :action => 'index', :year => /\d{4}/, :month => /\d{1,2}/ map.connect '/articles/:year/:month/page/:page', :controller => 'articles', :action => 'index', :year => /\d{4}/, :month => /\d{1,2}/ map.connect '/articles/:year', :controller => 'articles', :action => 'index', :year => /\d{4}/ map.connect '/articles/:year/page/:page', :controller => 'articles, :action => 'index', :year => /\d{4}/ # Legacy permalink format support map.resources :categories, :except => [:show, :update, :destroy, :edit], :path_prefix => '/articles' map.resources :categories, :as => 'category', :only => [:show, :edit, :update, :destroy], :path_prefix => '/articles' map.connect '/articles/category/:id/page/:page', :controller => 'categories', :action => 'show' </typo:code> Now the blog supports both new and old formats. Note that the url fo the articles can be modified in the settings, but I didn't find settings for the category permalinks and supporting both old and new format gives me a smooth transition forward. h2. Rails and Issue with Typo workaround? I was getting the following error when doing certain actions on the blog: <typo:code> ActionView::TemplateError (undefined method `interpolate_without_deprecated_syntax' for #<i18n::backend::simple:0x2b8d1ef90700>) on line #5 of themes/scribbish/views/articles/<em>coment.html.erb: </i18n::backend::simple:0x2b8d1ef90700></typo:code> So I assumed this was some compatibility between Typo and Rails and Typo had a workaround defined in the environment.rb file file. As I use Rails 2.3.8 I disabled that workaround and everything seems to work again: So I just removed the followed lines from the enviroment.rb file:</p><br />
<pre>environment.rb<br />
class I18n::Backend::Simple<br />
def interpolate(locale, string, values = {})<br />
interpolate_without_deprecated_syntax(locale, string, values)<br />
end<br />
end<br />
</pre><br />
<p><br />
h2. custom domain I'm sure there are a few more details I missed and hope my readers will point them out, but let's jump and turn the switch on. So you need to switch on custom domains on heroku as follows:</p><br />
<pre>$heroku addons:add custom</em>domains<br />
$ heroku domains:add www.onrails.org<br />
Added www.onrails.orgas a custom domain name to onrails.heroku.com <br />
$ heroku domains:add onrails.org<br />
Added onrails.orgas a custom domain name to onrails.heroku.co<br />
</pre><br />
<p><br />
Then I went on to pointed my dns to Heroku. The move is complete but the dns change to point to heroku still may take some time. So if you see the Scribbish theme you are still on the old server and if you see the Elegant Grunge theme you are right here on Heroku. Enjoy, Daniel <b><span class="caps">UPDATE</span> 1:</b> the dns updated www.onrails.org and onrails.org at different time. And all the images of the new sites where using urls of the old site and everything looked pristine. No mre…So a hidden issue is that Typo let's you upload files like images which are stored in the resources table and also copied to to the public/files folder. This is a convenient way to serve files and images for your blog entries. Well, that won't work very well while on heroku especially since we really made the file system read only. I need to read more on how to enable page caching on Heroku and see if it is compatible with Typo. If not… I will need to revert back to my previous host. For now I'll jst add the files via git…and that's not a solution.</p></p>RailsConf 2010 - Thank You!2010-06-10T00:00:00-07:00http://onrails.org/2010/06/10/railsconf-2010-thank-you<p>Wow, RailsConf is over. It ended nicely with <a href="http://twitter.com/@garyvee">@garyvee</a> giving a powerful and entertaining keynote covering many subjects but mostly his standard spiel on connecting with your customers or audience. I read his book, crush it, a while back and enjoyed it. Note since, I haven’t been the most active on my blog or website…but I’m working on changing this.</p>
<p>Now of course RailsConf was way more that this keynote. I must admit I really enjoyed Baltimore and having the convention center, the hotel and the port at a five minutes walking distance. It’s a great area, I understand that not the whole city is like that, but that doesn’t remove anything from the fact that I really appreciate the place right now.</p>
<p>The best thing at this conference is the energy that transpires and I really feel energized and want to start some new Rails venture. It’s fun to see so many enthusiasts trying to learn, share, and push the community forward.</p>
<p>I must admit I usually enjoy smaller conferences, like the <a href="http://mtnwestrubyconf.org">MoutainWest RubyConf</a> or the forthcoming <a href="http://mountainrb.com">Moutain.rb</a>, better as the tracks are more specialized and geekier. RailsConf tries to have several tracks for everybody but very few are very technical. Maybe the organizers should try to have an advanced track next time. That way the conference would stay appealing for the many people that have been doing Rails/Ruby for years and still be welcoming for beginners.</p>
<p>As usual there are always some talks that just suck. On the tutorial day I attended in the afternoon <a href="http://en.oreilly.com/rails2010/public/schedule/detail/13631">Rails 3 Deep Dive</a> and it wasn’t about Rails 3 nor a deep dive. Another talk that didn’t turn out the way it should have been was <a href="http://en.oreilly.com/rails2010/public/schedule/detail/11230">Scaling Rails on AppEngine with JRuby and Duby</a> where the speakers where knowledgeable but where note prepared enough and where counting on the wifi to work…The wifi never works at conference. This said the wifi was usually working pretty well at RailsConf this time.</p>
<p>I don’t wanna focus too much on the talks that didn’t work out as most of the talks where great and also not all my talks in the past always worked out they way they could have ;-)</p>
<p>One of the tutorial I really liked was <a href="http://en.oreilly.com/rails2010/public/schedule/detail/13613">Acceptance Testing With Cucumber</a>. David Chelimsky rocked and just knows his stuff and Aslak hanged in there pretty well. They had an application prepared with multiple branches that let the audience follow right along. That was great. They didn’t have time to access a few of the advanced Cucumber subjects…next time make that a full day tutorial.</p>
<p>The first talk I attended on tuesday was <a href="http://en.oreilly.com/rails2010/public/schedule/detail/14502">Building an <span class="caps">API</span> with Rails</a> which was a panel discussion with guys from Twitter, 37Signals, Github, the <span class="caps">NYT</span> and others. I really enjoyed that there was several distinct views on several aspects like on APIs like versioning, security, performance which relates exactly with some customer work I’m currently doing.</p>
<p>Then I went to the Metrics Magic by Aaron Bedra from Relevance which cover tools like RCov,Flog, Flay, Roodi, Reek and how to integrate them with your continuous integration build. For example why don’t you make your build fail when it reaches a certain threshold of uncovered code (let’s say 20%)…I like that idea. We do generate these stats in our ci builds but don’t fail the builds…yet.</p>
<p>Another great panel on tuesday was <a href="http://en.oreilly.com/rails2010/public/schedule/detail/13258">The State of Rails e-Commerce</a>. I’m interested in ecommerce since <a href="http://onrails.org/articles/2006/04/27/an-ecommerce-platform-in-ruby-on-rails">the first of Rails project</a> I worked on end of 2005.</p>
<p>Then I went to see <a href="http://www.igvita.com/">Ilya Grigorik</a> talk on “No callbacks, no threads: async & cooperative web servers with Ruby 1.9”…I just wish all the task where that awesome…Ilya tries to push the current stack of Ruby technologies to the next step to try to get the same benefits than what node.js provides…and he showed us how. Wow.</p>
<p>I’m not gonna list all the talks I attended here, but will provide a few more comments. There where two business oriented talks I enjoyed, the Million Dollar Mongo by Obie Fernandez and Durran Jordan from Hashrocket and the Agile the Pivotal Way talk by Ian MCFarland. Ian’s presented how his teams operates and I now see why Pivotal is on such a growth path. There are many cool aspects they are enforcing, one key I believe is to have really agile team members than can switch in an out of each team while still providing continuity to the customer by having one anchor member. Another essential aspect is the culture and how they propagate it buy doing peer programing to the extreme. Obie’s talk was an interesting retrospective on a very large project (10’0000 hours) they undertook. What surprised me is that he was pretty negative on his client and also went after some members of the Rails community…Well, maybe Hashrocket should stick to smaller projects ;-)</p>
<p>What else was cool? Rich Kilmer gave a nice talk about Authentication in a RESTful World. Again, that’s totally relevant to a customer project of mine. One of the best talks out there was <a href="http://en.oreilly.com/rails2010/public/schedule/detail/14404">Rocket Fueled Cucumbers</a> by Joseph Wilk, but I saw only the last quarter as I selected another talk that I decided to leave…too late.</p>
<p><a href="http://twitter.com/mdeiters">Matthew Deiters</a> also gave a presentation I really enjoyed about “Recommendations in Rails”…something I may have to build in one of my apps very soon. I’m less exited about the fact that he recommends a java tool (Neo4j) to manage your graph of relations…but I trust him that it’s the best of the solutions out there for now.</p>
<p>Besides the talks <a href="http://www.blueboxgrp.com/">Bluebox</a> threw a party at a local bar, besides the fact that <a href="http://www.liquidrail.com">Fernand</a> managed to get us lost on they way and I wasn’t sure we would survive the neighborhood we ended up in…the party was great and we met one of the Bluebox software developers and her mam and had a great time. At least I think so based on the trouble I had to wake up the next day.</p>
<p>I had fun with the keynotes. Derek Sivers gave a talk which I enjoyed even though it was not related to Rails but it was very entertaining. I really liked Yehuda Katz talk and he his certainly the driving factor behind Rails 3 but he gave a lot of credits to specific members of the community which took on many issues that most thought where impossible to address or change and fixed them.</p>
<p>The Ruby Heroe Awards Ceremony is always fun to watch, and Gregg puts lots of effort into making them happen. Next time just let the winners make a thank speech…that would stress them a little.</p>
<p>Overall there wasn’t enough coverage of Rails 3, I guess that’s gonna for next year when everyone migrated all there projects to it.</p>
<p>So reflecting on these 4 past days…it was a great conference. A big thanks to the organizers and all the presenters</p>
<p>Now time to kick off a new Rails 3 project.</p>
<p>Enjoy!<br />
Daniel</p>RailsConf 2010 - Baltimore2010-06-08T00:00:00-07:00http://onrails.org/2010/06/08/railsconf-2010-baltimore<div style="text-align:center;"><img src="http://onrails.org/files/20100606_RailsConf_View.jpg" alt="20100606_RailsConf_View.jpg" border="0" width="500" /></div>
<p>Here we go again RailsConf 2010 has started. The keynotes will be streamed online at http://railsconf.com and the <a href="http://en.oreilly.com/rails2010/public/schedule/proceedings">slides</a> of the presentation will also be posted there. I’ll provide more links once they become available.</p>
<p>This is the view from my hotel which is 5 minutes from the convention center where RailsConf is going on.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20100607_RailsConf_View_From_Hotel.jpg" alt="20100607_RailsConf_View_From_Hotel.jpg" border="0" width="400" /></div>
<div style="text-align:center;"><img src="http://onrails.org/files/20100607_RailsConf_Submarine.jpg" alt="20100607_RailsConf_Submarine.jpg" border="0" width="300" /></div>
<h2>Acceptance Testing with Cucumber</h2>
<p>I’m now following the <a href="http://en.oreilly.com/rails2010/public/schedule/detail/13613">Acceptance Testing with Cucumber</a> tutorial. You can find the app we built, a kanban manager, on <a href="http://github.com/dchelimsky/railsconf2010-app">github</a>.</p>
<p>Cucumber is executable documentation. Gurken is the <span class="caps">DSL</span> used to write your documentation in the form of</p>
<pre>
Scenario:
Given
When
Then
</pre>
<p>The app has different git branches for each stage of the application. Checkout the move-card-passing branch for the most complete functionality. It contains great examples of feature test.<br />
<pre><br />
master f294f72 patch number<br />
remotes/origin/<span class="caps">HEAD</span> → origin/master<br />
remotes/origin/first-feature-failing 475eb7e words<br />
remotes/origin/first-feature-passing e4ea67a gemfile<br />
remotes/origin/latest eacd855 Merge<br />
remotes/origin/master f294f72 patch number<br />
remotes/origin/more-features-failing aa2d97b new failing features<br />
remotes/origin/more-features-passing 03b6b44 added lane ordering<br />
remotes/origin/move-card-failing 02fa766 add move_card feature</p>
<ul>
<li>remotes/origin/move-card-passing 8c1d751 move cards from one lane to another<br />
</pre></li>
</ul>
<h2><span class="caps">BUILDING</span> AN <span class="caps">API</span> <span class="caps">WITH</span> <span class="caps">RAILS</span></h2>
<p>A <a href="http://en.oreilly.com/rails2010/public/schedule/detail/14502">great discussion</a> on building APIs using Ruby and Rails:</p>
<ul>
<li><a href="http://twitter.com/joshowens">joshowens</a> – <a href="http://fourbeansoup.com/">Four Bean Soup</a></li>
<li><a href="http://twitter.com/joeferris">joeferris</a> – <a href="http://joeferris.me/">thoughtbot</a></li>
<li><a href="http://twitter.com/bitsweat">bitsweat</a> – <a href="http://bitsweat.net/">37signals</a></li>
<li><a href="http://twitter.com/noradio">noradio</a> – <a href="http://twitter.com/">twitter</a></li>
<li><a href="http://twitter.com/technoweenie">technoweenie</a> – <a href="http://techno-weenie.net/">GitHub</a></li>
<li><a href="http://twitter.com/derekwillis">derekwillis</a> – <a href="http://www.nytimes.com/">The New York Times</a></li>
</ul>Dashcode 3.0 - the precursor to Gianduia - A Flash Killer?2010-05-10T00:00:00-07:00http://onrails.org/2010/05/10/dashcode-3-0-the-precursor-to-gianduia-a-flash-killer<p>All right beside the cheesy title of this blog entry I did play a few weeks ago with Dashcode 3.0 to build an iPad app for a customer. After seeing the <span class="caps">WWDC</span> 2009 presentation on DashCode 3.0 I realized how much leaps and bounds DashCode made over the last two years. Checkout the quick screen cast demo here after and let me know what you think!</p>
<p>After looking into Dashcode 3.0 and doing some online search I found out that Jeff Watkins created several years ago <a href="http://coherentjs.org/">coherentjs</a>, a Cocoa inspired javascript framework, and he joined Apple to work on Dashcode. As you can see on <a href="http://coherentjs.org/">http://coherentjs.org/</a> he since left Apple and revived Coherent as a multiple browser framework.</p>
<p>Based on the fact that <span class="caps">WWDC</span> 2010 is around the corner is it to be expected that the next version of Dashcode will be announced and among other things should provide an enhanced visual editor, enhanced frameworks, more components, improved datasource support, css transitions support, and iPad support. It could well be that Dashcode 4 is in fact what some refer to as Gianduia. The good thing is that we will find out soon.</p>
<p>Now let’s quickly look at what Dashcode currently offers, it’s pretty cool:</p>
<p><object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=11633455&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=11633455&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><p><a href="http://vimeo.com/11633455">Dashcode 3.0 – An <span class="caps">IDE</span> to build <span class="caps">HTML</span> apps for iPad, iPhone and Safari</a> from <a href="http://vimeo.com/user507500">daniel wanja</a>.</p></p>Shutting down Usage Report!2010-04-27T00:00:00-07:00http://onrails.org/2010/04/27/shutting-down-usage-report<p>Oops, I did it again. Abandoning an idea after I invested quite some time on it even before it was released. This morning I had a good talk with my wife on where I should go with this project. It’s always hard to call it quit after spending quite some time on something but I changed once too many direction in the last two month that I don’t have a product to put on the market yet and to reach a point where I could sell something would take me a few more months (working on Mondays only) to get there…So I think I will call it a day on this project. Now that doesn’t make me feel great as I start having a track record of starting things and not finishing them…at least for project I want to commercialize. I seem to have an easier time to create stuff that I give away for free for some reasons. Having three kids and only limited time I was hoping to turn my hobby of trying to create products into some revenue generating activity so I can easier justify the time I spend on it.</p>
<p>Now there are several lessons I’m learning the hard way here. First I shouldn’t get stuck in having so much fun trying new stuff or solving technical issues without knowing if there is even a market for it. I’m for sure not a great business person but I should really focus on finding something people would be interested before spending too much time in one direction. Based on the fact that I work only Monday’s on this, something that can be created in three weeks full time takes month and month when working part time. I was pretty sure the UsageReport tool was a short term project but of course it ended up being more complex and more time consuming than expected. I was trying to see if there is any side product I could create from this last effort but to create something useful from my code base would still be more work than I can/I’m willing to spare at this time.</p>
<p>In the same vein, I’m not too troubled of spending all this time on these projects as I see it more like practice which makes me a better programmer in the long run and often helps out tremendously on my consulting gigs, and it’s fun to do. And the fact that I’m not troubled by this is an issue in it self as I could spend a fraction of the time learning the same things while working on these projects if the goal was just to learn.</p>
<p>The main issue is still that I never went life with any of these projects. MySpyder.net was awesome, but we never opened it up to the public or even a private beta. SiteExtractor.com was a cool concept but it was too rough to release, before I changed focus and worked WatchThatSite.com. All along the way I used ec2, s3, and Co so I’ve create a tool to visualize the pricing breakdown…and thought I could make a product from it. So over the last few years, just when I had to release something I jumped to the next thing.</p>
<p>Now I want to write about this publicly as it helps me think about why I ended up in the same place again, and I want to find out a way to do it differently next time….Yea, I know some people never learn ;-). So let’s see where I will go from here.</p>
<p>I had several consulting opportunities over the last few month I didn’t follow as I currently only have 20% of my week still available and I really thought I could nail the Usage Report project over a 6 month period and didn’t want to take on any extra work. Well I still worked on the Vault (http://vault.ncaa.com) with Cameron, and that was really fun! I’m right at 5 month with no end in view.</p>
<p>My wife recommends taking on new gigs as she doesn’t believe that a product can be created working part time…At least by me, and I think I’m proving her point pretty well. But I’m not ready to give up yet on creating a product. So what can I do avoid repeating history? I think I loose quickly faith in the ideas I have, or rather I’m getting quickly excited about new ideas without even proving that something works or releasing the project. So instead of tackling 15 days project (that are really 60 days) projects, I should start with some mini projects where I can create something within 3 to 5 days, then release it. At least this will force me to focus really hard on one idea and implement it, get real user feedback and go from there. If I could pull this of, I could maybe create several smaller apps and see which one takes off. Hey let me dream of that at least :-).</p>
<p>Gatelys had the same approach with their eCommerce store. They had a main store where selling many different type of products and based on best sellers where opening custom store for that type of item. In the same way, instead of guessing what type of application could work, I could experiment with smaller apps and see which gains more tractions.</p>
<p>So what are the new ideas…Well, first I need to see if I really cannot create a version of the Usage Report within 3 to 5 days based on the code base I now have. That would be a great first app to add to http://appsden.com. Another idea would be a pro version of the WebSnapshot tool http://myspyder.net/tools/websnapshot/ I wrote several years ago and which was downloaded over 5000 times and received good reviews. I have a few good ideas on that front. Another tool I would love to write is something that provides the functionality of iAwsManager but by showing a visual representation of a data center, more like a 2.5D game…Well that sounds bigger than a few days of work. I would love to create a twitter visualization tools that shows discussion threads and retweet flows. And there are many more ideas poping every days…If only I can pick one and stick with it, I wouldn’t have to write such blog entries.</p>
<p>If you read so far, thank you for sticking with me during this long thought process. For me at least it was useful ;-)</p>
<p>Cheers,<br />
Daniel</p>Making CRUD less "Cruddy", one step at a time 2010-04-27T00:00:00-07:00http://onrails.org/2010/04/27/making-crud-less-cruddy-one-step-at-a-time<p>One of the great “new” features of Rails (as of 2.3) is <code>accepts_nested_attributes_for</code>, allowing you to build cross-model <span class="caps">CRUD</span> forms without “cruddying” your controller. There are some great examples out there about <a href="http://weblogs.manas.com.ar/spalladino/2010/03/03/handling-children-with-accepts_nested_attributes_for-in-rails/">how to</a> <a href="http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes">do</a> <a href="http://github.com/alloy/complex-form-examples">this</a>, but I’d like to walk thorough a particular use case — managing the “join” records in a <code>has_many :through</code> relationship.</p>
<p>Consider the following database schema:</p>
<typo:code lang="ruby">
<p>class Villain < ActiveRecord::Base<br />
has_many :gifts<br />
has_many :super_powers, :through => :gifts<br />
end</p>
<p>class Gift < ActiveRecord::Base<br />
belongs_to :villain<br />
belongs_to :super_power</p>
validates_uniqueness_of :super_power, :scope => :villain_id
<p>end</p>
<p>class SuperPower < ActiveRecord::Base<br />
has_many :gifts<br />
has_many :villains, :through => :gifts<br />
end</p>
</typo:code>
<p>In our dataset, there are a relatively small number of super powers which we wish to present as a list of checkboxes on the villain management form. Checking/unchecking the boxes will manage the gift records for that villain, effectively managing the list of super powers available to the baddy.</p>
<p>To get started, we need to add <code>accepts_nested_attributes_for :gifts</code> to the Villain class — piece of cake. To complete the implementation, we need to change the <code>params</code> hash that our form generates. Let’s review the cases that we need to support and the associated <code>params</code> hash format needed to implement the correct functionality.</p>
<p>The first case is a super power record that is not currently associated with the villain. Here, the UI should display an unchecked checkbox. If we check it and submit the form, a gift record should be created linking the villain with the super power, making this bad guy that much badder. Here is an example of the <code>params</code> hash we should be sending to accomplish this:</p>
<typo:code>
{
‘villain’ => {
‘name’ => ‘Lex Luthor’,
…
‘gifts_attributes’ => {
1 => { ‘super_power_id’ => 5 },
2 => { ‘super_power_id’ => 7 },
…
}
}
}
</typo:code>
<p>The alternate case is a super power this villain already possesses. In this instance, the UI should display a checked checkbox, and if we uncheck it, the existing <code>gift</code> record should be deleted, diminishing the villain’s capacity for evil. And our <code>params</code> hash needs to look like:</p>
<typo:code>
{
‘villain’ => {
‘name’ => ‘Two-Face’,
…
‘gifts_attributes’ => {
1 => { ‘id’ => 101, ‘_delete’ => true },
…
}
}
}
</typo:code>
<p>Note that the keys for the <code>gifts_attributes</code> hash are arbitrary; we can use any scheme to generate unique keys for the hash.</p>
<p>So how can we craft a form that sends the <code>params</code> hash that Rails wants to see? Here’s my implementation:</p>
<typo:code lang="ruby">
<%- SuperPower.all.each_with_index do |super_power, index| -%>
<label>
<%- if gift = @villain.gifts.find_by_super_power_id(super_power.id) -%>
<%= hidden_field_tag “villain[gifts_attributes][#{ index }][id]”, gift.id %>
<%= check_box_tag “villain[gifts_attributes][#{ index }][_delete]”, false, true %>
<%= hidden_field_tag “villain[gifts_attributes][#{ index }][_delete]”, true %>
<%- else -%>
<%= check_box_tag “villain[gifts_attributes][#{ index }][super_power_id]”, super_power.id %>
<%- end -%>
<%= super_power.name %>
</label><br />
<%- end -%>
</typo:code>
<p>If the gift is detected, the villain has the super power, and we handle our second case from above, using the checkbox / hidden field hack Rails employs in the <code>check_box</code> helper method to make sure a value is sent whether or not the checkbox is checked. The else block handles the other case, setting up our <code>params</code> hash to create the gift if the checkbox is checked.</p>
<p>This works, but we probably don’t want to copy and paste that code everywhere we use this pattern. How can we reuse this in a <span class="caps">DRY</span> fashion? Here’s a helper method that encapsulates the logic:</p>
<typo:code lang="ruby">
def has_join_relationship(model, join_collection_name, related_item, collection_index, options={})
returning "" do |output|
relationship_name = options[:relationship_name] || related_item.class.table_name.singularize + “_id”
tag_prefix = “#{ model.class.class_name.underscore }[#{ join_collection_name }_attributes][#{ collection_index }]”
if join_item = model.send(join_collection_name).find(:first, :conditions => { relationship_name => related_item.id })
output << hidden_field_tag(“#{ tag_prefix }[id]”, related_item.id)
output << check_box_tag(“#{ tag_prefix }[_delete]”, false, true)
output << hidden_field_tag(“#{ tag_prefix }[_delete]”, true)
else
output << check_box_tag(“#{ tag_prefix }[#{ relationship_name }]”, related_item.id, false)
end
end
end
</typo:code>
<p>Drop that in a helper, and then your form code becomes:</p>
<typo:code lang="ruby">
<%- SuperPower.all.each_with_index do |super_power, index| -%>
<label>
<%= has_join_relationship(@villain, :gifts, super_power, index) %>
<%= super_power.name %>
</label><br />
<%- end -%>
</typo:code>
<p>Much nicer … although I’m not sold on the name <code>has_join_relationship</code>. Any suggestions?</p>UsageReport Downloader for Amazon Web ServicesTM. A simple tool to download all you usage reports with one click. ec2, s3, sns, sqs and more2010-04-20T00:00:00-07:00http://onrails.org/2010/04/20/usagereport-downloader-for-amazon-web-servicestm-a-simple-tool-to-download-all-you-usage-reports-with-one-click-ec2-s3-sns-sqs-and-more<p>UsageReport Downloader for Amazon Web ServicesTM is a simple tool to download all you usage reports with one click.</p>
<p>Install <a href="http://appsden.com/usagereport/">UsageReport Downloader</a></p>
<div style="text-align:center;"><img src="http://onrails.org/files/mainui.png" alt="mainui.png" border="0" width="500" /></div>
<p>The files are download in your documents folder. You can change the default folder. You selection is kept for the next time.</p>
<p>Click the Download <span class="caps">XML</span> or Download <span class="caps">CSV</span> button to choose which format the report should be downloaded from and off you go…</p>
<div style="text-align:center;"><img src="http://onrails.org/files/downloading.png" alt="downloading.png" border="0" width="346" height="299" /></div>
<p>All you files are download to the select download folder (here /Users/daniel/Documents/usagereport/downloads/Current\ Billing\ Period)</p>
<div style="text-align:center;"><img src="http://onrails.org/files/downloadedfiles.png" alt="downloadedfiles.png" border="0" width="339" height="164" /></div>
<p>When the application start it checks if you already logged in and you will see the following message.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/pleasewait.png" alt="pleasewait.png" border="0" width="381" height="34" /></div>
You can stay logged in between launching the application, we recommend that you log out once you download all you files.
<p>If you need to login just enter your email and amazon password as usual for https://aws.amazon.com.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/usernamepassword.png" alt="usernamepassword.png" border="0" width="480" height="147" /></div>
<p>If you use the authentication tokens for signing in you will be presented this additional screen:</p>
<div style="text-align:center;"><img src="http://onrails.org/files/token.png" alt="token.png" border="0" width="451" height="120" /></div>
<p>Et voila…Happy downloading!</p>
<p>Please contact me at daniel@appsden.com for any bugs, issues, questions.</p>
<p>Enjoy!<br />
Daniel Wanja</p>Cucumber, meet Routes2010-04-06T00:00:00-07:00http://onrails.org/2010/04/06/cucumber-meet-routes<p>I’ve been loving Rails <span class="caps">BDD</span> with Cucumber for the past year or so — it helps me focus on the next required step to build a feature in my application, and better focus equals better development velocity. However, one thing I found tedious in starting with Cucumber was defining route matchers in <code>paths.rb</code>.</p>
<p>The stock <code>path_to</code> method is implemented as a case statement, allowing you to add a case for each path you want to recognize. This works, but leaves you feeling a bit un-<span class="caps">DRY</span> since you’re basically duplicating information in your <code>routes.rb</code> file.</p>
<p>Here’s a quick hack to <code>paths.rb</code> that lets you leverage your existing routes:</p>
<p>change</p>
<typo:code lang="ruby">
else
raise “Can’t find mapping from \”#{page_name}\" to a path.\n" +
“Now, go and add a mapping in #{__FILE__}”
end
</typo:code>
<p>to</p>
<typo:code lang="ruby">
else
begin
page_name =~ /the (.*) page/
path_components = $1.split(/\s+/)
self.send(path_components.push(‘path’).join(‘_’).to_sym)
rescue Object => e
raise “Can’t find mapping from \”#{page_name}\" to a path.\n" +
“Now, go and add a mapping in #{__FILE__}”
end
end
</typo:code>
<p>In your Cucumber steps, you can now use any named route that does not require a parameter. For example, <code>users_path</code> would become “the users page”, and <code>new_product_path</code> would become “the new product page”. As you add new resources, at least the index and new options should work out of the box — no further edits to <code>paths.rb</code> required!</p>
<p><strong><span class="caps">UPDATE</span>:</strong></p>
<p>w00t!</p>
<p>This is <a href="http://github.com/aslakhellesoy/cucumber-rails/commit/00a3bd796363c243b2ea15321e8dca62c7f002c6">now</a> baked into cucumber-rails!</p>Call for help for a Amazon Web Services Usage Report visualizer tool 2010-04-05T00:00:00-07:00http://onrails.org/2010/04/05/call-for-help-for-a-amazon-web-services-usage-report-visualizer-tool<p>I’ve cross posted this call for help on the <a href="http://developer.amazonwebservices.com/connect/thread.jspa?threadID=44752">Amazon Web Service Discussion Forum</a>.</p>
<p>I need your help understanding your usage reports logs for a visualization tool I’m currently developing.</p>
<p>I’ve been reading this forum for a while and found great information on it. The tool in question is for all Amazon services not just ec2, but I thought the ec2 forum was the most appropriate. Let me know if that’s not the case.</p>
<p>I’ve been working for a while on a desktop application to visualize your amazon web services usage logs, and it’s far from ready, however I should have reached out way earlier an figured out what others would like in such a tool and also I need help to make sure that I can visualize data for larger account and for accounts that use different services.</p>
<p>As a disclaimer, the tool will not be a free tool, but it will be very affordable but I didn’t figure the pricing out yet as I’m not exactly sure what functionality I can make work. Currently I’m having difficulties figuring out how I will make the pricing calculator work correctly after the recent announcement of the Combined <span class="caps">AWS</span> Data Transfer Pricing. So the first version of the tool will focus more on visualizing usage rather than calculating price.</p>
<p>So my call for help is to find out more information about your usage report logs. I’m looking for people that have larger accounts than my current usage. I currently have a few servers and pay a little more than $200 a month. I use ec2, sdb, sqs, rds, s3, but not cf. So I’m looking for a couple of different scenarios with people that pay $2000/month or even way larger usage would be great.</p>
<p>The best help would be if I can have a copy of to the monthly usage logs by hour in <span class="caps">XML</span> format. I would understand if you don’t want to give out that information. Please contact me if you are hesitant or need more information so I make clear what I’m trying to achieve and how I will proceed. If I don’t find anyone out there to share this information I would be able to create a tool that just extracts anonymous statistic from your logs that would help answer the different questions I have. Let me know if that would be something you are willing to share.</p>
<p>You can also just help by letting me know what size each of you log files is for each of the services when downloading it in <span class="caps">XML</span> format. And how many lines each of the files contains. That would verify some of the assumptions I’m currently making.</p>
<p>To access your logs you must login to your aws.amazon.com account go to the Account page and select Usage Reports from the right menu. Select one of the service from the dropdown, the list includes the following:</p>
<ul>
<li>Amazon CloudFront, Amazon Elastic Compute Cloud</li>
<li>Amazon Simple Storage Service</li>
<li>Amazon <span class="caps">RDS</span> Service</li>
<li>Amazon SimpleDB</li>
<li>Amazon Simple Queue Service</li>
<li>Amazon Virtual Private Cloud</li>
</ul>
<p>Then your are presented with the Download Usage Report form. For the Time Period field select “Last Month”. Then press the “Download report (<span class="caps">XML</span>)” button. This downloads the file my tool will analyze. Download it for each of the services.</p>
<p>My tool, tentatively named Usage Report for Amazon Web Servicesâ„¢, is a desktop application that doesn’t require any server side installation that with one click lets you download directly from Amazon website all the usage reports and give a summary of the usage and allows to view each service individually by providing usage charts and time series of what was used when.</p>
<p>You can find my not so interesting notes on the development progress of my tool at http://awsusageanalyzr.tumblr.com/. The tool will be made available via http://appsden.com. My other blog is http://onrails.org, I’m a Flex and Ruby on Rails developer in Denver.</p>
<p>Any help is appreciated.</p>
<p>Daniel Wanja <br />
d@n-so.com</p>Sneak peek of Usage Report for Amazon Web Servicesâ„¢2010-03-18T00:00:00-07:00http://onrails.org/2010/03/18/sneak-peek-of-usage-report-for-amazon-web-servicesâ„¢I have <a href="http://awsusageanalyzr.tumblr.com/">been working</a> on a tool to visualize your Amazon Web Services usage logs for EC2, RDS, SQS, S3, SDB (and soon CF). There will be a limited free version and a full version that has the dashboard and the drill down for each of the services. This tool is still in development but my todo list is getting shorter...so you can have a sneak peek here:<br/>
<object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=10251397&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=10251397&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><p><a href="http://vimeo.com/10251397">Sneak peek of Usage Report for Amazon Web Servicesâ„¢</a> from <a href="http://vimeo.com/user507500">daniel wanja</a>.</p>
MWRC 2010 - Notes from Day 1.2010-03-12T00:00:00-08:00http://onrails.org/2010/03/12/mwrc-2010-notes-from-day-1<a href="http://twitter.com/jakep36">Jake Parsell</a> took some really great notes using Google Wave. I know the videos will be available shortly but in the mean time if you want to figure out what you may want to watch you can find out more details below:
<style type="text/css">
#wave p.p1 {margin-left: 0.0px; font: 26.0px Arial}
#wave p.p2 {margin-left: 0.0px; font: 13.0px Arial; min-height: 15.0px}
#wave p.p3 {margin-left: 0.0px; font: 20.0px Arial}
#wave p.p4 {margin-left: 17.0px; font: 13.0px Arial; color: #0e3ea8}
#wave p.p5 {margin-left: 17.0px; font: 13.0px Arial}
#wave p.p6 {margin-left: 34.0px; font: 13.0px Arial}
#wave p.p7 {margin-left: 17.0px; font: 13.0px Arial; min-height: 15.0px}
#wave p.p8 {margin-left: 0.0px; font: 20.0px Geneva; color: #234455}
#wave p.p9 {margin-left: 34.0px; font: 13.0px Geneva; color: #234455}
#wave p.p10 {margin-left: 34.0px; font: 13.0px Arial; min-height: 15.0px}
#wave p.p11 {margin-left: 51.0px; font: 13.0px Arial}
#wave p.p12 {margin-left: 68.0px; font: 13.0px Arial}
#wave p.p13 {margin-left: 34.0px; font: 13.0px Arial; color: #0e3ea8}
#wave p.p14 {margin-left: 85.0px; font: 13.0px Arial}
#wave p.p15 {margin-left: 51.0px; font: 13.0px Arial; min-height: 15.0px}
span.s1 {font: 20.0px Geneva; color: #234455}
span.s2 {font: 20.0px Geneva; color: #003366}
span.s3 {font: 13.0px Geneva; color: #234455}
span.s4 {font: 13.0px Arial; text-decoration: underline ; color: #0e3ea8}
span.s5 {text-decoration: underline ; color: #0e3ea8}
span.s6 {color: #000000}
span.s7 {text-decoration: underline}
span.s8 {background-color: #ffe500}
</style>
<div id="wave">
<p class="p1"><b>MWRC</b></p>
<p class="p2"><br></p>
<p class="p3"><span class="s1">Giles Bowkett</span><b> - making some music with ruby </b><span class="s2">Archaeopteryx</span></p>
<p class="p4"><span class="s3">- <a href="http://gilesbowkett.blogspot.com/2008/02/archaeopteryx-ruby-midi-generator.html"><span class="s4">Giles Bowkett: Archaeopteryx: A Ruby MIDI Generator</span></a></span></p>
<p class="p5">- learn probability matrix</p>
<p class="p5">- google is easy if you understand prob matrix</p>
<p class="p5">- google spell check in 21 lines of python</p>
<p class="p5">- wonder how easy OCR would seem in this context?</p>
<p class="p5">- don't understand python community.... why are there not more dick jokes about pythons?</p>
<p class="p6">- how is there not a web framework called trouser snake?</p>
<p class="p5">- oh yeah... better talk about lambdas</p>
<p class="p7"><br></p>
<p class="p3"><span class="s1">James Golick</span><b> - Cooking with Chef - @jamesgolick </b><a href="http://github.com/jamesgolick"><span class="s5"><b>github.com/jamesgolick</b></span></a></p>
<p class="p4"><span class="s6">- <a href="http://www.rubyinside.com/chef-tasty-server-configuraiton-2162.html"><span class="s7">Chef: Quick and Tasty Ruby Powered Server Configuration</span></a></span></p>
<p class="p5">- sysadmin work is boring</p>
<p class="p5">- too many config languages</p>
<p class="p5">- amazed if anyone can get nagios working on a consistent basis</p>
<p class="p5">- ues recipes to install packages</p>
<p class="p5">- recipes written in ruby</p>
<p class="p5">- create services -> status, restart, reload, etc.</p>
<p class="p5">- templates to create config files</p>
<p class="p6">- erb</p>
<p class="p5">- notifies restart if config changes</p>
<p class="p6">- autoreload on save very handy for things like dynamic lists of ips that change when you start a new EC2 instance</p>
<p class="p5">- makes setting up stuff like haproxy and heartbeat easier</p>
<p class="p5">- security</p>
<p class="p6">- easy to include iptables</p>
<p class="p6">- <span class="s8">always turn off password ssh logins</span> - easier to remember when part of your cookbook</p>
<p class="p5">- look into chef server and chef client</p>
<p class="p7"><br></p>
<p class="p8">Joe Damato - RVM</p>
<p class="p9">- <a href="http://rvm.beginrescueend.com/"><span class="s7">RVM: Ruby Version Manager - RVM Ruby Version Manager - Documentation</span></a></p>
<p class="p6"><span class="s3">- </span>RVM gemset - different gemsets for the same ruby version per project</p>
<p class="p6">- create rvmrc to switch env automatically when you cd into a project directory</p>
<p class="p6">- export gemsets?</p>
<p class="p6">- should you use gemsets or just bundler</p>
<p class="p10"><br></p>
<p class="p8">Loren Segal - Documentation with YARD</p>
<p class="p9">- <a href="http://yardoc.org/"><span class="s7">YARD 0.5.3 - The Longest</span></a></p>
<p class="p6">- Yet Another Ruby Documentor</p>
<p class="p6">- Talk about documentation in general</p>
<p class="p11">- Documentation to help you think about your API</p>
<p class="p11">- What makes documentation good?</p>
<p class="p12">- consistency -> pick a style and stick with it</p>
<p class="p12">- correct -> it can be wrong and should be audited</p>
<p class="p12">- coherent</p>
<p class="p6">- YARD</p>
<p class="p11">- meta-data</p>
<p class="p11">- @param [Symbol] req_type :get or :post</p>
<p class="p11">- ....</p>
<p class="p11">- yard-respec</p>
<p class="p12">- shows rspec specs alongside method docs</p>
<p class="p11">- yard-sinatra</p>
<p class="p12">- shows your routes for api</p>
<p class="p10"><br></p>
<p class="p2"><br></p>
<p class="p8">Michael Jackson - Rack for web developers</p>
<p class="p13"><span class="s6">- <a href="http://rack.rubyforge.org/"><span class="s7">Rack: a Ruby Webserver Interface</span></a></span></p>
<p class="p6">- Read the Spec</p>
<p class="p6">- blah, blah, blah</p>
<p class="p6">- rack is cool in that it allows web frameworks to communicate with web servers, but not sure you care that much unless making a web framework</p>
<p class="p10"><br></p>
<p class="p3"><b>Yehuda Katz - Modularity - Lessons learned from Rails 3</b></p>
<p class="p6">- Try to become modular too soon and you will be wrong</p>
<p class="p6">- Become modular once lack of modularity is hurting you, then decouple</p>
<p class="p6">- Constants -> Globals</p>
<p class="p6">- router.url_for in rails 3</p>
<p class="p6">- easier to track down where instance variables came from than Globals</p>
<p class="p6">- eliminate things that are global</p>
<p class="p11">- tests are the canary in the coal mine</p>
<p class="p11">- instead of hard coding contants, pass things around</p>
<p class="p11">- be subspicious of Contant.foo</p>
<p class="p6">- stop caring about object allocations</p>
<p class="p11">- object allocations are essentially free</p>
<p class="p6">- Render</p>
<p class="p11">- Controller -> ViewPathSet -> ViewPath -> Template (on file system)</p>
<p class="p11">- Used to assume actual file path</p>
<p class="p12">- hard to cache</p>
<p class="p12">- Template.new takes a path</p>
<p class="p11">- Now</p>
<p class="p12">- Caller -> LookupContext -> ViewPaths -> PathResolver-> Resolver -> Template</p>
<p class="p12">- Template.new takes a source</p>
<p class="p12">- Could overide PathResolver to pull from database or S3 or something</p>
<p class="p14">- could be useful in making a CMS system with Rails</p>
<p class="p6">- Use Modules</p>
<p class="p11">- don't put methods you want people to be able to override in a class, make a module</p>
<p class="p11">- then you cna call super</p>
<p class="p11">- Use ActiveSupport::Concern</p>
<p class="p15"><br></p>
<p class="p3"><b>Paul Sadauskas - HTTP</b></p>
<p class="p6">- read the spec :-)</p>
<p class="p6">- prevent the requests that you don't have to answer</p>
<p class="p6">- Persistent Connections - so you don't have to create a new TCP connection for every request --- keepalive=onC</p>
<p class="p6">- Caching</p>
<p class="p11">- how do you decide when something is stale?</p>
<p class="p15"><br></p>
<p class="p15"><br></p>
<p class="p3"><span class="s1">Jeff Casimir </span><b>- Ruby Processing</b></p>
<p class="p6">- dynamically generate images in ruby app</p>
<p class="p6">- uses jruby</p>
<p class="p6">- first built to create verticle column headers</p>
<p class="p6">- Distributed Programming with Ruby -> to learn how to send jobs to ruby processing from rails</p>
<p class="p6">- Beanstalkd -> simple fast background processing -> brew install beanstalkd </p>
</div>
MWRC 2010 - Day 1 Live Video2010-03-11T00:00:00-08:00http://onrails.org/2010/03/11/mwrc-2010<p><a href="http://www.flickr.com/photos/wanja/4424356701/" title="Moutains Pano + fingers by danielwanja, on Flickr"><img src="http://farm3.static.flickr.com/2504/4424356701_61dae3c3b0.jpg" width="500" height="108" alt="Moutains Pano + fingers" /></a></p>
<p>The conference is about to start in 30 minutes, the room starts to buzz. The confreaks guys have their camera and video recording equipment all setup. So you will be able to catch up the conference online soon. Somehow I really like single track conferences and the sessions seem really great and will be fast passed, 30 to 45 minutes. Check out the <a href="http://mtnwestrubyconf.org/2010/schedule">schedule</a>. So I will sit back and enjoy the show.</p>
<p><strong>Follow it live on <a href="http://www.justin.tv/mwrc#r=hcNHcJU~">Justin TV</a>!!</strong></p>
<p><object type="application/x-shockwave-flash" height="300" width="400" id="live_embed_player_flash" data="http://www.justin.tv/widgets/live_embed_player.swf?channel=mwrc" bgcolor="#000000"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="allowNetworking" value="all" /><param name="movie" value="http://www.justin.tv/widgets/live_embed_player.swf" /><param name="flashvars" value="channel=mwrc&auto_play=false&start_volume=25" /></object><a href="http://www.justin.tv/mwrc#r=-rid-&s=em" class="trk" style="padding:2px 0px 4px; display:block; width:345px; font-weight:normal; font-size:10px; text-decoration:underline; text-align:center;">Watch live video from Mountain West Ruby Conference on Justin.tv</a></p>
<p>Salt Lake City is definitively a beautiful city, surrounded by it’s mountains…</p>
<p><a href="http://www.flickr.com/photos/wanja/4424356615/" title="Library by danielwanja, on Flickr"><img src="http://farm3.static.flickr.com/2780/4424356615_71c2a0edc3.jpg" width="350" alt="Library" /></a></p>
<p><a href="http://www.flickr.com/photos/wanja/4424356225/" title="Library by danielwanja, on Flickr"><img src="http://farm5.static.flickr.com/4022/4424356225_b242ec1275.jpg" width="350" alt="Library" /></a></p>360Flex last day.2010-03-11T00:00:00-08:00http://onrails.org/2010/03/11/360flex-last-day<p>What a conference! The talks where really awesome so far. Not exactly sure what I will attend today. I might attend “Optimize it! ActionScript Tips for iPhone Games” followed by “Adobe is from Mars, Microsoft is from Uranus: A View from the Client”. Then I will have to split early to catch a flight to Salt Lake City for the <a href="http://mtnwestrubyconf.org/2010/">MountainWest RubyConf 2010</a>.</p>
<h3>Optimize it! ActionScript Tips for iPhone Games Renaun Erickson</h3>
<p>Renaun is Plaform Evangelist for Adobe since last week. He will put up the slides and code on his <a href="http://renaun.com/blog/">blog</a> later today. Many of the tips are good for any Flash/Flex app not just for iPhone ones.</p>
<ul>
<li>Packager for iPhone (<span class="caps">PFI</span>)</li>
<li><span class="caps">LLVM</span> cross compiles</li>
</ul>
<p>He will focus the talk on Memory/Cpu/Mouse Move and Game Timers.</p>
<p>Instead of going to the Flex/Silverlight talk, sorry Jun and Eric, I went to Nate Beck’s talk on pushbutton. And Doug McCune had something special <a href="http://dougmccune.com/blog/2010/03/10/nate-becks-birthday-surprise-at-360flex/">planned</a> for Nate’s birthday…</p>
<p><object width="400" ><param name="movie" value="http://www.youtube.com/v/xEkUyNdj_4E&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/xEkUyNdj_4E&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="400" ></embed></object></p>
<p>Flex 4: It’s a Wrap</p>
<p><object width="400" ><param name="movie" value="http://www.youtube.com/v/PeTakZ-_sF0&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/PeTakZ-_sF0&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="400"></embed></object></p>
<p>Thank’s Tom and John…the conference was awesome!</p>360 Flex - Day 2 (Tuesday) - Live Blogging2010-03-09T00:00:00-08:00http://onrails.org/2010/03/09/360-flex-day-2-tuesday-live-blogging<p>As you saw yesterday afternoon I didn’t blog too much, so let’s how today goes. The party last night was really fun, lot’s of networking, rock band playing and just a nice general geek atmosphere.</p>
<h2>Evolution of <span class="caps">RIA</span> Design Principals</h2>
<p>Right now the “Evolution of <span class="caps">RIA</span> Design Principals” panel is about to start.</p>
<p>Panel is:</p>
<ul>
<li>Chet Haase – Senior Computer Scientists at Adobe</li>
<li>Bill Scott – Director UI Engineering at Netflix</li>
<li>Ehud Waizer – <span class="caps">SAP</span></li>
<li>Paul Guirata – Catalyst Resources</li>
</ul>
<p>Context: oriented to customer facing applications. Not games.</p>
<h3>Chet Haase</h3>
<p>He works on effects at Adobe. Effects used in a subtle way can make the user more effective.</p>
<p>What are the top 3 rules</p>
<ol>
<li>Transitioning</li>
<li>Anticipatory</li>
<li>well-timed.</li>
</ol>
<p>Don’t Lose the User.</p>
<h3>Bill Scott</h3>
<p>Principles for Interesting Moments</p>
<ul>
<li>Input where you output</li>
<li>Require a light footprint</li>
<li>Stay in the flow</li>
<li>Offer invitations</li>
<li>Be reactive</li>
<li>Use transitions</li>
</ul>
<h3>Paul Giurata</h3>
<p>Modular<br />
Reusable</p>
<ul>
<li>Panel vs Page</li>
<li>Panels being reusable application(s)</li>
<li>Panels being re-used down to the code level</li>
<li>Panels potentially being entirely separate applications</li>
</ul>
<p>Bill mentions <a href="http://www.perfettimedia.com/">Christine Perfetti</a> has a <a href="http://www.uxideas.com/shows/usability_tests_nutshell/">few videos</a> on usability testing.</p>
<h3>Compiled Favorite Principles</h3>
<ul>
<li>Transitioning (Animations)</li>
<li>Anticipatory</li>
<li>Timing</li>
<li>Don’t Lose the User</li>
<li>Interesting Moments</li>
<li>Modular</li>
<li>Reusable</li>
</ul>
<p>Consistency .via. developers working from the same code. Not a style guide as it’s open for interpretation.</p>
<h2>Whats New in Flex 4 that’s <span class="caps">NOT</span> Spark! – Deepa Subramaniam</h2>
<p>Deepa was on the engineering team for 7 years and now just got promoted as product manager.</p>
<p>She will put the slides on her <a href="http://iamdeepa.com/blog/">blog</a>. So I will go easy with the notes.</p>
<p>We will talk about:</p>
<ul>
<li>Enhanced States</li>
<li>Pixel Bender Integration</li>
<li>Text (<span class="caps">TLF</span>)</li>
<li>2-way Data Binding</li>
<li>Advanced <span class="caps">CSS</span></li>
<li><span class="caps">OSMF</span></li>
<li>MXItemRenderer</li>
<li>RSLs</li>
<li>Charting Enhancements</li>
<li>ASDoc</li>
<li><span class="caps">MXML</span> Vector</li>
<li>Compile time <span class="caps">FXG</span> Optimization</li>
<li>Improved Compiler</li>
</ul>
<h3>2-Way Databinding</h3>
<p>Inline declaration using the syntax, @{bindable_property}</p>
<pre>
<s:TextInput id="t1" text="@{t2.text}" />
<s:TextInput id="t2" />
</pre>
<h3>Enhanced States Syntax</h3>
<ul>
<li>AddChild/RemovedChild replaced with includeIn/excludeFrom</li>
<li>State Groups</li>
</ul>
<pre>
<m:states>
<m:Sate name="A"/>
<m:Sate name="B"/>
<m:Sate name="C"/>
</m:states>
<Button label="b1" includeIn="A,B" />
<Button label="b2" includeIn="C" />
</pre>
<h3>Text</h3>
<ul>
<li><span class="caps">FTE</span> – Flash Text Engine in FP10</li>
<li><span class="caps">TLF</span> – Text Layout Framework, set of ActionScript classes build atop <span class="caps">FTE</span>. Is <span class="caps">XML</span>-based markup</li>
</ul>
<p>Each text element maps to a class<br />
<pre><br />
<div> flash.textLayout.elements.DivElement<br />
<p> flash.textLayout.elements.ParagraphElement<br />
<span> flash.textLayout.elements.SpanElement<br />
<tab> flash.textLayout.elements.TabElement<br />
</pre></p>
<p><span class="caps">TLF</span> Partitioning:</p>
<ul>
<li>Simple, plain text</li>
<li>Rich text</li>
<li>Rich editable text</li>
<li>Rich, editable, selectable text</li>
</ul>
<h3>Pixel Bender Integration</h3>
<ul>
<li>Pixel Bender: language for hardware-indepdent image processing algorithm</li>
<li>Shader: compiled instance of a Pixel Bender kernel</li>
<li>Flex introduces the ShaderFilter class. Simplifies pixel bender such that they can be invoked in <span class="caps">MXML</span></li>
</ul>
<h3>Advanced <span class="caps">CSS</span></h3>
<ul>
<li>Flex 3: type and class selectors</li>
<li>Flex 4: Multiple class selectors, id selectors, descendant selectors, pseudo-selectors, pseudo-state selectors</li>
</ul>
<p>Eg pseudo-state selectors</p>
<pre>
@namespace s "library://ns.adboe.com/flex/spark";
s|Button:up {
color:#000000;
}
s|Button:down {
color:#FFFFFFF;
}
</pre>
<h3><span class="caps">OSFM</span></h3>
<ul>
<li>Generic framework for managing media in Flash applications</li>
<li>Offers playback functionality, exposed in the Spark video component</li>
<li>replaces FLVPlayback</li>
<li>org.osmf.media.MediaPlayer</li>
<li>Play, pause, stop, loop, seek, volume, autoLoop, autoPlay, …</li>
</ul>
<h3>MXItemRenderer</h3>
<ul>
<li>Spark ItemRenderers for use with MX List-based components</li>
<li>Extends Spark ItemRenderer and handles the contractual differences</li>
</ul>
<h3>Charting Enhancements</h3>
<ul>
<li>FilterFunctions for chart types. Can specify custom filter functions against the data set</li>
<li>Inverted axis support</li>
<li>RendererDirection in PieSeries</li>
<li>Performance related bug fixes</li>
</ul>
<h3>RSLs</h3>
<ul>
<li>By default <span class="caps">RSL</span> is turned on.</li>
<li>Default linked HelloWorld is 78% smaller</li>
<li>How to <a href="http://blogs.adobe.com/dloverin/2010/01/how_to_monkey_patch_when_using_flex_rsls.html">monkey patch when using RSLs</a>. If you monkey patch you loose the benefits off RSLs</li>
<li>Flex is split in 6 RSLs: textlayout, osmf, framework, spark, sparkskins, rpc</li>
</ul>
<h3><span class="caps">MXML</span> Vector</h3>
<ul>
<li>New type</li>
<li>Like Arrays but contents are restricted to a single base type</li>
<li>Faster than array</li>
</ul>
<pre>
<fx:Vector id="myVector" type="String">
<fx:String>hi</fx:String>
<fx:String>bye</fx:String>
</fx:Vector>
</pre>
<h3>Compile-time <span class="caps">FGX</span> Optimization</h3>
<ul>
<li><span class="caps">FXG</span> directly to <span class="caps">SWF</span> representation</li>
<li>Faster and smaller</li>
<li>.fxg or past <span class="caps">FXG</span> into an <span class="caps">MXML</span> Component uses compile-time <span class="caps">FXG</span> Optimization</li>
</ul>
<h3>ASDoc</h3>
<ul>
<li>Comments in <span class="caps">MXML</span></li>
<li>Support <span class="caps">DITA</span> creation</li>
<li>Max, Win, Linux</li>
</ul>
<h3>Improved Compiler</h3>
<ul>
<li>Incremental compilation. 50-80% better</li>
<li>Full compilation: 30-40% better (large apps)</li>
<li>Compiler Memory Usage: large apps are 30% better. multi-project apps are 70% better. Small apps are similar to Flex 3</li>
</ul>360 Flex - Day 2 (Monday Afternoon) - Live Blogging2010-03-09T00:00:00-08:00http://onrails.org/2010/03/09/360-flex-day-2-monday-afternoon-live-blogging<div style="text-align:center;"><img src="http://onrails.org/files/360flex_6_robot.png" alt="360flex_6_robot.png" border="0" width="400" height="300" /></div>
<h3>Obey: Building a Rules Engine with AS3 and the Hamcrest <span class="caps">API</span> – Drew McClean & RJ Owen</h3>
<div style="text-align:center;"><img src="http://onrails.org/files/360flex_7_rules.png" alt="360flex_7_rules.png" border="0" width="400" height="290" /></div>
<p>How are rules defined and implemented?</p>
<p>Rules Engine Anatomy: Facts → Rules [Conditions=>Actions] → Output</p>
<p>Battery is down!</p>
<h3>Flex + Phidgets = Beer – Kevin Hoyt</h3>
<p>Kevin’s presentation was how to drive a <a href="http://www.phidgets.com/">phidgets</a> board to control dispensing beer to users with an rfid, taking a picture along the way and counting the numbers of beers that user had so far. The board is driven from a Flex application. It was really impressive presentation.</p>
<h3>Intro to Flex Typography – Matt Guest</h3>
<ul>
<li>Flash Text Engine</li>
<li>Text Layout Framework</li>
</ul>Import your MacHeist serials to AppShelf2010-03-08T00:00:00-08:00http://onrails.org/2010/03/08/import-your-macheist-serials-to-appshelf<p>If you have purchased the latest MacHeist nano bundle, you might have noticed that there is no option this time to export as an AppShelf file. I felt a little guilty spamming my twitter followers to get my three free bonus apps (Airburst Extreme, Tracks, and Burning Monkey Solitaire), so to atone, I’m sharing a script that will translate your reciept into an AppShelf import file. Just save your receipt page from the browser, then pass the filename to this script as an argument:</p>
<span class="caps">RUBYOPT</span>=rubygems ruby generate-appshelf.import.rb MacHeist-Serial.html
<p>The script will create an import file named “nano-bundle-3.appshelf” in your current directory. Enjoy!</p>
<script src="http://gist.github.com/325458.js?file=generate-appshelf-import.rb"></script>360 Flex - Day 2 (Monday Morning) - Live Blogging2010-03-08T00:00:00-08:00http://onrails.org/2010/03/08/360-flex-day-2-monday-live-blogging<table><tr><td><br />
<img src="http://onrails.org/files/360flex_1_ebay.png" alt="360flex_1_ebay.png" border="0" width="221" height="166" /></td>
<td>
<p><img src="http://onrails.org/files/360flex_2_ebay.png" alt="360flex_2_ebay.png" border="0" width="124" height="166" /></p>
<p></td></tr></table></p>
<p>Actually today is the first day of the conference. Yesterday was a tutorial day which was really fun. Today there will be a bunch of 1h20m sessions throughout the day. The conference is at the ebay headquarters.</p>
<div><img src="http://onrails.org/files/360flex_3_keynote.png" alt="360flex_3_keynote.png" border="0" width="221" height="166" /></div>
<p>I was with three other guys from Denver and we nearly missed the start of the keynote as we took the light rail in the wrong direction. How can 4 engineers go so wrong? :-) Anyhow it doesn’t seem we missed to much as it’s starting with a talk from the sponsor (ebay/paypal) about the eBay developer program.</p>
<h3>Keynote</h3>
<p>Now onto the main keynote by Deepa Subramaniam on the Adobe Flash Platform for her first keynote given ever. She is the new Product Manager of the Flex <span class="caps">SDK</span>.</p>
<ul>
<li>The Flex 4 release is coming really soon.</li>
<li>Overview of Flex 4</li>
<li>Demo of spark components</li>
<li>Data-Centric Development</li>
<li>Video from the Flex team (geek funny)</li>
</ul>
<div style="text-align:center;"><img src="http://onrails.org/files/360flex_4__Deepa.png" alt="360flex_4_ Deepa.png" border="0" width="337" height="202" /></div>
<p>It’s great that Deepa become the project manager of Flex 4, she understand what’s programming is about. She now continues her talk on the Open Screen project.</p>
<p>Developing multi-screen applications (phone .vs. desktop…)</p>
<p>Cross screen challenges/Cross device challenges</p>
<ul>
<li>Screen size</li>
<li>Input mechanisms</li>
<li>Performance</li>
<li>Context/use case changes</li>
<li>Screen size, orientation</li>
<li>…</li>
</ul>
<p>Flex can help – <strong>Slider</strong> (Mobile Flex Framework)</p>
<ul>
<li>Deliver top quality experience</li>
<li>Across multiple platforms</li>
<li>Within performance constraints</li>
</ul>
<p>The Slider team is hard a work and hope to have a preview available this year :-(… I want it earlier!</p>
<p>Growing Flex Ecosystem:</p>
<ul>
<li>Functional Testing Tools</li>
<li>Performance and Load Test Tools</li>
<li>Flex Components</li>
<li>Frameworks</li>
<li><span class="caps">AMF</span> servers</li>
<li>Tooling Extensions</li>
<li>Licensing+Encryption</li>
<li>Security Testing</li>
</ul>
<p>All data visualization components now available in the free open-source Flex <span class="caps">SDK</span>!</p>
<p>Cool John is saying that they are recording the videos of each session.</p>
<h3>Appocalypse Soon? The remaking of ‘Flex Components’ – Michael Labriola</h3>
<p>It’s full house for Michael’s talk. I’m not sure how much live blogging I should do has they are video tapping each session.</p>
<p>This session is part of his continuing quest to teach Flex from the inside out. To learn about the Flash Player and the Flex framework.</p>
<p>Going to derive the Flex framework. Implement a custom component.</p>
<ul>
<li>Flex 3 and Flex 4 components both descend from UIComponents</li>
</ul>
<p>Michael is not explain how the code execution is managed by the Flash Player and executed during a frame.</p>
<ul>
<li>All the basic Flex 3 methods also apply to Flex 4.</li>
<li>Flex 3: A base class and then a descendent class for each Layout. Problem i.e. verticalScrollPolicy=“off” to avoid unwanted scrollbars.</li>
<li>Flex 4: doesn’t derive layout behavior but can assemble it. Frame (Horizontal, Vertical, Diagonal). So the visuals don’t exist inside of the class.</li>
<li>Flex 4 are based on two separate pieces: the form and the function.</li>
</ul>
<ul>
<li>Separating these pieces favors composition over inheritance. By separating these we gain and we loose…</li>
<li>Gain: have one set of functionality look many different ways</li>
<li>Loose: a lot of dead weight and lots of extra classes</li>
<li>Two type of components: Controls and Containers</li>
<li>Flex 4: two types of things… those that can be skinned and those that cannot</li>
<li>Groups are the base type of container</li>
<li>Groups don’t have visual identify</li>
<li>BasicLayout, HorizontalLayout, VerticalLayout, TileLayout</li>
</ul>
<p>New Hierarchy:</p>
<pre>
UIComponent
SkinnalbeComponent
SkinnableContainerBase
SkinnableContainer
Applicaiton
Panel
Window
SkinnableDataContainer
</pre>
<ul>
<li>Skins are classes defined in <span class="caps">MXML</span></li>
<li>Applied to components using the skinClass or by <span class="caps">CSS</span></li>
<li>Components: declare skin parts and declare skin states</li>
</ul>
<p>Skins: specify a HostComponent</p>
<pre>
<fx:Metadata>
[HostComponent("spark.components.Button")]
</fx:Metadata>
</pre>
<p>Declare states</p>
<pre>
<s:states>
<s:State name="up" />
<s:State name="over" />
</s:states>
</pre>
<ul>
<li>How it all works: components need to size themselves, need to be created at runtime, need to interact with parents and children</li>
<li>Instanciation: all Flex components start with a constructors. Constructors in Flex add event listeners and setup initial properties…That’s it.</li>
<li>Display List: list of all the components that are on the screen at one point or another</li>
<li>Creating children: all visual children of a component are created in the createChildren method. The visual children of a component exists in the skin and so the skin is first created at this time.</li>
<li>Skin Methods: attachSkin, detachSkin, partAdded, partRemoved</li>
<li>Sizing: each component implements the measure() method. Flex works on the principle that children must be sized before their parent and it makes the sizing process potentially asynchronous. It works via a priority queue. Priority based on nest level.</li>
<li>Flex 4: children leave inside a skin and not the parent. The skin is a component, so we ask it the size of it’s children.</li>
<li>Measured Data: measure is only a suggestion.</li>
<li>Sizing: parents size children. A component does not size itself.</li>
<li>Sizing and Positioning: sizing and positioning is done in a method called updateDisplayList().</li>
<li><span class="caps">UDL</span>: components are given a size. One the size is given, the component is free to do what is wishes. For the most part, this information is simply passed down to the skin. Again recursion.</li>
</ul>
<p>This was a great talk and clarifies many things which is great timing as I’m starting to dive deeper into Flex 4.</p>
<p><a href="http://onrails.org/articles/2010/03/08/360-flex-day-2-monday-afternoon-live-blogging">To be continued…</a></p>360 Flex - Day 1 (Sunday) - Live Blogging2010-03-07T00:00:00-08:00http://onrails.org/2010/03/07/360-flex-day-1-sunday-live-blogging<p>We just had a great breakfast at Peggy Sue’s Dinner…and moved over to the Ebay Headquarters where the conferences is about to start.</p>
<p>I’ll be taking notes during the day and updating this page as we go one.</p>
<p><span class="caps">UPDATE</span>: Now that I typed all that I realized that Justin put up the slides and code on his blog: <a href="http://blog.classsoftware.com/">http://blog.classsoftware.com/</a>.</p>
<h1>Connecting Arduino Hardware to Flex: Justin Mclean</h1>
<p>twitter: justinmclean<br />
Justin is from Sydney, Australia.</p>
<p>Content:</p>
<ul>
<li>Arduino platform, how to program and how to connect to Flex</li>
<li>2/3 Arduino 1/3 Flex</li>
<li>Hands on</li>
</ul>
<h3>So we’ll go through the followings:</h3>
<ul>
<li>Digital Inputs</li>
<li>Digital Outputs</li>
<li>Analogue Inputs</li>
<li>Pulse Width Modulation</li>
<li>Serial Communication</li>
<li>Connecting to Flex</li>
<li>Review and wrap up</li>
</ul>
<p>So Justin gave each attendee one board and a set of components. The board is open source hardware. I think that’s pretty cool. Feels like the hardware kit I bought for my 6 years son. The board is $25 and with all the components it’s about $40.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/arduino.png" alt="arduino.png" border="0" width="400" height="300" /></div>
<p>The hardware is provided to all participants by <a href="http://sparkfun.com"><strong>sparkfun.com</strong></a></p>
<h3>Software</h3>
<p>http://arduino.cc/en/Main/Software</p>
<div style="text-align:center;"><img src="http://onrails.org/files/arduino_software.png" alt="arduino_software.png" border="0" width="350" height="247" /></div>
<p>Also install the serial driver: FTDIUSBSerialDriver_10_4_10_5_10_6</p>
<h3>Other Hardwares</h3>
<ul>
<li>ATmega micro-controller from Atmel. It mostly runs in cars.</li>
<li>Arduino Duemilanove</li>
<li>Arduino Pro and Pro mini</li>
<li>Lyllypad (warable)</li>
<li>Funnell IO</li>
<li>Mega</li>
<li>Many others</li>
</ul>
<h3>ATMega328</h3>
<ul>
<li>Hight performance low power <span class="caps">RISC</span></li>
<li>16 Mzh up to 16 mips (faster as your first pc you owned – if you are a bit older)</li>
<li>32K of Memory</li>
<li><span class="caps">SPI</span> and 2 wire serial interfaces</li>
<li>External interrupts, timers, pulse width modulation</li>
</ul>
<h3><span class="caps">IDE</span></h3>
<ul>
<li><span class="caps">IDE</span> open sourcee and cross platform.</li>
<li>Based on the Processing language</li>
<li>Many open source sketches (projects) and libraries availables. Ethernet library, servers, …</li>
</ul>
<h3>First Program</h3>
<typo:code lang="javascript">
<p>int ledPin = 13; // <span class="caps">LED</span> connected to digital pin 13</p>
<p>// The setup() method runs once, when the sketch starts<br />
void setup() { <br />
// initialize the digital pin as an output:<br />
pinMode(ledPin, <span class="caps">OUTPUT</span>); <br />
}</p>
<p>// the loop() method runs over and over again,<br />
// as long as the Arduino has power</p>
<p>void loop() <br />
{<br />
digitalWrite(ledPin, <span class="caps">HIGH</span>); // set the <span class="caps">LED</span> on<br />
delay(1000); // wait for a second<br />
digitalWrite(ledPin, <span class="caps">LOW</span>); // set the <span class="caps">LED</span> off<br />
delay(1000); // wait for a second<br />
}</p>
</typo:code>
<p>Now this will make the led blink:</p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/PS5UcEYQdBA&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/PS5UcEYQdBA&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<h3>Programming</h3>
<ul>
<li>C like language based o wiring</li>
<li>Write code and compile in <span class="caps">IDE</span></li>
<li>Upload compiled code using <span class="caps">USB</span></li>
<li>Hard to debug</li>
</ul>
<h3>Circuit Basics</h3>
<ul>
<li>Ground and power</li>
<li>Potential difference required for current ot flow</li>
<li>Conductors and resistors</li>
</ul>
<h3>Digital Inputs/Outputs</h3>
<ul>
<li>Digital pins on Arduino are dual purpose</li>
<li>Digital logic and voltage on = 5V off = 0V</li>
<li>Can be set to be input or output via pinMode</li>
</ul>
<h3>Variables</h3>
<ul>
<li>boolean, char, byte, int, long, float, double, string and array</li>
<li>int 16 bits, long 32 bits, float 32 bits</li>
<li>Strings are nul terminated ‘\0’</li>
<li>Declare by <datatype> <variable name>; eg int i;</li>
</ul>
<p>It’s actually C++…What?! At a Flex conferences :-)</p>
<h3>Setup Function</h3>
<ul>
<li>Used for initialization</li>
<li>Run when program loaded or board reset</li>
<li>Best place to place calls to pinMode</li>
</ul>
<h3>LEDs</h3>
<ul>
<li>Current will only flow in one direction</li>
<li>Longest pin connect to positive side, shortest to ground</li>
<li>Dont’ connect directly to power source use in series with resistors</li>
</ul>
<div style="text-align:center;"><img src="http://onrails.org/files/leds.png" alt="leds.png" border="0" width="300" height="225" /></div>
<h3>Resistors</h3>
<ul>
<li>Resistors limit current flowing through them</li>
<li>Value and tolerance indicated by cooler bands</li>
<li>Resistor values for LEDs</li>
<li>For <span class="caps">RGB</span> or <span class="caps">LEG</span> digits you need multiple resitors</li>
<li><span class="caps">REG</span>/<span class="caps">GREEN</span>/<span class="caps">BLUE</span> 180 oms, <span class="caps">WHITE</span>/<span class="caps">ULTRAVIOLET</span> 100 oms</li>
</ul>
<div style="text-align:center;"><img src="http://onrails.org/files/resistors.png" alt="resistors.png" border="0" width="300" height="225" /></div>
<h3>Debugging ia Serial Port</h3>
<ul>
<li>Use Serial.begin to set speed</li>
<li>Serial.print, Serial.println to output</li>
<li>Use serial monitor in <span class="caps">IDE</span> to view</li>
</ul>
<h3>Blinking <span class="caps">LED</span></h3>
<p>Same program that the first program but this time we just set the led to the pin 3 which is connected to the board.</p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/H_nD-bWSNuI&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/H_nD-bWSNuI&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<h3>Digital Inputs</h3>
<ul>
<li>Some logic as inputs; hight 95V0 or low (0V)</li>
<li>Simplest digital input switch</li>
<li>Call pinMode to set as digital input as input</li>
</ul>
<h3>Connect Switch</h3>
<ul>
<li>Wire up push button on breadboard</li>
<li>Change code to turn light on/off</li>
</ul>
<p>Now switches have three states (on, off, and in between) to the board needs to be wired to take that into account so you can program it accordingly. We added a very high resistence (10k) next to switch to ensure that the switch reports 0V when not clicked.</p>
<typo:code lang="javascript">
<p>int led = 3;<br />
int button = 4;</p>
<p>void setup() {<br />
Serial.begin(9600);<br />
pinMode(led, <span class="caps">OUTPUT</span>);<br />
pinMode(button, <span class="caps">INPUT</span>);<br />
}</p>
<p>void loop() {<br />
if (digitalRead(button) == <span class="caps">HIGH</span>) { <br />
Serial.println(“on”); <br />
digitalWrite(led, <span class="caps">HIGH</span>); <br />
} else {<br />
Serial.println(“off”); <br />
digitalWrite(led, <span class="caps">LOW</span>); <br />
}<br />
}</p>
</typo:code>
<p>So let’s look at the wiring and how the switch operates:</p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/45Haml5UCIc&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/45Haml5UCIc&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<h3>Internal Pullup Resistors</h3>
<ul>
<li>Set mode to input</li>
<li>digitalWrite to <span class="caps">HIGHT</span> to turn on</li>
<li>digitalWrite to <span class="caps">LOW</span> to turn off</li>
</ul>
<p>So there is something like the 10K resistor built-in the board to avoid using an extra resistor on the board to make sure the switch values are on or off.</p>
<h3>Switch Issues</h3>
<ul>
<li>Switches can bounce and give and off values while switching</li>
<li>Noise can give false results</li>
<li>More a problem when switching needs to be counted</li>
<li>Use timer to solve issue (time = millis())</li>
</ul>
<h3>Analog Inputs & Potentiometer </h3>
<ul>
<li>Can read values via analogRead</li>
<li>Result is in range 0 to 1023 (10 bits)</li>
<li>Potentiometer is Variable resistor</li>
<li>Eg Read potentiometer values with Analog Inputs</li>
</ul>
<typo:code lang="javascript">
<p>int led = 3;<br />
int pot = 0;</p>
<p>void setup() {<br />
Serial.begin(9600);<br />
pinMode(led, <span class="caps">OUTPUT</span>);<br />
}</p>
<p>void loop() {<br />
int value = analogRead(pot);<br />
digitalWrite(led, <span class="caps">HIGH</span>); <br />
// Set delay based on analog input<br />
delay(value);<br />
digitalWrite(led, <span class="caps">LOW</span>); <br />
delay(value);<br />
}</p>
</typo:code>
<p>So now when the potentiometer is turned to the right a value of 1023 is returned and the lights blinks on and off for about 1 seconds. Turning to the left makes the delay shorted (down to 0) and you can get it to run blink really fast.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/potentiometer.png" alt="potentiometer.png" border="0" width="400" height="300" /></div>
<h3><span class="caps">LDR</span></h3>
<ul>
<li>Light dependent resistor (high resistance)</li>
<li>Set flash rate based on value of <span class="caps">LDR</span></li>
</ul>
<p>This is a great full day tutorial and everyone seems to have fun. It’s pretty basic, but it’s the first time I program hardware.</p>
<p>Now we are writing fadeIn and fadeOut functions and get the light to pulse on and off</p>
<pre>
void fadeIn(int led) {
for (int i=0; i<256; i++) {
analogWrite(led, i);
delayMicroseconds(5000);
}
}
void fadeOut(int led) {
for (int i=255; i >= 0; i--) {
analogWrite(led, i);
delayMicroseconds(5000);
}
}
void loop() {
fadeIn(led);
fadeOut(led);
}
</pre>
<p>Now we replace the light sensor by a temperature sensor. There are also air quality sensors, breathalyzers.</p>
<h3>Flex</h3>
<p>Communication between Flex and Arduinos.</p>
<ul>
<li>Software on Arduino (Firmata)</li>
<li><span class="caps">USB</span> serial to socket proxy</li>
<li>Flex event based library to talk to socket (as3Glue)</li>
</ul>
<p>Firmata is an Arduino library that support a binary protocol over serial interface. It’s Bi-directiona. Use version 2.</p>
<p>In the Arduino <span class="caps">IDE</span> let’s load the StandardFirmata program (File|Examples|Firmata|StandardFirmata). It’s a 286 lines program similar to the code we wrote so far, but more complex.</p>
<p>Server Proxy</p>
<p>From http://arduino.cc/en/Main/Software the server proxy (end of page)</p>
<p>To configure proxy first find what your serial device is. <br />
In terminal do: ls /dev/cu*</p>
<p>/dev/cu.Bluetooth-Modem <br />
/dev/cu.Bluetooth-<span class="caps">PDA</span>-Sync <br />
/dev/cu.usbserial-A600ailA</p>
<p>Then add this line to your serproxy.cfg:<br />
serial_device=/dev/cu.usbserial-A600ailA</p>
<p>Then we just start the server proxy:<br />
$ ./serproxy <br />
Serproxy – ©1999 Stefano Busti, ©2005 David A. Mellis – Waiting for clients</p>
<p>Now in Flex you need to add the as3glue code (http://code.google.com/p/as3glue/) then you can drive arduino as follows:</p>
<pre>
private var arduino:Arduino = new Arduino();
private function init():void {
arduino.addEventListener(ArduinoEvent.FIRMWARE_VERSION, turnLedOn);
}
private function turnLedOn(event:ArduinoEvent):void {
arduino.setPinMode(13, Arduino.OUTPUT);
arduino.writeDigitalPin(13, Arduino.HIGH);
}
</pre>
<p>A qik look at the class room in the middle of coding their Flex app to drive their Arduino device:</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0" width="425" height="319" id="qikPlayer" align="middle"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="true" /><param name="movie" value="http://qik.com/swfs/qikPlayer5.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#333333" /><param name="FlashVars" value="streamID=515f621ccf514b6b8ad9dfb0c62ad851&autoplay=false" /><embed src="http://qik.com/swfs/qikPlayer5.swf" quality="high" bgcolor="#333333" width="425" height="319" name="qikPlayer" align="middle" allowScriptAccess="sameDomain" allowFullScreen="true" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" FlashVars="streamID=515f621ccf514b6b8ad9dfb0c62ad851&autoplay=false"></embed></object></p>
<p>Now we are going to write some Flex code to have some buttons that turn on/off some functions of the board.</p>
<pre>
private var arduino:Arduino = new Arduino();
private const pin:int = 3;
private const button:int = 4;
private function arduinoInit(event:Event):void {
arduino.enableDigitalPinReporting();
arduino.setPinMode(pin, Arduino.OUTPUT);
arduino.setPinMode(button, Arduino.INPUT);
arduino.addEventListener(ArduinoEvent.DIGITAL_DATA, buttonChanged);
}
private function buttonChanged(event:ArduinoEvent):void {
if (event.pin==button) {
event.value == Arduino.HIGH ? turnOn() : turnOff();
}
}
private function turnOn():void {
arduino.writeDigitalPin(pin, Arduino.HIGH);
}
private function turnOff():void {
arduino.writeDigitalPin(pin, Arduino.LOW);
}
</pre>
<p>Thanks Justin, great talk!</p>vault.ncaa.com : under the hood of a cool Flex project.2010-03-05T00:00:00-08:00http://onrails.org/2010/03/05/vault-ncaa-com-under-the-hood-of-a-cool-flex-project<div style="text-align:center;"><img src="http://onrails.org/files/vault.png" alt="vault.png" border="0" width="350" height="378" /></div>
<p><a href="http://www.thoughtequity.com">Thought Equity Motion</a> and <a href="http://www.ncaa.com/"><span class="caps">NCAA</span></a> two days ago officially released the <a href="http://vault.ncaa.com/">Ncaa Vault</a>. A cool Flex app backed by an incredible video database with awesome metedata about each game…and released just in time for March Madness.</p>
<p>Here are a few of the announcements and online articles describing the services:</p>
<ul>
<li><a href="http://www.thoughtequity.com/video/shell/txp/ncaa-and-thought-equity-motion-unveil-first-ever-video-powered-vault-for-ncaa-march-madness.do?title=NCAA®%20and%20Thought%20Equity%20Motion%20Unveil%20First%20Ever%20Video-Powered%20Vault%20for%20NCAA%20March%20Madness®?title=NCAA®%20and%20Thought%20Equity%20Motion%20Unveil%20First%20Ever%20Video-Powered%20Vault%20for%20NCAA%20March%20Madness®&mkid=tw_3-3-10">NCAA® and Thought Equity Motion Unveil First Ever Video-Powered Vault for <span class="caps">NCAA</span> March Madness®</a> – by Thought Equity</li>
<li><a href="http://www.nytimes.com/2010/03/03/sports/ncaabasketball/03ncaa.html">N.C.A.A. Tournament Goes Online, Clip by Clip</a> – by the New York Times</li>
<li><a href="http://www.wired.com/playbook/2010/03/say-hello-to-the-ncaa-vault-adieu-to-productivity/#ixzz0hGq1bpTzhttp://www.wired.com/playbook/2010/03/say-hello-to-the-ncaa-vault-adieu-to-productivity/">Say Hello to <span class="caps">NCAA</span> Vault, Adieu to Productivity</a> – by Wired</li>
</ul>
<p>In fact with the Vault you can have a <span class="caps">URL</span> right into a specific moment of any game and Wired picked out a great <a href="http://bit.ly/c9eQSU">last second tying shot</a>.</p>
<p>The twittersphere feedback is also <a href="http://search.twitter.com/search?q=vault+ncaa">pretty impressive</a>.</p>
<p>This is the most visible Flex app I worked on :-) Late January <a href="http://twitter.com/theaboutbox">Cameron Pope</a> contacted me to ask if I could help on a Flex project for <span class="caps">NCAA</span> and Thought Equity. The funny part is that I didn’t know that Cameron was such a great Flex developer, I met him via the Denver Ruby on Rails User Group (derailed) and I also didn’t know what <span class="caps">NCAA</span> was (don’t shoot, I didn’t grow up in the US and we don’t have TV). So when I asked my father in law about <span class="caps">NCAA</span> and realized it was about Basketball I was intrigued by what type of application we needed to build. Cameron showed me the mockups built by Donny Wells which is just an awesome graphical designer. These mockups where just incredible and then I was presented the video service technology the Thought Equity Motion team put together, and I was just blown away and though that this would be a cool project to work on.</p>
<p>Cameron was the main Flex developer and I just worked part time on Monday’s on this project. If you need and incredible Flex developer just contact Cameron.</p>
<p>Now let’s dive more into the Flex nitty-gritty details:</p>
<p>For the mvc architecture we used the <a href="http://swizframework.org/">Swiz Framework</a> and this turned out to work exceptionally well. Swiz sports some dependency injection features that can be enabled via the [Autowire] tag and I was surprised when I realized I could also just use that feature in an item render. Let’s look at a little detail…For the play by play timeline if a play is in the future it is displayed in bold:</p>
<div style="text-align:center;"><img src="http://onrails.org/files/timeline.png" alt="timeline.png" border="0" width="350" height="129" /></div>
<p>So each line of the timelime is rendered by the TimeLineItemRender and you can just autowire the model which contains the playhead position.</p>
<pre>
[Autowire]
[Bindable]
public var vaultModel:Vault;
</pre>
<p>The we can set the style name accordingly based on the play’s start time and the current playhead position:</p>
<pre>
styleName="{data.startTime < vaultModel.playheadPosition ? 'past' : 'future'}"
</pre>
<p>The style of the application was created by the designer and Cameron did a great job reproducing it using <a href="http://www.degrafa.org/">Degrapha</a> for skinning () using an approach similar to this <a href="http://www.degrafa.org/source/ButtonLoader/ButtonLoader.html">example</a> (example <a href="http://www.degrafa.org/source/ButtonLoader/srcview/index.html">source</a>)</p>
<p>Most of my work was around the searching, bug fixing and general architecture overview. We took a similar approach to the one I described <a href="http://onrails.org/articles/2007/11/27/flash-utils-bytearray-compressing-4-1mb-to-20k">here</a> in order to avoid most of the server round trips during searching.</p>
<p>The Flex app is just a pretty face, behind the scene Thought Equity provides an incredible services that they will expose in many ways, the start can be seen <a href="http://www.thoughtequity.com/video/home/article/ncaa_vault_publishing.do">here</a> and all that data will be able to be accessed via <span class="caps">API</span> and other means.</p>
<p>This was a short but incredible project for me, the guys at Though Equity have such an incredible vision on how to turn these sport videos into something so much bigger! Thank you guys for getting me on board.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/thoughtequity.png" alt="thoughtequity.png" border="0" width="245" height="30" /></div>
<p>Enjoy!<br />
Daniel Wanja</p>Time.onrails.org is closing!2010-02-18T00:00:00-08:00http://onrails.org/2010/02/18/time-onrails-org-is-closing<p>I just send an email to thousands of users to notify them that time.onrails.org is closing down. I don’t think many of these users are active but just in case I wanted everyone to be able to get their data out of the system if so they wished.</p>
<p>I will turn down the service on March 17th at 9pm.</p>
<p>Now why in the hell would I close this service. In brief I created it for myself on the plane to RubyConf 2005, thought it was cool and opened it to the public in April 2006. I haven’t updated the code much since many years and just don’t have the time to add new features, and trust me Rails code from 2005 looks slightly different than nowadays Rails code.</p>
<p>For posterity here is the “official” announcement blog entry of the creation of the service:</p>
<p><a href="http://onrails.org/articles/2006/04/13/new-background-color-yellow-color-rgb-0-0-0-launch-time-onrails-org-time-tracking-made-simple">April 13, 2006 – <span class="caps">LAUNCH</span> time.onrails.org, time tracking made simple! </a></p>
<p>And here are <a href="http://onrails.org/articles/category/time-onrails-org">few more articles</a> related to time.onrails.org.</p>
<p>Here is part of the email I send to the users:</p>
<p><cite><br />
Time.onrails.org is closing down March 17th 2010 at 9pm Mountain time.</p>
<p>You can export your time entry for each project by clicking on the export buttons at the bottom of each project page or you can export your full account by just login and then go to this url:</p>
<p>Â Â http://time.onrails.org/export/xml/user</p>
<p>This will export each of the projects will all sections including the notes.</p>
<p>Please start transitioning to a new service now.</p>
<p>As a replacement service I would suggest harvest (http://www.getharvest.com/) which offers a free plan which allows for 2 projects, 4 clients, unlimited invoicing for 1 user absolutely <span class="caps">FREE</span>.</p>
<p>Thank you to all the users over the years I hope you enjoyed this free service. Time.onrails.org enjoyed thousands of users and I received many nice complimenting emails for the service over the years. The main reason that I close this service is that I am starting to use harvestapp for my own time tracking. I wrote time.onrails.org back in 2005 just for fun and thought it could be useful to others. It fulfilled my needs of keeping track of time for the various customer projects I worked on over the last few years.</p>
<p>Since we moved to slicehost it was very stable and I just have good things to say about slicehost, they are just great. Recently one of the slice time.onrails.org was running on had issues and got moved twice over two days. Again slicehost was on top of that situation and I just sat back and they did all the work. But this also reminded me that I cannot just keep the service running without giving it the time and effort it deserves and just now I don’t have that time as I am working on other projects, such as http://appsden.com.</p>
<p>So I went on the search for a replacement service and  looked at many out there. And Harvest just added the timestamp feature, which is exactly how I track time, their app is more fleshed out than time.onrails.org, so I decided to move over to use their services.</p>
<p>The great news is while I tweeted about my move to Harvest, Doug, which I knew from his time in Denver mentioned that he now works for Harvest. So he put me in contact with the cofounder and I asked him if they could get some deal for my current users, and they where very responsive and create a special promo code. Thanks for that and I hope you try and enjoy their services. Just for disclaimer I didn’t ask for any monetization or anything for referring you to Harvest, the idea was just to have an alternate offering in case you needed one. But they offered me a free Solo plan, so hey, at least I got that out of this whole ordeal.</p>
<p>Please don’t hesitate to contact me for any question at daniel@onrails.org.</p>
<p>Thank you again for having tried out or being a user of time.onrails.org over all these years.</p>
<p>Kind regards,<br />
Daniel Wanja<br />
</cite></p>Rails 3: Rack Middleware2010-02-18T00:00:00-08:00http://onrails.org/2010/02/18/rails-3-rack-middleware<p>I’m watching the <a href="https://oreillymedia.webex.com/mw0306l/mywebex/default.do?siteurl=oreillymedia">Rails Online Conference</a>, February 2010 Exploring Rails 3 and really like how they setup the rack middleware.</p>
<p>…From the slides.</p>
<h1>Rack Middleware</h1>
<p><a href="http://github.com/rack/rack/tree/master/lib/rack">http://github.com/rack/rack/tree/master/lib/rack</a></p>
<h3>Content Modifying</h3>
<pre>
Rack::Chunked
Rack::ContentLength
Rack::ConditionalGet
Rack::ContentType
Rack::Deflater
Rack::ETag
Rack::Head
Rack::MethodOverride
Rack::Runtime
Rack::Sendfile
Rack::ShowStatus
</pre>
<h3>Behavioral</h3>
<pre>
Rack::CommonLogger
Rack::Lint
Rack::Lock
Rack::Reloader
</pre>
<h3>Routing</h3>
<pre>
Rack::Cascade
Rack::Recursive
Rack::Static
Rack::URLMap
</pre>
<h1>Rack::Contrib</h1>
<p><a href="http://github.com/rack/rack-contrib">http://github.com/rack/rack-contrib</a></p>
<pre>
Rack::AcceptFormat
Rack::Access
Rack::Backstage
Rack::Callbacks
Rack::Config
Rack::Cookies
Rack::CSSHTTPRequest
Rack::Deflect
Rack::Evil
Rack::HostMeta
Rack::JSONP
Rack::LighttpdScriptNameFix
Rack::Locale
Rack::MailExceptions
Rack::NestedParams
Rack::NotFound
Rack::ProcTitle
Rack::Profiler
Rack::ResponseCache
Rack::ResponseHeaders
Rack::RelativeRedirect
Rack::Signals
Rack::SimpleEndpoint
Rack::TimeZone
</pre>
<h1>Coderack.org</h1>
<p>Check also out <a href="http://coderack.org/">http://coderack.org</a> …99 pieces of Rack Middleware</p>
<h1>RailsGuide: Rails On Rack</h1>
<p><a href="http://guides.rubyonrails.org/rails_on_rack.html">http://guides.rubyonrails.org/rails_on_rack.html</a></p>Mi-Fi 1.1 in AppStore Now and what I learned along the way...2009-11-17T00:00:00-08:00http://onrails.org/2009/11/17/mi-fi-1-1-in-appstore-now-and-what-i-learned-along-the-way<p>During <a href="http://www.360idev.com/">360idev</a> (Sept 27-30) I wrote a small app to check the battery and connectivity level of my <a href="http://www.verizonwireless.com/multimedia/360_demos/mifi_2200_hotspot/">Mifi Card</a>. I didn’t think many people would have an iPhone and a Mifi card. The iPhone is already 3g, but effectively there is not tethering allowed and the AT&T network is crapy. Nevertheless I thought my <a href="http://itunes.apple.com/us/app/mi-fi/id333601535?mt=8">Mi-Fi App</a> could be useful to others and along the way I would learn what it takes to submit an app to the AppStore.</p>
<p><br/>
I submitted the app on September 29th (during 360idev) and it was approved on October 12th. I submitted two other version since and last Monday I started collecting details of my experience of the AppStore, thoughts on the process, and various tibits around the web regarding this app and started writing this blog entry, but didn’t finished it as it was getting too late. Then last week I stumbled upon this article of <a href="http://www.rogueamoeba.com/utm/2009/11/13/airfoil-speakers-touch-1-0-1-finally-ships/">Rogue Amoeba</a> which detailed their experience with the store. I could relate on the feeling of waiting to know if you apps goes through or not, but fortunately the process took only two weeks for the first release. However I only had a Verizon card and was so eager to submit my app that I didn’t wait to find someone with a Sprint card. And of course the first version didn’t work with the Sprint card. Around the time the first version was approved I wrote a fix to support the Sprint cards and submitted that fix as version 1.1. Thanks to <a href="http://twitter.com/2busy2blog/"><code>2busy2blog</a> and <a href="http://twitter.com/pdsphil">pdsphil</a> for helping supporting the Sprint version. Then before it got approved Verizon put out a firmware update for their Mi-Fi card which of course broke version 1.1 (and 1.0). So I updated my Mi-Fi card and wrote a new version which additionally added support for the GSM version of the Mi-Fi card thanks to <a href="http://twitter.com/jkkmobile/"></code>jkkmobile</a>. That’s when I made a mistake…I wasn’t sure how to submit a new version when there is one waiting for approval so I just replaced the binary. What I didn’t know is that updating the binary puts you to the back of the queue. And I submitted version 1.1 two weeks before, and it took two more weeks to approve this “new” version 1.1 which was fortunately approved. Now I am not sure how they tested my app as it requires a piece of hardware. So maybe part of the two weeks is to find an approver that had a mifi card.</p>
<p><br/>
So all this approval process was new to me and indeed very frustrating when you are used to deploy several times a day fixes to your application in a “web” world. Now this is just a different paradigm and wether you like it or not thats’ the rules you need to play with (for the moment). That means several things. First your application must be tested way better before submitting and be more resilient to different scenarios. If you really have a bug that “Kills” you are just out of luck. It’s similar to developers writing games for the Nintendo DS…once you ship it…tough luck. Note the situation is slightly better, but if you have a fatal bug then people may never give it a second look, not time to cover up issues in a timely fashion. So Apple must find a way to allow fixes to be submitted and approved in a shorter time frame. Maybe two queues for approvals? Now I must admit the Rogue Amoeba guys had a different issue and they had to cripple their application just to have it approved and that for reasons that don’t make sense. Again this was an update to an application that was previously approved, so the wait time has to be way shorter and then again there needs to be some sort of “appeal” process where developers can justify why the app really should be approved.</p>
<p><br/>
Now you may argue why an approval process at all, why don’t let the user decide what to install. You may certainly not agree with me, but I like the fact that I can install apps and know they won’t reck my iPhone. I don’t think with an OS and an <span class="caps">SDK</span> like the iphone that this could be automated. Maybe an automation build where the apps are compiled by Apples and the compiler could check for any api call infringements? That would be fair, no? I don’t think no approval process is viable for the Apple as this would open the door to malware applications and even though many more savvy users would avoid bad apps the majority of users could end up just downloading any thing, would have issues, and that would be a bigger nightmare than facing the unhappy users. So in the mean time the iPhone development ecosystem is what it is and the platform is too cool to ignore. I’ll be working on several more iPhone apps over the next few months.</p>
<h2>But will it make me rich?</h2>
Well, that was not the intend of the Mi-Fi app and I sold it for $0 and I can assume that I won’t make it up in numbers. So what are the numbers?
<div style="text-align:center;"><img src="http://onrails.org/files/download.png" alt="download.png" border="0" width="500" /></div>
<p>As of today a little more than 2000 downloads which includes 695 upgrades. Wouhao, AT&T must really suck to have that many people that may potentially have an iPhone and a Mi-Fi card. Note these number are ridiculous compared to certain apps that get downloaded thousands a time a day, but hey, it’s all about learning here for me :-)</p>
<p>The interesting thing is that when Andy Ihnatko <a href="http://twitter.com/Ihnatko/statuses/5030359521">tweeted about it </a>and Robert Scoble <a href="http://friendfeed.com/scobleizer/c3263f8f/ihnatko-this-is-must-have-iphone-app-for-mifi">re-tweeted it</a> the downloads made a nice bump:</p>
<p><cite>“This is a must-have iPhone app for MiFi users: shows complete status of device. http://j.mp/2HBsso — big thanks to @2busy2blog – Andy Ihnatko”</cite></p>
<p>And it shows of the iPhone community is active as many iPhone blogs picked on it, here are a few reviews:</p>
<ul>
<li><a href="http://www.macsparky.com/2009/10/23/mifi-iphone-application">http://www.macsparky.com/2009/10/23/mifi-iphone-application</a></li>
<li><a href="http://www.gadgetreview.com/2009/10/mi-fi-iphone-app-monitors-your-mifis-battery-connections-and-more.html">http://www.gadgetreview.com/2009/10/mi-fi-iphone-app-monitors-your-mifis-battery-connections-and-more.html</a></li>
<li><a href="http://jkontherun.com/2009/10/23/iphone-app-monitors-mifi-3g-usage/">http://jkontherun.com/2009/10/23/iphone-app-monitors-mifi-3g-usage/</a></li>
<li><a href="http://www.gottabemobile.com/2009/10/23/do-you-use-mifi-with-your-iphoneipod-touch-theres-an-app-for-that">http://www.gottabemobile.com/2009/10/23/do-you-use-mifi-with-your-iphoneipod-touch-theres-an-app-for-that</a></li>
<li><a href="http://www.iphonefreak.com/2009/11/mi-fi-app-for-the-iphone-ipod-touch-gets-an-update.html">http://www.iphonefreak.com/2009/11/mi-fi-app-for-the-iphone-ipod-touch-gets-an-update.html</a></li>
<li><a href="http://www.appstorehq.com/mi-fi-iphone-78445/app">http://www.appstorehq.com/mi-fi-iphone-78445/app</a></li>
<li><a href="http://appsearch.justanotheriphoneblog.com/mi-fi-iphone-78445/app">http://appsearch.justanotheriphoneblog.com/mi-fi-iphone-78445/app</a></li>
<li><a href="http://iphoneblips.dailyradar.com/story/iphone-app-monitors-mifi-3g-usage/">http://iphoneblips.dailyradar.com/story/iphone-app-monitors-mifi-3g-usage/</a></li>
<li><a href="http://www.zatznotfunny.com/2009-10/the-mifi-updates/">http://www.zatznotfunny.com/2009-10/the-mifi-updates/</a></li>
<li><a href="http://technews.am/conversations/gottabemobile.com/iphone_mifi_app_needs_still_needs_some_work">http://technews.am/conversations/gottabemobile.com/iphone_mifi_app_needs_still_needs_some_work</a></li>
<li><a href="http://gearshrine.com/iPhone/opinion:iphone-app-monitors-mifi-3g-usage/">http://gearshrine.com/iPhone/opinion:iphone-app-monitors-mifi-3g-usage/</a></li>
</ul>
<p>So this was a good first learning experience and hopefully there will be more.</p>
<p>Enjoy!<br />
Daniel</p>Amazon RDS: Amazon Relational Database Service or MySQL in the Cloud for Ruby On Rails.2009-10-29T00:00:00-07:00http://onrails.org/2009/10/29/amazon-rds-amazon-relational-database-service-or-mysql-in-the-cloud-for-ruby-on-rails<p>For watchthatsite.com (not public yet) I have an instance on EC2 with Rails and MySQL but was looking for a more solid hosting solution for MySQL. And how fortunate, Amazon came out with the solution I need this week. Basically with two command line instructions you can start a new server with mysql configured, tuned, and secured. In this blog entry I will go through the steps that perform to move my sql database to Amazon <span class="caps">RDS</span>.</p>
<p>You can find more information on Amazon Relational Database Service (<span class="caps">API</span> Version 2009-10-16) <a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=2927&categoryID=290">here</a>.</p>
<p>Prerequisite: you need to <a href="http://aws.amazon.com/">signup</a> for an account on aws.amazon.com, it can be used for EC2, S3, SimpleDb and all the other services <span class="caps">AWS</span> provides.</p>
<h2>1) Install the Command Line Toolkit</h2>
<p>First thing, go download the command line toolkit and read the <span class="caps">README</span>.<span class="caps">TXT</span> on how to install it. In short you unzip the files, I did put mine at /Developer/aws/RDSCli-1.0.001. Then you create a credential file which contains your <span class="caps">AWS</span> access key id and secret key. Then I configured my ~/.bash_profile as follows:</p>
<typo:code>
<p>export AWS_RDS_HOME=/Developer/aws/RDSCli-1.0.001<br />
export AWS_CREDENTIAL_FILE=$AWS_RDS_HOME/credential-file-path.conf<br />
export JAVA_HOME=/Library/Java/Home<br />
export <span class="caps">PATH</span>=$AWS_RDS_HOME/bin:$<span class="caps">PATH</span></p>
</typo:code>
<p>to see that the command line toolkit is setup correctly type $rds —help</p>
<p>You will need the command line tool to execute several commands described here after.</p>
<h2>2) Create an Instance</h2>
<p>Let’s create a MySQL Server instance. <span class="caps">RDS</span> offers the following 5 server instance classes:</p>
<ul>
<li>db.m1.small (1.7 GB of <span class="caps">RAM</span>, $0.11 per hour)</li>
<li>db.m1.large (7.5 GB of <span class="caps">RAM</span>, $0.44 per hour)</li>
<li>db.m1.xlarge (15 GB of <span class="caps">RAM</span>, $0.88 per hour)</li>
<li>db.m2.2xlarge (34 GB of <span class="caps">RAM</span>, $1.55 per hour)</li>
<li>db.m2.4xlarge (68 GB of <span class="caps">RAM</span>, $3.10 per hour)</li>
</ul>
<p>I will choose a small instance which I will call dbserver1 with a database name db1 and allocate 5g of database space. I also set the master username as admin and password as secret.</p>
<typo:code>
<p>$ rds-create-db-instance —db-instance-identifier db1 —allocated-storage 5 —db-instance-class db.m1.small —engine MySQL5.1 —master-username admin —master-user-password secret —db-name db1 —headers</p>
</typo:code>
<p>The output is the following:</p>
<typo:code>
<p><span class="caps">DBINSTANCE</span> DBInstanceId Class Engine Storage Master Username Status Backup Retention<br />
<span class="caps">DBINSTANCE</span> db1 db.m1.small mysql5.1 5 admin creating 1 <br />
<span class="caps">SECGROUP</span> Name Status<br />
<span class="caps">SECGROUP</span> default active<br />
<span class="caps">PARAMGRP</span> Group Name Apply Status<br />
<span class="caps">PARAMGRP</span> default.mysql5.1 in-sync</p>
</typo:code>
<p>Now you have a server running and you are being billed $0.11 per hour, that’s like $80 a month without bandwidth but with backup…and it took only 2 minutes to get going. Can’t beat that.</p>
<p>To see all the instances you have you can issue the</p>
<typo:code>
<p>rds-describe-db-instances —headers</p>
</typo:code>
<h2>3) Grant Network Access</h2>
<p>So I will grant access from my notebook, assuming the ip address is 24.19.0.48 (you can also specify ranges i.e. 24.19.0.0/50). (Note that access was revoked by <span class="caps">AWS</span>, not sure why??)</p>
<typo:code>
<p>rds-authorize-db-security-group-ingress default —cidr-ip 24.19.0.48 —headers</p>
</typo:code>
<p>I also have an ec2 instance which I want to grant access to</p>
<typo:code>
<p>rds-authorize-db-security-group-ingress default —ec2-security-group-name watchthatsite —ec2-security-group-owner-id 526541544691</p>
</typo:code>
<p>Note the ec2-security-group-owner-id is your Amazon <span class="caps">AWS</span> account number, you can find it for example on you account activity page. To see your security configuration issue the following command: rds-describe-db-security-groups default —headers</p>
<h2>4) Using the Database</h2>
<p>To use your database you first need to find out the endpoint address of your new server. So describe you instances:</p>
<typo:code>rds-describe-db-instances —headers command</typo:code>
<typo:code>
<p><span class="caps">DBINSTANCE</span> DBInstanceId Created Class Engine Storage Master Username Status Endpoint Address Port AZ Backup Retention<br />
<span class="caps">DBINSTANCE</span> db1 2009-10-28T22:53:31.666Z db.m1.small mysql5.1 5 admin available db1.cyhik6zpub5c.us-east-1.rds.amazonaws.com 3306 us-east-1b 1 <br />
<span class="caps">SECGROUP</span> Name Status<br />
<span class="caps">SECGROUP</span> default active<br />
<span class="caps">PARAMGRP</span> Group Name Apply Status<br />
<span class="caps">PARAMGRP</span> default.mysql5.1 in-sync</p>
</typo:code>
<p>You find out your endpoint address, for me db1.cyhik6zpub5c.us-east-1.rds.amazonaws.com</p>
<p>So now you can connect to your database:</p>
<typo:code>
<p>mysql -h db1.cyhik6zpub5c.us-east-1.rds.amazonaws.com -P 3306 -u admin -p db1</p>
</typo:code>
<p>Let’s configure my Rails application to point to that database and run a migration:</p>
<p>So I change my config/database.yml to point to the above database</p>
<typo:code>
<p>development:<br />
adapter: mysql<br />
host: db1.cyhik6zpub5c.us-east-1.rds.amazonaws.com<br />
reconnect: false<br />
database: db1<br />
username: admin<br />
password: secret</p>
</typo:code>
<typo:code>
rake db:migrate
</typo:code>
<p>Wow, seem to work.</p>
<p>Let connect to the mysql console and do a show tables;</p>
<pre>
+-------------------+
| Tables_in_db1 |
+-------------------+
| schema_migrations |
| users |
| watches |
+-------------------+
</pre>
<p>Yep, all there.</p>
<p>Now I still have to move my old production database to the new one, so let’s dump the data from my old database:</p>
<typo:code>
<p>mysqldump watchthatsite_development -u admin > wts.sql</p>
</typo:code>
<p>and reload that data in the new database:</p>
<typo:code>
<p>mysql -h db1.cyhik6zpub5c.us-east-1.rds.amazonaws.com -P 3306 -u admin -p db1 < wts.sql</p>
</typo:code>
<p>Restarting my Rails server…That’s all!</p>
<p>Enjoy,<br />
Daniel.</p>You Mifi card status iPhone App on the Available on the AppStore now.2009-10-14T00:00:00-07:00http://onrails.org/2009/10/14/you-mifi-card-status-iphone-app-on-the-available-on-the-appstore-nowIf you have an iPhone and like several people i know you didn't tether it and you are not happy with AT&T's 3G network chances are you have a Mifi 2200 card from Sprint or Verizon. These Mifi cards are pretty cool and now you can use the <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=333601535&mt=8">Mi-Fi</a> app from your iPhone and see the following status: Battery Level, Connectivity, Data Received and Transmitted (since connected), Time Connected and IP address. Try it out and if you like it rate it!
Enjoy!
Daniel.
<div style="text-align:center;">
<img src="http://onrails.org/files/mi-fi.png" alt="mi-fi.png" border="0" width="250" />
<a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=333601535&mt=8"><img src="http://appsden.com/apps/marketing_badge.png" /></a>
</div>
360iDev is next week in Denver...and it's nearly sold out!2009-09-23T00:00:00-07:00http://onrails.org/2009/09/23/360idev-is-next-week-in-denver-and-its-nearly-sold-out<p><a href="http://360idev.com/">360iDev</a> is around the corner and if you know the organizers or have been to 360flex then you know Denver is the place to be starting next Sunday if you are or wanna be an iPhone developer. The conference starts with a day of tutorials on Sunday then kicks in full gear Monday through Wednesday with three tracks of 80 minute sessions covering all angles of iPhone development from some of the best authorities in the fields.</p>
<p>You can find the schedule as <a href="http://www.google.com/calendar/ical/f10f3ii076fjkoq17qn9fsphvc%40group.calendar.google.com/public/basic.ics"> ical</a> or <a href="http://360idev.com/downloads/schedule.pdf">download a pdf</a></p>
<p>Here is my schedule:</p>
<p>On Sunday I’ll attend the “Hands-On with the Appcelerator platform.” session.</p>
<p><strong>Monday</strong></p>
<div style="text-align:center;"><img src="http://onrails.org/files/360idev_monday.png" alt="360idev_monday.png" border="0" width="500"/></div>
<p><strong>Tuesday</strong></p>
<div style="text-align:center;"><img src="http://onrails.org/files/360idev_tuesday.png" alt="360idev_tuesday.png" border="0" width="500" /></div>
<p><strong>Wednesday</strong></p>
<div style="text-align:center;"><img src="http://onrails.org/files/360idev_wednesday.png" alt="360idev_wednesday.png" border="0" width="500" /></div>
<p>If you are not <a href="http://360idev-blogpost.eventbrite.com/">signed up</a> yet…you better hurry.</p>
<p>I hope I’ll see you there!</p>
<p>Daniel</p>RMagick (from source) on Snow Leopard2009-09-04T00:00:00-07:00http://onrails.org/2009/09/04/rmagick-from-source-on-snow-leopard<p>After the release of 10.5, I published an article about <a href="http://onrails.org/articles/2007/11/03/installing-rmagick-on-leopard-without-macports-or-fink">building RMagick from source on Leopard</a>. I won’t rehash the why, you can read the original article for that. My clean install necessitated updating the RMagick script, so here’s what worked for me to install from source on Snow Leopard! For the impatient, here’s the download link: <a href="http://onrails.org/files/rmagick-build.sh">rmagick-build.sh</a></p>
<p>First, we start with installing <code>wget</code>, as it seems to be a bit more clever than <code>curl</code> about dealing with mirrors, etc. Then, we compile and install each prerequisite package. Finally, we install the gem.</p>
<p>All the links in the script worked for me, but, depending on your location, network, conditions, etc, your mileage may vary. Enjoy!</p>
<typo:code>
<p>#!/bin/sh</p>
<ol>
<li>install wget, which is cleverer than curl<br />
curl -O http://ftp.gnu.org/gnu/wget/wget-1.11.tar.gz<br />
tar zxvf wget-1.11.tar.gz <br />
cd wget-1.11<br />
./configure —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd /usr/local/src</li>
</ol>
<ol>
<li>prerequisite packages<br />
wget http://nongnu.askapache.com/freetype/freetype-2.3.9.tar.gz<br />
tar zxvf freetype-2.3.9.tar.gz<br />
cd freetype-2.3.9<br />
./configure —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd /usr/local/src</li>
</ol>
<p>wget http://superb-west.dl.sourceforge.net/sourceforge/libpng/libpng-1.2.39.tar.gz<br />
tar zxvf libpng-1.2.39.tar.gz<br />
cd libpng-1.2.39<br />
./configure —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd /usr/local/src</p>
<p>wget ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz<br />
tar xzvf jpegsrc.v6b.tar.gz<br />
cd jpeg-6b<br />
ln -s `which glibtool` ./libtool<br />
export MACOSX_DEPLOYMENT_TARGET=10.6<br />
./configure —enable-shared —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd /usr/local/src</p>
<p>wget ftp://ftp.remotesensing.org/libtiff/tiff-3.9.1.tar.gz<br />
tar xzvf tiff-3.9.1.tar.gz<br />
cd tiff-3.9.1<br />
./configure —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd /usr/local/src</p>
<p>wget http://superb-west.dl.sourceforge.net/sourceforge/wvware/libwmf-0.2.8.4.tar.gz<br />
tar xzvf libwmf-0.2.8.4.tar.gz<br />
cd libwmf-0.2.8.4<br />
make clean<br />
./configure<br />
make<br />
sudo make install<br />
cd /usr/local/src</p>
<p>wget http://www.littlecms.com/lcms-1.17.tar.gz<br />
tar xzvf lcms-1.17.tar.gz<br />
cd lcms-1.17<br />
make clean<br />
./configure<br />
make<br />
sudo make install<br />
cd /usr/local/src</p>
<p>wget ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/<span class="caps">GPL</span>/gs870/ghostscript-8.70.tar.gz<br />
tar zxvf ghostscript-8.70.tar.gz<br />
cd ghostscript-8.70<br />
./configure —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd /usr/local/src</p>
<p>wget ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/<span class="caps">GPL</span>/gs860/ghostscript-fonts-std-8.11.tar.gz<br />
tar zxvf ghostscript-fonts-std-8.11.tar.gz<br />
sudo mv fonts /usr/local/share/ghostscript</p>
<ol>
<li>Image Magick<br />
wget ftp://ftp.fifi.org/pub/ImageMagick/ImageMagick.tar.gz<br />
tar xzvf ImageMagick.tar.gz<br />
cd `ls | grep ImageMagick-`<br />
export <span class="caps">CPPFLAGS</span>=-I/usr/local/include<br />
export <span class="caps">LDFLAGS</span>=-L/usr/local/lib<br />
./configure —prefix=/usr/local —disable-static —with-modules —without-perl —without-magick-plus-plus —with-quantum-depth=8 —with-gs-font-dir=/usr/local/share/ghostscript/fonts —disable-openmp<br />
make<br />
sudo make install<br />
cd /usr/local/src</li>
</ol>
<ol>
<li>RMagick<br />
sudo gem install rmagick<br />
</typo:code></li>
</ol>
<p><b style="color:red"><span class="caps">UPDATE</span></b> There is a bug with libgomp that breaks the <code>convert</code> utility (See comments below). the <code>--disable-openmp</code> configure option has been added to the script to fix this.</p>
<p><b style="color:red"><span class="caps">UPDATE</span> 2</b> A new patchlevel of ImageMagick has been released that supersedes the original one referenced in this script, and the original has been removed from the server. Thanks to Sebastian for this update that will grab the latest release.</p>Introducing Hashdown2009-08-04T00:00:00-07:00http://onrails.org/2009/08/04/introducing-hashdown<p>If your database is normalized, you will almost always end up with small tables (often referred to as reference data or lookup tables) which provide a set of possible values for a particular attribute. (e.g. Currency, Category, etc.) A common pattern that emerges in many applications is accessing these records by a symbolic name (as opposed to by id) for purposes of clarity when reading the code. In C (and friends), the database ids can be mapped to the positions of an enum datatype. I recently released the <a href="https://github.com/rubysolo/hashdown">hashdown</a> plugin that provides hash-like access for reference data records, and also adds some dropdown option list generation support, since this data is often used to populate select list in forms.</p>
<p>As an example of what hashdown does, suppose we have the following model:</p>
<typo:code lang="ruby">
<p>class CardType < ActiveRecord::Base<br />
end</p>
</typo:code>
<p>with the following data:</p>
<typo:code>
<p><ins><del>-</del>-</ins>———-<ins><del>-</del>———————-</ins><br />
| id | code | name |<br />
<ins>====</ins>=+====+<br />
| 1 | visa | Visa |<br />
| 2 | mc | MasterCard |<br />
| 3 | disc | Discover |<br />
| 4 | amex | American Express |<br />
<ins><del>-</del>-</ins>———-<ins><del>-</del>———————-</ins></p>
</typo:code>
<p>By adding the following line to the model:</p>
<typo:code lang="ruby">
<p>class CardType < ActiveRecord::Base<br />
finder :code<br />
end</p>
</typo:code>
<p>You get the functionality of a hash-like square-bracket accessor for the model that will let you do something like:</p>
<typo:code lang="ruby">
<p>@order.card_type = CardType[:visa]</p>
</typo:code>
<p>The underlying implementation is similar to:</p>
<typo:code lang="ruby">
<p>def CardType < ActiveRecord::Base<br />
def self.[](value)<br />
find_by_code(value)<br />
end<br />
end</p>
</typo:code>
<p>…except it adds a caching layer to boost performance by preventing repeated database access.</p>
<p>Adding the following directive:</p>
<typo:code lang="ruby">
<p>def CardType < ActiveRecord::Base<br />
selectable<br />
end</p>
</typo:code>
<p>to the model gives you a class method called <code>select_options</code> that can be used to populate a select list like this:</p>
<typo:code lang="ruby">
<p><%= form.select :card_type_id, CardType.select_options %></p>
</typo:code>
<p>produces:</p>
<typo:code lang="html">
<input type="select" name="order[card_type_id]" id="order_card_type_id">
<option value="1">Visa</option>
<option value="2">MasterCard</option>
<option value="3">Discover</option>
<option value="4">American Express</option>
</input>
</typo:code>
<p>By default, this will use the <code>id</code> attribute as the submitted value of the option and call a <code>display_name</code> method (if it exists) for the displayed value of the option, falling back to the <code>name</code> method/attribute. Each of these can be overridden by passing a symbol attribute / method name, or a lambda that will be executed to generate the value. For (a contrived) example:</p>
<typo:code lang="ruby">
<p><%= form.select :card_type_id, CardType.select_options(:key => :code, :value => lambda{|card_type| card_type.name.reverse }) %></p>
</typo:code>
<p>produces:</p>
<typo:code lang="html">
<input type="select" name="order[card_type_id]" id="order_card_type_id">
<option value="visa">asiV</option>
<option value="mc">draCretsaM</option>
<option value="disc">revocsiD</option>
<option value="amex">sserpxE naciremA</option>
</input>
</typo:code>
<p>Again, the <code>select_option</code> results are cached for better performance.</p>
<p>This is a pretty small plugin that I’m using to <span class="caps">DRY</span> up some code in a current project I’m working on. Let me know if you have feature requests (or fork and patch it on <a href="https://github.com/rubysolo/hashdown">GitHub</a>!)</p>Behind the scene: Quiltivate.com a beautiful Flex on Rails website.2009-07-16T00:00:00-07:00http://onrails.org/2009/07/16/behind-the-scene-quiltivate-com-a-beautiful-flex-on-rails-websiteI met Phil several years ago at Derailed, the (Denver Ruby on Rails user group, and for a long time he was curious about how Flex can be integrated with Rails, about the graphical possibilities that Flex offers, the advantages over plain HTML/CSS/Javascript. Then he told me Kacie, his wife, had an idea about a website. She is passionate about quilts and has an eye for details and excellence. Phil is a geek that loves Rails, Kacie loves quilts, it's like Quilting meets Web 2.0 and <a href="http://quiltivate.com/">quiltivate.com</a> was born. In fact Phil and Kacie hired me to create a Quilt Builder that integrates with <a href="http://quiltivate.com/">Quiltivate.com</a>. Kacie had the vision for the whole concept, a simple to use quilt builder that removes lots of the hassle of calculating how much fabric of what color is needed and allows to play with blocks, shapes and colors. She drew a paper prototype that really highlights the tag line of their site" Innovating Traditional Quilting". <a href="http://quiltivate.com/">Quiltivate.com</a> offer much more than a Quilt Builder, it's a blog and a community centered around the art and craft of quilting. Over the last year I spent a couple of hours here and there, well a little more than that, to transform the paper prototype into a real Flex application. Rather than writing about what the tool does and how it does it, let's have a little look at behind the scene of the Quilt Builder with this video:
<object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5619106&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=5619106&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><p><a href="http://vimeo.com/5619106">Behind the scene: Quiltivate.com a beautiful Flex on Rails website.</a> from <a href="http://vimeo.com/user507500">daniel wanja</a>.</p>
Check out <a href="http://quiltivate.com/">quiltivate.com</a> for a video on how to really use the Quilt Builder and go try it out. As it's fresh out of the gates their may be a little quirks here and there, so please let me know what you find. So thank you Kacie and Phil for getting me on this project, it was really fun!
Enjoy,
Daniel.
Screencast: Testing Flex Apps with Cucumber - Take 22009-07-13T00:00:00-07:00http://onrails.org/2009/07/13/screencast-testing-flex-apps-with-cucumber-take-2I was not really happy with <a href="http://onrails.org/articles/2009/07/08/screencast-testing-flex-apps-with-cucumber">last week's screencast</a> I did on testing Flex with Cucumber. Effectively doing screencast is not an easy endeavor and trying to it myself is making me appreciate all the other screencast I watch so much more. So last week I just wasn't comfortable while I recorded it, not sure why, but I thought I should try to capture it again. And the second time around I felt better, maybe I should alway take two takes (or even more :-). So here is the new one...
<object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5577569&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=5577569&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><p><a href="http://vimeo.com/5577569">Screencast: Testing Flex Apps with Cucumber - Take 2</a> from <a href="http://vimeo.com/user507500">daniel wanja</a>.<br/>
To run this code you need to have all the gems installed. So config your Rails to run Cucumber with FunFx (in config/environments/test.rb):
<typo:code lang="ruby">
config.gem "rspec", :lib => false, :version => ">= 1.2.7"
config.gem "rspec-rails", :lib => false, :version => ">= 1.2.7"
config.gem "webrat", :lib => false, :version => ">= 0.4.4"
config.gem "cucumber", :lib => false
config.gem "funfx"
config.gem "safariwatir"
</typo:code>
Config Cucumber to have @flex available (in features/support/env.rb)
<typo:code lang="ruby">
require 'funfx'
require 'funfx/browser/safariwatir'
browser = Watir::Safari.new
browser.goto("http://localhost:3000")
Before do
@flex = browser.flex_app('flashContent', 'flashContent')
end
at_exit do
browser.close
end
</typo:code>
In the same file disable transactional fixtures
<typo:code lang="ruby">
Cucumber::Rails.use_transactional_fixtures
</typo:code>
Ensure that your Flex application is compiled with the funfx library and the automation library linked in.
<typo:code lang="xml">
<flex-config>
<compiler>
<include-libraries append="true">
<library>../../lib/funfx-0.2.2.swc</library>
<library>../../lib/automation.swc</library>
<library>../../lib/automation_agent.swc</library>
<library>../../lib/automation_dmv.swc</library>
<library>../../lib/automation_agent_rb.swc</library>
</include-libraries>
</compiler>
</flex-config>
</typo:code>
Screencast: Testing Flex Apps with Cucumber2009-07-08T00:00:00-07:00http://onrails.org/2009/07/08/screencast-testing-flex-apps-with-cucumberI was playing with Cucumber and FunFx to drive a Flex application and it's really cool and created this screencast to show how this all works together. The first 5 minutes I build a Restfulx scaffolded Flex application. The following 5 minutes I configure the Flex app with FunFx, which is required to be able to drive the app from Cucumber. Then the main part which is 20 minutes of creating three cucumber scenarios that drives the Flex application. Check it out:
<object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5502928&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=5502928&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><p><a href="http://vimeo.com/5502928">Testing Flex Apps with Cucumber</a> from <a href="http://vimeo.com/user507500">daniel wanja</a>
The source code can be found on <a href="http://github.com/danielwanja/cucumberwithflex/tree/master">github</a>
Enjoy!
Daniel
<br/>
UPDATE: An updated version (and slightly) different version of the screencast can be found <a href="http://onrails.org/articles/2009/07/13/screencast-testing-flex-apps-with-cucumber-take-2">here</a>.
RailsConf 2009 Day Two2009-05-07T00:00:00-07:00http://onrails.org/2009/05/07/railsconf-2009-day-two<p>Day Two got off to a good start. Engine Yard did a promotional pitch — the speakers could have been a bit more polished, but it was interesting stuff about their one-button-deployment, and overall not bad for an advertisement.</p>
<p>Next up was Chris Wanstrath. He started with a lead in regarding how to become a famous Rails developer — focusing on yourself, your blog readership numbers, your twitter follower count, etc. Later, he talked about how he went from being an unemployed college dropout to co-founder of the very successful GitHub, due to <strong>sharing code</strong>. His point was that in his eyes, it’s better to focus more on the community: share code, contribute to open source projects, even write documentation for existing projects. Being a <strong>good</strong> developer trumps being a famous developer. The complete text of the talk is <a href="https://gist.github.com/0a2655aed6a26fa15a02">online here</a> .</p>
<p>For the first session of the day, it was a tough call between Rack/Sinatra and Metric Fu. I finally went with:</p>
<h2>Using metric_fu to Make Your Rails Code Better – Jake Scruggs</h2>
<p>The central theme of this talk was how to use automated code analysis to direct you on where to spend your refactoring cycles. He used Carlin’s law (Anyone going slower than me is stupid; anyone going faster than me is crazy), but applied to programming. As your programming skills change over time, you see the same code differently.</p>
<p>He touched on coverage as a baseline that you should be doing as a part of your code analysis, then went on to complexity analysis, reviewing two tools available to analyze the “complexity” of your code: Flog and Saikuro. Flog examines your code (<code>flog -g app</code> for a Rails app) and gives you a (somewhat arbitrary) numeric range measuring the relative complexity of your code. Basically, 0-10 is awesome (and practically unatainable), 11-20 is okay for real world methods, and it goes downhill from there. If you have 200+ complexity scores, refactor immediately! Flog is somewhat opinionated about what is good/bad or more/less complex, but generally does a good job in helping you avoid the “icebergs”.</p>
<p>Saikuro gives a more concrete result — the “score” is the number of branches through a method, including tertiary operators, foo if/unless bar, etc. This is a plus over Flog, and usually indicates about how many tests you should have (one per branch). The downside to Saikuro is that it does not pick up on dynamically defined methods, where Flog does.</p>
<p>Next, we walked through a refactoring example, where Jake showed using high Flog scores as a hit list of where to refactor next. He also mentioned that better readability trumps lower complexity scores, one thing to keep in mind — as being generated by automated tools, the scores should be taken as a guide, not a law. A good point was brought up during Q&A: there is currently no way to “flag” a high-scoring method as acceptable, so if you have a justifiably complex method that you choose to live with (e.g. for readability), then you’ll have to live with the flogging you will receive. I’m sure patches would be welcome if someone wanted to fix this!</p>
<p>On to code smell and Reek and Roodi, tools to identify smells (overly large methods, etc.) Reek tends to warn over smaller issues than Roodi, and can indicate false positives. Roodi generally tends to have fewer complaints — if it warns about something, it should probably be fixed!</p>
<p>Next up was Flay, which detects non-<span class="caps">DRY</span>-ness in code, anything from strict copy-n-paste to functionally identical blocks with different variable names to do..end blocks matching curly-brace blocks.</p>
<p>Also covered was a way to track source control churn. At this point, you’re probably thinking “How can I keep up with all this?” Luckily, there’s metric_fu, a way to wrap all this up into one package and get all this code analysis goodness in your project. Install the gem, then run <code>rake metrics:all</code>. For more info, installation instructions, etc., see: <a href="http://metric-fu.rubyforge.org/">http://metric-fu.rubyforge.org/</a> Looking forward to adding this bag of tricks to our CI toolset.</p>
<h2>Rails 3: Step off of the Golden Path – Matt Aimonetti</h2>
<p>Matt started off with a history of programming languages and how Ruby came to be, including some of Matz’ core philosophies embodied in the language. Moving along to Rails, he talked about the growth of Rails and the desire for increased performance and options that led to the split between Rails and Merb. This led us in to the discussion of the current and future state of affairs for Rails 3.</p>
<p>Currently, as <span class="caps">DHH</span> mentioned in the opening keynote, there is no official release for Rails 3. However, much work has been done, and a direction / ideas are emerging that will be implemented once an official release is ready. These include:</p>
<ul>
<li>improved performance</li>
<li>increased modularity</li>
<li>agnosticism</li>
<li>public api</li>
<li>mountable apps</li>
</ul>
<p>Matt emphasized that there will be no drastic changes, and by default, <code>rails app</code> will generate a very similar application to what you would get today under 2.×. However, there will no longer be the idea of “the one true Rails way” of building an app — the framework will be less opinionated. However, you should go through a process of justification to see if you really <strong>need</strong> something different than the default stack.</p>
<p>Some of the options you will be able to choose from:</p>
<ul>
<li>JavaScript frameworks, including jQuery, <span class="caps">YUI</span>, ExtJS, MooTools, Prototype, or the ability to write your own, and plug it in.</li>
<li>Different templating engines: <span class="caps">HAML</span>, ERb (this is already doable in Rails)</li>
<li>Different ORMs: ActiveRecord, DataMapper, <span class="caps">SEQUEL</span>, Hibernate, non-<span class="caps">RDBMS</span> stores like CouchDB, Tokyo Cabinet, etc.</li>
</ul>
<p>At this point, Matt gave a demo of some of the nicer features in DataMapper, contrasted with ActiveRecord:</p>
<ul>
<li>DataMapper re-uses existing Ruby object for both sides of a <code>has_many</code> / <code>belongs_to</code> relationship. In other words, if I load parent and child records from the database, and look at <code>parent.object_id</code> as compared to <code>child.parent.object_id</code>, under DataMapper, these will point to the same object automatically, while with ActiveRecord, these will be separate objects. (Note that <a href="http://github.com/rails/rails/commit/ccea98389abbf150b886c9f964b1def47f00f237">inverse_of</a> was recently checked into rails, which enables this in ActiveRecord as well )</li>
<li>DataMapper does automatic lazy loading as well as strategic eager loading, so in this scenario:</li>
</ul>
<typo:code language="ruby">
<p>@parent = Parent.find(12345)<br />
@parent.children.each do |child|<br />
puts child.name<br />
end</p>
</typo:code>
<p>ActiveRecord would need some hints (<code>:include => :children</code>) to be added to the original query to avoid the N+1 iteration problem, where DataMapper is clever enough to figure that out and generate 2 <span class="caps">SQL</span> queries for you automatically.</p>
<ul>
<li>The ability to have multiple repositories (which looks like it means databases), and a <code>copy</code> method on models to clone data from one database to another — one use case would be an automatic archive or backup process that copies data generated within the last week to a backup database.</li>
<li>Query Path, allowing more flexibility in <span class="caps">SQL</span> condition generation (<span class="caps">WHERE</span> name <span class="caps">LIKE</span> ‘<span>foo</span>’)</li>
<li>one potential gotcha that was mentioned: DataMapper does not support <span class="caps">STI</span> and Polymorphic associations as well as ActiveRecord does</li>
</ul>
<p>Finally, he highlighted some options that would be available for even further customization, such as defining your own:</p>
<ul>
<li>file structure</li>
<li>router <span class="caps">DSL</span></li>
<li>request handling<br />
But he voiced the opinion that the vast majority of Rails apps will not need anything like this — make sure your need justifies coloring outside the lines.</li>
</ul>
<p>All in all a good presentation, maybe a bit much focus on DataMapper specifically. However, I personally enjoyed the DataMapper bits, and might have to try it out on a project, if it’s a fit.</p>
<h2>Art of the Ruby Proxy for Scale, Performance, and Monitoring – Ilya Grigorik</h2>
<p>I skipped out on the afternoon sessions, so my next talk was Ilya’s — never disappointing. Ilya spoke about EM-Proxy, his event machine based proxy. He gave good example code of how EM proxy could be used to implement transparent and intercepting proxies.</p>
<p>It started with an itch at PostRank, Ilya’s blog aggregation solution. An effective staging environment should closely resemble the production environment — the problem was that their production environment spanned nearly 80 (virtual) servers on EC2’s cloud. Spinning up that many servers just as a staging environment was an expensive proposition. Also, simulating production traffic then becomes a challenge, as you end up trying to store production logs and “replay” them into the staging environment. The way that they chose to solve the problem was to separate a group of the servers into a staging app server pool, set up a proxy that would transparently (to the end user) intercept incoming requests, send them to both the production and staging pools simultaneously, then return only the production response to the user, using the staging response internally for benchmarking, testing output, etc. With this strategy, the more static parts of the system (web servers, load balancers, etc.) can be shared across environments, and the staging environment is testing the part that actually changes (the application servers).</p>
<p>The first example code was a transparent proxy that simply forwarded a request from one port to another. Ilya built on this to show how you could dynamically alter request/response data on the fly. Finally, he built up to the original scenario: duplexing a single request across two (or multiple) backend servers, but returning only a specific response. As he mentioned in the talk, one strategy for servicing a specific request as fast as possible might be to send the request to all machines in your pool, then respond with whichever request completed first.</p>
<p>These examples were centered around <span class="caps">HTTP</span> requests, but he went on to show some other examples of how this is not protocol-specific: you are just dealing with data over a socket connection, so as long as you understand the underlying protocol, EM-Proxy could be useful. His examples showed <span class="caps">SMTP</span> proxies for accepting/rejecting incoming mail by email address and implementing a spam filter by forwarding the incoming mail to Defensio before passing it along to your real <span class="caps">SMTP</span> server. The final example was pretty clever: an implementation of EM-Proxy to reduce the memory overhead of beanstalkd by selectively delaying queue inserts based on the scheduled execution time — basically buffering far future jobs into the database instead of immediately inserting into the work queue.</p>
<p>Slides are available here: <a href="http://bit.ly/ruby-proxy">http://bit.ly/ruby-proxy</a></p>
<p>Another packed day at RailsConf 09, one more to go!</p>RailsConf 2009 Day One2009-05-06T00:00:00-07:00http://onrails.org/2009/05/06/railsconf-2009-day-one<p>I’ve just finished my first day of RailsConf 09. Things have gotten started well — I’ve met several interesting people, found some interesting people to follow on twitter. I’ll try to post as much as I can in the way of reviews for those of you attending by blog.</p>
<p>Starting with the <span class="caps">DHH</span> Keynote. David’s talk was entitled “Rails 3 and the Real Secret to High Productivity”.</p>
<p>He started off by reviewing some of the so-called “mortal wounds” Rails has experienced:</p>
<ul>
<li>It was deemed as not enterprise-ready, just a lot of hucksters trying to generate interest in Ruby to sell their own books, etc.</li>
<li>it encountered an “attack of the clones” in which several other languages/frameworks tried to duplicate (what they felt was) the one “key” feature that was the root cause of Rails’ explosion in success and popularity</li>
<li>some early adopters switched back (Derek Sivers, CD Baby)</li>
<li>some early adopters encountered serious problems (Twitter), which may or may not have been Rails-specific issues, but were perceived as such</li>
<li>some people complained about “feature bloat” (Array#fourteenth, etc.)</li>
</ul>
<p>The takeaway from this review: There is no one best tool for <strong>every</strong> job — it’s okay if not everyone chooses Rails. Rails can’t be distilled down to a single feature, it must be viewed as a sum of its components. Emotions or reactions can be quite strong, but are usually not all that important/long-lasting.</p>
<p>Next, he outlined some central ideas of the Rails 3 philosophy:</p>
<ul>
<li>Lock up all the unicorns: This is not a complete rewrite. Many people might look at Rails 3 and be disappointed, expecting more radical changes.</li>
<li>No “Sacred Cows” allowed: Everything is on the table for possible change in Rails 3. That being said, it’s important to note that any changes causing backward compatibility issues will need a <strong>very</strong> good justification to be accepted/implemented.</li>
<li>“Have it your way”: The default application generated under Rails 3 will rock, but you can ask for things to be done a different way and override the defaults. This seems like a natural extension of the templates now available in Rails 2.</li>
</ul>
<p>He also covered some of the progress made to date in Rails 3. It sounds like things are not going as fast as was hoped, but there is code available now in GitHub — just no officially tagged release.</p>
<p>Plans for Rails 3 include:</p>
<ul>
<li>a new router, with the ability to route requests by subdomains, user-agent strings, etc. also able to route to other rack machinery</li>
<li><span class="caps">XSS</span> protection, in which any text output will be html-escaped by default, requiring you to explicitly request raw output if/when you need it.</li>
<li>JS will be unobtrusive and framework-agnostic. This is one of the more exciting plans for me. tags will be generated with the <span class="caps">HTML</span> 5 validating data-* attributes, which can be used as unobtrusive javascript hooks:</li>
</ul>
<h3><span class="caps">HTML</span><br />
<typo:code language="html"><br />
<a href="/person/1" data-remote="true" data-method="delete">Delete This Person</a></h3>
</typo:code>
<h3>JavaScript<br />
<typo:code language="javascript"><br />
$(document.body).observe(“click”, function(event) { <br />
var element = event.findElement(“a[‘data-remote’]”); <br />
if (element) { <br />
var method = element.readAttribute(“data-method”) || “get”; <br />
new Ajax.Request(element.readAttribute(“href”), { method: method }); <br />
event.stop(); <br />
} <br />
});</h3>
</typo:code>
also, much like the database adapters in ActiveRecord, there might be a “driver” layer between the Rails javascript calls and the underlying javascript framework, enabling easy adoption of jQuery, MooTools, or any alternative framework.
<ul>
<li>more agnosticism in <span class="caps">ORM</span> choice and generators</li>
<li>more refactoring of various “crufty” areas of the framework, speed related improvements</li>
</ul>
<p>Then, near the end, he got to the “secret to high productivity” part. In a nutshell — don’t view the requirements as carved in stone. If you are able to make (slight) changes to the requirements as originally communicated by the business, it may serve their purposes just as well as the original requirements but be drastically easier to implement. As cool as Rails is, no framework is going to match the performance boost this can bring.</p>
<h2>Don’t Mock Yourself Out – David Chelimsky</h2>
<p>I went to David Chelimsky’s talk on Mocks, but it was a bit too introductory-level. He basically explained good reasons to use mocks — from the title, I was expecting ways to determine if your mocks are becoming too heavy-handed, preventing you from actually testing any of your implementation!</p>
<p>Here are the highlights:</p>
<p>David Started with a review of the difference between mocks and stubs — basically, mock objects care about which methods are or aren’t called during the test, stubs are “dumb” containers to give canned responses to methods. See <a href="http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs">Martin Fowler’s explanation</a> for more information.</p>
<p>Here are examples of when stubs might be useful:</p>
<ul>
<li>isolation from non-determinism: when dealing with any randomly generated values, your tests face brittleness from non-determinism. Similar for timestamps, date ranges, etc.</li>
<li>isolation from external dependencies: Anything that connects to an external resource (e.g. network/db) can benefit from (smart) mocking. You should still test the “real” operation, but for adding permutations/edge case tests, mocks can speed up your test suite by multiple orders of magnitude.</li>
<li>polymorphic collaborators : (strategies / mixins/plugins) calling a method on the “main” object ends up delegating to a method somewhere else</li>
</ul>
<p>Here are examples of when mocks might be useful:</p>
<ul>
<li>testing side effects (e.g. something gets logged)</li>
<li>testing caching / memoization — ensure an expensive method gets called exactly once.</li>
<li>interface discovery : “outside-in” development : build a mock of something before it exists, use to discover the “ideal” interface, how you will be using this in the real world.</li>
</ul>
<p>At this point, we started getting to Rails-specific content. David pointed out that if you are doing traditional Unit/Functional/Integration tests, it’s not <span class="caps">DRY</span>-some parts of your app (e.g. model validations) are being tested multiple times across your test suite. He recommends to split tests instead into business-facing / developer-facing specs, even using different frameworks where appropriate-for example, RSpec stories are more suited for business-facing specs, since they are close to the natural language of the domain experts. For lower-level, developer-facing tests (e.g. database-level), it probably doesn’t make sense to invest time writing stories—the developer <strong>is</strong> the domain expert.</p>
<p>A couple of helpful tips — if you care about <strong>which</strong> template gets rendered, but not necessarily the content (which could change!), you can stub the call to render, and set an expectation that it receives the correct partial name when called. When doing Rails functional testing, you need to set up valid/invalid data to make sure both sides of create/update actions are executed. Instead, you could stub the new/save/etc methods on the object to force the branch you want to test.</p>
<p>Upcoming “stubble” project helps with this.</p>
<h2>UI Fundamentals For Programmers – Ryan Singer</h2>
<p>Next, I saw Ryan Singer (37 Signals) talk about UI design concepts for developers. This was a high-level talk to help developers with the approach to take to UI/design, not a how-to, recipe style talk.</p>
<p>First of all, Ryan advocates taking a <span class="caps">BDD</span>, outside-in approach — including the UI. The UI is the closest thing to the user, so start there and work your way in, implementing backend functionality as you need.</p>
<p>Next, overcome your natural tendency (as a developer) to be terse — you should add ample text to guide your end user through the flow of your site/screens. Don’t rely on implicit meaning in forms/layouts as a guide, be explicit and explain what is expected of the user.</p>
<p>You should form a model (conceptual model, not ActiveRecord model) of the domain problem that makes sense to the customer and is implementable (feasable). Recommended reading: Domain-Driven Design by Eric Evans. (also Tufte for information display in general)</p>
<p>Designers tend to think in “Screens” as the atomic unit of work. This plays nicely into <span class="caps">REST</span>/Resource conventions, mapping e.g. displaying a particular object to the “show” action of your resource controller. For multiple related objects, break the screen into multiple areas that each represent a resource.</p>
<p>Be careful with contrast-make sure that you emphasize the most important elements on the page. Watch colors, sizes, etc. Don’t present a visual “buffet line” — aim more for a “gourmet meal”. Less is more.</p>
<p>Every action a user can take on your site has three distinct parts, a beginning, a middle, and an end. Think about where the user is when they need/want to take the action (where they are linked from). For the middle, collect the data for the action, then consider what the user will want/need to do next.</p>
<p>Some rules of thumb: helpers should not generate blocks of <span class="caps">HTML</span> (although generating an <span class="caps">HTML</span> element is probably ok — think image_tag); Organize your <span class="caps">CSS</span>/JS around <span class="caps">REST</span> conventions for your application; Treat ERb partials that generate <span class="caps">HTML</span> just as you would an image tag; Use helpers to reveal intention.</p>
<h2>Smacking Git Around – Scott Chacon</h2>
<p>Scott’s talk (aka the Git Firehose) was just as awesome (and fast-paced) as last year. Much too quick to take good notes, but I was able to capture a couple of useful tips & tricks:</p>
<p>First, on the concept of reachability: every commit that is an ancestor of your current commit. Git uses this in the dot-dot syntax for git-log and subtracts the first from the second. So <code>git log origin/master..master</code> gives you everything in your local master not already pushed to the remote repo. Or, after a fetch, reversing it (<code>git log master..origin/master</code>) gives you all commits you just pulled down that haven’t been merged into local master. Handy! A couple of alternate syntaxes: <code>git log branch_a --not branch_b</code>, or <code>git log branch_a ^branch_b</code>. This is also extensible to more than two branches: <code>git log origin/master master ^experiment</code> would give you all commits on origin/master and/or master that are not in experiment.</p>
<p>Second, he illustrated a common problem with diffing between branches in Git. If you imagine a file existing in two branches, in which lines have been added on both branches, and you ask git for a diff, most often you want to know what has been added to the other branch that you don’t have. By default, though, the question git is answering is “how do I make this file look like the other file?”, which includes deleting the lines you have added on the current branch — probably not what you want. In this instance, you can use the triple-dot syntax: <code>git diff master...topic</code> (asking git “what would happen if I merged the two branches?”)</p>
<p>He talked about subtree merging as an alternative to submodules. Basically, the process is:</p>
<ol>
<li>add a remote to the project you want to add as a subtree and fetch:<br />
<typo:code language="sh"><br />
git remote add rails_remote git@github.com:myfork/rails<br />
git fetch rails_remote<br />
</typo:code></li>
<li>check out a local branch of the other project:<br />
<typo:code language="sh"><br />
git checkout -b rails_branch rails_remote/master<br />
</typo:code></li>
<li>return to your project and use git-read-tree to add the subtree, then add and commit:<br />
<typo:code language="sh"><br />
git checkout master<br />
git read-tree —prefix=vendor/rails -u rails_branch<br />
git add vendor/rails<br />
git commit<br />
</typo:code></li>
</ol>
<p>This keeps your ability to make changes to the remote project and submit them back upstream:</p>
<ol>
<li>make change(s) to in remote project and commit</li>
<li>go to remote project’s local branch<br />
<typo:code language="sh"><br />
git checkout rails_branch<br />
</typo:code></li>
<li>merge your changes in:<br />
<typo:code language="sh"><br />
git merge -s subtree —no-commit —squash master<br />
</typo:code></li>
</ol>
<p>This obviates the need for braid/piston! See http://tinyurl.com/braidgit for more info.</p>
<p>Also mentioned was patch staging — simple, but incredibly useful! Say you’ve made multiple changes to the same file, and you want to commit some, but not all. With patch staging (<code>git add -p</code>), you can select the hunks you want to stage for commit — awesome!</p>
<p>More useful info, including how to give Git the ability to diff binary files (kinda, but it can work). Slides are posted at http://tinyurl.com/gitrailsconf09</p>
<h2>Quality Code with Cucumber – Alsak Hellesøy</h2>
<p>For the last session, I saw Alsak Hellesøy’s most excellent talk on Cucumber. I was totally drained at this point, and took no notes. He gave an example of how to get started with Cucumber, working through a sample scenario, doing outside-in development. So far, I haven’t used RSpec / <span class="caps">BDD</span> in anything serious, but I’m looking forward to trying this out — looks pretty interesting.</p>
<h2>Ruby Heros / Evening Keynote</h2>
<p>The day ended with the Ruby Hero awards, and then the <span class="caps">DHH</span> / Tim Ferriss (4 hour workweek) interview/keynote. I think there was probably good content to be had in the keynote about refactoring your lifestyle. Unfortunately, the sound was bad — very muffled/echoy from where I was sitting. Also, the pace was so much different from the firehose of information presented by the technical talks that it was like a panic stop in a formula one racer.</p>
<p>Overall, a good but exhausting day here in Vegas. If you’re here, look me up and say hi, or give me a follow (rubysolo on Twitter).</p>RailsConf 20092009-05-05T00:00:00-07:00http://onrails.org/2009/05/05/railsconf-2009<p>Slides of the presentations can be found <a href="http://en.oreilly.com/rails2009/public/schedule/proceedings">here</a> as they are released</p>
<p>Follow “official” news on <a href="http://twitter.com/railsconf">Twitter</a>.</p>
<p><a href="http://blogs.sun.com/arungupta/entry/rails_conf_2009_day_2"><span class="caps">DHH</span> Keynote</a> notes and <a href="http://assets.en.oreilly.com/1/event/24/Rails%203%20and%20the%20Real%20Secret%20to%20High%20Productivity%20Presentation.pdf">slides</a>. The video is <a href="http://railsconf.blip.tv/file/2081411/">here on blip.tv</a></p>
<p>Video on the tutorials day from the <a href="http://railsenvy.com/2009/5/5/railsconf-2009-tutorials-day">Railsenvy</a> team.</p>
<p>More videos on <a href="http://railsconf.blip.tv/">blip.tv</a>.</p>
<p>And lots of <a href="http://picfog.com/tag/railsconf">pictures</a>.</p>
<p>Some good notes from <a href="http://blogs.sun.com/arungupta/entry/rails_conf_2009_day_1">day1</a>.</p>
<p>Please tweet links to @danielwanja for any good blog articles that does live coverage. I’ll post the links here.</p>
<p>We have Solomon White that regularly blogs on http://onrails.org covering the conference…let’s see the note he takes ;-)</p>
<p>Ruby Heroes:</p>
<div style="border: 1px solid grey">
<p>RT @igrigorik: congrats to #railsconf ruby heroes! cheers guys! @brynary, @tmm1, @luislavena, @pat, @dkubb, @jnunemaker</p>
</div>
<ul>
<li>Bryan Helmkamp http://www.brynary.com/</li>
<li>Aman Gupta http://github.com/tmm1</li>
<li>Luis Lavena http://blog.mmediasys.com/</li>
<li>Pat Allan http://freelancing-gods.com/</li>
<li>Dan Kubb http://github.com/dkubb/</li>
<li>John Nunemaker http://railstips.org/</li>
</ul>ActiveRecord's accepts_nested_attributes_for specification2009-04-12T00:00:00-07:00http://onrails.org/2009/04/12/activerecords-accepts_nested_attributes_for-specification<p>I was trying to figure out how to use the new AvtiveRecord accepts_nested_attributes_for functionality that enables saving nested active records. In fact I will try to use that functionality from a Flex application using the <a href="http://restfulx.github.com/">RestfulX</a> framework.</p>
<p>The cool thing about trying to understand Rails or ActiveRecord is that there are many tests available part of the source code which describe really well the framework. The functionality is provided by the NestedAttributes module defined in /activerecord-2.3.2/lib/active_record/nested_attributes.rb.</p>
<p>I just generated a basic specs from the associated test case which I included here after and this give a good idea of what the <i> accepts_nested_attributes_for</i> method supports:</p>
<p>Nested Attributes In General</p>
<ul>
<li>Base should have an empty reject new nested attributes procs</li>
<li>Should add a proc to reject new nested attributes procs</li>
<li>Should raise an argumenterror for non existing associations</li>
<li>Should disable allow destroy by default</li>
<li>A model should respond to underscore delete and return if it is marked for destruction</li>
</ul>
<p>Nested Attributes On A Has One Association</p>
<ul>
<li>Should define an attribute writer method for the association</li>
<li>Should build a new record if there is no</li>
<li>Should not build a new record if there is no id and delete is truthy</li>
<li>Should not build a new record if a reject if proc returns false</li>
<li>Should replace an existing record if there is no</li>
<li>Should not replace an existing record if there is no id and delete is truthy</li>
<li>Should modify an existing record if there is a matching</li>
<li>Should take a hash with string keys and update the associated model</li>
<li>Should modify an existing record if there is a matching composite</li>
<li>Should delete an existing record if there is a matching id and delete is truthy</li>
<li>Should not delete an existing record if delete is not truthy</li>
<li>Should not delete an existing record if allow destroy is false</li>
<li>Should also work with a hashwithindifferentaccess</li>
<li>Should work with update attributes as well</li>
<li>Should not destroy the associated model until the parent is saved</li>
<li>Should automatically enable autosave on the association</li>
</ul>
<p>Nested Attributes On A Belongs To Association</p>
<ul>
<li>Should define an attribute writer method for the association</li>
<li>Should build a new record if there is no</li>
<li>Should not build a new record if there is no id and delete is truthy</li>
<li>Should not build a new record if a reject if proc returns false</li>
<li>Should replace an existing record if there is no</li>
<li>Should not replace an existing record if there is no id and delete is truthy</li>
<li>Should modify an existing record if there is a matching</li>
<li>Should take a hash with string keys and update the associated model</li>
<li>Should modify an existing record if there is a matching composite</li>
<li>Should delete an existing record if there is a matching id and delete is truthy</li>
<li>Should not delete an existing record if delete is not truthy</li>
<li>Should not delete an existing record if allow destroy is false</li>
<li>Should work with update attributes as well</li>
<li>Should not destroy the associated model until the parent is saved</li>
<li>Should automatically enable autosave on the association</li>
</ul>
<p>Nested Attributes On A Has Many Association<br />
and Nested Attributes On A Has And Belongs To Many Association</p>
<ul>
<li>Should define an attribute writer method for the association</li>
<li>Should take a hash with string keys and assign the attributes to the associated models</li>
<li>Should take an array and assign the attributes to the associated models</li>
<li>Should also work with a hashwithindifferentaccess</li>
<li>Should take a hash and assign the attributes to the associated models</li>
<li>Should take a hash with composite id keys and assign the attributes to the associated models</li>
<li>Should automatically build new associated models for each entry in a hash where the id is missing</li>
<li>Should not assign delete key to a record</li>
<li>Should ignore new associated records with truthy delete attribute</li>
<li>Should ignore new associated records if a reject if proc returns false</li>
<li>Should sort the hash by the keys before building new associated models</li>
<li>Should raise an argument error if something else than a hash is passed</li>
<li>Should work with update attributes as well</li>
<li>Should update existing records and add new ones that have no id</li>
<li>Should be possible to destroy a record</li>
<li>Should not destroy the associated model with a non truthy argument</li>
<li>Should not destroy the associated model until the parent is saved</li>
<li>Should automatically enable autosave on the association</li>
</ul>Time tracking on Rails 2.3.22009-03-24T00:00:00-07:00http://onrails.org/2009/03/24/time-tracking-on-rails-2-3-2<a href="http://time.onrails.org/">time.onrails.org</a> was first deployed in 2005 and the last time I deployed it was in July 2007. This application is in use by several hundred people daily and several thousands did sign up over the year. It's written in old-style Rails (pre-resources) and I did port it to Rails 1.2 a while back. So today I decided to run the test suite and had a list of deprecation warnings for Rails 2.0. I did fix them all, then decided to run against Rails 2.3.2. A couple of more issues where identified (tests with fixtures should use ActionController::TestCase and ActiveRecord::TestCase) and all tests where passing. I used to have a timezone bug related to the old Rails support of time zones, so I decided to bite the bullet and try out the Rails 2.0 time zone support and found a good description <a href="http://mad.ly/2008/04/09/rails-21-time-zone-support-an-overview/">here</a>. The change was straight forward, et voila, time.onrails.org running on 2.3....not so quick. I did a <em>cap deploy</em> and then realized that I didn't have the latest version of Rails on my deployment system, nor did I have the latest version of the gems. So after a '<em>gem update --system</em> I encountered a gem related issue but with this <a href="http://blog.ra66i.org/archives/informatics/2007/12/23/a-quick-gem-101-faq-gemrunner-name-error/">solution</a> I was back in business....Et voila, time.onrails.org running on 2.3.2! Note it's still old style Rails and needs a good rewrite, but if you need a free time tracking application, just go try it out.
Confreaks: MountainWest RubyConf 2009 - videos available2009-03-18T00:00:00-07:00http://onrails.org/2009/03/18/confreaks-mountainwest-rubyconf-2009-videos-availableThe confreaks guy processed many of the videos and they start to appear on the MWRC section of their site:
<a href="http://mwrc2009.confreaks.com/">http://mwrc2009.confreaks.com/</a>
Check it out, lot of good stuff. Thanks again to the MWRC organizers.
Flex on Rails position at Rosetta Stone in Boulder.2009-03-16T00:00:00-07:00http://onrails.org/2009/03/16/flex-on-rails-position-at-rosetta-stone-in-boulderAt the RMAUG I met Kadri, the Director of Speech Technologies from Rosetta Stone, and he mentioned they where looking from a Flex/Rails developer.
You can see the job posting <a href="http://www.careerbuilder.com/JobSeeker/Jobs/JobDetails.aspx?IPath=CJR&APath=2.21.0.0.0&job_did=J8G6CV6R57VLRB6MGNW">here</a>.
Unfortunately I didn't have more time to speak with Kadri so I can not tell you much about the position or the company but If you are in Boulder and fit the profile why not just contact them.
Enjoy!
Daniel.
55 minute video: Flex on Rails presentation at RMAUG on March 10th2009-03-16T00:00:00-07:00http://onrails.org/2009/03/16/55-minute-video-flex-on-rails-presentation-at-rmaug-on-march-10thThis is the edited version of the talk Tony Hillerson and Daniel Wanja gave at the Rocky Mountain Adobe User Group on March 10th. There is an echo the first two minutes, then the sounds stabilize. We also had a software issue on Tony's notebook and display port issue on Daniel's, parts which I edited out. The demo gods where not with us that night :-), but we had fun and I hope we answered many of the questions the attendance had. Also we wanted to tailor the talk on Ruby on Rails rather than on Flex and be an open format, but we had more questions than anticipated and presented only 10% of the material we had.
<object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=3671443&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=3671443&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><br /><a href="http://vimeo.com/3671443">Flex on Rails presentation at RMAUG on March 10th</a> from <a href="http://vimeo.com/user507500">daniel wanja</a> on <a href="http://vimeo.com">Vimeo</a>.
Note: during the first 2 minutes there is an echo. Sound skips from time to time throughout the video.
The talk was recorded by RMAUG and posted on <a href="http://www.rmaug.com/community/forum/messageview.cfm?catid=5&threadid=124&messid=192">their blog</a>, and can be viewed using Connect <a href="http://realeyes.acrobat.com/p49039280/">here</a>.
Thanks again to everyone who attended!
Daniel.
MWRC - Thanks you, that what awesome!2009-03-15T00:00:00-07:00http://onrails.org/2009/03/15/mwrc-thanks-you-that-what-awesomeWe are at the airport on the way back to Denver from the <a href="http://mtnwestrubyconf.org/2009/">MountainWest RubyConf</a>. This was the best conference I went to in years. Fast passed talk with just incredible material and every presenter was just excellent. So to the organizers and presenters....Thank you! I'll be back!
This was the Official Meme:
<a href="http://skitch.com/blowmage/bedrb/official-mountainwest-rubyconf-2009-meme"><img src="http://img.skitch.com/20090315-n1h2y34i2c656icbu51edt4cxk.jpg" /></a>
Check out some of the comments from the last few hours or check all tweets regarding<a href="http://search.twitter.com/search?max_id=1329614940&page=1&q=+%23mwrc&rpp=50"> #mwrc</a>.
MWRC - Moutain West Ruby Conference is about to start.2009-03-13T00:00:00-07:00http://onrails.org/2009/03/13/mwrc-moutain-west-ruby-conference-is-about-to-start<div style="text-align:center;"><img src="http://onrails.org/files/20090313_mwrc_attrium1.jpg" alt="20090313_mwrc_attrium.jpg" border="0" width="500" /></div>
<p>The <a href="http://www.confreaks.com/">Confreaks</a> guys did setup their cameras, sound and lights, so you will certainly be able to see all the talks in a few weeks.</p>
<p>The conference takes place in Salt Lake City, the scenery is impressive as the city is surrounded by high mountains…even for someone living in Denver. The picture above was taken just before the conference starts and shows the atrium we gonna spend the next two days in. The <a href="http://mtnwestrubyconf.org/2009/schedule">talks</a> looks really cool and tonight the <a href="http://blog.engineyard.com/2009/03/09/mountainwest-hackfest-featuring-solo">Engine Yard’s Hackfest 2.0</a> in suite next to mine at the Hilton Salt Lake City Center.</p>
Advanced Ruby - Day 32009-03-11T00:00:00-07:00http://onrails.org/2009/03/11/advanced-ruby-day-3<div style="text-align:center;"><img src="http://onrails.org/files/20090311_avancedruby.jpg" alt="20090311_avancedruby.jpg" border="0" width="500"/></div>
<p>The first two days of the training were really excellent. Great pace, clear explanations and samples, very technical, Chad and Dave really rock at Ruby.</p>
<h2>Making Domain-Specific Languages</h2>
<p>We start with a discussion on <span class="caps">DSL</span> versus an <span class="caps">API</span>.</p>
<h3>Meat-and-Potato DSLs</h3>
<ul>
<li>Block based <span class="caps">API</span>.</li>
<li>Directly manipulating domain model classes</li>
<li>Defining classes and methods</li>
<li>Manually typing repetitive, low-level code</li>
</ul>
<p>Example is Rake. Rake is a dependency oriented programming language.</p>
<p>Eexample from Dhaka (a paraser generator)</p>
<typo:code lang="ruby">for_pattern(“\n”) do<br />
create_token(“newline”)<br />
end</typo:code>
<h3>method_missing Trick</h3>
<typo:code lang="ruby">require ‘pp’<br />
<br />
class CommandListener<br />
def initialize<br />
@commands = []<br />
end<br />
<br />
def method_missing(*args)<br />
@commands << args<br />
self<br />
end<br />
end<br />
<br />
listener = CommandListener.new<br />
<br />
listener.instance_eval do<br />
this object accepts whatever you type and stores it<br />
end<br />
pp listener</typo:code>
<p>outputs:</p>
<pre>
#<CommandListener:0x80264
@commands=
[[:you, CommandListener],
[:whatever, #<CommandListener:0x80264 ...>],
[:accepts, #<CommandListener:0x80264 ...>],
[:object, #<CommandListener:0x80264 ...>],
[:this, #<CommandListener:0x80264 ...>],
[:it],
[:stores, #<CommandListener:0x80264 ...>]]>
</pre>
<typo:code lang="ruby">listener = CommandListener.new<br />
listener.instance_eval do<br />
this.object.accepts.whatever.commands.and.stores.it<br />
end <br />
<br />
pp listener</typo:code>
<p>outputs:</p>
<pre>
#<CommandListener:0x712b4
@commands=
[[:this],
[:object],
[:accepts],
[:whatever],
[:commands],
[:and],
[:stores],
[:it]]>
</pre>
<p>Note any keyword can be used with method_missing…E.g. <em>freeze</em> is not a missing method.</p>
<p>Now by using a BlankSlate object we can avoid this issue:</p>
<typo:code lang="ruby">class BlankSlate<br />
instance_methods.each do |method|<br />
undef_method(method) unless method =~ /^__/ || method == ‘instance_eval’<br />
end<br />
end</typo:code>
<p>We can now create a command listener that can use any commands:</p>
<typo:code lang="ruby">require ‘pp’<br />
<br />
class CommandListener < BlankSlate<br />
def initialize<br />
@commands = []<br />
end<br />
<br />
def method_missing(*args)<br />
@commands << args unless [:inspect, :to_s].include? args.first <br />
self<br />
end<br />
<br />
def pretty_print(pp)<br />
pp.output.write @commands.inspect<br />
end<br />
<br />
end<br />
<br />
listener = CommandListener.new<br />
<br />
listener.instance_eval do<br />
You can even type freeze!<br />
end<br />
pp listener</typo:code>
<p>And we get the following output:</p>
<pre>[[:freeze!], [:type, #<CommandListener:0x7ee28>], [:even, #<CommandListener:0x7ee28>], [:can, #<CommandListener:0x7ee28>], [:You, #<CommandListener:0x7ee28>]]</pre>
<p>On the same principals we just create a morse encoder, and of course Dave had to show off and interface with the speech function of <span class="caps">OSX</span> and another version that interfaces with the <span class="caps">MIDI</span> controller.</p>
<h2>Exotic Control Flow</h2>
<p>Creating a loop with continuations</p>
<typo:code lang="ruby">def start_loop<br />
callcc{|c|c }<br />
end<br />
<br />
def end_loop©<br />
c.call©<br />
end<br />
<br />
<br />
i = 0<br />
again = start_loop<br />
<br />
puts i<br />
i += 1<br />
<br />
end_loop(again) unless i > 5</typo:code>
<h2>Moving on…</h2>
<p>We voted on what to cover next as we won’t have time to cover every thing…and the winners are:</p>
<pre>
* Concurrency ..................
* Debugging/Profiling ................
* JRuby ......
* Ruby Extras ...........
* Distributed Programming ......................
</pre>
<h2>Distributed Programming</h2>
<h3>DRb</h3>
<p><strong>Marshaling</strong></p>
<p>>> h = {:x => 1}<br />
>> Marshal.dump(h)<br />
=> “\004\b{\006:\006xi\006”<br />
>> Marshal.load(_)<br />
=> {:x=>1}</p>
<p><strong><span class="caps">DRB</span> Server</strong></p>
<typo:code lang="ruby">require ‘drb/drb’<br />
require ‘ostruct’<br />
<br />
DRb.start_service(“druby://localhost:4321”, OpenStruct.new)<br />
DRb.thread.join</typo:code>
<p><strong>DRb Client</strong></p>
<p>require ‘drb’<br />
<typo:code lang="ruby"><span class="caps">DRB</span>.start_service<br />
o = DRbOject.new_with_url(“druby:’’localhost:4321”)<br />
o.last_accessed = Time.now<br />
o.some_other_arbitrary_method = “Set this on the open struct”</typo:code></p>
<p>By default Pass-by-value, but can be Pass-by-reference can be enabled by including DRbUndumped.</p>
<ul>
<li>Rinda</li>
<li>Ring</li>
</ul>
<p>…</p>
<p>That’s all Folk! …my hands/brain where running tired during the last hour :-)</p>
<p>That was an incredible 3 days thanks to Chad and Dave. So if you want to dive deeper in Ruby, the <a href="http://pragmaticstudio.com/ruby/">Advanced Ruby </a> is the best way to get there!</p>
<p>Enjoy!<br />
Daniel</p>Starting an intense Ruby week.2009-03-10T00:00:00-07:00http://onrails.org/2009/03/10/starting-an-intense-ruby-weekIt starts with three days at the <a href="http://pragmaticstudio.com/ruby/">Advanced Ruby</a> training followed by two days at the <a href="http://mtnwestrubyconf.org/2009/">Mountain West Ruby Conference</a>. On Tuesday evening, I'll be giving a talk at the <a href="http://www.rmaug.com">Rocky Mountain Adobe Users Group</a>. I'll be blogging about these events here...so stay tuned.
<div><a href="http://mtnwestrubyconf.org/2009/"
title="I'm attending MountainWest RubyConf 2009!">
<img src="http://mtnwestrubyconf.org/2009/images/badges/attendee.png"
width="250" height="200" border="0"
alt="I'm attending MountainWest RubyConf 2009!">
</a></div>
Advanced Ruby - Day 22009-03-10T00:00:00-07:00http://onrails.org/2009/03/10/advanced-ruby-day-2I just missed the first half hour of the training due to a long commute due to a little snow in Denver.
Chad completed the design discussion on Inheritance .vs. Composition, using mixins and modules.
<typo:code>
1.class.ancestors
=> [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject]
1.class.instance_methods(false)
=> [:to_s, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**, :abs, :magnitude, :==, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, :to_f, :size, :zero?, :odd?, :even?, :succ]
m = 1.method(:inspect)
=> #<Method: Fixnum(Kernel)#inspect>
</typo:code>
We are moving on to performance.
<h2>...make it fast.</h2>
Rails doesn't scale and Ruby is slow. This said Ruby is arguably the slowest of the scripting languages with a naive implementation. But for 99% of the work we do, it's fast enough...Now let's talk about that last 1%.
Premature optimization is the root of all evil - Donald Knuth.
<h3>Benchmarking</h3>
In 1.9
<typo:code lang="ruby">require 'benchmark'
puts Benchmark.measure {(1..1000000).map{|num| ""+num.to_s}}
0.940000 0.050000 0.990000 ( 1.001714)
</typo:code>
In 1.8
<typo:code lang="ruby">puts Benchmark.measure {(1..1000000).map{|num| ""+num.to_s}}
1.800000 0.050000 1.850000 ( 1.850319)
</typo:code>
Yea, 1.9 is twice as fast.
Now to compare approaches, here using map or inject...which one is the fastest:
<typo:code lang="ruby">require 'benchmark'
Benchmark.bm do |b|
b.report("map") {(1..1000000).map{|num| ""+num.to_s}}
b.report("inject") {(1..1000000).inject(""){|accum, num| ""+num.to_s}}
end
user system total real
map 1.970000 0.070000 2.040000 ( 2.077786)
inject 1.910000 0.010000 1.920000 ( 1.978541)</typo:code>
<h3>Don't Use Ruby</h3>
* C (or OCAML?) extensions
* Sockets
* DL
* Don't use Ruby at all
DL is "Pure Ruby" way of calling native code form shared libraries.
<typo:code lang="ruby">require 'dl/import'
require 'dl/struct'
</typo:code>
<h3>memoization</h3>
<typo:code lang="ruby">def fib(n)
@k||={}
n<=2 ? 1 : (@k[n-1]||=fib(n-1))+(@k[n-2]||=fib(n-2))
end
puts fib(200)
280571172992510140037611932413038677189525
Program exited with code #0 after 0.02 seconds</typo:code>
Now the same code as above without the cluttering
<typo:code lang="ruby">def fib(n)
if n <= 2
1
else
fib(n-1) + fib(n-2)
end
end
alias :pre_memoized_fib :fib
def fib(n)
@cache ||= {}
@cache[n] ||= pre_memoized_fib(n)
end
</typo:code>
<h2>The Ruby Object Model</h2>
Now we move onto the essence of an Object in Ruby.
* self is the "current object"
* self always as a value
* two things change self: 1) method calls 2) class or module definition
<typo:code lang="ruby">class << str # << opens up the singleton class. Arrows seem to go wrong way.
p self # ghost class: <Class:#<String:0x1d0ec>> - class of the class String
def speak
puts "miaow"
end
end
puts str.speak
class Dave
class << self # puts the methods into the singleton class and becomes class methods
def do_something
end
end
end
class Person < Struct.new(:name, :age)
def greet
puts "Hello #{self.name}"
end
end
f = Person.new("Chad", 28)
</typo:code>
<typo:code lang="ruby">module Logger
def log(msg)
puts msg
end
end
class Album
include Logger
end
Album.ancestors # => [Album, Logger, Object, Kernel]
# Note that Logger becomes ancestor of Album...It's insert a generated class named after the module that shares the method table.
</typo:code>
Module can extend an object:
<typo:code lang="ruby">module Speak
def hello
puts "hello"
end
end
str = "cat"
str.extend Speak
puts str.hello
</typo:code>
<h2>Metaprogramming</h2>
After the break we will be diving into metaprogramming. I saw his talk at the Advanced Rails Studio a while back and took <a href="http://onrails.org/articles/2008/06/13/advanced-rails-studio-meta-programming">some notes</a> then. I will therefore sit back, relax, and code along his examples.
<h2>Library Organization</h2>
Multipart Request - revisited2009-03-09T00:00:00-07:00http://onrails.org/2009/03/09/multipart-request-revisitedI just posted on <a href="http://blog.flexonrails.com/">http://blog.flexonrails.com/</a> a post on creating Multipart Request with Flex to post data such as XML, images to a Rails server. Check it out!
Advanced Ruby - Day 12009-03-09T00:00:00-07:00http://onrails.org/2009/03/09/advanced-ruby<p>Let’s get started. I’m at the <a href="http://pragmaticstudio.com/ruby/">Advanced Ruby</a> training. Here are the topics we gonna cover</p>
<ul>
<li>Blocks, Procs, and Closures</li>
<li>Ruby 1.9</li>
<li>Your Own, Private Ruby</li>
<li>Design in a Dynamic Language</li>
<li>Messin’ with Types</li>
<li>…make it fast.</li>
<li>The Ruby Object Model</li>
<li>Metaprogramming</li>
<li>Making Domains-Specific Languages</li>
<li>Concurrency</li>
<li>Exotic Control Flow</li>
<li>Library Organization</li>
<li>Debugging and Profiling</li>
<li>JRuby</li>
<li>Ruby Extras</li>
<li>Distributed Programming</li>
<li>Onward and Upward!</li>
</ul>
<p>In fact when I saw the topics that will be covered by Dave Thomas and Chad Fowler, and the fact that some of my collogues from Pinnacol where attending I had to join…Oh yea, it’s a 25 minute drive from home too.</p>
<p>So this morning I woke up and installed Ruby 1.9. I didn’t use multiruby as many do I just downloaded <a href="ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p0.tar.gz">Ruby 1.9.1-p0</a> from http://www.ruby-lang.org/en/downloads. These are the steps to install:<br />
<pre><br />
cd ruby-1.9.1-p0<br />
autoconf<br />
./configure —prefix=/usr/local/ruby1.9<br />
make<br />
sudo make install<br />
</pre></p>
<p>Then you can check the version by</p>
<typo:code>
<p>$/usr/local/ruby1.9/bin/ruby -v <br />
ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-darwin9.6.0]<br />
$/usr/local/ruby1.9/bin/irb <br />
RUBY_VERSION <br />
=> “1.9.1”</p>
</typo:code>
<p>I didn’t add /usr/local/ruby1.9/bin to my path, so the default ruby is still my mack default, 1.8.6 of my mac (ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]).</p>
<p>Keep on reading to see some of the code we are walking through. This said it’s hard to convey how much value Chad and Dave are passing along with all their deep explanations of each of the examples…</p>Integrating FTP with Rails2009-03-06T00:00:00-08:00http://onrails.org/2009/03/06/integrating-ftp-with-rails<p>One interesting problem we faced at <a href="http://www.videopros.com">VideoPros</a> was file upload. In our application domain, the files tend to be orders of magnitude larger than, say, an avatar attachment for your blog post. <span class="caps">HTTP</span> multipart upload works for these large files, but users need an indication that the upload is progressing so they do not refresh the browser or navigate away from the page, killing the upload in mid-stream. To help out with this first facet of the problem, we implemented an apache handler that tracks file upload progress in front of the rails application. You can check it out <a href="http://drogomir.com/blog/2008/6/18/upload-progress-bar-with-mod_passenger-and-apache">here</a>.</p>
<p><strong><span class="caps">UPDATE</span></strong>: Here’s a <a href="http://www.railsillustrated.com/screencast-file-uploads-progress-in-rails-passenger.html">good screencast</a> that goes over getting this set up on <span class="caps">OSX</span> — you’ll need some extra arguments to correctly compile and install the apache module.</p>
<p>This worked well, but we still got requests for an alternative: the users wanted to use <span class="caps">FTP</span> to upload their files. The workflow would be: users would connect and upload a batch of video files into their <span class="caps">FTP</span> “inbox”. After the upload(s) were complete, the users would create video objects in the database and attach the uploaded files. As an interesting twist, the users requested the ability to re-use their existing application usernames and passwords to access <span class="caps">FTP</span>. Our goal was to meet this requirement while providing secure, low-maintenance <span class="caps">FTP</span> service.</p>
<p>A bit of research turned up <a href="http://www.pureftpd.org/project/pure-ftpd">PureFTPd</a>, an open-source implementation touted as secure, with an interesting-sounding feature called “virtual users”. My first hope was that we would be able to use the MySQL Auth feature, which reads usernames and passwords from a MySQL table for authentication. If your app is like ours, you have a users table with this info, so it doesn’t seem to be a stretch that we could get this to work. However, further investigation uncovered a problem — Pure’s MySQL Auth only supports plaintext, MD5, MySQL password, and <span class="caps">UNIX</span> crypt as formats for the password column. We’re using <a href="http://github.com/technoweenie/restful-authentication/tree/master">ReSTful Auth</a>, which means that our password are <span class="caps">SHA</span>-1’ed. This, combined with wanting to define users’ home folders programatically rather than storing them in the database, eliminated MySQL auth as a possibility for our implementation.</p>
<p>However, all was not lost. According to the documentation, another option for authentication is <a href="http://download.pureftpd.org/pub/pure-ftpd/doc/README.Authentication-Modules">Ext Auth</a>, which allows you to run an arbitrary process to perform the authentication. The way this works is pure-ftpd communicates over a socket to another daemon, pure-authd, which launches your authentication process, then sends the plaintext result back to pure-ftpd, which accepts or rejects the login. Sounds like a good candidate for a Ruby script!</p>
<p>To get started, first install Pure-FTPd. In my environment, this was as simple as:<br />
<typo:code lang="sh" title="build-pure-ftpd"><br />
./configure —with-extauth<br />
make<br />
sudo make install</p>
</typo:code>
<p>Next, we need to build an authentication script. The script receives the username and password (along with source IP / port …) as environment variables. It would be trivial to load up our Rails environment and use ActiveRecord to find_by_username, but it would also add several seconds of overhead to load the framework. I opted to go with the less-<span class="caps">DRY</span> but faster method of using the mysql gem directly. The first order of business is to load the user record that matches the specified username.</p>
<typo:code lang="ruby" title="select-user">
<p>begin<br />
dbh = Mysql.real_connect(config[‘host’], config[‘username’], config[‘password’], config[‘database’])<br />
res = dbh.query(%Q{<br />
<span class="caps">SELECT</span> *<br />
<span class="caps">FROM</span> users<br />
<span class="caps">WHERE</span> state = ‘active’<br />
<span class="caps">AND</span> login = ‘#{ENV[’AUTHD_ACCOUNT’].gsub(/‘/, "’‘“)}’<br />
<span class="caps">LIMIT</span> 1<br />
})<br />
user = res.fetch_hash<br />
res.free<br />
rescue Mysql::Error => e<br />
ensure<br />
dbh.close if dbh<br />
end</p>
</typo:code>
<p>If we can’t find a user, we can fail fast and return “auth_ok:0”. If we do find one, we need to mimic the password-hashing scheme from our user model so that we can validate that the password we were given is correct. If the password does not match, then we fail, otherwise, we send back “auth_ok:1”, along with effective <span class="caps">UNIX</span> user and group ids and home directory path. Whether or not the user is authenticated, we send back “end”</p>
<typo:code lang="ruby" title="validate-user">
<p>if user[‘crypted_password’].nil?</p>
<ol>
<li>no active user with given login<br />
puts “auth_ok:0”<br />
else</li>
<li>validate given password<br />
hashed_pw = Digest::SHA1.hexdigest(“<del>-#{user[‘salt’]}</del>-#{ENV[‘AUTHD_PASSWORD’]}—”)<br />
if user[‘crypted_password’] != hashed_pw<br />
puts “auth_ok:0”<br />
else<br />
puts “auth_ok:1”<br />
puts “uid:#{UID}”<br />
puts “gid:#{GID}”<br />
puts “dir:#{RAILS_ROOT}/private/ftp/#{user[‘login’]}”<br />
end<br />
end</li>
</ol>
<p>puts “end”</p>
</typo:code>
<p>Here’s the final product: <a href="http://onrails.org/files/ftpd-auth-handler">ftpd-auth-handler</a></p>
<p>This turned out to be a pretty straightforward implementation, but the functionality is quite useful for us. Shout out to the <a href="http://www.videopros.com">VideoPros</a> crew for agreeing to share this — hopefully this will help someone who needs to integrate <span class="caps">FTP</span> with their Rails app!</p>iPhone Mockups2009-02-27T00:00:00-08:00http://onrails.org/2009/02/27/iphone-mockups<p>The <a href="http://www.balsamiq.com/products/mockups/desktop/next">next version</a> of <a href="http://www.balsamiq.com/products/mockups">Balsamiq</a>, a really cool tool to create low fidelity mockups, will support mocking up of iPhone apps. That’s gonna be the quickest way to visuaizel and experiment with you next killer iPhone app idea.</p>
<p>Balsamiq allows to drag and drop components on a canvas and then just add content via text, which will be rendered as an image. So the text on the right below creates the interface on the right. That’s too cool.</p>
<table>
<tr halign="top">
<td>
<pre>
A Simple Label
- Delete
+ Add and sub-menu, >
Two Labels, yup
v A Checkmark, (>)
* A Bullet, Read >
_ Space for an icon
__ Space for a big icon
On button, ON
Off button, OFF
v And empty row, (above)
</pre>
</td>
<td>
<p><img src="http://onrails.org/files/balsmaiq_iphone.png" alt="balsmaiq_iphone.png" border="0" width="222" height="390" /></p>
</td>
</tr>
</table>Flex On Rails talk in Denver - Thursday 22nd2009-01-19T00:00:00-08:00http://onrails.org/2009/01/19/flex-on-rails-talk-in-denver-thursday-22nd<p>Tony and I will be giving a talk on Flex on Rails at Derailed, the Denver Rails User Group. This will take place at <a href="http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=forest+room+denver&sll=37.0625,-95.677068&sspn=37.410045,79.365234&ie=UTF8&ll=39.759991,-105.011272&spn=0.035498,0.077505&t=h&z=14&iwloc=A">Forest Room 5</a> in <span class="caps">LODO</span> at 6:30pm, this coming Thursday 22nd.</p>
<p>On the agenda.</p>
<ul>
<li>6:30 – 7:00: Meet and mingle</li>
</ul>
<ul>
<li>7:00 – 8:30: Flex on Rails – From the authors Daniel Wanja and Tony Hillerson</li>
</ul>
<ul>
<li>8:30 – … : Book raffle and spirits.</li>
</ul>
<p>We will show highlights of each of the chapters and samples from the book.</p>
<p>I hope to see you there!<br />
Daniel</p>New Book: "Flex on Rails: Building Rich Internet Applications with Adobe Flex 3 and Rails 2" 2009-01-03T00:00:00-08:00http://onrails.org/2009/01/03/new-book-flex-on-rails-building-rich-internet-applications-with-adobe-flex-3-and-rails-2<div style="text-align:center;"><img src="http://onrails.org/files/2009.01.02_CoverSmall.jpg" alt="2009.01.02 CoverSmall.jpg" border="0" width="500" height="333" /></div>
<p>Finally our book on using Flex with Rails is released and will appear over the next few days in stores around the US and is available on <a href="http://www.amazon.com/gp/product/0321543378?ie=UTF8&tag=flexonrails-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0321543378">Amazon</a>. I received a couple of copies from the publisher and it felt like an accomplishment to hold a physical version in my hands. I am sure my co-author, <a href="http://thillerson.blogspot.com/">Tony</a>, felt the same. Good job man! With this release we are also launching <a href="http://flexonrails.com">http://flexonrails.com</a> where you can find all the source code of the book as well as other resources related to Flex and Rails, and our blog <a href="http://blog.flexonrails.com">http://blog.flexonrails.com</a> the blog for everything on Flex with Ruby On Rails…</p>
<p>So here are the top 10 reasons why should you absolutely buy this book even if you are not a programmer….1) Your vision will improve 2) You’ll run faster 3) Aging gets reverted 4)… Just kidding, the main reasons for us to write this book was that we really wanted to share many of the experiences and findings we had on using Flex and Rails on many projects, and we are proud of the outcome. It’s a book by developers for developers. I’ll be blogging in a next entry about the process of writing this book, and will create a screencast presenting the different applications we are creating in the book, so stay tuned. When writing the book we assumed that you where a developer, either a Flex developer or a Rails developer that needed to interact with the other side and wanted to add Rails or Flex to it’s battery of languages. You will certainly find your way around even if you don’t know Flex or Rails. In either case we didn’t create a reference book so you won’t find all the answers about each api that is available in both frameworks, but you will find everything you need to get started integrating Flex with Rails, and delve into wonderful world of Flex on Rails applications. For the example code we didn’t want to build a large application and refine it over time through the chapters, so most chapter contain one or several working applications used to highlight the major integration aspects explained in that chapter. And Rails is just fantastic to create small applications on the fly, and Flex and Actionscript is pretty good for that too. So to give you a better overview of the content of this book I have attached the official description and the table of content. For more info come back to <a href="http://blog.flexonrails.com">http://blog.flexonrails.com</a> and <a href="http://flexonrails.com">http://flexonrails.com</a>. I hope you enjoy the book and the sample applications. So go check it out and let us know what you think.</p>
<p>Daniel.</p>
<h2>Description</h2>
<p>“There’s no question you’re going to be a better Flex and Rails developer when you’re done reading this book.â€<br />
–From the Foreword by Matt Chotin, Senior Product Manager, Adobe Systems, Inc.</p>
<p>Â <br />
Adobe Flex enables the rapid development of rich and engaging user experiences. Ruby on Rails dramatically simplifies the development of database-driven web applications. Now there’s a book that shows how to use the newest versions of both frameworks together to create state-of-the-art Rich Internet Applications (RIAs).</p>
<p>Â <br />
Flex on Rails begins with the absolute essentials: setting up your environment for Flex and Rails, passing data with <span class="caps">XML</span>, and integrating Flex front-ends with Rails back-ends. Then, using practical, easy-to-understand code examples, the authors take you from the basics to advanced topics only discussed in this book. Techniques covered here include </p>
<ul>
<li>Constructing sophisticated interfaces that can’t be created with <span class="caps">AJAX</span> alone</li>
</ul>
<ul>
<li>Using RESTful services to expose applications for access via APIs</li>
</ul>
<ul>
<li>Testing Flex and Rails together</li>
</ul>
<ul>
<li>Using Flex Frameworks</li>
</ul>
<ul>
<li>Getting Flex into your build/deploy process</li>
</ul>
<ul>
<li>And more… </li>
</ul>
<p>The authors also offer practical introductions to powerful complementary technologies, such as RubyAMF and Juggernaut.<br />
 </p>
<p>Written by developers with extensive experience using both frameworks, this book covers the new Adobe Flex 3 and Ruby on Rails 2 from the ground up. Even if you have minimal experience with Flex or Rails, you’ll learn all you need to know to use them to build exceptional production applications.</p>
<h2>Table of Contents</h2>
<pre>
Foreword xv
Preface xvii
Acknowledgments from Tony Hillerson xxi
Acknowledgments from Daniel Wanja xxii
About the Authors xxiv
Â
<strong>PART I: Flex and Rails Essentials</strong>
Â
Chapter 1: Developing with Flex and Rails 3
Installation: What You Need to Get Running 3
The Structure of a Flex and Rails Application 6
The Example Code 9
Compiling MXML 9
Running the Rails Server 9
Summary 9
Â
Chapter 2: Passing Data with XML 11
XML in Rails 11
XML in Flex 14
Getting XML to Flex 17
Sending XML to Rails 19
Mapping Data Types 21
Error Handling 25
Summary 28
Â
Chapter 3: Flex with RESTful Services 29
Creating the Stock Portfolio Rails Application 29
Accessing Our RESTful Application with Flex 39
Summary 48
Â
Chapter 4: Using Fluint to Test a Flex with Rails Application 49
Using Fluint to Write Your Flex Unit Tests 50
The Basics of Testing a Flex Application 51
Testing a Cairngorm-Based Application 59
Using Fixtures 79
Summary 83
Â
Chapter 5: Passing Data with AMF 85
What Is AMF? 85
Benefits of AMF 86
RubyAMF 87
A Simple RubyAMF Example 95
A RESTful RubyAMF Integration 101
Summary 103
Â
Chapter 6: Debugging 105
Logging 106
Debuggers 110
Command Line Debuggers 117
Debugging Communication 127
Summary 129
Â
Chapter 7: Data Visualization 131
Online Analytical Processing (OLAP) 133
Advanced DataGrid 144
Charting 147
Summary 152
Â
Chapter 8: Flex MVC Frameworks 153
What Do We Mean by a Framework? 153
Roll Your Own 154
Cairngorm at a High Level 154
PureMVC at a High Level 159
Stuff 163
Summary 182
Â
Chapter 9: Performance and Optimization 185
Flex Performance 185
Rails Performance 206
Summary 211
Â
<strong>PART II: Cookbook Recipes</strong>
Chapter 10: Source Control Flex and Rails Projects 215
Goal 215
Solution 215
Ignoring Files in Subversion 215
Git 217
Discussion 218
Summary 219
Â
Chapter 11: Building Flex with Rake 221
Goal 221
Solution 221
Rake Is Your Friend 221
The Rakefile 222
Summary 225
Â
Chapter 12: Deploying Flex and Rails Applications 227
Goal 227
Solution 227
Capistrano 227
Deploying with Capistrano 228
Summary 232
Â
Chapter 13: Read the Source! 233
Goal 233
Solution 233
The Beauty of Open Source 233
The Rails Source 235
Flex Source 238
Generated Flex Source 240
Summary 243
Â
Chapter 14: Using Observers to Clean Up Code 245
Goal 245
Solution 245
BindingUtils and ChangeWatchers in Flex 245
Taking Action on ActiveRecord Lifecycle Events 248
Summary 250
Â
Chapter 15: Authenticating 251
Goal 251
Solution 251
Authenticating Users 251
Installing restful_authentication 251
Summary 257
Â
Chapter 16: Reusing Commands with Prana Sequences 259
Goal 259
Solution 259
Sequences 259
Prana’s EventSequence 261
Summary 265
Â
Chapter 17: Hierarchical Data with RubyAMF 267
Goal 267
Solution 267
Nested Sets 267
Summary 273
Â
Chapter 18: Advanced Data Grid and Awesome Nested Set 275
Goal 275
Solution 275
Overview 275
Create the Rails Application and Database 275
Creating a Script to Load the Data 276
Flex Application 279
Adding CRUD 282
Summary 287
Â
Chapter 19: Runtime Flex Configuration with Prana 289
Goal 289
Solution 289
IoC, Eh? 289
Summary 293
Â
Chapter 20: Server Push with Juggernaut 295
Goal 295
Solution 295
Push Technology 295
Juggernaut 295
Creating the Rails Messaging Application 297
Creating the Flex Messaging Client Application 299
Summary 301
Â
Chapter 21: Communicating between Flex and JavaScript 303
Goal 303
Solution 303
Communication between Flex and JavaScript 303
Security 303
Building the Samples 304
ExternalInterface 304
SWFObject and Prototype 305
ExternalInterface in Action 305
Flex-Ajax Bridge in Action 309
Summary 311
Â
Chapter 22: File Upload 313
Goal 313
Solution 313
File Upload 313
Creating the Rails Application and Installing attachment_fu 315
Using Flex’s FileReference Class to Upload
One or Several Files 316
Using Flex URLLoader Class to Upload a PNG File 318
Summary 320
Â
Index 321
</pre>The future of Rails: Rails 3.02008-12-24T00:00:00-08:00http://onrails.org/2008/12/24/the-future-of-rails-rails-3-0<p>The Merb team joins force with the Rails core team to work on Rails 3.0 and brings many of the modularity and performance concepts from Merb to Rails. At first I thought “Oh, no”, that’s gonna be a mess. But after reading several of the announcements I can see the benefits of the effort and this will make Rails more simple, more modular, more robust, better defined, and certainly faster. Bringing two different teams together is very difficult but the fact that both team are complementary and look for excellence in their work and managed to come up with a great vision of the future of Rails, got me excited about the future of Rails. They gonna make it happen. You can read more about here:</p>
<ul>
<li><a href="http://weblog.rubyonrails.org/2008/12/23/merb-gets-merged-into-rails-3">http://weblog.rubyonrails.org/2008/12/23/merb-gets-merged-into-rails-3</a></li>
<li><a href="http://rubyonrails.org/merb">http://rubyonrails.org/merb</a></li>
<li><a href="http://yehudakatz.com/2008/12/23/rails-and-merb-merge/">http://yehudakatz.com/2008/12/23/rails-and-merb-merge/</a></li>
<li><a href="http://brainspl.at/articles/2008/12/23/merb-is-rail">http://brainspl.at/articles/2008/12/23/merb-is-rail</a>s</li>
<li><a href="http://merbist.com/2008/12/23/rails-and-merb-merge/">http://merbist.com/2008/12/23/rails-and-merb-merge/</a></li>
</ul>
<p>Merry Christmas/Hanukkah/Hollidays!</p>
<p>Daniel.</p>Flex Job: Full time Flex developer in Denver at Videopros.com2008-12-23T00:00:00-08:00http://onrails.org/2008/12/23/flex-job-full-time-flex-developer-in-denver-at-videopros-com<p>Solomon, who also writes on this blog, is currently doing Ruby on Rails work for <a href="">videopros.com</a> and they are looking to hire a Flex developer to complement their small development team. Here are the details…</p>
<div style="text-align:center;"><img src="http://onrails.org/files/VP_Logo_300x100.jpg" alt="VP_Logo_300x100.jpg" border="0" width="300" height="100" /></div>
<p>We seek a Flex on Rails Kingpin to lead our development team. This is for a full-time or contract-to-hire position. Private consultants should not apply. Depending on skill level and commitment an equity stake is available.</p>
<p>Compensation</p>
<ul>
<li>70-100K</li>
<li>Potential Equity</li>
<li>Potential Profit Sharing</li>
</ul>
<p>Skills and Experience</p>
<ul>
<li>Ruby on Rails | 2.5 Years minimum</li>
<li>Flex | 1 Year minimum</li>
<li>Web Services</li>
<li>Experience as the lead developer for a commercial project.</li>
<li>Agile development</li>
<li>Subversion (<span class="caps">GIT</span>)</li>
<li>Linux</li>
<li>MySQL</li>
<li><span class="caps">XML</span></li>
</ul>
<p>Benefits</p>
<ul>
<li>Competitive Salary</li>
<li>Health Insurance</li>
<li>Long Term Disability Insurance</li>
</ul>
<p>About Us – The VideoPros Dojo</p>
<p>Dojo means “place of the Way.†Much like a martial arts practice hall, the <span class="caps">WAY</span> we operate at VideoPros is a pursuit for mastery in the face of adversity and challenge. The true challenge is not between people and external things – but within ourselves. 
<br />
Working at VideoPros means going within yourself and seeing the work you do as a reflection of who you are on the inside. It’s more than “work†or “my job.†We are a place you go to practice being the best you can be – every day.</p>
<p>Apply</p>
<p>VideoPros is motivated to fill this position quickly. To apply, email your resume and one reason why you want to join us at the Dojo to:<br />
Careers{at}VideoPros{dot}com</p>Screencast: Using Webby to create a static website.2008-12-11T00:00:00-08:00http://onrails.org/2008/12/11/screencast-using-webby-to-create-a-static-websiteI am currently using <a href="http://webby.rubyforge.org/">Webby</a> to generate a static website. I think it's a pretty cool tool, so I made a small video to show how to get started with it and explain what it does. Check it out:
<object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=2492090&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=2492090&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><br /><a href="http://vimeo.com/2492090">Screencast: Using Webby to create a static website</a> from <a href="http://vimeo.com/user507500">daniel wanja</a>.
Enjoy!
Daniel.
RubyConf 2008 videos available at confreaks.com - Thank you!2008-12-01T00:00:00-08:00http://onrails.org/2008/12/01/rubyconf-2008-videos-available-at-confreaks-com-thank-you<p>I couldn’t make it this year to RubyConf so I am really thankful to see that most of the presentations are online at <a href="http://rubyconf2008.confreaks.com/">confreaks</a>. It’s just awesome that these videos are made available online and so quickly after the conference and for free. It’s a real tribute to the Ruby community and it’s open and sharing spirit. Thanks guys! My understanding is that the <a href="http://rubyconf.org/">rubyconf</a> pays <a href="http://www.confreaks.com/">Confreaks</a> to take, processes and distribute these videos. Let me know if the arrangement is different, to give credit where credit is due. Thanks RubyConf and the presenters, and good job Confreaks.</p>
<p>Here are the videos I selected for my commute this week.</p>
<ul>
<li><a href="http://rubyconf2008.confreaks.com/keynote.html">Keynote</a> – Dave Thomas</li>
<li><a href="http://rubyconf2008.confreaks.com/questions-and-answers.html">Questions & Answers</a> – Yukihiro ‘Matz’ Matsumoto</li>
</ul>
<ul>
<li><a href="http://rubyconf2008.confreaks.com/introducing-red-sun-ruby-to-flash.html">Introducing Red Sun – Ruby to Flash</a> – Jonathan Branam</li>
<li><a href="http://rubyconf2008.confreaks.com/macruby-ruby-for-your-mac.html">MacRuby: Ruby for your Mac</a> – Laurent Sansonetti</li>
<li><a href="http://rubyconf2008.confreaks.com/os-x-application-development-with-hotcocoa.html">OS X Application Development with HotCocoa</a> – Rich Kilmer</li>
<li><a href="http://rubyconf2008.confreaks.com/hacking-with-ruby2ruby.html">Hacking with ruby2ruby</a> – Marc Chung</li>
<li><a href="http://rubyconf2008.confreaks.com/using-git-in-ruby-applications.html">Using Git in Ruby Applications</a> – Scott Chacon</li>
</ul>
<ul>
<li><a href="http://rubyconf2008.confreaks.com/adrenaline-driven-development.html">Adrenaline-Driven Development</a> – Bruce Williams</li>
<li><a href="http://rubyconf2008.confreaks.com/fear-of-programming.html">Fear of Programming</a> – Nahaniel Talbott</li>
<li><a href="http://rubyconf2008.confreaks.com/recovering-from-enterprise.html">Recovering from Enterprise</a> – Jamis Buck</li>
</ul>
<p>View the full list of videos available <a href="http://rubyconf2008.confreaks.com/">here</a>.</p>
<p>You may wonder why I would watch videos during my commute. Effectively I drive 40 minutes each way to my customers (happen to be both near enough for me to drive and not tele-commute) and this gives me a chance to catch up on many of the excellent screencast and podcast out there. Now when one screencast really sticks out, I watch it again at night…without driving ;-).</p>
<p>This said I converted the confreaks small videos format (640 × 240) to the iPhone format using Quicktime pro, but I only get the sound…which is fine for my commute. Any hint on how I can convert them to also get the video going would be appreciated?</p>
<p>Enjoy!<br />
Daniel</p>Moving "private" and non-Rails related entries to http:blog.wanja.com2008-11-17T00:00:00-08:00http://onrails.org/2008/11/17/moving-private-and-non-rails-related-entries-to-http-blog-wanja-comI received a couple of comments and emails about my non-Rails related entries, more specifically about the iPhone related entries. So from now on I will move these type of entries to my new "private" blog <a href="http://blog.wanja.com">http://blog.wanja.com</a>. As I am starting the development of a new iPhone app and will report about it over there. I am still doing quite some Rails related work and will keep posting about it here (http://onrails.org). I am also experimenting with MacRuby, which is so cool, and will report about it here unless it's specific to iPhone development. I short if you are only interested in Rails or Ruby keep ready this blog, if you are interested in the other "stuff" I play with, such a iPhone, games, Wii, PS3, programming the Wii Remote, and any other geek stuff, check out <a href="http://blog.wanja.com">http://blog.wanja.com</a>
Rails Deployment On Heroku Using Git2008-11-08T00:00:00-08:00http://onrails.org/2008/11/08/rails-deployment-on-heroku-using-gitI was checking out different sites to deploy the Rails apps we presented with Tony at RailsConf for our Powering AIR with Rails tutorial and the easiest and fastest way is still <a href="http://heroku.com">heroku.com</a>. So for the 3rd app, <a href="http://www.flexonrails.com/air_apps.html">TwitterFriends</a>, I make this little video showing how I deployed the Rails to heroku using the heroku gem and git:
<object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=2184908&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=2184908&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><br /><a href="http://vimeo.com/2184908">Rails Deployment On Heroku Using Git</a> from <a href="http://vimeo.com/user507500">daniel wanja</a> on <a href="http://vimeo.com">Vimeo</a>.
Note flexonrails.com is still "under constructions" and I am adding stuff for the launch of the book...which is now set to shortly after December 19th. Yea!
Determine Test Coverage on your Flex Projects with Flexcover.2008-10-24T00:00:00-07:00http://onrails.org/2008/10/24/determine-test-coverage-on-your-flex-projects-with-flexcover<p>This week I was playing with <a href="http://code.google.com/p/flexcover/">Flexcover</a> a test coverage tool for Flex…and it’s really cool. If you you to determine how much test coverage you have in your Flex application then check out this screencast…maybe skip to the end where you will see flexcover in action. The first part is how to assemble the Flexcover <span class="caps">SDK</span> to use with FlexBuilder. Again this is a non-scripted screencast with several “oops” and a big Swiss-French accent which I hope you will find useful.</p>
<p>The key here is if you do Flex, write unit tests and use this test coverage tool.</p>
<p><object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=2185199&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=2185199&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><br /><a href="http://vimeo.com/2185199">Setting up Flexcover as test coverage tool for your Flex applications.</a> from <a href="http://vimeo.com/user507500">daniel wanja</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>Enjoy,<br />
Daniel.</p>Flex test coverage?2008-10-11T00:00:00-07:00http://onrails.org/2008/10/11/flex-test-coverage<p>It’s hard to imaging writing a Rails application without using <a href="http://eigenclass.org/hiki.rb?rcov">rcov</a> and get that fuzzy feeling you tested most if not all you application. Or at least get a good idea of what’s tested. I <a href="http://weblogs.macromedia.com/swebster/archives/2007/11/unit_testing_an.html">heard</a> way back that Alex Uhlmann was working on some test coverage tools, but I didn’t see anything coming out from Adobe. I haven’t used test coverage for my Flex apps, but want to start. Any body has any good hints, stories, frameworks they use for test unit coverage in Flex? A quick google search pointed me to this <a href="http://www.joeberkovitz.com/blog/2008/04/12/flex-air-code-coverage-announce/">article</a> describing <a href="http://code.google.com/p/flexcover/">Flexcover</a>, just what I was looking for. Please share your experience.</p>
<p>Thanks!<br />
Daniel.</p>
<p><span class="caps">UPDATE</span>: I am playing with FlexCover and just saw this “Flexcover is a joint effort with Alex Uhlmann of Adobe Consulting, who has been working on a related set of ideas.”. So I guess this is really Alex’s work that Steven was referring to which is now open source under the <span class="caps">MIT</span> license. Cool!</p>iPhone NDA - Call for arms [Update: NDA lifted :-)]2008-09-26T00:00:00-07:00http://onrails.org/2008/09/26/iphone-nda-call-for-arms<p><span class="caps">UPDATE</span>: today (10/01/2008) Apple <a href="http://developer.apple.com/iphone/program/">lifted</a> the iPhone <span class="caps">NDA</span>. New agreement will come out in a week (or so).</p>
<p>Until now I wasn’t concerned about the iPhone <span class="caps">NDA</span> as the iPhone is really cool, there are nice apps appearing on the App Store and face it, this platform is there to stay, the iPhone is just impressively useful and versatile. But recent news on applications being rejected by Apple for undefined reasons and the fact that the pragmatic programmers book on iPhone was pulled due to the <span class="caps">NDA</span>, ticked me off. That’s what the <a href="http://pragprog.com/news/ubuntu-kung-fu-shippingpodcast-iphone-news">“Prag’s”</a> released in their news: “It now appears that Apple does not intend to lift the <span class="caps">NDA</span> any time soon. Regrettably, this means we are pulling our iPhone book out of production.”</p>
<p>Damn that! That was <span class="caps">THE</span> book I was waiting for. I am a developer, did Objective-C development on NeXTSTEP 15 years ago and follow closely what’s going on with the iPhone. I was one of the first admitted to the iPhone developer program and I am certainly bound by <span class="caps">NDA</span> beyond my comprehension, but I was also really hoping that the platform would open up. Early on it made sense as Apple wants to have the “Wow” factor when they first announce their product, and that’s worth millions to them. But now that the phone is out for quite a while, that all Apple competitors have access to all the beta SDKs, let me ask you this:</p>
<p><span class="caps">WHY</span>?</p>
<p>Why does Apple keeps this <span class="caps">NDA</span>…I just doesn’t make sense. Let the development community go crazy, share the knowledge, create something unique beyond what you have. Apple, you are making your development community <span class="caps">ANGRY</span>.</p>
<p>I tried to find a good reasons why there is still this <span class="caps">NDA</span> in place, but there is just no reason. What did I miss? What has Apple to gain? What can we do?</p>
<p>Please leave your thought as comment here after.</p>
<p>Daniel.</p>First Apple Store in Switzerland and it's in Geneva my ex-home town.2008-09-26T00:00:00-07:00http://onrails.org/2008/09/26/first-apple-store-in-switzerland-and-its-in-geneva-my-ex-home-town<p><img src="http://onrails.org/files/2202E22E-571F-4452-BD1F-1298E43E8A10.jpg" alt="2202E22E-571F-4452-BD1F-1298E43E8A10.jpg" border="0" width="400" /></p>
<p>Photo from <a href="http://www.iphonemag.ch/2008/09/exclu-les-photos-interieurs-de-apple-store-geneve/">iphonemag.ch</a>.</p>
<p>Cool now my brother doesn’t have to bug me to check out stuff at the Apple Store every time something new comes out ;-).</p>
<p>Also with the current value of the dollars you now can buy a MacBook Air for 199 Swiss Francs :-)</p>Full time hard core Flex Developer position in Denver.2008-09-22T00:00:00-07:00http://onrails.org/2008/09/22/full-time-hard-core-flex-developer-position-in-denver<p>One of my customers, Fiserv Insurance Solutions, looks for an experienced Flex Developer for one of it’s new project. In short they are looking for a good Flex developer. Here is an extract of the job post and you can read more about <a href="http://tbe.taleo.net/NA9/ats/careers/requisition.jsp?org=FISERV_INSURANCE&cws=1&rid=63">here</a>.</p>
<p>We are seeking a senior level software developer proficient in ActionScript and Flex to join our team building the cutting-edge browser-based applications. Extensive experience with Rich Internet Application (<span class="caps">RIA</span>) development using Adobe Flex and ActionScript is required. You will be involved in designing and implementing a creative and innovative application platform with Adobe Flex which will be used to build very large projects (300+ screens). Qualified applicants will have 3+ years of in-depth ActionScript development experience developing <span class="caps">RIA</span> applications, and at least a year of full time, hard core Flex experience. Also required is experience with Flex Remoting (<span class="caps">AMF</span>) and experience with Flex frameworks such as Mate, PureMVC or Cairngorm.</p>
<p>Knowledge and Desire Skills</p>
<ul>
<li>Experience with Flex <span class="caps">MVC</span> frameworks: Mate, Cairngorm, etc.</li>
<li>Source control system</li>
<li>Agile development methodology, <span class="caps">SCRUM</span> preferred</li>
<li>Effective, creative problem solving skills</li>
<li>Strong organization skills, self-motivated, team player</li>
<li>Excellent verbal and written communication skills</li>
<li><span class="caps">MUST</span> be proficient in ActionScript 3.0 and Adobe Flex development</li>
<li>Experience with custom component development</li>
<li>Extensive experience with AS3 & <span class="caps">MXML</span></li>
<li>Experience building large, enterprise applications with Flex</li>
<li>Strong Object Oriented Programming expertise</li>
</ul>
<p>Deep understanding of Flex internals:</p>
<ul>
<li>data binding</li>
<li>event system</li>
<li>data grids & custom renderers</li>
<li>module-based application development</li>
<li>internationalization & localization</li>
<li><span class="caps">AMF</span> Remoting</li>
</ul>Sarah Palin Email...forget privacy on the net.2008-09-18T00:00:00-07:00http://onrails.org/2008/09/18/sarah-palin-email-forget-privacy-on-the-net<p>I was watching <a href="http://www.billoreilly.com/">Bill O’reilly</a> on Fox and just saw that Sarah Palin’s email account was hacked and leaked to on the internet…that’s 11 or more hours after the fact apparently and I wanted to do a quick check if they managed to stop the propagation of these emails. I said to myself, left see if I can get access to the full text in less than 5 minutes starting on Google. Well, it didn’t work out, but many source reported the information, but most of the sites that have it are currently down. But in short, on the net just forget about privacy. I know, you don’t want your private stuff to be out there, but it eventually will be. I don’t want the picture of my kids on the net…but if they once get indexed by on of the bots…google and others..they are out there. Now I hope my emails don’t become public…but emails are not secure anyhow unless you encrypt them.</p>
<p>So here is what my quick search returned:</p>
<ul>
<li>Watched Bill Oreilly and heard about the hack.</li>
<li>Checked cnn.com home page…nothing.</li>
<li>Search google and followed the first link…which was a link to a Yahoo <a href="http://news.yahoo.com/s/ap/20080917/ap_on_el_pr/palin_hacked">news story</a>, with not much information.</li>
<li>Then <a href="http://search.twitter.com ">searched</a> twitter and followed a link from chrisgen to <a href="http://pastebin.com/f7fb944c5">http://pastebin.com/f7fb944c5</a></li>
<li>That link was point to the following links on artvoice.com with some pictures of the email<br />
<strong>* <a href="http://blogs.artvoice.com/techvoice/2008/09/17/hackers-break-into-sarah-palins-inbox/">http://blogs.artvoice.com/techvoice/2008/09/17/hackers-break-into-sarah-palins-inbox/</a><br />
*</strong> <a href="http://blogs.artvoice.com/techvoice/wp-content/uploads/2008/09/011.jpg">http://blogs.artvoice.com/techvoice/wp-content/uploads/2008/09/011.jpg</a><br />
<strong>* <a href="http://blogs.artvoice.com/techvoice/wp-content/uploads/2008/09/04.jpg">http://blogs.artvoice.com/techvoice/wp-content/uploads/2008/09/04.jpg</a><br />
*</strong> <a href="http://blogs.artvoice.com/techvoice/wp-content/uploads/2008/09/03.jpg">http://blogs.artvoice.com/techvoice/wp-content/uploads/2008/09/03.jpg</a><br />
** <a href="http://blogs.artvoice.com/techvoice/wp-content/uploads/2008/09/02.jpg">http://blogs.artvoice.com/techvoice/wp-content/uploads/2008/09/02.jpg</a></li>
<li>Checked out <a href="http://digg.com/2008_us_elections/The_Incident_Did_4Chan_Anon_Hack_Palin_s_Yahoo_Email">digg</a> which pointed to <a href="http://www.sarahpalinisnthillaryclinton.com/">http://www.sarahpalinisnthillaryclinton.com/</a></li>
<li>Which highlighted some name that I fed to the google machine: Ivy Frye Nizich, Michael</li>
<li>Which pointed to two interesting links, the first being down:<br />
<strong>* <a href="http://wikileaks.org/leak/sarah-palin-hack-2008/email-index.txt">http://wikileaks.org/leak/sarah-palin-hack-2008/email-index.txt</a><br />
*</strong> <a href="http://www.mahalo.com/Sarah_Palin_Email">http://www.mahalo.com/Sarah_Palin_Email</a></li>
</ul>
<p>Well that was futile search, but I wanted to see how news spreads on the internet and how the force will try to stop it. Now it’s time to check out <a href="http://kotaku.com/5033529/the-iphone-force-unleashed-in-action">Star Wars the Force Unleashed</a> for the iPhone.</p>
<p>Now for the readers of my blog, this has nothing to do with Flex or Rails, but hey! Also if you wonder what I was doing watching O’Reilly, let’s simply say I watch many news source from many countries and like diversity of information, but very often I don’t share his or Fox way of propaganda, but I enjoy the topics addressed.</p>
<p>That’s the most political blog ever as I don’t want to bug my readers here, I’m definitively less expressive than my friend <a href="http://zablanc.blogspot.com/">John</a>, but in any case and for the future or the country my children, go <a href="http://www.barackobama.com/index.php">Obama</a>!</p>Ignite Denver - 6 hours left to register - it's free and at an Irish Pub2008-09-09T00:00:00-07:00http://onrails.org/2008/09/09/ignite-denver-6-hours-left-to-register-its-free-and-at-an-irish-pub<p>Ignite Denver: you can register <a href="http://ignitedenver.eventbrite.com/">here</a> and read more about it <a href="http://ignitedenver.blogspot.com/">here</a></p>
<p>When: Wednesday, September 10, 2008 from 06:00 PM – 11:00 PM (MT)</p>
<p>Where: Fado Irish Pub, 1735 19th Street, Denver, CO</p>
<p><img src="http://bp0.blogger.com/_OcPqJoX43Cc/SIVPJigDFVI/AAAAAAAAABY/uOrX7PGf8hk/S660/ignite_logo_small.png" /></p>
<p>Some of the talks planned for Denver on the 10th:</p>
<ul>
<li>Kevin Hoyt – The wonderful world of Cigars</li>
<li>Rob McNealy – Social media for low tech companies (AskAFloorGuy.com)</li>
<li>Peter Batty – Future Location and Social Networking – Location aware applications are a hot topic in the social networking space at the moment. This presentation will talk about a different approach to this space, focusing on future location – where will you and your friends be in the future? This is harder to implement than an approach based on current location but more useful if you can do it successfully. We will talk about some of the challenges in this area and the many cool applications of this technology.</li>
<li>Brian Holmes – how to swear in French</li>
<li>Jim Hutchison – The glamorous world of Entertainment Business lighting and how rockstar-ish it can and cannot be, followed by a side order of ridiculously simply difficult lighting math chased with industry information and quirky stories. Living like a rockstar is fun!</li>
<li>Andrew Hyde – TechStars is a entrepreneur boot camp that every summer selects and seed funds 10 startups. From an inside viewpoint, what is the experience like? What are the biggest lessons, and the biggest challenges of starting the startup.</li>
<li>Scott Dudley – Digital Theatrics</li>
<li>Dave Taylor – Filmbuzz (get your hollywood news fix!)</li>
<li>Jun Heider – 5 minute intro to the world of Hackintosh</li>
</ul>Feature article on Compassionate Communications, a Ruby on Rails website.2008-09-03T00:00:00-07:00http://onrails.org/2008/09/03/feature-article-on-compassionate-communications-a-ruby-on-rails-website<p>A while back I worked with Lee and Sean on <a href="http://www.compassionatecommunications.com/">Compassionate Communications</a> which was featured in an interview/article in the <a href="http://www.nctimes.com/articles/2008/09/03/lifeandtimes/z8a0df10c4ac0a197882574b20076a4c1.txt">San Diego North County Times</a> last week. Read it <a href="http://www.nctimes.com/articles/2008/09/03/lifeandtimes/z8a0df10c4ac0a197882574b20076a4c1.txt">here</a>.</p>Flex on Rails: the book - release date?2008-08-29T00:00:00-07:00http://onrails.org/2008/08/29/flex-on-rails-the-book-release-date<p>As you may know we started a while back with <a href="http://thillerson.blogspot.com/">Tony</a> on concocting some of our experiments, war stories, successes, discoveries, real life project experience on using Flex with Rails into a book titled “Flex on Rails: Building Rich Internet Applications With Adobe Flex 3.0 and Rails 2.0”. We are now “code complete”, wrote all the chapters and are in what I suspect (/hope) is the final editing stage. Yea!… well, that may end up being a longer process than I imagined and was told that it may take up to four month once the final manuscript is accepted. Nevertheless it was funny seeing our book appear on different book selling website as pre-order. Being my first (published) book I was curious and did some googling to see when it will be really ready. It’s pretty ‘funny’ to see how the dates are moving as the days go buy, but in short here is a quick overview on when the book will be released according to google…note..we are not totally done yet…so I wouldn’t really announce a date yet, but if google says…then it must be true :-) !!! Well, I was really hoping it hits the shelves earlier than some of these:<br />
<ul><br />
<li>1/16/2009 <a href="http://www.buy.com/prod/flex-on-rails-building-rich-internet-applications-with-adobe-flex-3-0/q/loc/106/208500393.html">buy.com</a> – $29.70<br />
<li>02/28/2009 <a href="http://www.amazon.co.uk/Books/s?ie=UTF8&rh=n%3A266239%2Cp_27%3ADaniel%20Wanja&field-author=Daniel%20Wanja&page=1">amazon.co.uk</a> – $28.79<br />
<li>May 29, 2008 <a href="http://search.oreilly.com/?author=Daniel+Wanja&i=1&q=flex&u1=q&u2=author">oreilly.com</a><br />
<li>12/26/2008 <a href="http://www.biggerbooks.com/bk_detail.aspx?ISBN=9780321543370">biggerbooks.com</a> – $38.21<br />
<li>12/1/2008 <a href="http://www2.loot.co.za/shop/product.jsp?lsn=0321543378">loot.co.za</a> – R385.00<br />
<li>12/26/2008 <a href="http://www.ecampus.com/book/9780321543370">ecampus.com</a> – $38.99<br />
<li>2008/12/2 <a href="http://monoclip.jp/by/kyow/monodtl/40755">monoclip.jp</a><br />
<li>2009/01 <a href="http://bookweb.kinokuniya.jp/guest/cgi-bin/booksea.cgi?ISBN=0321543378">bookweb.kinokuniya.jp</a><br />
<li>2009/01<a href="http://www.amazon.co.jp/Flex-Rails-Building-Internet-Applications/sim/0321543378/1"> www.amazon.co.jp</a> – 5,772(税込) この商品は1500円以上国内配送料無料</p>
</ul>Flex from Ford, Power by Microsoft.2008-08-29T00:00:00-07:00http://onrails.org/2008/08/29/flex-from-ford-power-by-microsoft<p><img src="http://onrails.org/files/20080828_FlexByFord.png" alt="20080828_FlexByFord.png" border="0" width="517" height="256" /><br />
Is Ford is jumping on the Flex bandwagon? And powered by Microsoft?</p>
<p><img src="http://onrails.org/files/20080828_poweredByMicrosoft.png" alt="20080828_poweredByMicrosoft.png" border="0" width="135" height="57" /></p>Check out the Advanced ActiveRecord Envycast2008-08-29T00:00:00-07:00http://onrails.org/2008/08/29/check-out-the-advanced-activerecord-envycast<p>I just went through the first <a href="http://envycasts.com/">screencast</a> from the <a href="http://www.railsenvy.com/">Rails Envy</a> guys’. I wasn’t sure if I would liked the fact that they used a green screen approach, but thought I would support their effort as I really like their weekly podcast. Guess what? It’s a really good screen cast, very informative, high quality and well done. Wait, there is more, they have a cool Cheat Sheet that comes with the download. Well worth the money, go <a href="http://envycasts.com/">check it out</a>.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20080829_EnvyCast.jpg" alt="20080829_EnvyCast.jpg" border="0" width="480" height="396" /></div>Flash Player 10 Mobile for iPhone?2008-08-27T00:00:00-07:00http://onrails.org/2008/08/27/flash-player-10-mobile-for-iphone<style>
.qttitle {
padding-left: 120px;
min-height: 120px;
background-image: url(http://images.apple.com/downloads/images/essentials_quicktime20070611.png);
background-position: top left;
background-repeat: no-repeat;
vertical-align: middle;
}
.playButton {
background-color: rgb(20,20,20);
cursor: pointer;
font-weight: bold;
font-size: 1.25em;
opacity: .8;
filter: alpha(opacity=80);
-moz-border-radius: 1em;
-webkit-border-radius: 1em;
position: relative;
top: 50%;
zoom: 100%;
padding: .5em 1em;
color: white;
}
.playBackground {
background-color: rgb(0,0,0);
opacity: 0.0;
filter: alpha(opacity=0);
position: absolute;
top: 0px; left: 0px;
}
</style>
I was viewing the video of the <a href="http://www.onflex.org/ted/2008/08/360flex-day-1-keynote-by-mark-anders.php">Day 1 Keynote</a> by Mark Anders at 360Flex where he made a reference to a mobile Flash application build in Flex. Mark just skinned a desktop app which turned in into a very iPhone like application which just happen to have the iPhone screen dimensions and behavior. It's 56 minutes in the presentation. Check it out and let me know what you think. I've included a video extract here after (without the sound):
<script src="http://www.apple.com/library/quicktime/scripts/ac_quicktime.js" language="JavaScript" type="text/javascript"></script>
<script src="http://www.apple.com/library/quicktime/scripts/qtp_library.js" language="JavaScript" type="text/javascript"></script>
<script type="text/javascript"><!--
QT_WritePoster_XHTML('Click to Play', 'http://onrails.org/files/20080827_flexiphoneskin_action-poster.jpg',
'http://onrails.org/files/20080827_flexiphoneskin_action.mov',
'246', '385', '',
'controller', 'true',
'autoplay', 'true',
'bgcolor', 'black',
'scale', 'aspect');
//-->
</script>
<noscript>
<object width="246" height="385" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab">
<param name="src" value="http://onrails.org/files/20080827_flexiphoneskin_action-poster.jpg" />
<param name="href" value="http://onrails.org/files/20080827_flexiphoneskin_action.mov" />
<param name="target" value="myself" />
<param name="controller" value="false" />
<param name="autoplay" value="false" />
<param name="scale" value="aspect" />
<embed width="246" height="385" type="video/quicktime" pluginspage="http://www.apple.com/quicktime/download/"
src="http://onrails.org/files/20080827_flexiphoneskin_action-poster.jpg"
href="http://onrails.org/files/20080827_flexiphoneskin_action.mov"
target="myself"
controller="false"
autoplay="false"
scale="aspect">
</embed>
</object>
</noscript>
That's when he changed the skin:
<div style="text-align:center;"><img src="http://onrails.org/files/20080827_flexiphoneskin.png" alt="20080827_flexiphoneskin.png" border="0" width="567" height="179" /></div>
That would be cool if we could soon start coding in Flex for the iPhone.
Enjoy!
Daniel.
What are all the Rails Date Formats?2008-08-20T00:00:00-07:00http://onrails.org/2008/08/20/what-are-all-the-rails-date-formats<p>Ever forget what all the Rails defined <code>Date/DateTime/Time#strftime</code> formats are? Or forget what ones you added to the project yourself?</p>
<p>Ala <code>rake routes</code> comes <code>rake date_formats</code>:</p>
<script src="http://gist.github.com/1352.js"></script><p>Sample output from a Rails 2.1 app:<br />
<pre><br />
Date<br />
====<br />
db:‘%Y-%m-%d’ 2008-08-20<br />
long_ordinal:‘&proc’ August 20th, 2008<br />
long:‘%B %e, %Y’ August 20, 2008<br />
rfc822:‘%e %b %Y’ 20 Aug 2008<br />
number:‘%Y%m%d’ 20080820<br />
short:‘%e %b’ 20 Aug</p>
<p>DateTime<br />
====<br />
db:‘%Y-%m-%d’ 2008-08-20 16:56:21<br />
long_ordinal:‘&proc’ August 20th, 2008 16:56<br />
long:‘%B %e, %Y’ August 20, 2008 16:56<br />
rfc822:‘%e %b %Y’ Wed, 20 Aug 2008 16:56:21 -0600<br />
number:‘%Y%m%d’ 20080820165621<br />
short:‘%e %b’ 20 Aug 16:56</p>
<p>Time<br />
====<br />
db:‘%Y-%m-%d %H:%M:%S’ 2008-08-20 16:56:21<br />
long_ordinal:‘&proc’ August 20th, 2008 16:56<br />
long:‘%B %d, %Y %H:%M’ August 20, 2008 16:56<br />
rfc822:‘%a, %d %b %Y %H:%M:%S %z’ Wed, 20 Aug 2008 16:56:21 -0600<br />
short:‘%d %b %H:%M’ 20 Aug 16:56<br />
number:‘%Y%m%d%H%M%S’ 20080820165621<br />
time:‘%H:%M’ 16:56<br />
</pre></p>Nested to_xml for awesome_nested_set2008-08-19T00:00:00-07:00http://onrails.org/2008/08/19/nested-to_xml-for-awesome_nested_set<p>I was updating an example build using the better_nested_set to use the awesome_nested_set. One thing that I didn’t find in awesome_nested_set are some helper methods that are returning a full tree of the nested set as one <span class="caps">XML</span> document. With better nested set I could do</p>
<typo:code lang="ruby">
<p>Category.result_to_attributes_xml(Category.root.ancestors)</p>
</typo:code>
<p>So I have added the following <em>full_xml</em> method to my nested active record to recurse all the children. Note that the <em>full_method</em> calls the <em>full_method</em> on the children passing along the xml builder that is created by the to_xml method and passed as the <em>xml</em> variable to block, thus building a nested <span class="caps">XML</span> document.</p>
<typo:code lang="ruby">
<p>class Category < ActiveRecord::Base<br />
belongs_to :parent, :class_name => “Category”<br />
acts_as_nested_set</p>
def full_xml(builder=nil)
to_xml(:builder => builder, :skip_instruct => true) do |xml|
children.each { |child| child.full_xml(xml) }
end
end
<p>end</p>
</typo:code>
<p>Obviously it would be nice that the awesome_nested_set provides such a method.</p>
<p>So let’s assume I create the following nested structure:</p>
<typo:code lang="ruby">
<p>Category.transaction do<br />
root = Category.create(:name => “Main Category”)</p>
cameras = Category.create(:name => “Cameras & Photo”)
cameras.move_to_child_of(root)
Category.create(:name => “Bags”, :qty_in_stock => 2).move_to_child_of(cameras)
Category.create(:name => “Accessories”, :qty_in_stock => 12).move_to_child_of(cameras)
Category.create(:name => “Analog Cameras”, :qty_in_stock => 0).move_to_child_of(cameras)
Category.create(:name => “Digital Cameras”, :qty_in_stock => 5).move_to_child_of(cameras)
phones = Category.create(:name => “Cell Phones”)
phones.move_to_child_of(root)
Category.create(:name => “Accessories”, :qty_in_stock => 8).move_to_child_of(phones)
Category.create(:name => “Phones”, :qty_in_stock => 20).move_to_child_of(phones)
Category.create(:name => “Prepaid Cards”, :qty_in_stock => 3).move_to_child_of(phones)
dvds = Category.create(:name => “Dvds”)
dvds.move_to_child_of(root)
Category.create(:name => “Blueray”, :qty_in_stock => 10).move_to_child_of(dvds)
Category.create(:name => “HD <span class="caps">DVD</span>”, :qty_in_stock => 0).move_to_child_of(dvds)
Category.create(:name => “<span class="caps">DVD</span>”, :qty_in_stock => 100).move_to_child_of(dvds)
<p>end</p>
</typo:code>
<p>I can now get the whole nested structure in one go:</p>
<typo:code lang="ruby">
<p>Category.roots.first.full_xml</p>
</typo:code>
<p>And get the following <span class="caps">XML</span> in return.</p>
<p><typo:code lang=“xml><br />
<category><br />
”datetime">2008-08-18T14:46:07Z</created-at><br />
<description nil="true"></description><br />
<id type="integer">1</id><br />
<lft type="integer">1</lft><br />
<name>Main Category</name><br />
<parent-id type="integer" nil="true"></parent-id><br />
<qty-in-stock type="integer" nil="true"></qty-in-stock><br />
<rgt type="integer">28</rgt><br />
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at><br />
<category><br />
<created-at type="datetime">2008-08-18T14:46:07Z</created-at><br />
<description nil="true"></description><br />
<id type="integer">11</id><br />
<lft type="integer">2</lft><br />
<name>Dvds</name><br />
<parent-id type="integer">1</parent-id><br />
<qty-in-stock type="integer" nil="true"></qty-in-stock><br />
<rgt type="integer">9</rgt><br />
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at><br />
<category><br />
<created-at type="datetime">2008-08-18T14:46:07Z</created-at><br />
<description nil="true"></description><br />
<id type="integer">14</id><br />
<lft type="integer">3</lft><br />
<name><span class="caps">DVD</span></name><br />
<parent-id type="integer">11</parent-id><br />
<qty-in-stock type="integer">100</qty-in-stock><br />
<rgt type="integer">4</rgt><br />
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at></p>
</category>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">13</id>
<lft type="integer">5</lft>
<name>HD <span class="caps">DVD</span></name>
<parent-id type="integer">11</parent-id>
<qty-in-stock type="integer">0</qty-in-stock>
<rgt type="integer">6</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
</category>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">12</id>
<lft type="integer">7</lft>
<name>Blueray</name>
<parent-id type="integer">11</parent-id>
<qty-in-stock type="integer">10</qty-in-stock>
<rgt type="integer">8</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
</category>
</category>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">7</id>
<lft type="integer">10</lft>
<name>Cell Phones</name>
<parent-id type="integer">1</parent-id>
<qty-in-stock type="integer" nil="true"></qty-in-stock>
<rgt type="integer">17</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">10</id>
<lft type="integer">11</lft>
<name>Prepaid Cards</name>
<parent-id type="integer">7</parent-id>
<qty-in-stock type="integer">3</qty-in-stock>
<rgt type="integer">12</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
</category>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">9</id>
<lft type="integer">13</lft>
<name>Phones</name>
<parent-id type="integer">7</parent-id>
<qty-in-stock type="integer">20</qty-in-stock>
<rgt type="integer">14</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
</category>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">8</id>
<lft type="integer">15</lft>
<name>Accessories</name>
<parent-id type="integer">7</parent-id>
<qty-in-stock type="integer">8</qty-in-stock>
<rgt type="integer">16</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
</category>
</category>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">2</id>
<lft type="integer">18</lft>
<name>Cameras & Photo</name>
<parent-id type="integer">1</parent-id>
<qty-in-stock type="integer" nil="true"></qty-in-stock>
<rgt type="integer">27</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">6</id>
<lft type="integer">19</lft>
<name>Digital Cameras</name>
<parent-id type="integer">2</parent-id>
<qty-in-stock type="integer">5</qty-in-stock>
<rgt type="integer">20</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
</category>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">5</id>
<lft type="integer">21</lft>
<name>Analog Cameras</name>
<parent-id type="integer">2</parent-id>
<qty-in-stock type="integer">0</qty-in-stock>
<rgt type="integer">22</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
</category>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">4</id>
<lft type="integer">23</lft>
<name>Accessories</name>
<parent-id type="integer">2</parent-id>
<qty-in-stock type="integer">12</qty-in-stock>
<rgt type="integer">24</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
</category>
<category>
<created-at type="datetime">2008-08-18T14:46:07Z</created-at>
<description nil="true"></description>
<id type="integer">3</id>
<lft type="integer">25</lft>
<name>Bags</name>
<parent-id type="integer">2</parent-id>
<qty-in-stock type="integer">2</qty-in-stock>
<rgt type="integer">26</rgt>
<updated-at type="datetime">2008-08-18T14:46:07Z</updated-at>
</category>
</category>
</category>
</typo:code>
<p>How do you deal with that situation?</p>360Flex sessions video - Day one2008-08-19T00:00:00-07:00http://onrails.org/2008/08/19/360flex-sessions-video-day-one<p><iframe src=“http://216.92.94.180/1733261879.html” scrolling=“auto” frameborder=“no” align=“center” height = “220px” width = "250px"></iframe></p>
<p>Sessions Posted:</p>
<ul>
<li>TicketMaster Kiosk by Kevin Fauth</li>
<li>Flex Accessibility by Giorgio Natili</li>
<li>Reading the Flex source code by Jonathan Branam</li>
<li>Project Workflow by Axel Jensen</li>
<li>Creating Reusable Components by Ben Clinkbeard</li>
</ul>
<p><a href="http://www.onflex.org/ted/2008/08/recording-360flex-free-full-sessions-on.php">From Ted’s blog.</a></p>iPhone in nearly every state. 147 out of 188 stores.2008-07-22T00:00:00-07:00http://onrails.org/2008/07/22/iphone-in-nearly-every-state-147-out-of-188-stores<p><img src="http://onrails.org/files/20080722_IphoneEveryWhere.png" alt="20080722_IphoneEveryWhere.png" border="0" width="286" height="184" /></p>
<p>From <a href="http://hasiphone.com/">hasiphone.com</a> July 22nd 2pm.</p>hasiphone.com now with US map2008-07-21T00:00:00-07:00http://onrails.org/2008/07/21/hasiphone-com-now-with-us-map<p>Thanks to the <a href="http://degrafa.com/">Degrafa</a> library I was able to add a “US Map of iPhone 3G” Availability in an hour to the <a href="http://hasiphone.com/">hasiphone.com</a> application.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20080721_hasiphoneusmap.png" alt="20080721_hasiphoneusmap.png" border="0" width="495" /></div>
<p>Also I automated the extraction part of the data and check every hour if new data is there. I was assuming that the data changes only once a day and therefore all the delta (the + and – next to the availability) are based on previous day. This morning there were only four stores with iPhones, and hour ago 76 and now 78. So it seems that the data is updated more frequently or I have a bug in my extraction routing. Whatever the situation I am leaving on vacations for the next two weeks and won’t take my notebook with me, so hopefully the data is correct. My good friend Sol will keep an eye on the extraction process to see that we get some daily data. Thanks Sol, ya da man.</p>
<p>Enjoy!<br />
Daniel.</p>
<p><img src="http://degrafa.com/images/banners/degrafa-badge-88x35.gif" /> is cool</p>4 stores out of 188 has iPhones 3G2008-07-21T00:00:00-07:00http://onrails.org/2008/07/21/4-stores-out-of-188-has-iphones-3g<div style="text-align:center;"><img src="http://onrails.org/files/20080721_ModelByStores.png" alt="20080721_ModelByStores.png" border="0" width="668" height="201" /></div>
<p>The phones are going faster than they are coming, only one store in each of these states are listed as having one type of the models: Florida, New Hampshire, California and Michigan. So if you take into account that some store list phones that didn’t work out of the box as available, the Apples Stores may well be out of stock today.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20080721_4stores.png" alt="20080721_4stores.png" border="0" width="486" height="103" /></div>
<p>Data from: Apple.com and visualized by <a href="http://hasiphone.com/">hasiphone.com</a></p>hasiphone.com - Statistics and Overview of iPhone availability at US Apple Stores2008-07-18T00:00:00-07:00http://onrails.org/2008/07/18/hasiphone-com-statistics-and-overview-of-iphone-availability-at-us-apple-stores<p>As part of the iPhone 3G mania I checked out Apple iPhone 3G availability <a href="http://www.apple.com/retail/iphone/availability.html">website</a> and that’s how I found where to buy my iPhone in Denver. I was however also wondering how many Apple store still had the iPhone in the US, so I wrote <a href="http://hasiphone.com">http://hasiphone.com</a> that provides an overview of the availability of the iPhone 3G in the US based on the data provided by Apple website. <div style="text-align:center;"><img src="http://onrails.org/files/20080717_hasiphone.png" alt="20080717_hasiphone.png" border="0" width="453" height="273" /></div></p>
<p>On the server an <span class="caps">AIR</span> application checks once a day the new availability data, crunches it up and saves it a a serialized datastructure to a ByteArray. The Hasiphone Flex application reads this data and visualizes it. Well, I spend 4 hours (which I didn’t really have before my vacations) on it, so their may be some glitches here and there. Leave comment on this blog if you find any issues.</p>
<p>Also a note of caution on the data. Like Apple’s site mentions it’s updated only once a day in the evening. One of the sales guy also mentioned to me that any iPhone that has an issue and cannot be sold but still is in stock may appear as available, thus their are stores that don’t have any 3G to sell but still show up on the list.</p>iPhone 3G or not?2008-07-08T00:00:00-07:00http://onrails.org/2008/07/08/iphone-3g-or-not<p>Since they announced the iPhone 3G I am pretty convinced that there isn’t much new over my current iPhone. Camera is still 2Mega pixels, the plastic case is not so nice, gps is cool, but I have one in my car, 16Gb over 8 could be useful, form factor changed slightly so it may not fit in my car cradle. So it’s basically the same phone with slightly faster internet. But I’m such a sucker when it comes to gadgets and I was just reading this article on <a href="http://support.apple.com/kb/HT2109">How to replace an original iPhone with an iPhone 3G</a>. Now if only my wife didn’t want my current iPhone, I wouldn’t have to buy the new one :-)</p>Compassionate Communications. A different kind of Rails application.2008-06-19T00:00:00-07:00http://onrails.org/2008/06/19/compassionate-communications-a-different-kind-of-rails-applicationI have been working with Sean and Lee on <a href="http://www.compassionatecommunications.com">Compassionate Communications</a> a Ruby on Rails website. My role was small thanks to the <a href="http://www.activemerchant.org/">ActiveMerchant</a> plugin, I helped with the online payment but my part was done in no time. The site launched just before Rails Conference and I wanted to write about what the site is. It's about giving, reaching out, helping...but I didn't find the right words to describe it. The team at <a href="http://www.compassionatecommunications.com/">Compassionate Communications</a> made the following video that captures the essence of what they want to achieve way better I could describe..so go check it out.
<div id="video_container" style="border: 1px solid rgb(204, 204, 204); padding: 4px;">
<embed id="mediaplayer" width="420" height="280" flashvars="usefullscreen=false&volume=100&width=420&height=280&file=http://www.compassionatecommunications.com/videos/promo.flv&image=http://www.compassionatecommunications.com/images/video_logo.png" quality="high" name="mediaplayer" style="" src="http://www.compassionatecommunications.com/swfs/mediaplayer.swf" type="application/x-shockwave-flash"/>
</div>
Running mod_rails on Leopard (OSX 10.5)2008-06-14T00:00:00-07:00http://onrails.org/2008/06/14/running-mod_rails-on-leopard-osx-10-5<p>From the command line:</p>
<typo:code>
<p>gem install passenger<br />
sudo passenger-install-apache2-module</p>
</typo:code>
<p>The Apache 2 module was successfully installed.</p>
<p>Please edit your Apache configuration file, and add these lines:</p>
LoadModule passenger_module /Library/Ruby/Gems/1.8/gems/passenger-1.0.5/ext/apache2/mod_passenger.so
RailsSpawnServer /Library/Ruby/Gems/1.8/gems/passenger-1.0.5/bin/passenger-spawn-server
RailsRuby /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
<p>Hey…where is the configuration. Google told me to read this blog entry: http://www.fuzzylizard.com/archives/2008/05/29/947/</p>
<p>So copy these three lines and add them to the end of this file: /etc/apache2/httpd.conf</p>
<p>$ sudo mate /etc/apache2/httpd.conf</p>
<p>Start and stop Apache go the to the System Preferences|Sharing and select the Web Sharing service:</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20080616_syspref.jpg" alt="20080616_syspref.jpg" border="0" width="467" height="382" /></div>
<p>Then the install script gives you the following instructions.</p>
<typo:code>
<p>Deploying a Ruby on Rails application: an example</p>
<p>Suppose you have a Ruby on Rails application in /somewhere. Add a virtual host<br />
to your Apache configuration file, and set its DocumentRoot to<br />
/somewhere/public, like this:</p>
<VirtualHost *:80>
ServerName www.yourhost.com
DocumentRoot /somewhere/public
</VirtualHost>
<p>And that’s it! You may also want to check the Users Guide for security and<br />
optimization tips and other useful information:</p>
/Library/Ruby/Gems/1.8/gems/passenger-1.0.5/doc/Users guide.html
<p>Enjoy Passenger, a product of Phusion (www.phusion.nl) :-)<br />
http://www.modrails.com/</p>
</typo:code>
<p>Now where is “my” apache configuration file? And more important where is yours? On the command line do</p>
<p>$ ls /etc/apache2/users/</p>
<p>And I see daniel.conf, so let’s edit that one. I am developing one Rails app in this folder: /Users/daniel/SvnProjects/for/stockportfolio/rails. So let’s define this application in that conf file:</p>
<p>$ sudo mate /etc/apache2/users/daniel.conf</p>
<typo:code>
<p><Directory “/Users/daniel/SvnProjects/for/stockportfolio/rails/”><br />
Order allow,deny<br />
Allow from all</p>
</Directory>
<p><VirtualHost *:80><br />
ServerName dev.stockportfolio.com<br />
DocumentRoot /Users/daniel/SvnProjects/for/stockportfolio/rails/public</p>
</VirtualHost>
</typo:code>
<p>Note the /public at the end of the folder in the DocumentRoot. <br />
Now I am adding dev.stockportfolio.com in my /etc/hosts file. So just add the following line</p>
<typo:code>
<p>127.0.0.1 dev.stockportfolio.com</p>
</typo:code>
<p>Now go back to the system preference sharing tab and restart the web service. Now you have your application running … in production mode. Just point your browser to dev.stockportfolio.com.</p>
<p>Enjoy Daniel!</p>Advanced Rails Studio: Day 32008-06-14T00:00:00-07:00http://onrails.org/2008/06/14/advanced-rails-studio-day-3<p>We are onto the 3rd day of the training, and the guys are still kicking. We are now onto Asynchronous processing. That’s good as I needed to catch up on what’s out there. I didn’t know about Starling. A light-weight queue server, might be a better solution than the heavier BackgroundRb based on the scenario you need to address. Any of you using Starling? Chad now goes into creating a plugin…ReviewableFu! Now onto debugging. And Caching.<br />
<br/>
Thanks guys awesome training, you covered tons of good material. Again, really worthwhile if you want to go to the next level with Rails.</p>At the Advanced Rails Studio in Denver2008-06-13T00:00:00-07:00http://onrails.org/2008/06/13/at-the-advanced-rails-studio-in-denver<p>We are just starting Day 2. Mike Clark and Chad Fowler are giving the training and are really good at it. They are 24 people taking the training, most not from Denver, and one from Mexico. Right now attendees are not awake and Mike and Chad are trying to wake us up. Yesterday we covered routes, looked at the Rails and Mongrel source code, looked at a RESTful application, covered ActiveResource, and checked ActiveRecord Associations. It’s nice to be able to sit back and take time to play with all these goodies without having to deliver code. It’s a nice refresher for me. Next step will be meta programming.</p>
<h3>Here are some notes from the ActiveRecord Associations part of the training:</h3>
<p><strong>Join Model</strong>: has_many :through</p>
<p><strong>Polymorphic Associations:</strong> has_many :address, :as => :addressable</p>
<p><strong>Custom Finders:</strong></p>
<typo:code lang="ruby">
<p>class User <br />
has_many :visits do<br />
def recent(limiit – 5)<br />
find(:all, :order => ‘created_at <span class="caps">DESC</span>’, :limit => 5)<br />
end<br />
end</p>
</typo:code>
<p><strong>Active Record Scoping:</strong></p>
<p>with_scope # protected now</p>
<p>before_filter :find_account</p>
<p><strong>Scoped Relationships:</strong></p>
<typo:code lang="ruby">
<p>@event.registations.find(params[:id])<br />
@user.events.find_by_id(params[:id])<br />
@event.registations.find(:all, :conditions => “pre_register is true”)</p>
</typo:code>
<p><strong>Named Associations:</strong></p>
<typo:code lang="ruby">
<p>class Event < ActiveRecord::Base<br />
has_many :registrations<br />
has_many :pre_registrations,<br />
:class_name => “Registration”,<br />
:conditions => “pre_register is true”<br />
end</p>
<p>@event.pre_registrations</p>
</typo:code>
<p><strong>Named Scope:</strong></p>
<typo:code lang="ruby">
<p>class Coupon < ActiveRecord::Base<br />
named_scope :limit_not_exceeded, :conditions => “use_count < max_uses”<br />
named_scope :usable_in_store, :conditions => “external_only is false”<br />
end</p>
<p>Coupon.limit_not_exceeded<br />
Coupon.usable_in_store<br />
Coupon.limit_not_exceeded.usable_in_store</p>
</typo:code>
<p><strong>Dynamic Named Scope:</strong></p>
<typo:code lang="ruby">
<p>class Coupon < ActiveRecord::Base<br />
named_scope :not_expired, lambda { { :conditions => [‘expires_at > ?’, Time.now] } }<br />
named_scope :used_at_most, lambda { |uses| { :conditions => [‘use_count <= ?’, uses] } }<br />
end</p>
<p>Coupon.not_expired<br />
Coupon.used_at_most(30)<br />
Coupon.not_expired.used_at_most(10)</p>
</typo:code>Advanced Rails Studio: Meta Programming2008-06-13T00:00:00-07:00http://onrails.org/2008/06/13/advanced-rails-studio-meta-programming<p>Chad is giving a very nice presentation walking us through meta programming step by step. You can see the code examples we are creating during his talk, but just looking at the code will note give the whole picture.</p>Advanced Rails Studio: Custom Form Builder2008-06-13T00:00:00-07:00http://onrails.org/2008/06/13/advanced-rails-studio-custom-form-builder<p>Custom Form Builder</p>
<p>Use a custom form builder to clean up your html.erb files.</p>
<typo:code title="lib/label_form_builder.rb" lang="ruby">
<p>class LabelFormBuilder < ActionView::Helpers::FormBuilder<br />
helpers = field_helpers +<br />
%w{date_select datetime_select time_select} +<br />
%w{collection_select select country_select time_zone_select} -<br />
%w{hidden_field label fields_for} # Don’t decorate these</p>
helpers.each do |name|
define_method(name) do |field, *args|
options = args.last.is_a?(Hash) ? args.pop : {}
label = label(field, options[:label], :class => options[:label_clas])
@template.content_tag(:p, label +’<br/>’ + super) #wrap with a paragraph
end
end
<p>end</p>
</typo:code>
<p>Then you can remove all the <p> and label tags from you form.</p>
<typo:code title="app/views/users/edit.html.erb">
<h1>Editing user</h1>
<p><% form_for(@user, :builder => LabelFormBuilder) do |f| <span>><br />
<</span>= f.error_messages <span>><br />
<</span>= f.text_field :name <span>><br />
<</span>= f.text_field :address <span>><br />
<</span>= f.text_area :comment <span>><br />
<</span>= f.check_box :check <span>><br />
<</span>= f.submit “Update” <span>><br />
<</span> end %></p>
<p><%= link_to ‘Show’, @user <span>> |<br />
<</span>= link_to ‘Back’, users_path %></p>
</typo:code>
<p>Add this to your application initializer to have all form use this form builder</p>
<typo:code>
<p>ActionView::Base.default_form_builder = LabelFormBuilder</p>
</typo:code>
<p>Then you can replace<br />
<typo:code><br />
<% form_for(@user, :builder => LabelFormBuilder) do |f| %></p>
</typo:code>
<p>with <br />
<typo:code><br />
<% form_for(@user) do |f| %></p>
</typo:code>
<p>Now the same form with no custom builder was looking like this before.</p>
<typo:code>
<h1>Editing user</h1>
<p><% form_for(@user) do |f| <span>><br />
<</span>= f.error_messages %></p>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :address %><br />
<%= f.text_field :address %>
</p>
<p>
<%= f.label :comment %><br />
<%= f.text_area :comment %>
</p>
<p>
<%= f.label :check %><br />
<%= f.check_box :check %>
</p>
<p>
<%= f.submit “Update” %>
</p>
<p><% end %></p>
<p><%= link_to ‘Show’, @user <span>> |<br />
<</span>= link_to ‘Back’, users_path %></p>
</typo:code>RailsConf 2008 Ruby Hero Awards Video2008-06-01T00:00:00-07:00http://onrails.org/2008/06/01/railsconf-2008-ruby-hero-award-video<p><a href="http://www.RubyHeroes.com" title="Ruby Heroes"><img alt="Ruby Heroes" src="http://rubyheroes.morphexchange.com/images/rubyhero_button_small.png" /></a></p>
<p><object width="400" height="300"> <param name="allowfullscreen" value="true" /> <param name="allowscriptaccess" value="always" /> <param name="movie" value="http://www.vimeo.com/moogaloop.swf?clip_id=1099180&server=www.vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /> <embed src="http://www.vimeo.com/moogaloop.swf?clip_id=1099180&server=www.vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><br /><a href="http://www.vimeo.com/1099180?pg=embed&sec=1099180">RailsConf 2008 Ruby Hero Award Video</a> on <a href="http://vimeo.com?pg=embed&sec=1099180">Vimeo</a>.</p>
<p>The guys over at <a href="http://www.railsenvy.com/">Rails Envy</a> somehow managed to present (and create) the Ruby Heroes Awards at RailsConf…funny as usual. Check out this video extracts from the talk.</p>
<p><span class="caps">UPDATE</span>: what I didn’t mention for this video and what remi realized is that I was sitting way back in the room and took only sections of the video and it’s quite ruff and shaky.</p>RailsConf 2008 Git Talk by Scott Chacon Video2008-06-01T00:00:00-07:00http://onrails.org/2008/06/01/railsconf-2008-git-talk-by-scot-chacon-video<p><strong>Update</strong>: Scott did a voice-over with his slides he presented at Railsconf, so to get the full presentation, head-over at <a href="http://www.gitcasts.com/posts/railsconf-git-talk">gitcasts</a> now. The video here after is only a subset of the talk, so first go check out his <a href="http://www.gitcasts.com/posts/railsconf-git-talk">gitcast</a>.</p>
<p>Most awesome talk of RailsConf 2008.</p>
<p><object width="400" height="300"> <param name="allowfullscreen" value="true" /> <param name="allowscriptaccess" value="always" /> <param name="movie" value="http://www.vimeo.com/moogaloop.swf?clip_id=1099027&server=www.vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /> <embed src="http://www.vimeo.com/moogaloop.swf?clip_id=1099027&server=www.vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><br /><a href="http://www.vimeo.com/1099027?pg=embed&sec=1099027">RailsConf 2008 Git Talk by Scot Chacon Video</a> on <a href="http://vimeo.com?pg=embed&sec=1099027">Vimeo</a>.</p>
<p>As everyone in the Rails community is moving towards using Git, there are many new concepts to grasp and Scott provides an astonishing, fast passed and very visual presentation providing everything you need to master git. He published the slides on his gitcasts website (http://www.gitcasts.com/git-talk). Also checkout his pdf http://peepcode.com/products/git-internals-pdf</p>
<p>Warning: I apparently didn’t choose the right conversion ratio and the image is a little squeezed…and again…I was still sitting at the back of the room.</p>RailsConf 2008 David Heinemeier Hansson's Keynote Video2008-05-31T00:00:00-07:00http://onrails.org/2008/05/31/railsconf-2008-david-heinemeier-hanssons-keynote-video<p><object width="400" height="300"> <param name="allowfullscreen" value="true" /> <param name="allowscriptaccess" value="always" /> <param name="movie" value="http://www.vimeo.com/moogaloop.swf?clip_id=1096456&server=www.vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /> <embed src="http://www.vimeo.com/moogaloop.swf?clip_id=1096456&server=www.vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><br /><a href="http://www.vimeo.com/1096456?pg=embed&sec=1096456">RailsConf 2008 David Heinemeier Hansson Keynote</a> on <a href="http://vimeo.com?pg=embed&sec=1096456">Vimeo</a>.</p>
<p>Part of dhh’s message was to spread the message…so I assume I should be fine to publishing these extracts from David’s keynote. I was sitting at the back of the room and took some videos snapshot. I didn’t film all the talk as I didn’t have a tripod, but this will give you a nice overview of the what was going on during the talk…Rails is pretty big, there where lots of people there…and David was going beyond technology and telling the attendance that all Rails developers should seize the opportunity Rails create to improve themselves and not only from a technical point of view. Check it out.</p>
<p>Warning: I didn’t edit the video and didn’t have a tripod so it’s quite ruff and shaky. Also oreilly is going to publish an high quality official one.</p>
<p><strong>Update</strong>: video was gone…seems to be back now.</p>RailsConf tutorial and source code open sourced2008-05-30T00:00:00-07:00http://onrails.org/2008/05/30/railsconf-tutorial-and-source-code-open-sourced<p>Thanks to everyone that attended the Powering <span class="caps">AIR</span> with Rails talk. That was really cool. I didn’t realize how hard it is to give such talks, but hey…party time now. It’s fun to give a presentation the first day at a conference, we can now enjoy the rest of the conference.</p>
<p>You can find the slides and the source code at:</p>
<p><a href="http://github.com/danielwanja/railsconf2008">http://github.com/danielwanja/railsconf2008</a></p>
<p>We presented the following 10 <span class="caps">AIR</span> applications:</p>
<pre>
01_AIRBrowser
mx:HTML
dougmccune CoverFlowContainer
02_HelloBlog
ActionScript/Javascript Brige
Drag Drop API
03_WebSnippet
javascript injection using HTMLComponent
File
Sprite/drawing API
Window API
Bitmap manipulation
04_HTMLFileBrowser
File System Access
AIRAliases.js
05_OfflineCampfire
Windowing API
flash.desktop.NativeApplication
DockIcon
SharedObject
06_S3Browser
flash.filesystem.File.upload
HTTPService + REST (list, create, delete)
attachment_fu (S3)
07_SQLExample
sql lite from AIR
08_PhotoBooth
flash.media.Camera
flash.media.Video
flash.net.URLLoader
attachment_fu (file)
09_TwitterSpider
Charting API
DataGrid/Filtering
10_TwitterFriends
com.adobe.flex.extras.controls.springgraph
twitter4r
</pre>
<p>Enjoy,</p>
<p>Daniel and Tony!</p>RailsConf 2008 is started.2008-05-29T00:00:00-07:00http://onrails.org/2008/05/29/railsconf-2008-is-started<p>RailsConf this year has a pre-conference tutorials days which was optional and it’s starting now. However attendance seems already pretty big and there was a quite long queue to the registrations desks. I am now at Denny’s for my breakfast and will skip the first tutorial and meet with Tony to apply the finishing touch to our talk. We have a lot of code to present, I hope we can cover all the details in the 3.5 hours we have. We will publish the slides and the source code of the 10 apps we are going to present, so if you didn’t make it to RailsConf or our talk you still can get a glimpse at what we are presenting. The slides will have code extracts, but during the talk we will not use them as we will run and show the apps, so there is still good value if you attend the talk :-). See you there!</p>
<p>Enjoy, Daniel.</p>Powering AIR Applications with Rails - RailsConf tutorial preview.2008-05-23T00:00:00-07:00http://onrails.org/2008/05/23/powering-air-applications-with-rails-railsconf-tutorial-preview<p>Last night I gave a 2 1/2 hour tutorial preview at Derailed (Denver’s Ruby On Rails User Group) of the <a href="http://en.oreilly.com/rails2008/public/schedule/detail/1213">talk</a> <a href="http://thillerson.blogspot.com/">Tony</a> and myself will be giving at RailsConf next week. This allowed me to understand if we have enough material and what needs to be changed for the different sections we are going to present. I guess we have too much material as I wasn’t able to present some of the apps I have created for the presentation. Attendance was pretty low, about 15 people, but the feedback was excellent and it seems they have appreciated the talk. For the talk we will be showing how to code many of the features and ways in which using <a href="http://www.adobe.com/products/air/"><span class="caps">AIR</span></a> can enhance your Rails application. Lot’s of code in the second part. We will cover the different APIs <span class="caps">AIR</span> provides such a File system access, Native Drag&Drop, Native Windowing, Dock Notification, Sending binary files to S3 via attachment_fu, taking photos from your webcam and sending them directly to your Rails app (attachment_fu again!), how to manipulate the <span class="caps">HTML</span> <span class="caps">DOM</span>, and of course a couple of twitter related apps, one using <a href="http://twitter4r.rubyforge.org/">twitter4r</a> and the other spidering twitter.com (I hope I am not the guy who is bringing it down)…and much more. If you intend to attend drop us a line. See you there!</p>
<p>Daniel. </p>My RailsConf Schedule2008-05-09T00:00:00-07:00http://onrails.org/2008/05/09/my-railsconf-schedule<p>Railsconf now has an <a href="">iCal version</a> of the schedule. if you are logged in you can even select individual sessions and you will then have your personal schedule available in iCal format. I know..I know…it’s a little early, but hey, I wanted to see what’s talks they have, and there is really a bunch of goods ones. Here is my selection so far</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20080508_RailsConfSchedule.jpg" alt="20080508_RailsConfSchedule.jpg" border="0" width="520" /></div>Interview with the owner of MunchAway: an online food ordering application build with Ruby On Rails. 2008-05-07T00:00:00-07:00http://onrails.org/2008/05/07/interview-with-the-owner-of-munchaway-an-online-food-ordering-application-build-with-ruby-on-rails<p>Interview with the owner of MunchAway: an online food ordering application build with Ruby On Rails.</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20080506_MunchAwayMenu.jpg" alt="20080506_MunchAwayMenu.jpg" border="0" width="456" height="273" /></div>
<p>I was working at the end of last year and the beginning of this year part time on a cool Ruby on Rails project. I recently contacted the owner of the project and asked him if I could interview him to share his thoughts on different aspects on the project in an interview to be posted on my blog. He shared openly his views on Ruby on Rails, on using a mix of consultants and employes, and on the project in general. I think you find will his answers informative.</p>
<p>Rob, the owner of <a href="http://www.lt2sys.com">lt2sys.com</a> had a vision to make an online food ordering platform that can easily add online food ordering to Restaurants that already use an existing point of sale (basically the touch screens when you order your food at the restaurant). So Rob put together a team of consultants, employees and offshore Rails developers and created the application which has a front-end online ordering, a back-end system to configure new stores, and communication system that interacts with the point of sales. The development of the initial phase took several month and the system is now live serving many restaurants.</p>
<p><strong>Interview with the Rob, the owner of lt2sys</strong></p>
<div style="text-align:center;">On Using Rails</div>
<p><strong>Question</strong>: What made you choose Ruby on Rails to develop your solution?<br/>
<strong>Rob</strong>: I made a strategic decision to use what I perceived to be the best available web development technology available. This was difficult for me because by using Ruby on Rails, I was choosing a technology that I had no personal experience in using. I read many blogs and product reviews, and discussed this with my internal staff.<br/></p>
<p><strong>Question</strong>: Did you consider other technologies like .Net, Java, Php, Phyton? <br/>
<strong>Rob</strong>: Beside Ruby, the only other product that I considered besides Rails was .Net. We have a lot of .<span class="caps">NET</span> expertise inhouse, and I had some Java <span class="caps">JSP</span> experience. We had one developer in house with Ruby on Rails expertise.. I didn’t really consider Java because I wanted to use something that my internal team would be willing to use. That came down to Ruby or .<span class="caps">NET</span> We debated this for quite a while. I ultimately decided on Ruby because of my longterm frustrations of using Microsoft development products. Every new version of .<span class="caps">NET</span> requires more and more resources, the development tools take longer to use, and it seems that Microsoft is constantly changing the languages or key features that you come to rely on. <br/></p>
<p><strong>Question</strong>: Where do you see the strong/weak points of Rails? <br/> <br />
<strong>Rob</strong>: My in-house developers and I have had a hard time adapting to development with Rails. This was a key goal of the project – to develop additional inhouse expertise in Rails. I was unable to find sufficient time, and one of my senior .Net developers grew frustrated with Rails and stopped developing with it (however he learned Ruby and continues to contribute with that expertise). On the plus side, for those that understand the Ruby on Rails framework, they do seem to develop new features quickly.<br/></p>
<p><strong>Question</strong>: Would you Rails for another project? <br/>
<strong>Rob</strong>: From a technology viewpoint, the answer is Yes, but from a business viewpoint I haven’t made a decision on that yet. <br/></p>
<p><strong>Question</strong>: What do you think of developing and running Rails applications for so many customers? <br/>
<strong>Rob</strong>: I took a big risk in utilizing Rails to develop this application. So far it’s working, but the actual performance of the application is just barely acceptable. We need to optimize the application for further expansion.<br/></p>
<div style="text-align:center;">On Using a mix on Consultants/Employees/Offshore Resources</div><p><br/></p>
<p><strong>Question</strong>: You used a mix of consultants, employees and offshore resources for this project, can you elaborate on this choice? <br/>
<strong>Rob</strong>: After I had completed the project’s high level design specifications (40+ pages) and a detailed data model in a “platform neutral” fashion, I was in a position to determine how I wanted to develop the project. I knew that due to internal resource constraints that outsourcing was the only real alternative to getting the project done in a timely manner. So I approached the problem of finding outside resources and making a final choice between using Ruby on Rails or .<span class="caps">NET</span> more or less simultaneously. Cost was an issue; but also what concerned me was that since I was not providing an extremely detailed design and I didn’t have the right system architecture experience to personally architect an enterprise web application using either Rails or .<span class="caps">NET</span>, I wanted the initial developers to be very senior and highly experienced developers who could look at the big picture of systems design and put something together that would support a large number of simultaneous users. I also needed to transfer a lot of domain knowledge to them, so I decided that going offshore for the initial phase of development would entail a tremendous amount of brain damage at best and a highly risky proposition in any case. So I decided that finding the right developers to initially build the system the right way was in our best interest. <br/></p>
<p><strong>Question</strong>: How did you ensure proper workflow between the different teams? <br/>
<strong>Rob</strong>: The application has a consumer front end, an administrative console, and a communications component with the restaurant.. I put my Ruby on Rails experts on design of the Front End application, my internal Ruby on Rails expert on the Administrative console, and a 2nd internal resource on the communications component. As I had spec’d out the communications component in great detail this was easier to manager. My ruby on rails experts that were working on the consumer application reviewed the data model and reworked it to make it work better with ruby. I acted as project manager and worked to explain the domain knowledge to all parties and resolve design issues as they occurred. It was a very hands on approach.<br/></p>
<p><strong>Question</strong>: Did you have difficulties finding Rails consultants? <br/>
<strong>Rob</strong>: I did. There didn’t seem to be much of a pool locally. Because I needed to transfer a lot of domain knowledge I wanted to find people locally that could come into the office and work. I was able to find 2 very key people to do the Ruby on Rails development, but struggled to find a graphics designer that had experience with Ruby on Rails and Liquid. It seemed to be a very small community of people that actually knew how to work with the technology.<br/></p>
<p><strong>Question</strong>: How did you select an offshore service provider? <br/>
<strong>Rob</strong>: I did a number of web searches to find companies offshore that claimed to have experience. I emailed each and began a dialogue with the ones that responded. I had several conversations with each company. Some I dropped off the list because I frankly couldn’t understand what there were saying! Another company I dropped off because I had a conversation with their lead technology guy and he started dissing the technology choices and suggested they could do better. It seemed like a classic case of <span class="caps">NIH</span>. The problem with that was I was looking for a company to take over the project and do new development, not rewrite the product! I ultimately got down to two companies, both of which seemed acceptable. I choose one and gave them a project that I felt was low risk to start with. Even if they failed completely the product would not be in jeopardy. Fortunately they did a good job and over time have made several enhancements to the product.<br/></p>
<div style="text-align:center;">On Using Hosted environment .vs. hosting your own servers</div><p><br/></p>
<p><strong>Question</strong>: You choose a hosted environment, did you consider using your own servers? <br/>
<strong>Rob</strong>: No. That would require additional investment in IT management resources that frankly we don’t have.<br/></p>
<p><strong>Question</strong>: What do you think of Engineyard? <br/>
<strong>Rob</strong>: Engine Yard has been a great choice for us because they have acted as the IT department for MunchAway. It’s great that almost every time I call them a real person that knows something answers the phone!<br/></p>
<div style="text-align:center;">On the Project Development</div>
<p><strong>Question</strong>: Did the project work as expect?<br/>
<strong>Rob</strong>: Performance is an issue for us. This is really the only issue, and I expect that we will be able to resolve it over time.<br/></p>
<p><strong>Question</strong>: Did you encounter issues?<br/>
<strong>Rob</strong>: The issue that we ran into was that we expected to provide an application that would be easily maintainable the graphics designers by our users. This has not been the case, in fact, we have had to retain a graphics designer with Ruby on Rails and Liquid expertise to help us in this area.<br/></p>
<p><strong>Question</strong>: What’s planned next for the application? <br/>
<strong>Rob</strong>: The consumer side of the application needs to be extended so that it can be easily used on IPhone and Blackberry devices. <br/></p>
<div style="text-align:center;">On the Application</div>
<p><strong>Question</strong>: Is this you first online food ordering application you developed? <br/>
<strong>Rob</strong>: Not directly. We originally developed a middleware application that provides the ability for web developers to interface with Restaurant Point of Sale. This is in use with several different online ordering companies for several years. MunchAway connects to that middleware and provides the full online ordering solution for restaurants.<br/></p>
<p><strong>Question</strong>: What differentiates your platform from your competitors? <br/>
<strong>Rob</strong>: Technically, because our middleware application extracts the restaurant’s menu from the point of sale system, we can construct a customer’s web ordering system quickly and maintain it very easily. Also, many online ordering solutions do not integrate with the point of sale system at all; they use a fax machine or email as the delivery mechanism for the order. From a business standpoint we are unique in that we market the product through a well established point of sale dealer network which understands the restaurant customer base and this is a real value add.<br/></p>
<p><strong>Question</strong>: Why do you offer a subscription based solution rather than providing one off solutions for you customers? <br/>
<strong>Rob</strong>: <span class="caps">SAAS</span> makes sense for our customers as we offer the hosting service as well as ongoing product improvement to our entire customer base.<br/></p>
<div style="text-align:center;">On Running the Application</div>
<p><strong>Question</strong>: How restaurants (locations) are now served with your platform? <br/>
<strong>Rob</strong>: At each restaurant we install our middleware application which acts as the conduit between the MunchAway website and the Restaurant Point of Sale System. The middleware extracts menus (which incorporates the business rules of ordering each item on the the <span class="caps">POS</span>)_and posts them to the MunchAway website; it also accepts orders from the website and posts them on the restaurant point of sale system. This is a major plus for the restaurant as this eliminates all the labor involved in reentering the order and insures no mistakes are made in the process.<br/></p>
<p><strong>Question</strong>: How quickly can you add a new customer/new locations? <br/>
<strong>Rob</strong>: 4 man hours to add the customer’s first location, which includes installing the software at the restaurant <span class="caps">POS</span> and applying the customer’s graphic look and feel to the MunchAway website. Locations 2 thru X take 1 hour each to setup.<br/></p>
<p><strong>Question</strong>: Can a customer change the look and feel of your solutions? <br/>
<strong>Rob</strong>: No. This was an original goal of the project, but this has not yet been achieved. We rely on a graphic designer with ruby on rails and liquid experience to make customer customizations as needed.<br/></p>Just signed up for Advanced Rails Studio2008-05-02T00:00:00-07:00http://onrails.org/2008/05/02/just-signed-up-for-advanced-rails-studio<p><a href="http://pragmaticstudio.com/railsadvanced/">It’s</a> in Denver on June 12 to 14. And from May 29th to June 1st I’ll be at RailsConf. Wouhao…Not sure when I will do customer work, but it’s gonna be a fun couple of month ahead. I haven’t been at a Rails studio before, but have been at the <a href="http://pragmaticstudio.com/therailsedge/">The Rails Edge Conference</a> and it was a pretty awesome and intense conference, so I expect a lot from the Rails Studio. I’ll keep you informed. Of course before that there will be RailsConf 2008, last year I thought it was getting too big for a conference, but it was still really fun to geek out there. So let’s get ready!!! Let me know if you attend one or the other of these conferences/trainning.</p>Color Syntax copying for TextMate2008-04-29T00:00:00-07:00http://onrails.org/2008/04/29/color-syntax-copying-for-textmate<p>Just in time for preparing our RailsConf talk I found out how to copy text with color syntax from TextMate. Simply Ctrl+Alt+Cmd+R in TextMate and paste in Keynote. Of course you need the copy-as-rtf-tmbundle from <a href="http://muermann.org/">Max Muermann</a>. I was using XCode for that before, but the keyword detection was different that Textmate’s which I prefer.</p>
<p>To install:<br />
<typo:code><br />
cd ~/Library/Application\ Support/TextMate/Bundles<br />
git clone git://github.com/drnic/copy-as-rtf-tmbundle.git “Copy as <span class="caps">RTF</span>.tmbundle”</p>
</typo:code>
<p>DrNic put the bundle on <a href="http://github.com/drnic/copy-as-rtf-tmbundle/tree/master">github</a>.</p>Flash Media Server(s) in Ruby?2008-04-25T00:00:00-07:00http://onrails.org/2008/04/25/flash-media-server-s-in-ruby<p>While preparing an application to be presented during our <a href="http://en.oreilly.com/rails2008/public/schedule/detail/1213">talk</a> for RailsConf I was looking for a “Flash Media Server” written in Ruby that could record video form a Flash Player. I found <a href="http://code.google.com/p/rubyizumi/">rubyizumi</a> but it doesn’t support recording (to my understanding). In Javaland they are a couple, <a href="http://osflash.org/red5">red5</a> and <a href="http://code.google.com/p/demou/">demou</a>, but they are too convoluted for just a demo. Red5 allows Ruby scripting which is pretty cool. I found one which I really like and will certainly use which is named <a href="http://haxevideo.org/">haxe Video</a> which is written in <a href="http://haxe.org/">haXe</a> and is very succinct and works. It’s open source and can be found on <a href="http://code.google.com/p/haxevideo">googlecode</a>. Of course there is Adobe’s <a href="http://www.adobe.com/products/flashmediaserver/">Flash Media Server</a> but I would prefer finding a Ruby specific solution. Do you know any Flash Media Server written in Ruby? Drop me a line or a comment.</p>Don't use networksolutions.com for you domain name searches...2008-04-24T00:00:00-07:00http://onrails.org/2008/04/24/dont-use-networksolutions-com-for-you-domain-name-searches<p>I frequently get “great” ideas and reserve some domain names. Call me silly, but this makes the ideas more tangible even if I never work on them. I book my domain names through 1and1.com, for about $7 a year, but I do usually the search on netsol.com . So I searched for some names this morning, then decided to abandon, my idea didn’t need a separate domain for now, and to my surprise I got the following dialog when leaving the site:</p>
<p><img src="http://onrails.org/files/20080424_netsol.jpg" alt="20080424_netsol.jpg" border="0" width="392" height="262" /></p>
<p>So what does that mean? Well, it seems if I click OK they will hide the names I searched for from others users who are doing searches for 4 days. So my recommendation: don’t use networksolutions.com for your search.</p>WebSnapshot Updated. 2008-04-22T00:00:00-07:00http://onrails.org/2008/04/22/websnapshot-updated<div style="text-align:center;"><img src="http://onrails.org/files/websnapshot_1.jpg" alt="websnapshot_1.jpg" border="0" width="450" /></div>
<p>The guys running the Adobe <span class="caps">AIR</span> Marketplace contacted me a couple of weeks ago to publish Websnapshot on the market place. Then they kindly gave me a free Thawte code signing certificate. So I republished the app and changed the skin, I used the Darkroom theme found on <a href="http://www.scalenine.com/">scalenine.com</a>. Thawte didn’t make it easy on me to get the certificate. The main issue was that I didn’t have a phone number associated with my company name, therefore Thawte wanted me to send a phone bill with my company name (thug!) or a notarized letter. I had to resend three times the letter as first they couldn’t read it, then it didn’t show some required date…Well, finally I got the certificate and could sign the application. I don’t believe it will make a difference to many users as most people currently install non-signed apps anyhow. Now that certificate was changed from the initial I used to sign the application it will however require that you uninstall first the application if it was already installed.</p>
<p>You can now find the application on the <a href="http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&loc=en_us&extid=1460520">Marketplace</a> or <a href="http://myspyder.net/tools/websnapshot/">here</a>.</p>
<p>It’s basically the same version than before with just a minor scaling issue fixed. What I need to add next is auto update, custom filenames, saving to s3 and Flickr.</p>
<p>Enjoy!<br />
Daniel.</p>
Google's appengine is up and running.2008-04-08T00:00:00-07:00http://onrails.org/2008/04/08/googles-appengine-is-up-and-running<p><a href="http://code.google.com/appengine/">Appengine</a> is Google’s answer to Amazon’s web services (ec2, s3, …). I just signed up and got the following message: “Thanks for checking in! When space in the Google App Engine preview release becomes available, we’ll notify you by emailing…”</p>
<p>While waiting you can read there <a href="http://code.google.com/appengine/docs/gettingstarted/">doc</a> or download the <a href="http://code.google.com/appengine/downloads.html"><span class="caps">SDK</span></a>.</p>
<p>They have some <a href="http://appgallery.appspot.com/">demo apps</a>. Also, the runtime or development language of choice seems to be Python…hopefully Ruby is next on the line.</p>
<p>Update: 11:14pm Got an Invitation to try Google App Engine saying my account has been activated. The account allows me to create 3 applications.</p>iPhone SDK - first 5 minutes.2008-03-07T00:00:00-08:00http://onrails.org/2008/03/07/iphone-sdk-first-5-minutes<p>Off course I couldn’t resist, I had to give it a try. The sdk is a whopping 2GB download and 5.6 Gb install. It installs all the developers tools, java, gcc4.2, WebObjects, the kitchen sink. Upon successful installation the system needs to be restarted.</p>
<p>Start XCode and select ‘New Project…’ from the File menu.<br />
You can then select from 3 type of iPhone Applications <br />
<div style="text-align:center;"><img src="http://onrails.org/files/20080307_1_iphone_projects.gif" alt="20080307_1_iphone_projects.gif" border="0" width="455" height="103" /></div></p>
<p>Let’s try the Cocoa Touch List and I name my test project TimeList.</p>
<p>This creates a standard XCode project:<br />
<div style="text-align:center;"><img src="http://onrails.org/files/20080307_2_XCodeProject.jpg" alt="20080307_2_XCodeProject.jpg" border="0" width="447" height="335" /></div></p>
<p>I clicked “Build and Go”…the application is compiled and linked after 20 seconds got an emulate iPhone with the TimeList app visible:</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20080307_3_iPhoneHome.jpg" alt="20080307_3_iPhoneHome.jpg" border="0" width="231" height="445" /></div>
<p>Clicking on it we get a pre-populated list of timezones which behaves just like an iPhone:</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20080307_4_TimeList.jpg" alt="20080307_4_TimeList.jpg" border="0" width="231" height="445" /></div>
<p>Note the emulator application is called Aspen Simulator, it has a ‘Hardware’ menu that should allow to rotate the UI but that doesn’t seem to work. The emulator really feels like an iPhone, all the finger gestures can be done with the mouse and the UI behaves like an iPhone. Pretty cool.</p>
<p>Let’s look at the TimeListAppDelegate generated code:</p>
<typo:code>
<p>//<br />
// TimeListAppDelegate.m<br />
// TimeList<br />
//<br />
// Created by Daniel Wanja on 3/7/08.<br />
// Copyright <i>MyCompanyName</i> 2008. All rights reserved.<br />
//</p>
<p>#import “TimeListAppDelegate.h”</p>
<p>@implementation TimeListAppDelegate</p>
<p>@synthesize window;<br />
@synthesize tableView;</p>
<p>- init {<br />
if (self = [super init]) {<br />
// Your initialization code here<br />
}<br />
return self;<br />
}</p>
<p>- (void)applicationDidFinishLaunching:(UIApplication *)application {<br />
// Create window<br />
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];</p>
<p>// Set up table view<br />
tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain];<br />
tableView.delegate = self;<br />
tableView.dataSource = self;</p>
// Show the window with table view
<p>[window addSubview:tableView];<br />
[window makeKeyAndVisible];<br />
[tableView reloadData];<br />
}</p>
<p>- (void)dealloc {<br />
[tableView release];<br />
[window release];<br />
[super dealloc];<br />
}</p>
<p>- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {<br />
return 1;<br />
}</p>
<p>- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {<br />
return [[NSTimeZone knownTimeZoneNames] count];<br />
}</p>
<p>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath withAvailableCell:(UITableViewCell *)availableCell {<br />
UISimpleTableViewCell *cell = nil;<br />
if (availableCell != nil) {<br />
cell = (UISimpleTableViewCell *)availableCell;<br />
} else {<br />
CGRect frame = CGRectMake(0, 0, 300, 44);<br />
cell = [[[UISimpleTableViewCell alloc] initWithFrame:frame] autorelease];<br />
}<br />
cell.text = [[NSTimeZone knownTimeZoneNames] objectAtIndex:[indexPath row]];<br />
return cell;<br />
}</p>
<p>@end</p>
</typo:code>
<p>Looks like I have lots to read about before I can start changing that application. From what I can decipher once the application is initialized a UITableView is created and the delegate of the table view becomes the TimeListAppDelegate whish implements the numberOfRowsInSection and cellForRowAtIndexPath methods which uses the NSTimeZone knowTimeZonesNames as data source.</p>
<p>That was my first 5 minutes with the <span class="caps">SDK</span>. More to follow…now I have to go back to work :-( Next thing I will try out is the Interface Builder…stay tuned.</p>
<p>Enjoy!<br />
Daniel.</p>gemedit version 0.0.2 has been released!2008-03-07T00:00:00-08:00http://onrails.org/2008/03/07/gemedit-version-0-0-2-has-been-released<p>A utility to view a gem’s source in your favorite editor</p>
<p>Changes:</p>
<h2 id="002_20080307">0.0.2 2008-03-07</h2>
<ul>
<li>
<p>1 minor enhancement:</p>
<ul>
<li>add -p/–pretend option to show what gem(s) would be edited and with what command</li>
</ul>
</li>
<li>
<p><a href="http://gemedit.rubyforge.org">http://gemedit.rubyforge.org</a></p>
</li>
</ul>gemedit version 0.0.1 has been released!2008-02-29T00:00:00-08:00http://onrails.org/2008/02/29/gemedit-version-0-0-1-has-been-released<p>Check out my first published gem: <b>gemedit</b></p>
<p>A utility to view a gem’s source in your favorite editor</p>
<p>Changes:</p>
<ol>
<li>0.0.1 2008-02-27</li>
</ol><ul>
<li>1 major enhancement:
<ul>
<li>Initial release</li>
</ul></li>
</ul>
<ul>
<li><a href="http://gemedit.rubyforge.org/">http://gemedit.rubyforge.org/</a></li>
</ul>
<p>Specials thanks go to the following gems for making it easy to put this out there:</p>
<ul>
<li><a href="http://newgem.rubyforge.org/">newgem</a> by <a href="http://drnicwilliams.com/">Dr. Nic Williams</a></li>
<li><a href="http://seattlerb.rubyforge.org/hoe/">hoe</a> by <a href="http://blog.zenspider.com/">Ryan Davis</a></li>
<li><a href="http://rubyforge.org/projects/codeforpeople">rubyforge</a> by
<ul>
<li><a href="http://codeforpeople.com/">Ara T Howard</a></li>
<li><a href="http://blog.zenspider.com/">Ryan Davis</a></li>
<li><a href="http://blog.segment7.net/">Eric Hodel</a></li>
</ul></li>
</ul>WebSnapshot and RailsLogVisualizer ported to AIR 1.02008-02-26T00:00:00-08:00http://onrails.org/2008/02/26/websnapshot-and-railslogvisualizer-ported-to-air-1-0<p>I ported the <a href="http://www.myspyder.net/tools/websnapshot/">WebSnapshot</a> and <a href="http://www.myspyder.net/tools/railslogvisualizer/">RailsLogVisualizer</a> application to <span class="caps">AIR</span> 1.0</p>
<p><a href="http://www.myspyder.net/tools/websnapshot/"><img src="http://onrails.org/files/20080225_WebSnapshot.jpg" alt="20080225_WebSnapshot.jpg" border="0" width="225" height="137" /></a></p>
<p><a href="http://www.myspyder.net/tools/railslogvisualizer/"><img src="http://onrails.org/files/20080225_RailsLogVisualizer.jpg" alt="20080225_RailsLogVisualizer.jpg" border="0" width="225" height="137" /></a></p>
<p>Enjoy,<br />
Daniel</p>Something in the AIR? 2008-02-23T00:00:00-08:00http://onrails.org/2008/02/23/something-in-the-air<p><a href="http://www.360conferences.com/360flex/">360Flex</a> in Atlanta starts this monday. I was at the first 360Flex conference last year and it was a blast. I will miss going to that one. Also it seems that many Flex User Groups meetings around the world (Atlanta, <a href="http://groups.google.com/group/bangalorefx/browse_thread/thread/8bc14b067958e5af">Bangalore</a>, <a href="http://www.pokercoder.com/">London</a>, <a href="http://rmaug.com/">Denver</a>, <a href="http://adobeusergroup.be/index.php?option=com_content&task=view&id=49&Itemid=6">Amsterdam</a>) will held on this monday. When so many planets will align perfectly something special is bound to occur.</p>
<p>So more specifically from the Special Meeting invites:</p>
<ul>
<li>Exclusive user group video presentation by Adobe Chief Software Architect, Kevin Lynch</li>
<li>In-person presentation from Adobe Platform Evangelist, Kevin Hoyt</li>
<li>And…<strong>important product news!</strong></li>
</ul>
<p>That can mean only one thing. It’s gonna be soon time to recompile all my apps ;-)</p>
<p>Update 1: the Denver meeting is not on the 25th but on March 11th.<br />
Update 2: Ted Patrick <a href="http://www.onflex.org/ted/2008/02/flex-30-and-air-10-are-days-away.php">announces</a> yesterday that the Flex 3.0 and <span class="caps">AIR</span> 1.0 releases is days away.<br />
Update 3: <a href="http://www.adobe.com/products/flex/">Flex 3.0</a> and <a href="http://www.adobe.com/products/air/"><span class="caps">AIR</span> 1.0</a> are out. Go try out <a href="http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3email">FlexBuilder</a> if you haven’t yet, it’s the easiest way to get started.</p>Heroku.com - An impressive online Ruby on Rails Platform.2008-02-21T00:00:00-08:00http://onrails.org/2008/02/21/heorku-com-an-impressive-online-ruby-on-rails-platform<p>You’ve have to try it to believe it. It’s awesome that you can create a Rails application and deploy it all online. Nothing to install, it’s all there. I think it’s an awesome addition to the Rails world. It may not replace your development environment, but for deployment it’s pretty flexible and is based on <a href="">Amazon EC2</a>.</p>
<p>From their website the feature description is as follows:</p>
<ul>
<li>Instant Deployment</li>
<li>Create and Edit Online</li>
<li>Integrated Stack</li>
<li>Elastic Performance</li>
<li>Share and Collaborate</li>
<li>Import & Export</li>
<li>Full Ruby Environment</li>
<li>Gems & Plugins</li>
<li>Rails Console</li>
<li>Generate Code</li>
<li>Painless Migrations</li>
<li>Rake Console</li>
</ul>
<p>But you gotta see this to believe it. I made a quick screencast, so if you are not scared of a thick (swiss) french accent, have a look: (click image to open screencast in separate browser):<br />
<a href="http://myspyder.net/screencast/heroku" target="_blank"><br />
<div style="text-align:center;"><img src="http://onrails.org/files/20080220_HerokuSmall.jpg" alt="20080220_HerokuSmall.jpg" border="0" width="319" height="198" /></div></a></p>
<p>I can foresee, at least hope, that they will quickly add support for subversion and for Capistrano based deployment, hence becoming the ultimate deployment platform for Rails in addition to the powerful and flexible environment they already provide.</p>
<p>I signed up and received my invite three days later. If you can’t wait send me an email daniel[at]onrails.org, and I sign you up, that will allow to skip the wait.</p>
<p>Enjoy,<br />
Daniel.</p>Flexible Rails: A book on using Flex with Rails.2008-02-20T00:00:00-08:00http://onrails.org/2008/02/20/flexible-rails-a-book-on-using-flex-with-rails<p>As many of you know I really enjoy using Flex with Rails. So I finally picked-up a copy of <a href="http://manning.com/armstrong/">FlexibleRails</a> which is written by Peter Armstrong and started browsing through it last week-end. For anyone out there trying to enrich their application with some Flex or even writing the whole UI in Flex, check out this book as it’s a good starting point and Peter addresses many of the aspects that you will be faced with. Peter goes through several iterations of creating an application and introduces the reader to using Flex against a RESTful Rails application, he refactors the application to Cairngorm, uses <span class="caps">AMF</span>. So congratulations Peter of getting this done!</p>Dealing with HTTP errors in a Flex with Rails application.2008-02-20T00:00:00-08:00http://onrails.org/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application<p>The Flash Player is restricted in the way it deals with <span class="caps">HTTP</span> errors. This is mainly due to provide cross browser consistency and I believe is due to the restrictions the browser imposes on the Flash Player plugin. In fact when your Flex application performs <span class="caps">HTTP</span> requests using the HTTPService class, the request is passed by the Flash Player to the browser and in case of an Rails error (500, 404, …) the response is somehow crippled on the way back.</p>
<h2>Problem</h2>
<p>So let’s consider that the Flex application requests to update a Person but the validation fails. In the update method of our Rails controller the <span class="caps">HTTP</span> Status is set to :unprocessable_entity. This corresponds the <span class="caps">HTTP</span> error code 422.</p>
<typo:code language="ruby">
<ol>
<li><span class="caps">PUT</span> /people/1</li>
<li><span class="caps">PUT</span> /people/1.xml<br />
def update<br />
@person = Person.find(params[:id])</li>
</ol>
respond_to do |format|
if @person.update_attributes(params[:person])
flash[:notice] = ‘Person was successfully updated.’
format.html { redirect_to(@person) }
format.xml { head :ok }
else
format.html { render :action => “edit” }
format.xml { render :xml => @person.errors, :status => :unprocessable_entity }
end
end
end
</typo:code>
<p>Now in our Flex application by default we cannot identify that the error 422 occured, more annoyingly we cannot retrieve the Rails error messages. All we get back is the following:</p>
<typo:code>
<p>[FaultEvent fault=[<span class="caps">RPC</span> Fault faultString=“<span class="caps">HTTP</span> request error” faultCode=“Server.Error.Request” faultDetail=“Error: [IOErrorEvent type=”ioError" bubbles=false cancelable=false eventPhase=2 text=“Error #2032: Stream Error. <span class="caps">URL</span>: http://localhost:3000/people/8.xml?_method=put”]. <span class="caps">URL</span>: http://localhost:3000/people/8.xml?_method=put"] messageId=“65EBBA92-5911-68D2-1710-18A687C28455” type=“fault” bubbles=false cancelable=true eventPhase=2]</p>
</typo:code>
<h2>Solution</h2>
<p>I haven’t found a way to have the status code and error message appear in the Flex application without having to change the Rails application. But fortunately, I was able to deal with that by using an after_filter at the application controller level, hence having only one place in the application to take care of all controllers and requests. The trick is to “hide” the <span class="caps">HTTP</span> Status error code in Rails and as the Flex application deals with <span class="caps">XML</span> responses, simply check in Flex if the response starts with <errors>. This can then also be dealt with in the Flex application in one place of the application. In a Cairngorm application I had the Delegate transform these “errors” responses to Faults.</p>
<p>Here is an example of the change to the Rails ApplicationController.</p>
<typo:code language="ruby">
<p>class ApplicationController < ActionController::Base</p>
after_filter :flex_error_handling
def flex_error_handling
response.headers[‘Status’] = interpret_status(200) if response.headers[‘Status’] == interpret_status(422)
end
def rescue_action_in_public(exception)
render_exception(exception)
end
def rescue_action_locally(exception)
render_exception(exception)
end
rescue_from ActiveRecord::RecordNotFound, :with => :render_exception
def render_exception(exception)
render :text => “<errors><error>#{exception}</error></errors>”, :status => 200
end
<p>end</p>
</typo:code> Does a good idea make a good business?...One year later!2008-02-07T00:00:00-08:00http://onrails.org/2008/02/07/does-a-good-idea-make-a-good-business-one-year-later<p>A year ago we started a <a href="http://onrails.org/articles/2007/02/01/does-a-good-idea-make-a-good-business">new venture</a> to create small internet “service” business. We had an idea, and started implementing it Monday nights. I would like to use this blog post to reflect on where we are at. The short story is that a year after we still haven’t released a version and that feels a little frustrating. A year ago I asked on this blog if a good idea makes a good business? I was really trying to think about which of the different ideas we had I wanted to follow. Several people contacted me on the blog and offline, and I liked <a href="http://blog.nanorails.com/">Pascal’s</a> comment on the question mentioning that it boils down to execution. Reflecting on this, I believe we executed well, we persevered, we made huge progress, we solved many technical challenges, the application starts to look good, starts to work pretty well, is useful, but is not done yet. The main reasons is that we need to build a massive server side infrastructure to support this service. This isn’t as bad as it sounds as today with EC2, S3, and other hosting providers you can create some pretty scalable solutions in a pretty cost effective way, but we need to nail this down before starting to open the service to the public. Now you may wonder why we don’t just doit! This is the reasons why I am writing this post. I’ll be slowing down my “outside normal work” activities over the next several month to focus on our soon to be released child #3. Lee also just had child #1, and it will certainly take him some time to adjust to his new environment and schedule. It wouldn’t be fair to let Sol carry the development on by himself during that time and Lomax, the designer, really needs the developers to get the backend going before adding his magic design touch to the user interface. So I believe focus, patience and perseverance is also required to make a good business. It’s hard to explain in words, but the service we are developing will be useful for many internet users in it’s first iteration, and we already envision the next version that will allow to target online companies and will provide them with a unique service which hopefully will be very profitable for us. So I hope we will pickup the development in a couple of month and just be able to get it out the door. This will then only be the beginning…</p>
<p>Have fun!<br />
Daniel.</p>RailsConf registration opens today. Be ready!2008-01-29T00:00:00-08:00http://onrails.org/2008/01/29/railsconf-registration-opens-today-be-ready<p>May 29-June 1, 2008 in Portland, Oregon,</p>
<p><span class="caps">UPDATE</span>: registration is now <a href="http://en.oreilly.com/rails2008/public/content/home">open</a>.</p>
<p>UPDATE2: I’ll be presenting with <a href="http://thillerson.blogspot.com/">Tony</a> a 3 hour tutorial on <a href="http://en.oreilly.com/rails2008/public/schedule/detail/1213">Powering <span class="caps">AIR</span> Applications with Rails</a>. See you all there!</p>I Always Knew IE Was Shifty2008-01-27T00:00:00-08:00http://onrails.org/2008/01/27/i-always-knew-ie-was-shifty<p>While working on a Rails project, I stumbled upon a (probably) obscure positioning bug in IE, triggered by the ubiquitous “Yellow Fade Technique”, of all things. The symptom, as reported by the user, was that form elements on a page were “jumping around” when items were added to the cart. I’ve distilled the issue down to what I believe is the smallest reproduction of the issue, which I present to you now, in glorious validated <span class="caps">HTML</span> 4.01 strict:</p>
<typo:code lang="html">
<p><!<span class="caps">DOCTYPE</span> html <span class="caps">PUBLIC</span> “-//W3C//<span class="caps">DTD</span> <span class="caps">HTML</span> 4.01//EN”><br />
<html><br />
<head><br />
<title>IE Shifting Bug</title><br />
<style type="text/css"><br />
div { position: relative;}</p>
</style>
</head>
<body>
<div style="float:right; width:49%">
<div style="display:none;">
some hidden content
</div>
<div id="container">
<label>Overlap Me:</label>
<input type="text" value="<< this should shift">
<input type="submit" value="«this too">
</div>
</div>
<!-- trigger to illustrate the bug: -->
<p>
<input type="button" value="apply background color"
onclick="document.getElementById('container').style.backgroundColor = 'yellow'">
</p>
</body>
</html>
</typo:code>
<p>If you view this page in IE (I’m using version 7), when you apply the background color to the container div, the two form elements jump to the left, overlapping the label element. Interestingly enough, this seems to require the convergence of many things, including the floated outer div, the hidden content above, the relative position on all the divs, etc. If you remove any of them from the equation, things work as expected. In an even more bizarre twist, the <em>length</em> of the label seems to come into play as well — if you add even one more character to the label text, things return to “normal”.</p>
<p>In the extremely unlikely event that anyone else has run across this issue, hopefully I can save you a couple of hours of frustration. I worked around the issue by overriding the position of the “container” div (to “static”), although given the fragility of the trigger, any number of small changes should work as well.</p>BenchmarkForRails Viewer Ruby on Rails plugin (with Juggernaut's server push technology).2008-01-06T00:00:00-08:00http://onrails.org/2008/01/06/benchmarkforrails-viewer-ruby-on-rails-plugin-with-juggernauts-server-push-technology<p>Release early, release often they say. I don’t know if I’m going to release often but this is very early for this project. In fact yesterday I was testing the excellent <a href="http://juggernaut.rubyforge.org/">Juggernaut plugin for Ruby on Rails</a>, a “server push technology”, created by <a href="http://www.eribium.org/">Alex McCaw</a> and at the same time I was trying out the <a href="http://code.google.com/p/benchmarkforrails/">BenchmarkForRails</a> plugin. The BenchmarkForRails plugin adds some detailed log information about the time breakdown for a request in the following format:<br />
<pre><br />
- [0.0954] <span class="caps">GET</span> /categories <del>-</del>——————————<br />
0.0791 action<br />
0.0098 development mode<br />
0.0026 finders<br />
0.0003 session<br />
0.0001 rendering<br />
0.0001 filters<br />
<del>-</del>—————————————- BenchmarkForRails -<br />
</pre></p>
<p>Of course I had to look how it was implemented and it didn’t take me long, (once I overcame a self inflicted issue for which Alex McCaw helped me out. Thanks man!), to try to combine the BenchmarkForRails, Juggernaut, and Adobe’s Flex to create a little Benchmark Viewer that looks as follows:</p>
<p>http://localhost:3000/benchmark/BenchmarkForRails.html<br />
<img src="http://onrails.org/files/20080105_bencmarkforrailsviewer.jpg" alt="20080105_bencmarkforrailsviewer.jpg" border="0" width="456" height="192" /></p>
<p>Note: that’s the only view currently supported. The ‘last’, ‘last 5’, ‘last’, ‘last 5 (same), selection will provide different views of your requests but this functionality isn’t yet coded. Also filtering by controller and action would be nice.</p>
<p>Like I said this is very early but combining Benchmarking with server push technology offers quite some potential, but let’s keep it simple for now…</p>
<p>Well, the installation is not as simple as it could be for the moment I provided some steps here after. To run the application simply start the Juggernaut push server, start you server as usual, and you will see the time details of each request in the viewer. The time is color coded to indicate wether the time was slower (red), faster (green), or same (white) than the previous request of the same type (controller, action, method).</p>
<p>Note for the installation you must use the http://juggernaut.rubyforge.org/svn/branches/juggernaut_1.0/ version. This is a more recent version than trunk and Alex will put it to trunk soon. Also the Flex client uses the default port 5001 to talk to the push server. If that’s an issue for you then you are out of luck. Not for long, as this is the next thing I will change in the Flex application.</p>
<p><strong><span class="caps">INSTALLATION</span></strong></p>
<p>You need the following plugins: benchmarkforrails, juggernaut, and benchmarkforrails_viewer</p>
<p>a) benchmarkforrails<br />
<pre><br />
$ svn export http://benchmarkforrails.googlecode.com/svn/trunk vendor/plugins/benchmarkforrails<br />
</pre></p>
<p>b) juggernaut<br />
<pre><br />
$ svn export http://juggernaut.rubyforge.org/svn/branches/juggernaut_1.0/ vendor/plugins/juggernaut<br />
$ rake juggernaut:reinstall <br />
</pre><br />
This creates the conf/juggernaut.yml and conf/juggernaut_hosts.yml file. <br />
Note juggernaut has detailed installation instruction. But in short you need the json and the eventmachine gems.</p>
<p>c) benchmarkforrails_viewer<br />
<pre><br />
$ svn export http://onrails.googlecode.com/svn/trunk/plugins/benchmarkforrails_viewer vendor/plugins/benchmarkforrails_viewer<br />
$ rake benchmarkforrails_viewer:reinstall<br />
</pre><br />
The later copies the UI files into the public/benchmark folder.</p>
<p><strong><span class="caps">RUNNING</span> <span class="caps">THE</span> <span class="caps">VIEWER</span></strong></p>
<p>1) Start the juggernaut push_server. <br />
<pre><br />
cd vendor/plugins/juggernaut/media/<br />
# The first time you need to generate a config file using:<br />
ruby juggernaut -g<br />
# Start the push_server<br />
ruby juggernaut <br />
</pre></p>
<p>2) In a different terminal start your rails server, ./script/server</p>
<p>3) Start the BenchmarkForRails Viewer: http://localhost:3000/benchmark/BenchmarkForRails.html<br />
Note you need the Flash Player 9 installed.</p>
<p>4) Run your application (only in development) as usual and see the request benchmarks in the viewer.</p>
<p>The next functionality I would like to add is to make the port configurable in the Flex application, to add different views to view the requests. I shall also contact the guys that developed the BenchmarkForRails plugin to see if they could add a standard ways of plugging different reporting engines. But more importantly I would like to get your feedback. Let me know if this worked for you and if what else you would expect from such a viewer. I am sure I will hear from you if I forgot some details….Yea, like I think this only works for Rails 2.</p>
<p>Enjoy!<br />
Daniel</p>What's in for 20082008-01-03T00:00:00-08:00http://onrails.org/2008/01/03/whats-in-for-2008<p>Thank you and Happy New Year to all the readers. 2007 was impressive over 101,740 page views on this blog. I am always amazed that people come read what is on this blog, as it’s often written very late at night or on the spur of the moment. Thank you again. As usual there are many objectives I didn’t reach in 2007, but the ride was worthwhile. So without commitments :-) here are a couples of things I like to work on (and blog about) in 2008:</p>
<ul>
<li>MySpyder.net with Lee, Sol, and Lomax we started a side project early last year. It’s looking really promising but we recently went back to the drawing board to be able to scale massively from a server side point of view. Many blog entries originate from this project. I hope that we get this project back on track and be able to show something cool in a couple of month.</li>
</ul>
<ul>
<li>Flex On Rails – the book. One must be nuts to write a book, so I though why not give it a try. It’s definitively a long process but I have some partners in crime that seem even crazier than me…so there is hope that we get something cool out the doors.</li>
</ul>
<ul>
<li>Flex Dynamic Scaffolding for Rails. This is more a thought, but I would love to create a small Scaffolding framework showing off the potential of Flex.</li>
</ul>
<ul>
<li>RailsLogVisualizer plugin. A nice plugin to shows real time usage of a Rails application.</li>
</ul>
<ul>
<li>Amazon Web Services. Build a nice application that makes uses of S3, EC2, SimpleDB and DevPay. I should be able to find a problem to my solution.</li>
</ul>
<p>Have a great year everybody!<br />
Daniel</p>BlazeDS and open source version of livecycle data services...2007-12-13T00:00:00-08:00http://onrails.org/2007/12/13/blaze-ds-and-open-source-version-of-livecycle-data-services<p>That sounds cool. Read all about it here…</p>
<p><a href="http://www.techcrunch.com/2007/12/12/adobe-releases-blaze-ds-open-source-version-of-livecycle-data-services/">http://www.techcrunch.com/2007/12/12/adobe-releases-blaze-ds-open-source-version-of-livecycle-data-services/</a></p>
<p>Maybe not. Techcrunch released this message on their blog but no text was attached and comments where closed. Maybe somebody clicked the submit button to quickly. Now I am curious…</p>
<p><span class="caps">UPDATE</span>: 10:17pm Denver time…it’s official: <a href="http://www.adobe.com/aboutadobe/pressroom/pressreleases/200712/121307BlazeDS.html">http://www.adobe.com/aboutadobe/pressroom/pressreleases/200712/121307BlazeDS.html</a></p>Rails 2.02007-12-07T00:00:00-08:00http://onrails.org/2007/12/07/rails-2-0<p><a href="http://dev.rubyonrails.org/changeset/8328">Rails 2.0 is out</a>! Thanks guys for all the hard work, this release is just impressive.</p>Analyzing the Subversion logs from the Rails project with mx:OLAPCube2007-11-29T00:00:00-08:00http://onrails.org/2007/11/29/analyzing-the-subversion-logs-from-the-rails-project-with-mx-olapcube<p>I started playing with <a href="http://anthonyeden.com">Anthony Eden’s</a> <a href="http://activewarehouse.rubyforge.org/">ActiveWarehouse</a> and followed his <a href="http://anthonyeden.com/2006/12/20/activewarehouse-example-with-rails-svn-logs">excellent tutorial</a> on how to analyze the Ruby On Rails Svn Commit Log with the ActiveWarehouse framework. Of course this made me want to try to do the same with the new mx:OLAPCube and mx:OLAPDataGrid provided by Flex 3 as part of the DataVisualization components. Let me just say this…I am not done playing with either the Flex OLAPCube nor the Rails ActiveWarehouse framework as these are pretty complex beasts. Both of these frameworks are overlapping and complementary. There are overlapping as both can digest raw data and perform aggregation of that data. They are complementary in the sense that a server side warehouse needs a good visualization front-end. Maybe the OLAPCube and OLAPDataGrid can be this front-end. In my initial trials I haven’t come up with a compelling way to integrate both, but by using some simple <span class="caps">SQL</span> I could extract the data from the ActiveWarehouse and pass it to the OLAPCube.</p>
<p>Before going on you may want to read Anthony’s <a href="http://anthonyeden.com">blog</a> and check his presentation on <a href="anthonyeden.com/assets/2007/5/20/activewarehouse.pdf">Data Warehouses with ActiveWarehouse</a>. I didn’t find much information on the Flex OLAPCube besides these: <a href="http://labs.adobe.com/wiki/index.php/Flex_3:Feature_Introductions:_OLAPDataGrid">Feature_Introductions:<em>OLAPDataGrid on Adobe’s labs</a>, <a href="http://labs.adobe.com/technologies/flex/videos/olap/">Flex 3: Feature Introduction Video for <span class="caps">OLAP</span> Support</a>, and these </em>beta2.zip">Flex examples</a>.</p>
<p>So I create the following sample application. You can try it out <a href="http://myspyder.net/tools/svnlogvisualizer/" target="_blank">here</a>. Note it’s pretty slow, it takes up to a minute to aggregate 10000 values. The Flex team mentioned they didn’t optimize this component yet. I can confirm this. But I may also have messed something up as these are only my initial steps with that component. The application displays the Author dimension with the Author Name as rows and the Time dimension with the Year and Quarter as columns. The facts is the File Change count during that period. Flex calls the “facts” a measure. <br />
<br/>
<img src="http://onrails.org/files/20071128_OLAPCube.jpg" alt="20071128_OLAPCube.jpg" border="0" width="495" /><br />
<br/>
<a href="http://myspyder.net/tools/svnlogvisualizer/" target="_blank">Run the applicaiton</a></p>
<p>To extract the data from the ActiveWarehouse I created this <span class="caps">SQL</span> to join the facts table with all the dimensions table. I need to find out if the ActiveWarehouse doesn’t just return this data in xml format by using it’s build-in classes.</p>
<typo:code lang="ruby">
def report_as_xml
sql = <<-<span class="caps">EOSQL</span>
<span class="caps">SELECT</span>
date.calendar_year,
date.calendar_quarter,
date.calendar_month_name,
author.name,
file_revision_facts.file_changed AS `file_changed`
<span class="caps">FROM</span>
file_revision_facts
<span class="caps">JOIN</span> date_dimension as date
ON file_revision_facts.date_id = date.id
<span class="caps">JOIN</span> author_dimension as author
ON file_revision_facts.author_id = author.id
<span class="caps">WHERE</span>
date.calendar_year > ‘2005’
<span class="caps">EOSQL</span>
@@xml ||= ActiveRecord::Base.connection.select_all(sql).to_xml(:dasherize => false)
render :text => @@xml
end
</typo:code>
<p>In Flex the OLAPCube can be loaded with the <span class="caps">XML</span></p>
<typo:code>
<p>var data:ICollectionView = new ArrayCollection(result.records.record); // is Array<br />
cube.dataProvider = data;<br />
cube.addEventListener(CubeEvent.CUBE_COMPLETE, creationCompleteHandler);<br />
cube.refresh();</p>
</typo:code>
<p>Once the cube is loaded you can slice and dice it in many ways by using an OLAPQuery. I still need to figure out all the possibilities which are offered.</p>
<typo:code>
<p>[Bindable]<br />
private var cubeResult:IOLAPResult;</p>
<p>private function creationCompleteHandler(event:CubeEvent):void<br />
{<br />
//Cube was created, let’s query it<br />
var query:OLAPQuery = new OLAPQuery;</p>
<p>// <span class="caps">TIME</span> <span class="caps">DIMENSION</span> <br />
var yearSet:IOLAPSet = new OLAPSet;<br />
yearSet.addElements(cube.findDimension(“Time”).findAttribute(“Year”).members);</p>
<p>var quarterSet:IOLAPSet = new OLAPSet;<br />
quarterSet.addElements(cube.findDimension(“Time”).findAttribute(“Quarter”).members);</p>
<p>//year-quarter<br />
var newTimeSet:IOLAPSet = yearSet.crossJoin(quarterSet);</p>
<p>// <span class="caps">AUTHOR</span> <span class="caps">DIMENSION</span> <br />
var authorSet:IOLAPSet = new OLAPSet;<br />
authorSet.addElements(cube.findDimension(“Author”).findAttribute(“Name”).members);</p>
<p>// <span class="caps">ROW</span>/<span class="caps">COLUMNS</span> <br />
var rowAxis:IOLAPQueryAxis = query.getAxis(OLAPQuery.ROW_AXIS);<br />
rowAxis.addSet(authorSet.hierarchize(true));<br />
var colAxis:IOLAPQueryAxis = query.getAxis(OLAPQuery.COLUMN_AXIS);<br />
colAxis.addSet(newTimeSet.hierarchize(true));</p>
<p>// <span class="caps">QUERY</span> <span class="caps">CUBE</span><br />
var token:AsyncToken = cube.execute(query);<br />
token.addResponder(new AsyncResponder(displayResult, olapFaultHandler));<br />
}<br />
private function displayResult(result:Object, token:Object=null):void<br />
{<br />
cubeResult = result as IOLAPResult;<br />
}</p>
</typo:code>
<p>The cube result is the dataProvider of the Cube which in it’s simplests form can be defined as follows:</p>
<typo:code>
<mx:OLAPDataGrid id="olapGrid" dataProvider="{cubeResult}" />
</typo:code>
<p>I’ve then added a change listener for the grid to create the dataProvider for the ColumnChart.</p>
<typo:code>
<p>[Bindable]<br />
private var chartData:Array;</p>
<p>private function gridSelectionChanged():void {<br />
if (!(olapGrid.selectedItem is OLAPAxisPosition)) return;<br />
var rowIndex:Number = olapGrid.selectedIndex;<br />
var axis:IOLAPQueryAxis = cubeResult.query.getAxis(OLAPQuery.COLUMN_AXIS);<br />
var columnLength:Number = cubeResult.getAxis(OLAPQuery.COLUMN_AXIS).positions.length;<br />
var newChartData:Array = [];<br />
for (var i:int=0;i<columnLength;i++) {<br />
var tuple:OLAPTuple = axis.tuples[i];<br />
var key:String = tuple.explicitMembers.toArray().join(“,”);<br />
if (key.indexOf(“(All)”) > -1) continue; newChartData.push({key:key, value:cubeResult.getCell(rowIndex, i).value});<br />
}<br />
chartData = newChartData;<br />
}</p>
</typo:code>
<p>This code to extract a time serie for the chart is a little “hairy”. I hope the Flex team has some OLAPCharts on their todo list ;-)<br/>
<typo:code><br />
<mx:ColumnChart id="chart" width="100%" height="30%" dataProvider="{chartData}"><br />
<mx:series><br />
<mx:ColumnSeries yField="value" /></p>
</mx:series>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="key" />
</mx:horizontalAxis>
</mx:ColumnChart>
</typo:code>
<p>This are my first tribulations with both frameworks. Over the next few month I will have to dive more deeply into the possibilities which are offered. Thanks to both teams as this is pretty cool.</p>
<p>Enjoy!<br />
Daniel.</p>Scripting the Leopard Terminal2007-11-28T00:00:00-08:00http://onrails.org/2007/11/28/scripting-the-leopard-terminal<p>Hypothetical situation: you’re sitting down with your favorite tasty beverage close at hand for some Rails hacking, and what commands do you run every single time? It’s probably something like this:</p>
<typo:code lang="sh" title="RSI">
<p>cd Projects/KillerApp<br />
mate .<br />
rake log:clear<br />
tail -f log/development.log</p>
<p>[Command – T for new tab]<br />
cd Projects/KillerApp<br />
mongrel_rails start</p>
<p>[Command – T for new tab]<br />
cd Projects/KillerApp<br />
ruby script/console</p>
<p>[Command – T for new tab]<br />
cd Projects/KillerApp<br />
rake</p>
<p>…etc…</p>
</typo:code>
<p>Hmmm. We’re coding <span class="caps">DRY</span>, but this bootstrap process doesn’t seem very <span class="caps">DRY</span>. This had been bugging me, so I set out on a Google quest to learn to script Terminal.app in Leopard so that I could do something about it. I first looked at <a href="http://www.apple.com/applescript/">AppleScript</a>, since that’s the de facto scripting language of all things Apple. Given a specimen, I could decipher what it was trying to do reasonably well, but going the other way was difficult — starting with a goal, I was generally unsuccessful in trying to express it in AppleScript. This was the best I could come up with:</p>
<typo:code lang="AppleScript" title="utopia">
<p>tell executive SteveJobs<br />
tell developers at Apple<br />
set theScriptingLanguage of <span class="caps">OSX</span> to Ruby<br />
end tell<br />
end tell</p>
</typo:code>
<p>Which was a good thought, but didn’t actually do much. At <a href="http://rubyconf.org/">RubyConf</a> last year, <a href="http://chopine.be/lrz/">Laurent Sansonetti</a> talked about <a href="http://rubyosa.rubyforge.org/">RubyOSA</a>, a scripting bridge between Ruby and the Apple Event Manager, which sounds great, because you can code in Ruby and control AppleScript-able applications, like iTunes. So I ran this:</p>
<typo:code lang="ruby" title="fail">
<p>require ‘rbosa’<br />
terminal = <span class="caps">OSA</span>.app(‘Terminal’)</p>
</typo:code>
<p>Which resulted in this rather discouraging output:</p>
<typo:code lang="ruby" title="rubyosa-error">
<p>RuntimeError: Can’t get the target bundle signature<br />
from /Library/Ruby/Gems/1.8/gems/rubyosa-0.4.0/lib/rbosa.rb:329:in `__scripting_info__’<br />
from /Library/Ruby/Gems/1.8/gems/rubyosa-0.4.0/lib/rbosa.rb:329:in `app’<br />
from (irb):3</p>
</typo:code>
<p>Hmmm. Not exactly useful. Maybe if I did my coding in iTunes, I could use RubyOSA to build some useful automation. Hopefully someone at Apple can fix Terminal — Hint, Hint. Back to Google…</p>
<p>I eventually ran across Matt Mower’s <a href="http://matt.blogs.it/entries/00002674.html">scripting a better ‘cd’ and then some</a> article. Beautiful. Exactly what I wanted. Except I didn’t want to have to switch to iTerm just to use it. I’m fairly happy with the native Terminal.app in Leopard — the tabs are nice. My biggest complaint is that you cannot name individual tabs, which seems like a glaring omission. Hopefully that will be updated soon.</p>
<p>So Matt’s gp command uses another Ruby / Apple event bridge, called <a href="http://rb-appscript.rubyforge.org/">Appscript</a>, which “allows you to control scriptable Mac OS X applications using ordinary Ruby scripts”. Sounds cool, and most of the examples feature TextEdit, which isn’t Terminal, but at least is more of a developer application than iTunes, so we seem to be on the right track.</p>
<p><code>gem install rb-appscript</code>, and let’s play. In <span class="caps">IRB</span>:</p>
<typo:code lang="irb" title="appscript1">
<p>>> require ‘appscript’<br />
>> include Appscript<br />
>> term = app(‘Terminal’)<br />
=> app(“/Applications/Utilities/Terminal.app”)<br />
>> term.windows<br />
=> app(“/Applications/Utilities/Terminal.app”).windows<br />
>> term.windows.first<br />
=> app(“/Applications/Utilities/Terminal.app”).windows.first</p>
</typo:code>
<p>Okay, this is a bit strange — it seems to just repeat what you say back to you. After a bit of playing, I understand what’s going on. Some of the methods aren’t executed until you explicitly tell them to execute. For instance:</p>
<typo:code lang="irb" title="appscript2">
<p>>> term.windows.get<br />
=> [app(“/Applications/Utilities/Terminal.app”).windows.<acronym title="915"><span class="caps">ID</span></acronym>, app(“/Applications/Utilities/Terminal.app”).windows.<acronym title="498"><span class="caps">ID</span></acronym>, app(“/Applications/Utilities/Terminal.app”).windows.<acronym title="667"><span class="caps">ID</span></acronym>]<br />
>> term.windows.first.get<br />
=> app(“/Applications/Utilities/Terminal.app”).windows.<acronym title="915"><span class="caps">ID</span></acronym></p>
</typo:code>
<p>Why? Most likely, this is for efficiency reasons. With many of these “Event Bridge” solutions, there is a significant “toll” that must be paid to cross the bridge. If we can batch together a string of method invocations and send them across the bridge for a single round trip, it performs much better than multiple round trips would.</p>
<p>At any rate, we can now get a handle on the Terminal application and its already-open windows. The next step is to be able to open new windows and tabs. There is a somewhat useful tool on the rb-appscript download page called ASDictionary, which can examine an application and dump out the objects and methods that it exposes to the bridge. Kinda like rdoc for AppleScript. Running the dictionary against Terminal.app, I found the <code>do_script(command)</code> method, which, when called on the terminal application object, launches a new terminal window and runs the specified <span class="caps">UNIX</span> command in it.</p>
<typo:code lang="irb" title="appscript3">
<p>>> term.do_script(“ls”)<br />
=> app(“/Applications/Utilities/Terminal.app”).windows.<acronym title="951"><span class="caps">ID</span></acronym>.tabs<sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup></p>
</typo:code>
<p>If you’re following along, you should have a new Terminal window containing a listing of the files and folders in your home directory. Also, notice that the command returns a reference to the first (and only) tab in the new window — we’ll come back to that later. So, new windows, check; now for new tabs.</p>
<p>The Appscript examples show creating new TextEdit documents by executing:</p>
<typo:code lang="irb" title="appscript4">
<p>app(‘TextEdit’).documents.end.make(:new => :document)</p>
</typo:code>
<p>And the Appscript dictionary of Terminal showed the <code>make</code> method, and <code>window</code> and <code>tab</code> classes, so I figured something like this might work:</p>
<typo:code lang="irb" title="appscript5">
<p>>> window = term.windows.first.get<br />
=> app(“/Applications/Utilities/Terminal.app”).windows.<acronym title="915"><span class="caps">ID</span></acronym><br />
>> window.make(:new => :tab)<br />
Appscript::CommandError: CommandError<br />
<span class="caps">OSERROR</span>: -10000<br />
<span class="caps">MESSAGE</span>: Apple event handler failed.<br />
<span class="caps">COMMAND</span>: app(“/Applications/Utilities/Terminal.app”).windows.<acronym title="915"><span class="caps">ID</span></acronym>.make({:new=>:tab})</p>
<p>from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.4.0/lib/appscript.rb:505:in `<em>send_command’<br />
from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.4.0/lib/appscript.rb:585:in `method</em>missing’<br />
from (irb):11</p>
</typo:code>
<p>Appscript is having none of that. After many frustrating, fruitless attempts to create a new tab, I found a workaround in native AppleScript <a href="http://hohonuuli.blogspot.com/2007/11/applescript-for-open-terminal-here.html">here</a>. Here’s the Appscript translation:</p>
<typo:code lang="irb" title="appscript6">
<p>app(“System Events”).application_processes[<br />
“Terminal.app”<br />
].keystroke(“t”, :using => :command_down)</p>
</typo:code>
<p>Well, okay, sending a Command-T keystroke works, but it’s a little disappointing. Anyone who knows how to programatically create a new tab, feel free to chime in on the comments, and I’ll update the script.</p>
<p><code>do_script(command)</code> also takes an optional parameter specifying options. One of the available options is <code>:in</code>, which tells terminal in which window and tab to run the command. Putting this together, we can run a command in the new tab we just created:</p>
<typo:code lang="irb" title="appscript7">
<p>app(‘Terminal’).do_script(“ls”, :in => window.tabs.last.get)</p>
</typo:code>
<p>We don’t have a handle to the new tab, because it was created via hackery, so we need a handle to its parent window object so we can get at its tabs. Well, our first command we ran with do_script returned us a handle to the first tab of the window, surely we can get the window from that. Right? Anyone?</p>
<typo:code lang="irb" title="appscript8">
<p>>> tab = term.do_script(“ls”)<br />
=> app(“/Applications/Utilities/Terminal.app”).windows.<acronym title="1159"><span class="caps">ID</span></acronym>.tabs<sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup><br />
>> tab.window<br />
RuntimeError: Unknown property, element or command: ‘window’<br />
from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.4.0/lib/appscript.rb:591:in `method_missing’<br />
from (irb):11<br />
from :0</p>
</typo:code>
<p>(Sigh) Not so much. Time for a hack on a hack, and this one is just embarrassing. Observant readers have probably noticed that the tab referenced shows its parent window id in the string of object references. What if we use that to get a handle to the parent window? Something like this:</p>
<typo:code lang="irb" title="evil-hack">
<p>>> window = eval(“app(\”/Applications/Utilities/Terminal.app\“).windows.<acronym title="1159"><span class="caps">ID</span></acronym>”)<br />
=> app(“/Applications/Utilities/Terminal.app”).windows.<acronym title="1159"><span class="caps">ID</span></acronym></p>
</typo:code>
<p>I’m not proud of it, but it works. Again, if someone knows the “right” way to do this, please let me know—although programatically creating a tab should obviate the need for this hack, too.</p>
<p>Another thing I wanted to change from the original script was that with Matt’s solution, you need to specify the type of project you are opening, either as a command-line argument, or by symlinking the script to a new name with the type embedded. I want the computer to figure all that out for me. Computers are real smart. So my script includes some configurable heuristics for determining project type based on the folder contents. You should be able to specify set of files and folders that defines a project type. For Rails, I used the “skeleton” folders that every Rails app starts with. I haven’t been programming in Erlang very long, so honestly I just guessed at the folders based on some projects I have seen. If you’re a more experienced Erlang programmer, and feel that the project detection or task list should be changed, please let me know.</p>
<p>Matt later enhanced his script to <a href="http://matt.blogs.it/entries/00002676.html">label the iTerm tabs</a> so that you can easily find the tab you need, so naturally I <del>stole</del> incorporated this idea too. It sorta works in Leopard’s Terminal—it does change the name of the Terminal window, but the tab name is unaffected, so you still have to flip through the tabs and watch the window name. This is my biggest request for a feature enhancement for the Terminal, Hint, Hint again, Apple.</p>
<p>So enjoy. You can use the script anywhere — it will look first in your current directory for a matching folder (you only have to specify a non-ambiguous substring of the project folder name), then falls back to the “project root” folder you specify (currently ~/development, ‘cause that’s what I use.). You can configure how deep it should recurse your projects so that the disk seeking time doesn’t eat up all the time you’re saving from not typing the same “cd” commands over and over.</p>
<p>You can download the finished script <a href="/files/hack">here</a>. I call it hack, because <code>hack KillerApp</code> flows so nicely as a command. Also, that’s the way I roll. Feel free to send in money, or flattery, or hate mail, I suppose. Thanks to Matt Mower for the inspiration and also to all the other references I’ve linked!</p>flash.utils.ByteArray compressing 4.1MB to 20K2007-11-27T00:00:00-08:00http://onrails.org/2007/11/27/flash-utils-bytearray-compressing-4-1mb-to-20k<p>I am currently preparing a demo using an mx:OLAPCube and OLAPDataGrid which analyze the Rails svn commit log. however I don’t want to deploy a specific server side application as the Cube can load data from <span class="caps">XML</span>. So I have an report.xml that is 4.1MB. I created the following <span class="caps">AIR</span> application (ZlibCompressor.mxml) that use the standard compression provided by the ByteArray class to compress this file down to 20Kb. The application that consumes this file (UnzipTest.mxml) uses the URLLoader to read this file straight into a ByteArray and uncompress the data. It’s fast!</p>
<p>The key code for compression is the ‘compress’ and ‘uncompress’ method provided by the ByteArray. Note the URLLoader dataFormat is set to “binary”.</p>
<h3>ZlibCompressor.mxml</h3>
<typo:code>
<p><?xml version=“1.0” encoding=“utf-8”?><br />
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
nativeDragDrop="onDrop(event)"
nativeDragEnter="onDragIn(event)" ><br />
<mx:Script><br />
<![<span class="caps">CDATA</span>[<br />
import flash.desktop.ClipboardFormats; <br />
import flash.utils.CompressionAlgorithm;<br />
public function onDragIn(event:NativeDragEvent):void {<br />
var transferable:Clipboard = event.clipboard;<br />
if (transferable.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)) {<br />
DragManager.acceptDragDrop(this);<br />
} <br />
}<br />
public function onDrop(event:NativeDragEvent):void {<br />
var fileList:Array = event.clipboard.dataForFormat(ClipboardFormats.FILE_LIST_FORMAT) as Array;<br />
if (fileList.length==0) return;</p>
<p>var inFile:File = fileList<sup class="footnote" id="fnr0"><a href="#fn0">0</a></sup>;<br />
var fileStream:FileStream = new FileStream();<br />
fileStream.open(inFile, FileMode.<span class="caps">READ</span>);<br />
var ba:ByteArray = new ByteArray();<br />
fileStream.readBytes(ba, 0, fileStream.bytesAvailable);<br />
fileStream.close();</p>
<p>var newFileName:String = inFile.nativePath+".zlib";<br />
ba.compress();</p>
<p>var outFile:File = new File(newFileName);<br />
fileStream = new FileStream();<br />
fileStream.open(outFile, FileMode.<span class="caps">WRITE</span>);<br />
fileStream.writeBytes(ba, 0, ba.length);<br />
fileStream.close(); <br />
} <br />
]]></p>
</mx:Script>
</mx:WindowedApplication>
</typo:code>
<h3>UnzipTest.mxml</h3>
<typo:code>
<p><?xml version=“1.0” encoding=“utf-8”?><br />
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="loadData()"><br />
<mx:Script><br />
<![<span class="caps">CDATA</span>[<br />
import mx.rpc.events.ResultEvent;<br />
import flash.utils.ByteArray;</p>
import flash.events.*;
import flash.net.*;
<p>private function loadData():void {<br />
var loader:URLLoader = new URLLoader();<br />
loader.dataFormat = “binary”;<br />
loader.addEventListener(Event.<span class="caps">COMPLETE</span>, completeHandler); <br />
var request:URLRequest = new URLRequest(“../data/report.xml.zlib”);<br />
loader.load(request);<br />
}<br />
private function completeHandler(event:Event):void {<br />
var loader:URLLoader = URLLoader(event.target);<br />
var ba:ByteArray = loader.data;<br />
ba.uncompress();<br />
var s:String = ba.toString();<br />
var xml:<span class="caps">XML</span> = new <acronym title="s"><span class="caps">XML</span></acronym>;<br />
}<br />
]]></p>
</mx:Script>
</mx:Application>
</typo:code>Acts_as_nested_set ActiveRecord rendered with mx:Tree in Flex.2007-11-24T00:00:00-08:00http://onrails.org/2007/11/24/acts_as_nested_set-activerecord-rendered-with-mx-tree-in-flex<p>ActiveRecord: app/models/category.rb<br />
<typo:code lang="ruby" title="app/models/category.rb"><br />
class Category < ActiveRecord::Base<br />
acts_as_nested_set<br />
end</p>
</typo:code>
<p>Controller: app/controllers/categories_controller.rb<br />
<typo:code lang="ruby" title="app/controllers/categories_controller.rb"><br />
class CategoriesController < ApplicationController<br />
def index<br />
Category.result_to_attributes_xml(Category.root.full_set)<br />
end<br />
end</p>
</typo:code>
<p>Flex Application: ActsAsNestedSet.mxml<br />
<typo:code lang="javascript" title="ActsAsNestedSet.mxml"><br />
<?xml version=“1.0” encoding=“utf-8”?><br />
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
applicationComplete="categories.send()"><br />
<mx:HTTPService id="categories" url="http://localhost:3000/categories" resultFormat="e4x" /><br />
<mx:Tree dataProvider="{categories.lastResult}"
labelField="@name"
width="100%" height="100%" /></p>
</mx:Application>
</typo:code>
<p>Result:<br />
<img src="http://onrails.org/files/20071123_categories.jpg" alt="20071123_categories.jpg" border="0" width="264" height="296" /></p>
<p><span class="caps">XML</span> generated by Category.result_to_attributes_xml(Category.root.full_set):<br />
<typo:code lang="xml" title="XML generated by Category.result_to_attributes_xml(Category.root.full_set)"><br />
<node name="Main Category" id="15" description=""><br />
<node name="Cameras & Photo" id="16" description=""><br />
<node name="Bags" id="17" description=""/><br />
<node name="Accessories" id="18" description=""/><br />
<node name="Analog Cameras" id="19" description=""/><br />
<node name="Digital Cameras" id="20" description=""/></p>
</node>
<node name="Cell Phones" id="21" description="">
<node name="Accessories" id="22" description=""/>
<node name="Phones" id="23" description=""/>
<node name="Prepaid Cards" id="24" description=""/>
</node>
<node name="Dvds" id="25" description="">
<node name="Blueray" id="26" description=""/>
<node name="HD DVD" id="27" description=""/>
<node name="DVD" id="28" description=""/>
</node>
</node>
</typo:code>
<p>I used the http://wiki.rubyonrails.org/rails/pages/BetterNestedSet plugin.</p>
<p>Too cool!</p>
<p><span class="caps">UPDATE</span>: The BetterNestedSet plugin doesn’t work out of the box with Rails 2.0 RC1. Thanks Joel for that info. Read more in the comment of this blog entry.</p>
<p>UPDATE2: Thanks Fabien, BetterNestedSet now works with Rails 2.0!</p>RailsLogVisualizer0.7 for AIR beta 2.2007-11-08T00:00:00-08:00http://onrails.org/2007/11/08/railslogvisualizer0-7-for-air-beta-2I recompiled the RailsLogVisualizer for AIR beta. I added drag&drop of log files to bypass an AIR bug on Leopard. File.browseForOpen doesn't trigger the Event.SELECT when the file is selected. I haven't yet tried this version of the application on older versions of OSX or on Windows. Let me know how it works. Also the feedback when loading large log files could be improved, as the application seems to freeze once the progress bar is complete. Just be a little patient as the AVM is working hard for you to compute all these number.
<h3>Install RailsLogVisualizer0.7.air</h3>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
id="RailsLogVisualizer" width="215" height="138"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="http://myspyder.net/tools/railslogvisualizer/badge.swf" />
<param name="FlashVars" value="appUrl=http://myspyder.net/tools/railslogvisualizer/RailsLogVisualizer0.7.air&airversion=1.0.M5" />
<embed src="http://myspyder.net/tools/railslogvisualizer/badge.swf" quality="high" bgcolor="#ffffff"
FlashVars="appUrl=http://myspyder.net/tools/railslogvisualizer/RailsLogVisualizer0.7.air&airversion=1.0.M5"
width="215" height="138" name="RailsLogVisualizer" align="middle"
play="true"
type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer"> </embed>
</object>
<h3>Install Manually</h3>
1) Instal Adobe AIR beta 2. (See release notes if previous version was installed)<br/>
<a href="http://download.macromedia.com/pub/labs/air/air_b2_mac_100107.dmg">Download AIR for OSX</a> <a href="http://download.macromedia.com/pub/labs/air/air_b2_win_100107.exe">Download AIR for Windows</a><br/>
Learn more on <a href="http://labs.adobe.com/technologies/air/">AIR</a> <br/>
<br/>
2) Download and install <a href="RailsLogVisualizer0.7.air">http://myspyder.net/tools/railslogvisualizer/RailsLogVisualizer0.7.air</a>
<p style="clear:both" />
For <a href="http://time.onrails.org/">time.onrails.org</a> the log file is currently 98Mb and is loaded and process in less than a minute. Here are the loading details:
<pre>
Loaded 98571986bytes in 28093 milliseconds.
Parsing file. Please Wait this may take some time....
Parsing. Split 1639453entries in 1447 milliseconds.
found:220767 in 1925 milliseconds.
Aggregating data.
aggregated:220767 in 13426 milliseconds.
Aggregated:89135
aggregated String :4440464(bytes) in 2790 milliseconds.
</pre>
Then you can navigation through time and see how many request where processed and drill down in specific action and specific methods. For example, here we can quickly see that for October 99 people signed up, 869 did login, 22 forgot their password.
<div style="text-align:center;"><img src="http://onrails.org/files/20071106_railslogvisualizer.jpg" alt="20071106_railslogvisualizer.jpg" border="0" width="480" height="373" /></div>
Enjoy,
Daniel.
Sweet way to write Flex Unit tests for Rails2007-11-05T00:00:00-08:00http://onrails.org/2007/11/05/sweet-way-to-write-flex-unit-tests-for-rails<p>Using ActiveResources from Flex? Using FlexUnit? Here is a nice way to write your tests.</p>
<typo:code lang="ruby" title="Example Test Case">
<p>package tests<br />
{<br />
import flexunit.framework.*; <br />
import mx.rpc.AsyncToken;<br />
import mx.rpc.events.ResultEvent;<br />
import resources.Raffles;</p>
<p>public class TestRaffles extends BaseTestCase<br />
{ <br />
private var raffles:Raffles; <br />
public function TestRaffles(name : String = null)<br />
{<br />
super(name);<br />
fixtures([“raffles”]);<br />
raffles = new Raffles();<br />
} <br />
public function testRemoteFindRaffle():void<br />
{<br />
assertRemote(raffles.show(1));<br />
}<br />
public function assertRemote_testRemoteFindRaffle(data:Object):void<br />
{<br />
Assert.assertTrue(“Raffle show successfully called”, data is ResultEvent); <br />
assertEquals(“MyString”, data.result.name);<br />
}</p>
<p>}<br />
}</p>
</typo:code>
<p>Note this code is not yet a plugin and is using code you can find here: <a href="http://code.google.com/p/flexonrails/source">http://code.google.com/p/flexonrails/source</a>. I was starting to use it on multiple projects so I thought it was to time find a home for it. Also it is using the org.onrails.rails.ActiveResourceClient Flex class. I would recommend that you use <a href="http://code.google.com/p/as3-active-resource/">Alex MacCaw’s ActvieResrouce for Actionscript</a>. I still need to talk with Alex and integrate this fixture loading code with his code.</p>
<p>The BaseTestCase Flex class is an extended TestCase that provides support for fixtures. Now in your constructor you can define which fixtures you want to reload between each test. Only tests methods starting with “testRemote” will trigger refreshing the fixtures. As you know, when using <span class="caps">AMF</span> or HttpService remote invocations are asynchronous and you cannot test the result of a remote call in the same method than where the call is made from. That’s why I added the assertRemote method which takes an AsyncToken as parameters. This will automatically invoke a method whos name starts with assertRemote_ followed by the test method name. This simplifies greatly writing asynchronous tests. FlexUnit provides the <em>addAsync</em> method, we just add the convenience assertRemote function to setup all the callbacks.</p>
<p>To make this work for you Flex with Rails project. You need to fixtures_controller.rb to your controllers and setup the following routes:</p>
<typo:code lang="ruby">
if RAILS_ENV == “test”
map.resources :fixtures, :new => { :test_results => :post }
map.crossdomain ‘/crossdomain.xml’, :controller => ‘fixtures’, :action => ‘crossdomain’
end
</typo:code>
<p>You need to extend your Flex TestCase from tests.BaseTestCase.</p>
<p>Enjoy,<br />
Daniel.</p>Finding Balance.2007-11-05T00:00:00-08:00http://onrails.org/2007/11/05/finding-balance<p>Are you a Dad ? Are you thinking becoming one or about to become one? Many people I know in the software development field are Dads and still having fun doing software development, spending late night in front of the computer and getting woken up early by their kids…it’s time to play. My brother in law, RC, is not a software developer but a very successful business man, father of three, dedicates lots of time to his family, is coach on the team for his kids, and regularly manages to take week-ends of with his wife. How does it do all? Well, he even found time to write a book about this. So I offered him to talk about it on my blog as I believe it’s a good read. It’s not only a book about finding balance between your family and work life, but also the influence you can have on your children and children around you. He gave out two chapters of the book and I published them (formatting is not perfect) on <a href="http://thenextgenerationofdads.com">http://thenextgenerationofdads.com</a>/.</p>
<p><span class="caps">TABLE</span> OF <span class="caps">CONTENTS</span><br>

<a href="http://thenextgenerationofdads.com/why/why.html">Why This Book?</a><br>
<a href="http://thenextgenerationofdads.com/balance/balance.html">Chapter 1 : Finding Balance</a><br>
Chapter 2 : Be an Example; Be a Man<br>
Chapter 3 : The Importance of Play<br>
Chapter 4 : Where Do We Draw the Line?<br>
Chapter 5 : Dads and Daughters<br>
Chapter 6 : Teaching Kids about the Real World<br>
Chapter 7 : Raising Independent Thinkers<br>
Chapter 8 : Breaking the Cycle<br></p>Installing RMagick on Leopard (without MacPorts or Fink)2007-11-03T00:00:00-07:00http://onrails.org/2007/11/03/installing-rmagick-on-leopard-without-macports-or-fink<p>I’ve recently upgraded to OS X 10.5 (Leopard), and all-in-all, I’m pleased with the experience. My biggest issue has been the default stacks behavior—the icon changes to the last thing added to the stack, making visual identification unnecessarily cumbersome. I worked around this annoyance (as outlined <a href="http://www.ryanirelan.com/past/2007/10/31/leopard-stack">here</a>) by changing the sort to name rather than date added, and adding a dummy folder named “_1” that will sort to the top. For extra bonus points, I customized the icon of the dummy folder. For some yet unknown reason, the most recently downloaded item still peeks through from time to time, but it’s much better than before.</p>
<p>Maybe it’s my Windows history showing through, but I went with the “clean-sweep” erase and install method. For a non-developer, I’d probably recommend the upgrade (and in fact I used that method for my Father-in-law’s MacBook), but I had lots of custom bits scattered about my machine, and didn’t want to be chasing any incompatibility gremlins.</p>
<p>So now, to get my development environment set up on the new machine… Leopard includes a fairly complete Rails stack out of the box, with a non-<a href="http://hans.fugal.net/yodl/blosxom.cgi/mac/ruby-pack.html">broken</a> Ruby, readline support, and most of the commonly used gems. Read more <a href="http://trac.macosforge.org/projects/ruby/wiki/WhatsNewInLeopard">here<br />
</a>.</p>
<p>MySQL was not included, but the latest installer (mysql-5.0.45-osx10.4-i686.dmg) for 10.4 from dev.mysql.com downloads worked (mostly) fine. The Server and the StartupItem install and operate correctly. The PrefPane installs, but does not appear to actually do … anything. I’ll have to work on that, but I can live without it for now. After a bit of manual hacking on my database dump file from Tiger (where I was running a 5.1.x beta of MySQL), all my databases are back in place.</p>
<p>One last piece that I needed for my Rails apps—RMagick. I know it’s possible to install RMagick and its dependencies, um, “autoRMagickally” via a package management system like MacPorts or Fink, but I prefer not to. For some background on why not, you can read this <a href="http://hivelogic.com/narrative/articles/using_usr_local">article at hivelogic</a>. The last time I was rebuilding my laptop and desktop near the same time, I put together a shell script to automate the process of installing RMagick. I got it back out and dusted off the cobwebs, and voila! RMagick on Leopard. (note: replace wget with “curl -O”, if you don’t have wget installed on your machine) Here’s the code:</p>
<typo:code lang="sh" title="install_rmagick.sh">
<p>#!/bin/sh<br />
wget http://download.savannah.gnu.org/releases/freetype/freetype-2.3.5.tar.gz<br />
tar xzvf freetype-2.3.5.tar.gz<br />
cd freetype-2.3.5<br />
./configure —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd ..</p>
<p>wget http://superb-west.dl.sourceforge.net/sourceforge/libpng/libpng-1.2.22.tar.bz2<br />
tar jxvf libpng-1.2.22.tar.bz2<br />
cd libpng-1.2.22<br />
./configure —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd ..</p>
<p>wget ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz<br />
tar xzvf jpegsrc.v6b.tar.gz<br />
cd jpeg-6b<br />
ln -s `which glibtool` ./libtool<br />
export MACOSX_DEPLOYMENT_TARGET=10.5<br />
./configure —enable-shared —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd ..</p>
<p>wget ftp://ftp.remotesensing.org/libtiff/tiff-3.8.2.tar.gz<br />
tar xzvf tiff-3.8.2.tar.gz<br />
cd tiff-3.8.2<br />
./configure —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd ..</p>
<p>wget http://jaist.dl.sourceforge.net/sourceforge/wvware/libwmf-0.2.8.4.tar.gz<br />
tar xzvf libwmf-0.2.8.4.tar.gz<br />
cd libwmf-0.2.8.4<br />
make clean<br />
./configure<br />
make<br />
sudo make install<br />
cd ..</p>
<p>wget http://www.littlecms.com/lcms-1.17.tar.gz<br />
tar xzvf lcms-1.17.tar.gz<br />
cd lcms-1.17<br />
make clean<br />
./configure<br />
make<br />
sudo make install<br />
cd ..</p>
<p>wget ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/<span class="caps">GPL</span>/gs860/ghostscript-8.60.tar.gz<br />
tar zxvf ghostscript-8.60.tar.gz<br />
cd ghostscript-8.60/<br />
./configure —prefix=/usr/local<br />
make<br />
sudo make install<br />
cd ..</p>
<p>wget ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/<span class="caps">GPL</span>/current/ghostscript-fonts-std-8.11.tar.gz<br />
tar zxvf ghostscript-fonts-std-8.11.tar.gz<br />
sudo mv fonts /usr/local/share/ghostscript</p>
<p>wget http://imagemagick.site2nd.org/imagemagick/ImageMagick-6.3.5-9.tar.gz<br />
tar xzvf ImageMagick-6.3.5-9.tar.gz<br />
cd ImageMagick-6.3.5<br />
export <span class="caps">CPPFLAGS</span>=-I/usr/local/include<br />
export <span class="caps">LDFLAGS</span>=-L/usr/local/lib<br />
./configure —prefix=/usr/local —disable-static —with-modules —without-perl —without-magick-plus-plus —with-quantum-depth=8 —with-gs-font-dir=/usr/local/share/ghostscript/fonts<br />
make<br />
sudo make install<br />
cd ..</p>
<p>sudo gem install RMagick</p>
</typo:code>17 store driven by Ruby On Rails are shutting down.2007-11-02T00:00:00-07:00http://onrails.org/2007/11/02/17-store-driven-by-ruby-on-rails-are-shutting-down<p>I usually prefer announcing good news but it seems that one of our former customer, Gatelys, is closing doors. We did some work for them last year to create an eCommerce platform in Ruby On Rails that was driving most of their website. From a technological point this was quite a success. The website was able to handle nicely quite some heavy traffic. It is unfortunate to see these sites disappear as I considered them to be a success for Ruby On Rails. But I understand that they had quite some business related issues. Even I was getting some emails from disgruntled customers, and even some of the writers on this blog where not fully paid for their work. I must admit that the people I worked with on the technical side were awesome and a real pleasure working with. I know they will be successful in whichever endeavor there will undertake.</p>
<p>Here are the closed stores: Gatelys.com, Sleek Spaces, Home Fitness Club, Ray’s Golf Shop, Monster Bounce, Swingsets Direct, Back Relief Store, Futons Store, National Table Tennis, Wicker And Wine, Bedroom King, Planet Grind, Playful Rooms, Duffy’s Gameroom, Full House Poker Supply, Grill Gods, <span class="caps">MVP</span> Hoops.</p>
<p><img src="http://onrails.org/files/20071101_GatelysStores.jpg" alt="20071101_GatelysStores.jpg" border="0" width="495" /></p>World Series Tickets Time line2007-10-24T00:00:00-07:00http://onrails.org/2007/10/24/world-series-tickets-time-line<p>As many, I tried to buy a couple of tickets to the World Series. Hey, it’s coming to Denver. Go Rockies! Well, yesterday the online ticket sales was quite a debacle. ‘They’ blame it on a vicious attack…hmmm…well…EC2 could have helped, I guess they just didn’t think that nearly everyone in the US would go on their website at 10am <span class="caps">MDT</span>, yesterday. Well, today things went well for them, and all the tickets sold in less than 3 hours. So what does this have to do with Rails? We are working on MySpyder.net, which allows to track changes on websites. So I create a watch on the “”http://colorado.rockies.mlb.com/col/ticketing/postseason_2007.jsp">The Official Site of The Colorado Rockies</a>". I was hoping getting an advantage, find out before others that sell are back..Didn’t work out that way. I didn’t get tickets, but find here after how Myspyder.net saw the World Series Tickets online sales.MySpyder.net is not public yet as we need to ensure that we can handle the load :-)</p>
<p>All times are in <span class="caps">UTC</span>. Ok, on to the events..as seen by Myspyder.net</p>
<ul>
<li>2007-10-23 03:30:17 Tickets go on sales tomorrow at 12pm</li>
<li>2007-10-23 16:30:31 Oops, official press release announced regarding sales of Tickets.</li>
<li>2007-10-23 18:00:17 Sales is back on!</li>
<li>2007-10-23 20:30:22 27th Sold out, 26 Sold out.</li>
<li>2007-10-23 21:01:07 Sold out :-(</li>
<li>2007-10-23 21:30:46 Good news! Parking passes still available.</li>
</ul>
<p><img src="http://onrails.org/files/world_series_tickets.gif" alt="world_series_tickets.gif" border="0" width="495" height="1404" /></p>WebSnapshot 0.3 - a simple (and powerful) Adobe AIR application.2007-10-20T00:00:00-07:00http://onrails.org/2007/10/20/websnapshot-0-3-a-simple-and-powerful-adobe-air-application<p>I finally got around an recompiled WebSnapshot for <span class="caps">AIR</span> beta 2. While doing this I’ve added some cool new features.</p>
<p><img src="http://onrails.org/files/websnapshot_3.jpg" alt="websnapshot_3.jpg" border="0" width="495" /></p>
<p><a href="http://myspyder.net/tools/websnapshot/">Download Info</a></p>
<p>Check the Auto Save box and start drag and dropping URL’s from your browser into the address bar of WebSnapshot. Quickly you’ll get some pretty cool snapshots of WebSites in png format. You can now have Full Page, Browser Size snapshots in addition to the Thumbnail snapshot like before. You can define the scale of how much the size needs to be reduced before saving and other parameters that define how the snapshot is taken.</p>
<p>I moved the project to the MySpyder.net website and you can <a href="http://myspyder.net/tools/websnapshot/">download</a> it and find more information <a href="http://myspyder.net/tools/websnapshot/">here</a>.</p>Rails Rocks!2007-10-02T00:00:00-07:00http://onrails.org/2007/10/02/rails-rocks<p>I am trying so see the result of a change in a Java program….5 minutes compilation…5 minutes deployment. Arggggggggggg!</p>
<p>Rails Rocks! Change + refresh = done!</p>
<p>Short term memory is good, hopefully I will forget that experience soon.</p>
<p>;-)</p>Total ADD!2007-09-21T00:00:00-07:00http://onrails.org/2007/09/21/total-add<p>As you may have noticed I really like Flex and Ruby On Rails. So my days job is to provide consulting services for Flex and Ruby On Rails. Currently I am working on a cool Ruby On Rails project for a customer in the online food ordering world. Man I get hungry when testing the application we write. I also work for another customer to create a Flex front-end for an online application in the insurance arena (First Notice of Injury, Certificate of Insurance, Payroll report and Web Payment).</p>
<p>As if that wasn’t enough, I agreed to write a book together with a couple of other cool guys in the Flex and Ruby On Rails arena. That’s still far away, but we will provide some more information on this in the coming weeks. If that’s not enough I am creating two startups.</p>
<p>So besides my consulting engagements my professional life looks this:</p>
<div style="text-align:center;"><img src="http://onrails.org/files/20070921_add.gif" alt="20070921_add.gif" border="0" width="466" height="410" /></div>
<p>Now if that doesn’t qualify as Attention Deficit Disorder.</p>
<p>I am writing this more as a reflection to myself. At the beginning of the year <a href="http://blog.nanorails.com/">Pascal</a> commented on my blog that execution is everything to turn an idea into a business. We have been working hard on myspyder.net and it’s start to be looking really good. Digital-seed has the potential to become a really cool platform for eLearning and has the potential to turn into a big business. The “Book”, is more of a personal challenge and interest.</p>
<p>So besides execution, focus and determination are required to turn an idea into a real business.</p>
<p>So something will need to give. I still need to continue my consulting engagements in order to bring in money for the food. The “Book” will be a challenge from a writing point of view, but it will be a great learning and self improvement experience. The material for the book is what I have been “geeking” around for the past several years so it’s going to be a pleasure to write about it. Phase one for MySpyder is close to completion (still a couple of month). And phase two is really where the beef will be. So right now it looks like DigitalSeed is on the line for me. The contracts are not yet signed, so the door is open for me to pull out. This will hurt the people I started the endeavor with, and I really don’t like this. But I cannot stay on board some project unless I can dedicate enough resource to complete it. Let me chew on these thoughts over the week-end.</p>
<p>In Spirit,<br />
Daniel.</p>Exceptional Slicehost support2007-09-03T00:00:00-07:00http://onrails.org/2007/09/03/exceptional-slicehost-support<p>Our server that hosts onrails.org and time.onrails.org died on Sunday. Before we could react <a href="http://www.slicehost.com/">Slicehost</a> migrated us to new hardware and everything was up and running. Thanks guys, awesome support!</p>
<p>The events where the following:</p>
<ul>
<li>[Slicehost] Sep 1, 2007 3:04 PM, Emergency Server Reboot and HW Migration – onrails</li>
<li>[Montastic] Sep 1, 2007 3:20 PM, Website status: unreachable</li>
<li>[Slicehost] Sep 1, 2007 3:44 PM, Emergency HW Migration #2 – onrails.</li>
<li>[Montastic] Sep 1, 2007 4:12 PM, Website status: OK</li>
</ul>
<p>[Slicehost] indicates emails we received from Slicehost, and [Montastic] emails from the <a href="http://www.montastic.com/">monitoring</a> system we use. Slicehost warned us of the situation and action they are taking before our monitoring system found out that the service was down. Well, apparently they migrated us to new hardware that had another issue (bad memory) and they moved us a second time to different hardware. Well no data was lost, all our service are up and running and I didn’t have to cut short my <span class="caps">BBQ</span>. Thanks!</p>
<p>Update1: Well something is wrong with the template of our blogs. I am not sure it’s related to the update of hardware as it was working last night. More to come.</p>Monitoring Rails Performance with Munin and a Mongrel2007-08-31T00:00:00-07:00http://onrails.org/2007/08/31/monitoring-rails-performance-with-munin-and-a-mongrel<p>Rails makes things easy on developers—maybe <strong>too</strong> easy. It’s not uncommon to reference an association while iterating over a collection of objects, resulting in a performance-devouring N+1 queries being executed. Of course, this is easily fixed with eager loading of the association, but you get my point. Rails can be a big gun, and it’s easy to blow off your foot.</p>
<p>Once your application is moved into production, it becomes important to keep an eye on performance over time in order to get a feel for trends and plan capacity intelligently. Numerous Rails <a href="http://rails-analyzer.rubyforge.org/">performance</a> <a href="http://cfis.savagexi.com/articles/2007/07/10/how-to-profile-your-rails-application">measuring</a> <a href="http://railsbench.rubyforge.org/">tools</a> exist, but I find that it helps to correlate performance of your application with simultaneous lower-level performance metrics of your system (<span class="caps">CPU</span> and Memory usage, Load Average, etc). Besides that, hey! Pretty Graphs! Enter <a href="http://munin.projects.linpro.no/">munin</a>, an open-source, extensible monitoring tool with a number of out-of-the-box plugins that are useful to SysAdmin type folks. There’s a pretty decent (though brief) <a href="http://www.howtoforge.com/server_monitoring_monit_munin">writeup on howtoforge</a> that explains a bit more about how to go about getting your own munin. Go ahead and check it out — I’ll chill here until you’re back.</p>
<center>…</center>
<p>That wasn’t too bad, huh? Okay, so at this point you should have a working munin instance. It will take a few minutes of data collection before your graphs look like anything, but going forward, you’ll have historical graphs of several key metrics for managing your server(s). It’s outside the scope of this article, but you can also set up munin to monitor multiple servers on your network, and/or alert you when critical threshold levels are passed.</p>
<p>Well, knowing <span class="caps">CPU</span> usage is great, but it would also be nice to have some idea what the average user experience is like on your site. Does your Rails app perform differently at different times of day? How long does it typically take for your app to render a page? Is the majority of the time spent in the database, or rendering? Is the response time about the same between production deployment versions? I wanted answers to these questions too, so I came up with a small ruby program that watches your Rails log in realtime, and when munin asks, provides summary information about the performance of your application. Below, I’ll go over the code section by section; for those who want it now, scroll to the bottom of the article to find the download link.</p>
<p>The basis of the solution is a Ruby array: we stuff values into it, then compute the average of all the values and clear the array each time munin pings us. Every time a value is added, we also check it against the maximum already seen, so we can report the maximum response time in addition to the average. We keep three of these objects around, one each for DB, Rendering, and Total response times. There is also a mode that lets you look at the current value without consuming it — useful for peeking inside without affecting the data that munin will ultimately see. Here’s the class that implements this functionality:</p>
<typo:code lang="ruby" title="accumulator">
<p>class Accumulator<br />
def initialize<br />
@values = Array.new()<br />
@max = 0<br />
end</p>
def add(value)
@values << value
@max = value if value > @max
end
def average(read_only=false)
return_value = if @values.length == 0
nil
else
@values.inject(0) {|sum,value| sum + value } / @values.length
end
@values = Array.new() unless read_only
return_value
end
def max(read_only=false)
return_value = @max
@max = 0 unless read_only
return_value
end
<p>end</p>
</typo:code>
<p>In the next section of the code, we build our accumulators, and begin tailing the logfile to extract performance numbers. This requires the <a href="http://file-tail.rubyforge.org/">file-tail gem</a>, available from rubyforge. Note that in my setup, this file resides in a subdirectory under <code>lib</code> in <code>RAILS_ROOT</code>. If you choose to place this file elsewhere, you’ll have to adjust the path to the logfile accordingly. Another thing to note: in our environment, the load balancer continually pings a “heartbeat” action on each node to make sure it is still responsive. As we will be hitting this action repeatedly, it is engineered to be as lightweight as possible. Therefore, any numbers from it are pretty meaningless to our overall statistics, so we don’t want to include them. To keep these numbers from skewing our results, we define an <code>IGNORE_PATTERNS</code> regexp (earlier in the code). If the request matches a pattern we want to ignore, its statistics are not collected.</p>
<typo:code lang="ruby" title="tail">
<p><span class="caps">LOGFILE</span> = File.join(File.dirname(<i><span class="caps">FILE</span></i>), ‘..’, ‘..’, ‘log’, “#{RAILS_ENV}.log”)<br />
$response_data = { :total => Accumulator.new(),<br />
:rendering => Accumulator.new(),<br />
:db => Accumulator.new() }</p>
<p>Thread.abort_on_exception = true<br />
logtail = Thread.new do<br />
File::Tail::Logfile.tail(<span class="caps">LOGFILE</span>) do |line|<br />
if line =~ /^Completed in /<br />
parts = line.split(/\s+\|\s+/)<br />
resp = parts.pop<br />
requested_url = resp[/http:\/\/[^\]]*/]<br />
next if requested_url =~ IGNORE_PATTERNS</p>
parts.each do |part|
part.gsub!(/Completed in/, “total”)
type, time, pct = part.split(/\s+/)
type = type.gsub(/:/,’’).downcase.to_sym
$response_data[type].add(time.to_f)
end
end
end
<p>end</p>
</typo:code>
<p>So now we have a thread busy gathering our data—how can we expose the data to a munin plugin? There are multiple ways to do this, but I chose to use a small <span class="caps">HTTP</span> server listening to requests from the local machine only. We could build such a thing in Rails, but we really don’t need about 90% of the features Rails has to offer. Since we’re running Rails as a Mongrel cluster, we already have a perfect tool at our disposal for writing small <span class="caps">HTTP</span> request handlers in Ruby: Mongrel. Here are a couple of pages about how to get started <a href="http://www.urbanhonking.com/ideasfordozens/archives/2007/05/my_first_mongre.html">writing</a> <a href="http://adam.blogs.bitscribe.net/2007/05/06/howto-custom-mongrel-handlers/">Mongrel</a> <a href="http://errtheblog.com/post/8444">handlers</a> —it’s pretty straightforward. Here’s our handler:</p>
<typo:code lang="ruby" title="mongrel handler">
<p>class ResponseTimeHandler < Mongrel::HttpHandler<br />
def initialize(method)<br />
@method = method<br />
end</p>
def process(request, response)
response.start(200) do |head,out|
debug = Mongrel::HttpRequest.query_parse(request.params[“QUERY_STRING”]).has_key? “debug”
head[“Content-Type”] = “text/plain”
output = $response_data.map do |k,v|
value = v.send(@method, debug)
formatted = value.nil? ? ‘U’ : sprintf(‘%.5f’, value)
“#{k}.value #{formatted}”
end.join(“\n”)
output << “\n”
out.write output
end
end
<p>end</p>
<p>h = Mongrel::HttpServer.new(“127.0.0.1”, <span class="caps">PORT</span>)<br />
h.register(“/avg_response_time”, ResponseTimeHandler.new(:average))<br />
h.register(“/max_response_time”, ResponseTimeHandler.new(:max))<br />
h.run.join</p>
</typo:code>
<p>The handler is generic so that it can call an arbitrary method on our collection of data arrays, so we can set up one <span class="caps">URI</span> for the average, and one for the maximum. With this in place, we can write a simple munin plugin script that uses <code>Net::HTTP</code> to query our Mongrel to get at the performance data.</p>
<p>Basically, a munin plugin has two usage scenarios. When called with the single argument “config”, it should output information about itself in a format that Munin understands. This includes how to label the chart, scaling information, how many series will be included on the chart, etc. When called with no arguments, the plugin should output the current values of each series. For more information on writing your own munin plugin, start with the <a href="http://munin.projects.linpro.no/wiki/HowToWritePlugins">HowToWritePlugins munin wiki page</a>. And now, our plugin script:</p>
<typo:code lang="ruby" title="rails_response_time">
<p>#!/usr/bin/env ruby</p>
<ol>
<li>munin plugin to render rails response time graphs</li>
<li>link to /etc/munin/plugins/avg_response_time and /etc/munin/plugins/max_response_time</li>
</ol>
<p>require ‘open-uri’<br />
<span class="caps">PORT</span> = <span class="caps">ENV</span>[‘<span class="caps">PORT</span>’] || “8888”</p>
<p>def config<br />
title = File.basename($0).split(‘_’).map{|s| s.capitalize }.join(’ ’)<br />
config=<<<i>END_CONFIG</i><br />
graph_title #{title}<br />
graph_vlabel response time<br />
graph_category rails<br />
total.label total<br />
rendering.label rendering<br />
db.label db<br />
<i>END_CONFIG</i><br />
puts config<br />
end</p>
<p>def get_data(read_only=false)<br />
qs = read_only ? ‘?debug’ : ’’<br />
puts open(“http://127.0.0.1:#{PORT}/#{File.basename($0)}#{qs}”).read<br />
end</p>
<p>case <span class="caps">ARGV</span>.first<br />
when ‘config’<br />
config<br />
when ‘debug’<br />
get_data(true)<br />
else<br />
get_data<br />
end</p>
</typo:code>
<p>The script will examine the name with which you linked it in to the munin plugins directory to determine which <span class="caps">URI</span> to query. I have also added a debug mode that will show you the current values, so you’re not consuming any data that munin needs to see for an accurate graph. The final piece is a small <a href="http://daemons.rubyforge.org/">Daemons</a> wrapper script to control the main log-tailing process, and you should be set. Make sure to restart munin-node so it will notice the new plugins, and after a while, you’ll see something like this:</p>
<p><img src="/files/avg_response_time.png" alt="" /></p>
<p>It is worth noting that the numbers from the Rails log might not be 100% accurate, and this won’t replace the results that you can get from seriously profiling your application. Also, the information you are getting is a bit generic — all actions are lumped together, so there is not a lot of information about the cause of the performance problem. But, for insight into your production application performance, this setup should at least give you some indications about how well your baby is playing in the interwebs.</p>
<p>Download <a href="/files/rails_log_monitor.rb">rails_log_monitor.rb</a></p>
<p>Download <a href="/files/rails_response_time">rails_response_time</a></p>Focus of the day.2007-08-31T00:00:00-07:00http://onrails.org/2007/08/31/focus-of-the-day<p>I am writing this to make sure I stay focused today. There are currently four projects in my head… MySpyder.net sorry, but not you today. That’s three left. Then there is MunchAway which I need to put on hold unil Monday, where I should Ajaxify the login. Ok, that leaves the “<span class="caps">BOOK</span>” and Digital-Seed.</p>
<p>For the book I should</p>
<p>1) write a script to generate the whole model and controllers using generate scaffolding…that will let me rerun it a couple of times until we get it right. I.e. rake scaffold:migrate [<span class="caps">VERSION</span>=n] allowing to add and remove stuff…this should also take care of nested resource.</p>
<p>2) Write some initial rSpecs to ensure that the model is right</p>
<p>For DigitalSeed I need</p>
<p>1) integrate the LayoutManager functionality into the base application</p>
<p>2) Refine the Widget drap&drop to visually indicate where the dragged item will appear if dropped.</p>
<p>The Book will be for tonight once the kids and wife are asleep…so let’s get started with Digital-Seed!</p>Unobtrusive Javascript with Lowpro and Ruby On Rails2007-08-28T00:00:00-07:00http://onrails.org/2007/08/28/unobtrusive-javascript-with-lowpro-and-ruby-on-rails<p>Check out http://www.danwebb.net/lowpro for more info on LowPro, a very elegant approach to do Unobtrusive Javascript with Ruby On Rails. Find hereafter a small example of how to add a custom behavior to link.</p>
<p>The View<br />
<typo:code lang="ruby" title="_watch_results.erb" ><br />
<%= javascript_include_tag ‘prototype’, ‘lowpro’, ‘remote’, ‘application’ <span>> <br />
<div id="result_list"><br />
<ul><br />
<</span> for watch_result in <code>watch_results %>
<li>
<%= link_to watch_result.created_at.to_s(:db),
diff_watch_result_url(</code>watch, watch_result),<br />
{:id => dom_id(watch_result) }<br />
%></p>
</li>
<% end %>
</ul>
</div>
</typo:code>
<p>The Javascript<br />
<typo:code lang="ruby" title="application.js" ></p>
<p>LoadWatchResult = Remote.Link({<br />
onLoading : function() {<br />
$(‘watch_result_difference’).innerHTML=‘’;<br />
$(’watch_result_difference’).addClassName(‘pleaseWait’); <br />
},<br />
onComplete : function(e) {<br />
var source = Event.element(e);<br />
$(‘watch_result_difference’).removeClassName(‘pleaseWait’);<br />
$$(‘div#result_list ul a.active’).each(function (e) {e.removeClassName(‘active’)}); <br />
source.addClassName(‘active’);<br />
}<br />
});</p>
<p>Event.addBehavior({<br />
‘#result_list ul li a’: LoadWatchResult<br />
});</p>
</typo:code>
<p>The ‘remote.js’ provides additional behaviors creatde by Dan Wedb as part of LowPro (http://svn.danwebb.net/external/lowpro/trunk/behaviours/). The LoadWatchResult behavior we created in this example transforms a ‘standard’ link_to to a link_to_remote with additional behavior on the onLoading and onComplete of the remote call. The view stays clean.</p>
<p>Enjoy!<br />
Daniel</p>Flex Dynamic Scaffolding for Ruby on Rails.2007-08-05T00:00:00-07:00http://onrails.org/2007/08/05/flex-dynamic-scaffolding-for-ruby-on-rails<p>No I am not announcing the next killer scaffolding framework but I had a couple of hours available today so I just explored some of the cool features or Ruby On Rails and Flex. The part I was most interested in (today) is dynamic user interface creation and not generating and application like several scaffolding frameworks are doing. So I was able to create a UI that adapts to a given model of a Rails application. Of course I didn’t go as far as I wished, but I thought I could share it with my readers as I usually get valuable feedback. Right now the application doesn’t even manage data. That will be the next step.</p>
<p><img src="http://onrails.org/files/20070804_FlexScaffolding.jpg" border="0" width="500" alt="20070804_FlexScaffolding.jpg" align="" /><br />
In a first phase I have adapted <a href="http://railroad.rubyforge.org/">RaildRoad</a> Rails model class diagram generation tool to generate an xml definition that the UI would use to create it’s components. I generated an xml model for <a href="http://trac.streamlinedframework.org/wiki/SampleProject">Sports</a> a sample application provided with Streamlined and <a href="http://typosphere.org/">Typo</a> a blog server.</p>
<p>The UI generation from the typo model is quite cpu intensive. There is not lazy instanciation of components, when you select the model, all the Tabs, lists and forms are created.</p>
<p>You can <a href="http://nouvelles-solutions.com/onrails/flexscaffolding/FlexScaffolding#">run the application</a> and press view source from the context menu. Or you can see the source <a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/index.html">here</a>. The generated xml can be seen <a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/source/sports_models.xml.txt">here</a> and <a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/source/typo_models.xml.txt">here</a></p>
<p>In a second phase I created a Flex application that generates a UI from the given xml.</p>
<p>I was writing this blog entry while coding, so if you are more curious about how all this works, keep on reading.</p>
<h1>Getting the schema of your ActiveRecords</h1>
<p>We will generate an xml version of the schema that Flex can use to assemble a UI. So we need to find out info about each ActiveRecord of the application, it’s association with other ActiveRecords, and all it’s attributes. Later on would also be nice to identify the validation rules, so that we can build some validations on the fly without having to do a server round trip for some of the basic validations, (required, length, confirmation, regex). Supporting the various acts_as could also provide lots of functionality that doesn’t need to be coded over and over.</p>
<p>I will use the Streamlined Sports example database to experiment with. Later on we may have a look at Typo a blog server.</p>
<p>Let’s use the community to see how to parse the ActiveRecord. I am now checking out <a href="http://railroad.rubyforge.org">RailRoad (0.4.0)</a> a class diagram generator for Rails. Railroad has the ModelsDiagram class that gather the information we need and then uses the DiagramGraph class to generate a <em>dot</em> format file that in turn is used to generate .svg or .png of the diagram. We are not interested in the dot generation, but will just ‘adapt’ the to_dot method to get the xml we need. So I simply reopened the class and created a new <i>to_dot</i> method as follows:</p>
<typo:code lang="ruby">
<ol>
<li>http://chadfowler.com/2007/8/3/enumerable-injecting<br />
module Enumerable<br />
def injecting(s)<br />
inject(s) do |k, i|<br />
yield(k, i); k<br />
end<br />
end<br />
end</li>
</ol>
<p>class DiagramGraph</p>
def to_dot
return definition.to_xml(:root => ‘active_records’, :dasherize => false)
end
#Let organize the data in a way closer to the xml we want to generate.
def definition
active_records = {}
@nodes.each do |node|
attributes = node<sup class="footnote" id="fnr2"><a href="#fn2">2</a></sup>.injecting({}) {|accumulator, value| k,v=value.split(" :"); accumulator[k] = v}
class_name = node<sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup>
active_records[class_name] = { :name => class_name, :attributes => attributes, :relations => [] }
end
@edges.each do |edge|
association_type = edge<sup class="footnote" id="fnr0"><a href="#fn0">0</a></sup>
from_class_name = edge<sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup>
to_class_name = edge<sup class="footnote" id="fnr2"><a href="#fn2">2</a></sup>
active_records[from_class_name][:relations] << {association_type.to_sym => to_class_name}
end
active_records
end
<p>end</p>
</typo:code>
<p>The <em>definition</em> method generates a hash map with the information of the model. The <em>to_xml</em> is all that is needed to get an <a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/source/sports_models.xml.txt">xml version</a> of the data that the map contains.</p>
<typo:code lang="ruby">
<p>definition.to_xml(:root => ‘active_records’, :dasherize => false)</p>
</typo:code>
<h1>Dynamically Generate a Flex UI</h1>
<p>Let looks at the model.</p>
<pre>
Player has_many Sponsor
Coach has_many Sponsor
Team has_one Coach
has_many Player
Sponsor has nobody!
</pre>
<p>The UI generation should be lot smarter and configurable. For now I have taken the approach to create one view for each model. This view shows all the records in a data grid and the detail of the selected record in a form view. All associations of the record are represented by a Tab Navigator. You will notice that this is not very practical for the Typo datamodel. We should have main ActiveRecords that are entry points to the application. Also the depth of the active record view is one association down but could be driven by definition i.e. Team => Coach => Sponsor, similar to the :include option of the find methods. We should be able to flatten a “to one” relation and have all the attributes of the association in the same view than the source ActiveRecord.</p>
<p>You can <a href="http://nouvelles-solutions.com/onrails/flexscaffolding/FlexScaffolding">run the application</a> and <a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/index.html">view the source</a>.</p>
<p>The main application, FlexScaffolding, adds dynamically a ActiveRecordsView for each ActiveRecord in the model to the Tab navigator. That’s too many tabs for the Typo model…</p>
<typo:code>
private function generateView():void {
for each (var activeRecord:<span class="caps">XML</span> in definition.children()) {
var arView:ActiveRecordsView = new ActiveRecordsView();
arView.definition = activeRecord;
mainView.addChild(arView);
}
}
</typo:code>
<p>The ActiveRecordsView.mxml does the main work of generating the UI. It’s not very big (66 lines), but is also limited for now. I let you check out the source code if you a curious. Next on the list is to map too more data types (ie a “text” ActiveRecord attribute should be mapped to a TextArea, date and datetime should be support). I need to add configuration options where the defaults can be overridden. I need to create a Rails controller that uses the same xml model to expose the data to the view. There shouldn’t be the need to hand code RESTFul controllers. Or maybe the UI should be build from the routes…</p>
<p>That’s all for now. Enjoy!<br />
Daniel Wanja</p>Flex Automation Manager2007-07-23T00:00:00-07:00http://onrails.org/2007/07/23/flex-automation-manager<p>At the beginning of the year I was investigating the new automation functionality Flex 2.0.1 brought to the table. So I looked into what it would take to implement a tool like QuickTest Pro and made some initial progress, but then got called back to reality and other projects. I mentioned this and several readers of this blog contacted me and asked If they could get the source code or if I could open source it. Well, the code is not in any stage where I could open source it or even show it. It doesn’t work under Flex 3 anymore. But as you asked for it, feel free to have a look at this “experiment”. This code is not an example on how to structure you code or the right way of doing things…it’s rather some dark side coding during a late night session. Be warned only check this out if you are really curious or asked for it :-) Use at your own risk, and don’t ask too many questions: <a href="http://nouvelles-solutions.com/onrails/flextester/srcview/">view source here</a>. They are many parts I haven’t even looked into it such as drag&drop, mouse movement emulation, text selection… so Good luck! Also note that Adobe removed from the source code the mx.automation.delegates folder in the Moxie release…These classes are required to make automation work, and I assumed they where part of the <span class="caps">SDK</span> and are an important part to understand how the automation is working. So I am not sure what the status on using these classes is.</p>On The (onAIR) Bus - Denvers stop live coverage!2007-07-20T00:00:00-07:00http://onrails.org/2007/07/20/on-the-onair-bus-denvers-stop-live-coverage<p><img src="http://onrails.org/files/20070720_onairtour.png" border="0" height="321" width="490" alt="20070720_onairtour.png" align="" /></p>
<p>Not really on the bus but at the onairbustour stop in Denver. Check out Flickr Tags (onairbustour and onair2007denver). Today’s agenda looks quite interested and there will lots of info regarding Adobe’s <span class="caps">AIR</span> technology. The Keynote by Ryan Stewart will start in 1 minutes. I’ll take some notes during the day…so check back!</p>
<p><strong>Keynote</strong></p>
<p>Ryan now shows <a href="http://pownce.com/">pownce</a> (I am still waiting for my invite…I tried to get one via <a href="http://www.inviteshare.com">inviteshare</a> but no success yet!). He shows the nice <a href="http://finetune.com/">finetune</a> application that has a nice <span class="caps">AIR</span> application to complement their website. He demoes a word processor (buzzword) created in Flex and <span class="caps">AIR</span>, ask your preview <a href="http://www.virtub.com/signup/">here</a>.</p>
<p>Now Ryan shows the <span class="caps">AIR</span> Roadmap, next big steps is Max 2007. Beta 2 will be release around Max 2007 which will add functionality like Flash <span class="caps">AIR</span> Support. An <span class="caps">AIR</span> version support Linux appear in the <span class="caps">AIR</span> 1.x version.</p>
<p>Now back to Mike Chambers that will provide a technical introduction on <span class="caps">AIR</span> and will create a Hello World application. At the end of the presentation Mike points to <a href="http://code.google.com/p/onairbustour/">http://code.google.com/p/onairbustour/</a> where the post the various applications they are building on the tour about the tour.</p>
<p><strong>Kevin Hoyt – <span class="caps">AIR</span> application with javascript</strong></p>
<p>What a slacker Kevin is…only two slides :-) No it’s pretty cool, Kevin is a hands on guys and is building some <span class="caps">AIR</span> javascript application live and shows some nice tricks.</p>
<p>I won’t transcode all the code he show, but there is a tight integration between javascript and actionscript. He shows how to call directly actionscript methods from javascript.</p>
<typo:code lang="javascript" title="Javascript calling Actionscript">
<p>function doSave() {<br />
var file = air.File.desktopDirectory.resolve(“denver.txt”)<br />
air.FileStream().open (…) // some code left out.<br />
}</p>
</typo:code>
<p>So this is javascript and the <em>air</em> object allows access to Actionscript. In this case he is saving some text entered in htm l to the file system. Cool.</p>
<p>He presents Aptana and shows that they have some <span class="caps">AIR</span> integration. Check out Kevin’s <a href="http://blog.kevinhoyt.org/">blog</a></p>
<p><strong>Kevin Hoyt – Another session on script bridging.</strong></p>
<p>Kevin now builds a web browser in <span class="caps">AIR</span>/Flex that uses the mx:<span class="caps">HTML</span> component.</p>
<typo:code>
<p>web.htmlControl.load(new URLRequest(address.text))<br />
<mx:HTML id="web" /></p>
</typo:code>
<p>The following provides access to any public actionscript class described in library.swf to javascript.<br />
<typo:code><br />
<script src="library.swf" /></p>
</typo:code>
<p>Lunch!!!</p>
<p>All right, I didn’t catch up the beginning of Daniel Dura’s talk…Sorry, I was <em>playing</em> with my <span class="caps">EVDO</span> card.</p>
<p><strong>Daniel Dura – <span class="caps">AIR</span> <span class="caps">API</span> Overview</strong></p>
<p>Daniel describes the various apis and shows lots of code. He starts showing the different options the Window <span class="caps">API</span> offers (transparent, system, dialog, lightweight). He shows the Drag and Drop <span class="caps">API</span> (<span class="caps">AIR</span> to <span class="caps">AIR</span>, <span class="caps">AIR</span> to OS, OS to <span class="caps">AIR</span>, Desktop to <span class="caps">AIR</span>). It’s pretty cool to see all these APIs in action. The Service Monitoring allows to detected network connection changes. <br />
Database Support: just added <span class="caps">SQL</span> integration to the new beta. Fully local database. Can be used to sync data with an online application. You can store data while being offline. He demonstrates an example written by <a href="http://coenraets.org">Christophe Conraets</a> show the SQLite integration (SQLQueue, SQLStatement).</p>
<p><strong>Salesforce.com</strong></p>
<p>Salesforce and Flex was used to improve the User Experience they where providing before.</p>
<p><strong>Contest to give away schwag</strong></p>
<p>Yea, Kevin Hoyt got taped at the back of bus…I rememberd that…answered Mike Chambers question..and won the following 7 books:<br />
<img src="http://onrails.org/files/20070720_onair_books.png" border="0" height="300" width="225" alt="20070720_onair_books.png" align="" /></p>
<p><strong>Yahoo Media Innovation Group – Jason</strong></p>
<p>Some demos of what Yahoo is doing with <span class="caps">AIR</span>. One application is <em>Minibar</em>, a Dashboard like widget.</p>
<p><strong>Developing <span class="caps">AIR</span> Applications with Ajax Components – Andre Charland from Nitobi</strong></p>
<p><strong>Why Ajax in <span class="caps">AIR</span>?</strong></p>
<ul>
<li>Code Reuse, Skills Reuse, <span class="caps">HTML</span> is <span class="caps">REALLY</span> good at some things, Maintain UI Patterns, Javascript is growing.</li>
</ul></li>
<li>What more can we do than the browser?
<ul>
<li>Files, Windows & Chrome, Drag&Drop, Copy&Paste, Offline, Background process, notifications, keyboard shortcuts.</li>
</ul></li>
<li>Demo <span class="caps">APP</span>
<ul>
<li>Ajax Fisheye Menu (mac like dock)</li>
<li>Offline Sales Force</li>
</ul><p><strong>eBay San Dimas – Sean Chirstmann from EffectiveUI</strong></p>
<p>San Dimas is eBay on the Desktop build with <span class="caps">AIR</span>. Why? What’s the point? This is a big question for many <span class="caps">AIR</span> applications. New experience for customers and new functionality <span class="caps">AIR</span> provides. For example alerts, notifications and the live nature of Flash is a big deal to the user.</p>
<ul>
<li>Development Pattern
<ul>
<li>San Dimas is built on Cairngorm</li>
<li>Assets externalized to allow for new skins</li>
<li>String externalized for internationalization</li>
</ul></li>
<li>eBay <span class="caps">SDK</span> Overview*
<ul>
<li>AS3 classes generated from eBay <span class="caps">WSDL</span></li>
<li>Objects in AS3 are serialized into <span class="caps">XML</span> and sent to server</li>
<li><span class="caps">XML</span> received from server is assembled into corresponding AS3 objects</li>
<li>Benefit from working with typed native objects that are bindable</li>
</ul></li>
<li>Upcoming Features
<ul>
<li>eBay: Browsing, Selling</li>
<li><span class="caps">AIR</span>: <span class="caps">SQL</span> database integration for category/attribute info</li>
<li>OS Alerts, System Tray</li>
</ul></li>
</ul>
<p>see <a href="http://projectsandimas.com">http://projectsandimas.com</a></p>
<p><strong>Transitioning to the Desktop – Lee from frog design</strong></p>
<p>The presentation will mostly focus on design. Lee also likes Microsoft products, so he can provide some perspective.<br />
Lee did the bus wrap for the tour. Some interactive part of the onAir website. His blog is the <a href="http://theflexblog.com/">theflexblog.com</a></p>
<p>Lee is actually showing some cool stuff done with <span class="caps">AIR</span> just to highlight animation and custom chrome performance. He will post these examples on his blog.</p>
<p><strong>Buzzword</strong></p>
<p><img src="http://onrails.org/files/20070720_onair_buzzword.jpg" border="0" height="70" width="311" alt="20070720_onair_buzzword.jpg" align="" /></p>
<p>Cool I just go my invite. Man just logged in and it’s refreshing to see such such a cool word processor. Hehe, bye-bye word! Well, I don’t use Word anymore anyhow.</p>
<p><strong>The Schedule for the rest of the onAIR tour</strong></p>
<p><img src="http://onrails.org/files/20070720_onair_thebus.png" border="0" height="299" width="400" alt="20070720_onair_thebus.png" align="" /></p>
<p><strong>The bus in the bus!!!</strong></p>
<p><img src="http://onrails.org/files/20070720_onair_businbus.png" border="0" height="240" width="320" alt="20070720_onair_businbus.png" align="" /></p>
<p><strong>The Kevin in the bus!!!</strong></p>
<p><img src="http://onrails.org/files/20070720_onair_viewfromthebug.png" border="0" height="320" width="240" alt="20070720_onair_viewfromthebug.png" align="" /></p>Updated: http://time.onrails.org2007-07-14T00:00:00-07:00http://onrails.org/2007/07/14/updated-http-time-onrails-org<p>Time.onrails.org – a simple time tracking application has been updated.</p>
<ul>
<li>Time shifting – Let’s assume you entered time from 08:00-12:00 13:00-17:00. Then you notice that you effectively took a longer lunch. Simply edit the 12:00 to 11:45, then tab to the next field and change 13:00 to 13:15 and press enter. In the same way, if you didn’t come back from lunch at all that day. Simply clear out the 13:00-17:00 field and press enter. This will delete this time slot.</li>
</ul>
<ul>
<li>Running Timers – When a timer is running (i.e. 11:30- ), the time line (day) is highlighted in green. That way it’s easy to detect which timers are still running.</li>
</ul>
<ul>
<li>IE6 Support. Time entry was pretty broken with IE. This should have been fixed. I haven’t installed IE7…so I assume it doesn’t work there.</li>
</ul>
<ul>
<li>Rails Migration. Behind the scenes Rails was migrated from 1.1.6 to 1.2.3.</li>
</ul>
<p><img src="http://onrails.org/files/20070713_timeonrails.jpg" border="0" height="234" width="534" alt="20070713_timeonrails.jpg" align="" /></p>
<p>Please let me know if you find anything unusual.</p>
<p>Enjoy!<br />
Daniel.</p>RailsLogVisualizer now for Windows.2007-07-06T00:00:00-07:00http://onrails.org/2007/07/06/railslogvisualizer-now-for-windows<p>I got around and fixed the Windows specific issue as <a href="http://onrails.org/articles/2007/07/03/railslogvisualizer-meets-adobe-air#comments">Philipp</a> pointed out. I also had to take into account the File.lineEnding in order to make sure the parsing works on <span class="caps">OSX</span> and Windows.</p>
<p>If you haven’t yet, first <a href="http://labs.adobe.com/downloads/air.html">download the Adobe Integrated Runtime (<span class="caps">AIR</span>) <br />
</a></p>
<p>Then download: <a href="http://onrails.org/files/RailsLogVisualizer0.6.air">RailsLogVisualizer0.6.air</a></p>
<p>After the log file is loaded the parsing takes some time and the UI doesn’t yet provide feedback for the progress. See be a little patient.</p>
<p>Please let me know how the RailsLogVisualizer works for you!</p>
<p>Enjoy!<br />
Daniel.</p>RailsLogVisualizer meets Adobe AIR2007-07-03T00:00:00-07:00http://onrails.org/2007/07/03/railslogvisualizer-meets-adobe-air<p>I recompiled the Log Visualizer with Adobe <span class="caps">AIR</span>. You can download it <a href="http://onrails.org/files/RailsLogVisualizer0.5.air">here</a>.</p>
<p><img src="http://onrails.org/files/20070702RailsLogVisualizer.jpg" border="0" width="490" alt="20070702RailsLogVisualizer.jpg" align="left" /></p>
<p>I tried it under Windows XP (Parallels) and it seems that the File.browseForOpen doesn’t fire the Event.<span class="caps">SELECT</span> event under Windows. So the bug is that you can open a file, but the application doesn’t know when you selected it. I was contacted by Logan today who wanted to know if there is a Windows version. So sorry for the Windows users out there for the moment. Note that the <a href="http://onrails.org/articles/2007/03/29/railslogvisualizer-meets-apollo">Apollo version</a> of the Log Visualizer was working under windows.<br />
<br/>
Download: <a href="http://onrails.org/files/RailsLogVisualizer0.5.air">RailsLogVisualizer0.5.air</a></p>iPhone Web Development2007-06-30T00:00:00-07:00http://onrails.org/2007/06/30/iphone-web-development<p>I haven’t found much info on developing for the iPhone, but this <a href="http://stakeventures.com/articles/2007/06/19/repost-of-wwdc-iphone-safari-info">link</a> provides some good info. Here are some extracts:</p>
<ul>
<li>Safari User Agent for iphone:: Mozilla/5.0 (iPhone; U; <span class="caps">CPU</span> like Mac OS X; en) AppleWebKit/420+ (<span class="caps">KHTML</span>, like Gecko) Version/3.0 Mobile/1A538a Safari/419.3</li>
<li>No Java, No Flash</li>
<li>HTML5</li>
<li>10MB max html size for web page</li>
<li>Javascript limited to 5 seconds run time</li>
<li>Javascript allocations limited to 10MB</li>
<li>8 documents maximum loaded on the iPhone due to page view limitations</li>
<li>Quicktime used for audio and video</li>
<li>stylesheet device width:480px</li>
<li>there are no scroll bars or resize knobs. the iphone will automatically expand the content</li>
<li>new telephone links allows you to integrate phone calls directly from your webpage. remember this is only on safari.</li>
<li>built in google maps client for integrated mapping from your website</li>
<li>iPhone screen size 480×320</li>
<li>encode movie size 480×360</li>
<li>Links to movies on a web page will take users directly to video full screen playback</li>
</ul>
<p>I didn’t have to say in line to buy an iPhone, the Apple Store in Aspen Groove served everyone that was waiting in line in about 30 minutes, I just happened to go eat next to the Apple Store with my wife and kids ;-). So I just picked one up on the way to the Restaurant, zero wait. The store is open to midnight but there is not too much activity. I guess only geeks like me (or Sol) will try to pick one the first day, even while being fully aware of the limitations or the price. And this despite that I told everyone that in no way I will get one. Note, we have to test our different web applications on the new platform. <span class="caps">ATT</span> seems a little overwhelmed and iTunes provides me with a nice message that it will take a little longer and I will be notified by email when I can activate the phone. Note that I just received a follow-up email that telling me to that the phone will be activated by July 1st noon.</p>From Flex, to Spry, to Rails2007-06-29T00:00:00-07:00http://onrails.org/2007/06/29/from-flex-to-spry-to-rails<p>For one of the product we are currently developing for ourselves, we want to create a very slick interface. When we started, I was doing some Flex work at that time, so we (I) decided to start building the UI in Flex against a RESTFul Rails application. I used <a href="http://labs.adobe.com/wiki/index.php/Cairngorm">Cairngorm</a> and I spent 10 days over several month developing the main functionality. I created a Flex <a href="http://onrails.org/articles/2007/02/10/restful-rails-from-flex">ActiveResourceClient</a> class (Actionscript) to access our RESTFul Rails server. I found a nice mechanism to display <a href="http://onrails.org/articles/2007/03/06/mapping-rails-errors-to-flex-fields">Rails errors in Flex</a> similar to what scaffolding provides. I managed to add some Flex charting to show time series. We also nicely integrated testing with rake to allow running Flex unit tests from rake (rake test:flex). All was good. All was good, if it wasn’t for a little feeling that coding was slowing down. And it was getting a little slow to add new features. And I wasn’t so sure any more that we really needed flex for that project. So as the server was RESTFul, I thought why not use <a href="http://labs.adobe.com/technologies/spry/">Adobe’s <span class="caps">SPRY</span> framework</a> that consumes <span class="caps">XML</span> to drive <span class="caps">HTML</span> generation in Javascript. And our Rails application returns <span class="caps">XML</span>. So I devised a nice way to integrate Spry with Rails. I thought let’s give it a try. Four hours later I had a working demo, and 12 hours later a working application. The result was a cool application that behaves like Gmail. Erb was used to generate Spry templates and once the client was loaded (html+javascript) only calls to get new data from the server where issued. Then came RailsConf 2007 and my vacations (without any computer). Well, coming back to the project I wondered if I really needed Spry and if I could just go plain old Rails for the views. So on I went back and rewrite once more the UI just using standard Rails views. Eight hours later I had a clean, simple UI.</p>
<p>Lessons learned: keep it simple, don’t use technology for technology, don’t find a problem to your solution. Well, I got to enthusiastic about trying out new stuff, but now we are back on track.</p>
<p>So, 10 days for Flex, 12 hours for Rails+Spry, and 8 hours for plain Rails. Now this comparison is not fair as we spent quite some time on integrating Flex and Rails. But definitively when a Flex application becomes quite large, the compile time causes a drag to the development time. This is compared to plain Rails where you can just keep doing changes at which ever level you want (model, controller, view) and instantly see the change, resulting in a way faster development cycle. Don’t take me wrong I love Flex, but for this project Rails is a better fit.</p>Open For Business: eBay Desktop Beta - an Adobe AIR Application.2007-06-21T00:00:00-07:00http://onrails.org/2007/06/21/open-for-business-ebay-desktop-beta-an-adobe-air-application<p>The invitations are going out! So, if you haven’t yet, go <a href="http://www.projectsandimas.com/">signup</a> for the eBay Desktop beta (code name Project “San Dimas”“) at ”http://www.projectsandimas.com/">http://www.projectsandimas.com/</a>.</p>
<p>The eBay Desktop is an Apollo Application, oops, Adobe <span class="caps">AIR</span> application, that is developed by our friends <a href="http://thillerson.wordpress.com/">Tony Hillerson</a> and <a href="http://www.craftymind.com/">Sean Christmann</a> from EffetiveUI for eBay. As they had their hand full applying the finishing touch to the beta, they asked Lee and myself to help with the beta Signup program and administration site which is a Ruby on Rails application. How cool is that! Thanks guys for the opportunity to work on such a visible project…</p>
<p>Now if you know Sean you will understand why using the eBay Desktop is fun. When Sean is not coding he is playing games, and he want’s any application to be fun and playful. Even when he gives talks he manages to <a href="http://www.youtube.com/watch?v=iNnRrzKuzt4">demonstrates</a> how to program a <span class="caps">WII</span> controller. It’s cool that <a href="http://alanlewis.typepad.com/">Alan Lewis</a> gave them the creative freedom to create some new user experience concepts on top of the existing eBay apis.</p>
<p>Ken, my desk <em>neighbor</em> at one of my clients asked why would you need something like Adobe <span class="caps">AIR</span>? Well in the case of the eBay Desktop, you are provided with an immersive experience, having a dedicated application will encourage the user to stay within that application and not get (too) distracted. The desktop also allows to save custom searches and additional information locally, thus providing functionality that may not be available by the existing eBay apis. It could also allow for functionality like drag&drop of images and text from the file system to create online auctions, use a connected camera to snap pictures, scan bar codes to retrieve product information, and so on…</p>
<p><img src="http://onrails.org/files/20070620_eBayDesktop.jpg" border="0" width="450" alt="20070620_eBayDesktop.jpg" /></p>
<p>PS: Hey Sean what’s your blog…or are you too busy coding?</p>Happy Birthday to Me!2007-06-21T00:00:00-07:00http://onrails.org/2007/06/21/happy-birthday-to-me<p>42! No way, that’s twice the legal drinking ages in most of the US states, 2.625 times the Swiss legal drinking age. I have been a professional programmer half my life and I am still having fun. I am now the oldest coder on most of the projects I work on :-) Ruby and Ruby on Rails is inspiring me in trying to write elegant and better code. But it’s really working on awesome projects and working with awesome people that inspires me to continue developing software. This said I will be away from my computer today. I will go to the Zoo with the kids and then to the pool. Couldn’t be much better. Have fun!</p>Free Rails Training2007-06-15T00:00:00-07:00http://onrails.org/2007/06/15/free-rails-training<p>From my perspective (as someone who has been doing <a href="http://www.rubyonrails.com">Rails</a> development full time for the past two years or so) it’s hard to believe, but there still are web developers who aren’t familiar with Rails. I was recently approached by an old friend about doing a training session on <a href="http://www.mono-project.com/Main_Page">Mono</a>. The last time we had been in close contact, I was exploring Mono and excited about the possibility of a .<span class="caps">NET</span> environment on Linux. Of course, that was before I discovered ActiveRecord and became a card-carrying Rails fan club member.</p>
<p>I told him that while that would probably be fun, I’d rather talk about something I didn’t have to learn for the presentation, and by the way, had he ever considered having a session on Rails? Well, I’m just back from the first segment of the course, which consisted of installing a Rails development stack in an Xubuntu virtual machine. Due to bandwidth limitations and a delayed start, that was all we accomplished tonight, but the remainder of the course (actually learning about Rails) will be in two weeks. We will provide a ready-to-go virtual machine to anyone interested in an introduction to Rails, and there are a few seats still available.</p>
<p>So if you or someone you know will be in the Denver area at 6:30 on June 28 (the day before the iPhone!), and have a couple of hours to be <del>indoctrinated</del> introduced to Rails, drop me a line [my gmail account is rubysolo].</p>WebSnapshot - a simple Adobe AIR application.2007-06-13T00:00:00-07:00http://onrails.org/2007/06/13/websnapshot-a-simple-adobe-air-application<p><span class="caps">UPDATE</span>: new version can be found <a href="http://myspyder.net/tools/websnapshot/">here</a><br />
<p/><br />
I converted the <a href="http://onrails.org/articles/2007/04/05/web-snapshot-a-simple-apollo-application">original Apollo WebSnapshot</a> Application to Adobe <span class="caps">AIR</span> using <a href="http://labs.adobe.com/technologies/flex/flexbuilder3/">FlexBuilder 3</a>. Now WebSnapshot works on <span class="caps">OSX</span> and Windows.</p>
<p>The conversion was straight forward. I changed the root tag of the application from <br />
<pre><mx:ApolloApplication></pre> to <pre><mx:WindowedApplication></pre></p>
<p>Then I used the new File.browseForSave method to show the save dialog when clicking on the thumbnail. No need anymore for the workaround that was required for this before. One thing I didn’t find out (yet) is how to set the file type and default filename in the save dialog. Any pointer is welcome!</p>
<p>Download it now: <a href="http://onrails.org/files/WebSnapshot0.2.air">WebSnapshot0.2.air</a> (right click and ‘Download Linked File’)</p>
<p><img src="http://onrails.org/files/20070613_websnapshot_osx.gif" border="0" height="270" width="500" alt="20070613_websnapshot_osx.gif" /></p>
<p><img src="http://onrails.org/files/20070613_websnapshot.gif" border="0" height="285" width="500" alt="20070613_websnapshot.gif" align="" /></p>
<p>To run the application you need to <a href="http://labs.adobe.com/downloads/air.html">Adobe Integrated Runtime (<span class="caps">AIR</span>)</a>. Also uninstall Alpha 1 before installing Beta 1 if you had Apollo installed.</p>
<p>To uninstall the runtime on Windows:</p>
1. In the Windows Start menu, select Settings > Control Panel.
2. Select the Add or Remove Programs control panel.
3. Select “Adobe Apollo 1.0 Alpha1” to uninstall the Apollo runtime.
4. Click the Change/Remove button.
<p>To uninstall the runtime on Macintosh:</p>
1. Delete the /Library/Frameworks/Adobe Apollo.framework directory.
2. Delete the /Library/Receipts/Adobe Apollo.pkg file.
3. Empty the Trash.Scribbish Spam Comments in Typo2007-05-24T00:00:00-07:00http://onrails.org/2007/05/24/scribbish-spam-comments-in-typoWe've been getting a bunch of comment spam lately and they are still displayed when correctly marked as spam in <a href="http://typosphere.org/">Typo 4.0.3</a> with the <a href="http://quotedprintable.com/pages/scribbish">Scribbish 2.0</a> theme. I believe this is fixed in Scribbish 3.0, but I'm not sure if it's compatible with our version of Typo. Here's a small patch to the Scribbish theme that only displays published comments instead of all comments.
<style type="text/css">
/* Stylesheet generated from TextMate theme
*
* All Hallow's Eve
*
*
*/
/* Mostly to improve view within the TextMate HTML viewer */
body {
margin: 0;
padding: 0;
}
pre.textmate-source {
margin: 0;
padding: 0 0 0 2px;
font-family: Monaco, monospace;
font-size: 16px;
line-height: 1.3em;
word-wrap: break-word;
white-space: pre;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -o-pre-wrap;
}
pre.textmate-source.all_hallow_s_eve {
color: #FFFFFF;
background-color: #000000;
}
pre.textmate-source .linenum {
width: 75px;
padding: 0.1em 1em 0.2em 0;
color: #888;
background-color: #eee;
}
pre.textmate-source.all_hallow_s_eve span {
padding-top: 0.2em;
padding-bottom: 0.1em;
}
pre.textmate-source.all_hallow_s_eve ::selection {
background-color: rgba(115, 89, 126, 0.88);
}
/* Text base */
pre.textmate-source.all_hallow_s_eve .text {
color: #FFFFFF;
background-color: #434242;
}
/* Source base */
pre.textmate-source.all_hallow_s_eve .source {
color: #FFFFFF;
background-color: #000000;
}
/* Comment */
pre.textmate-source.all_hallow_s_eve .comment {
color: #9933CC;
}
/* Constant */
pre.textmate-source.all_hallow_s_eve .constant {
color: #3387CC;
}
/* Keyword */
pre.textmate-source.all_hallow_s_eve .keyword {
color: #CC7833;
}
/* Pre-processor Line */
pre.textmate-source.all_hallow_s_eve .meta_preprocessor_c {
color: #D0D0FF;
}
/* Pre-processor Directive */
pre.textmate-source.all_hallow_s_eve .keyword_control_import {
}
/* Function name */
pre.textmate-source.all_hallow_s_eve .entity_name_function {
}
/* Function argument */
pre.textmate-source.all_hallow_s_eve .variable_parameter {
font-style: italic;
}
/* Block comment */
pre.textmate-source.all_hallow_s_eve .source .comment_block {
color: #FFFFFF;
background-color: #9B9B9B;
}
/* String */
pre.textmate-source.all_hallow_s_eve .string {
color: #66CC33;
}
/* String escapes */
pre.textmate-source.all_hallow_s_eve .string .constant_character_escape {
color: #AAAAAA;
}
/* String (executed) */
pre.textmate-source.all_hallow_s_eve .string_interpolated {
color: #000000;
background-color: #CCCC33;
}
/* Regular expression */
pre.textmate-source.all_hallow_s_eve .string_regexp {
color: #CCCC33;
}
/* String (literal) */
pre.textmate-source.all_hallow_s_eve .string_literal {
color: #CCCC33;
}
/* String escapes (executed) */
pre.textmate-source.all_hallow_s_eve .string_interpolated .constant_character_escape {
color: #555555;
}
/* Type name */
pre.textmate-source.all_hallow_s_eve .entity_name_type {
text-decoration: underline;
}
/* Class inheritance */
pre.textmate-source.all_hallow_s_eve .entity_other_inherited-class {
font-style: italic;
text-decoration: underline;
}
/* Tag name */
pre.textmate-source.all_hallow_s_eve .entity_name_tag {
text-decoration: underline;
}
/* Tag attribute */
pre.textmate-source.all_hallow_s_eve .entity_other_attribute-name {
}
/* Support function */
pre.textmate-source.all_hallow_s_eve .support_function {
color: #C83730;
}
</style>
<pre class="textmate-source all_hallow_s_eve">
<span class="source source_diff"><span class="meta meta_diff meta_diff_header meta_diff_header_from-file"><span class="punctuation punctuation_definition punctuation_definition_from-file punctuation_definition_from-file_diff">---</span> themes/scribbish/views/articles/_comment.rhtml 2007-05-24 10:36:20.000000000 -0600
</span><span class="meta meta_diff meta_diff_header meta_diff_header_to-file"><span class="punctuation punctuation_definition punctuation_definition_to-file punctuation_definition_to-file_diff">+++</span> themes/scribbish/views/articles/_comment_no_spam.rhtml 2007-05-24 10:35:14.000000000 -0600
</span><span class="meta meta_diff meta_diff_range meta_diff_range_unified"><span class="punctuation punctuation_definition punctuation_definition_range punctuation_definition_range_diff">@@</span> <span class="meta meta_toc-list meta_toc-list_line-number meta_toc-list_line-number_diff">-1,5 +1,6</span> <span class="punctuation punctuation_definition punctuation_definition_range punctuation_definition_range_diff">@@</span>
</span> <ol id="comments" class="comments">
<span class="markup markup_deleted markup_deleted_diff"><span class="punctuation punctuation_definition punctuation_definition_inserted punctuation_definition_inserted_diff">-</span> <% for comment in @article.comments -%>
</span><span class="markup markup_inserted markup_inserted_diff"><span class="punctuation punctuation_definition punctuation_definition_inserted punctuation_definition_inserted_diff">+</span> <% if @article.published_comments.any? -%>
</span><span class="markup markup_inserted markup_inserted_diff"><span class="punctuation punctuation_definition punctuation_definition_inserted punctuation_definition_inserted_diff">+</span> <% for comment in @article.published_comments -%>
</span> <li class="comment" id="comment-<%= comment.id %>">
<div class="author">
<%= content_tag(:div, gravatar_tag(comment.email)) if config_value(:use_gravatar) and comment.email %>
<span class="meta meta_diff meta_diff_range meta_diff_range_unified"><span class="punctuation punctuation_definition punctuation_definition_range punctuation_definition_range_diff">@@</span> <span class="meta meta_toc-list meta_toc-list_line-number meta_toc-list_line-number_diff">-10,5 +11,8</span> <span class="punctuation punctuation_definition punctuation_definition_range punctuation_definition_range_diff">@@</span>
</span> <%= comment_html(comment) %>
</div>
</li>
<span class="markup markup_inserted markup_inserted_diff"><span class="punctuation punctuation_definition punctuation_definition_inserted punctuation_definition_inserted_diff">+</span> <% end -%>
</span><span class="markup markup_inserted markup_inserted_diff"><span class="punctuation punctuation_definition punctuation_definition_inserted punctuation_definition_inserted_diff">+</span> <% else -%>
</span><span class="markup markup_inserted markup_inserted_diff"><span class="punctuation punctuation_definition punctuation_definition_inserted punctuation_definition_inserted_diff">+</span> <li class="dummy_comment" style="display:none">No comments</li>
</span> <% end -%>
</ol>
</span>
</pre>
All Hallow's Eve Syntax Highlighting2007-05-24T00:00:00-07:00http://onrails.org/2007/05/24/all-hallows-eve-syntax-highlightingOur syntax highlighting is now closer to <a href="http://macromates.com/">Textmate's</a> "All Hallow's Eve" theme. This was taken from the latest version of <a href="http://www.quotedprintable.com/2006/10/5/all-hallows-eve">Scribbish 3.0</a>. Here's our version of <a href="/stylesheets/theme/syntax.css">syntax.css</a>
<typo:code lang="ruby">
# Show off All Hallow's Eve theme
module Theme
class AllHallowsEve < Base
def description
desc = "My TextMate theme"
end
end
end
</typo:code>
Upgraded Syntax Highlighting for Scribbish Theme2007-05-22T00:00:00-07:00http://onrails.org/2007/05/22/upgraded-syntax-highlighting-for-scribbish-theme<p>We were bored of the plain green on black syntax highlighting for our code blocks, not to mention sick of the weird borders around code comments, so I hunted around for a little to find something a little better. The theme we’re using, Scribbish, didn’t have any <span class="caps">CSS</span> defined for Typo’s code blocks, so I stole them from <a href="http://blog.wilf.me.uk/articles/2006/10/03/syntax-highlighting-for-scribbish">James Wilford’s post</a>. Thanks, James.</p>
<p>Maybe we’ll tweak the colors some more later, but these will do for now.</p>
<typo:code lang="ruby">
<p>class Scribbish < TypoTheme<br />
include JamesWilfordCSS<br />
end</p>
</typo:code>Download RailsConf 2007 Presentations2007-05-21T00:00:00-07:00http://onrails.org/2007/05/21/download-railsconf-2007-presentations<p><strong>Updated: <a href="/articles/2007/05/21/bloated-railsconf-presentation-downloader">Now more bloated!</a></strong></p>
Run this to get the <a href="http://www.web2expo.com/pub/w/51/presentations.html">RailsConf 2007 presentations</a>:
<typo:code lang="ruby">
#!/usr/bin/env ruby
require 'rubygems'
require 'hpricot'
require 'open-uri'
base = 'http://www.web2expo.com'
h = Hpricot(open("#{base}/pub/w/51/presentations.html"))
h.search('div .presentation > a[@href^="/presentations/rails2007/"]').each do |a|
url = "#{base}#{a[:href]}"
if File.exists?(File.basename(url))
puts "skipping #{url}... already downloaded"
else
puts "downloading #{url}..."
`wget --quiet #{url}`
end
end
</typo:code>
I might clean it up more later to name the files better and not use wget, but this was quick and easy... not to mention a way to use everyone's favorite parsing tool: <a href="http://code.whytheluckystiff.net/hpricot/">Hpricot</a>.
Bloated RailsConf Presentation Downloader2007-05-21T00:00:00-07:00http://onrails.org/2007/05/21/bloated-railsconf-presentation-downloader<p>I’ve updated my downloader from <a href="/articles/2007/05/21/download-railsconf-2007-presentations">earlier</a> to include all sorts of fancy options. It no longer requires wget, it just uses open-uri. It can give the files a fancy name. It can be told where to download the files to. It will skip files that won’t download for some reason. It will even butter your toast if you can find the correct command line switch.</p>
<p>It’s about 3 times bigger than the previous one. But maybe you can learn a little more about <a href="http://www.ruby-doc.org/core/classes/OptionParser.html">optparse</a>, <a href="http://code.whytheluckystiff.net/hpricot/">hpricot</a>, file handling, and error handling along the way.</p>
<p>Here it is:</p>
<typo:code lang="ruby">
<p>#!/usr/bin/env ruby</p>
<p>require ‘optparse’</p>
<p><span class="caps">OPTIONS</span> = { :Verbose => false,<br />
:Force => false,<br />
:DownloadDir => ‘.’,<br />
:DescriptiveFilenames => true<br />
}<br />
OptionParser.new do |opts|<br />
opts.banner = “Usage: #{$0} [options]”</p>
opts.on(“-v”, “<del>-[no</del>]verbose”, “Run verbosely, default #{OPTIONS[:Verbose]}”) do |verbose|
<span class="caps">OPTIONS</span>[:Verbose] = verbose
end
opts.on(“-f”, “<del>-[no</del>]force”, “Force downloads, default #{OPTIONS[:Force]}”) do |force|
<span class="caps">OPTIONS</span>[:Force] = force
end
opts.on(“-d”, “<del>-[no</del>]descriptive”, “Use long descriptive filenames, default #{OPTIONS[:DescriptiveFilenames]}”) do |long|
<span class="caps">OPTIONS</span>[:DescriptiveFilenames] = long
end
opts.on(“-p”, “—path <span class="caps">PATH</span>”, “Path to download to, default #{OPTIONS[:DownloadDir]}”) do |path|
<span class="caps">OPTIONS</span>[:DownloadDir] = path
end
opts.on_tail(“-h”, “—help”, “Print help message”) do |help|
puts opts
exit
end
<p>end.parse!</p>
<p>require ‘rubygems’<br />
require ‘hpricot’<br />
require ‘open-uri’<br />
require ‘fileutils’</p>
<p>BASE_URL = ‘http://www.web2expo.com’</p>
<p>def log(str)<br />
puts str if <span class="caps">OPTIONS</span>[:Verbose]<br />
end</p>
<p>def download(href, filename)<br />
url = “#{BASE_URL}#{URI.escape(href)}”<br />
download_file = File.join(<span class="caps">OPTIONS</span>[:DownloadDir], filename)<br />
if <span class="caps">OPTIONS</span>[:Force] || !File.exists?(download_file)<br />
log “downloading #{File.basename(href)}…”<br />
begin<br />
File.open(download_file, ‘w’) { |f| f.write(open(url).read)}<br />
log “\tsaved as #{download_file}”<br />
rescue Object => e<br />
FileUtils.rm(download_file)<br />
$stderr.puts “<span class="caps">ERROR</span> downloading #{url}: #{e.message}”<br />
end<br />
else<br />
log “skipping #{File.basename(href)}… already downloaded as #{download_file}”<br />
end<br />
end</p>
<p>FileUtils.mkdir_p(<span class="caps">OPTIONS</span>[:DownloadDir])<br />
h = Hpricot(open(“#{BASE_URL}/pub/w/51/presentations.html”))<br />
h.search(‘div.presentation’).each do |presentation_node|<br />
href = presentation_node.at(‘a[@href^=“/presentations/rails2007/”]’)[:href]<br />
if <span class="caps">OPTIONS</span>[:DescriptiveFilenames]<br />
name = presentation_node.at(‘b a’).inner_text.strip<br />
text = presentation_node.inner_text<br />
speaker = text[/Speaker\(s\):\s+(.<strong>)\s</strong>$/, 1]<br />
date = Date.parse(text[/Presentation Date:\s+(.<strong>)\s</strong>$/, 1])<br />
filename = [speaker, date, name, File.basename(href)].compact.map { |s| s.to_s.strip.gsub(/[^\w\.]/, ‘_’).squeeze(‘_’) }.join(‘-’)<br />
else<br />
File.basename(href)<br />
end<br />
download(href, filename)<br />
end</p>
</typo:code>RailsConf 2007 - Day 42007-05-20T00:00:00-07:00http://onrails.org/2007/05/20/railsconf-2007-day-4<h2>The Rails Way Jamis Buck, Michael Koziarski</h2>
<p>See the <a href="http://therailsway.com/">http://therailsway.com/</a></p>
<p>#railsway on irc.freenode.net for questions at the end of the presentation.</p>
<typo:code lang="ruby">
<p>class TheRailsWay < BLog<br />
authored_by :jamis<br />
authored_by :koz<br />
end</p>
</typo:code>
<p>Instead of teaching you how to build things in Rails, Jamis and Koz will show us they things <b>should</b> be built.</p>
<ul>
<li>The Fat controller (Anti-pattern). Use Skinny Controller instead . Move logic out of controller to Model (i.e total_invoice), easier to test, can use form_for, …</li>
</ul>
<ul>
<li>With Scope. Is always abused. Step back and think “Is there a simpler way than using with_scope?”. I.e. implement an accessor to the attribute you need in your scope instead of using with_scope. I.e. current_organization. If the fix is worth than the initial desease don’t do it.</li>
</ul>
<typo:code lang="ruby">
<p>attr_read :current_organization.<br />
helper_method :current_organization.</p>
</typo:code>
<ul>
<li>Use self commenting code. Use before ‘some_explicit_method_name’ instead of a before_create method. An example of transforming some code where the intend was not explicit into the following code using before_create.</li>
</ul>
<typo:code lang="ruby">
<p>class Expense < ActiveRecord::Base<br />
before_create :mate_created_now_if_created_today</p>
protected
def mate_created_now_if_created_today
if self.created_at Time.now.beginning_of_day
<p>self.create_at = Time.now<br />
end<br />
end<br />
end</p>
</typo:code>
<ul>
<li>Associations.</li>
</ul>
<typo:code lang="ruby">
<p><code>john.documents #use this
Document.find_all_by_user_id(</code>john.id) # instead of this</p>
<p>@john.documents.find(:all, :conditions=>[“title like ?” “<span>koz</span>”] # use this<br />
Document.find(:all, …) # instead of</p>
<p>#This becomes even easier to read when the search conditions become more elaborate, <br />
#i.e. Find all documents by john tagged with ‘cool’? <br />
#This should be coded as <br />
cool.documents.find_by_user_id(@john.id) <br />
Document.find(:all, …) #instead of using with now much more conditions .</p>
<p>#Even better add a method explicating the association: <code>john.docouments.taged_with(</code>cool) <br />
#or <br />
<code>cool.documents_authored_by(</code>john). <br />
#But just use one, don’t repeat yourself. <br />
#You can get fancy you can use assosciation extensions: <code>john.documents.tagged_with(</code>cool).</p>
</typo:code>
<ul>
<li>Cargo-cult. Don’t just copy-paste the re-factoring you find on the RailsWay, try to understand the principles behind it. Make sure the concept applies to your code.</li>
</ul>
<typo:code lang="ruby">
<ol>
<li>Dont’ use of !!<br />
def account_code?<br />
!! @account_code.nil?<br />
end</li>
</ol>
<ol>
<li>use. More intention revealing<br />
def account_code?<br />
@account_code ? true : false<br />
end<br />
</typo:code></li>
</ol>
<ul>
<li>Share edit/new form. Don’t build the associations if required in the controller. Move it to a model class method.</li>
</ul>
<typo:code lang="ruby">
def self.build_with_associations
<p>returning new do |billable|<br />
blillable.booking = Book.build_with_assocations<br />
end<br />
end</p>
<ol>
<li>some code omitted…man, the speakers are going to fast for my typing!<br />
</typo:code></li>
</ol>
<ul>
<li>Simplifying non restfull routes. Use map.with_options. Also format and indent nicely your routes.</li>
</ul>
<p><b>Now onto some QA.</b></p>
<p>Q: Is the code from the code gonna be posted?<br />
A: Yes, on the website.</p>
<p>Q: In the Account code example, could you use @account_code.<br />
A: That would test something different as an empty string would return true. It depends on the requirement.</p>
<p>Q: Guidelines or best practices for overriding to_param?<br />
A: If you want prettier Urls you can provide a to_param. Otherwise don’t bother.</p>
<p>Q: returning?<br />
A: returning passes an object to a block and returns the object.</p>
<p>Q: Cascading validations?<br />
A: Validations can be tricky in that case. They don’t have a best practices to present on that right at this moment. But don’t worry about that too much.</p>
<p>Q: Koz. Can you clarify what’s the context key is (in the routes)?<br />
A: Forces a params[:context] = “www”</p>
<p>Q: How long does it take to do a typical RailsWay articles<br />
A: 1 day or 2. But it depends.</p>
<p>Q: has_many : through. What about multiple : through? I.e. A through B through C through D?<br />
A: I.e. A give me all yours Ds? If you really need it…add a custom method to the top.</p>
<p>Q: Attributes on join tables and conditions? Multiple associations? I.e has_many and has_one_current (through)<br />
A: I.e. document has_many versions, current_version. Implementation doesn’t really matter, but if current_version has business meaning make it an explicit method.</p>
<p>Q: What is your advice on keeping a database column private? I.e. a Model cannot access a column.<br />
A: We don’t see much value in that. Document this to not “touch” this. But try to find a solution. This can be difficult has private methods can be circumvented by send. Just make it explicit.</p>
<p>Q: Final words of wisdom? <br />
A: The RailsWay has been a little quiet, but now that the conference has been wrapping up, we will dive back into it.</p>
<p>Q: How do you answer questions that relate to deprecated features?<br />
A: We try to keep it to Rails 1.2.</p>
<h2>JRuby on Rails: A Taste of Honey (for the Enterprise)</h2>
<p>by Charles Nutter and Thomas Enebo JRuby Core Developer, Sun Microsystems.</p>
<p>Enterprise can be “doing cool new things and cool new ways”.</p>
<ul>
<li>The talk will cover
<ul>
<li>JRuby 101</li>
<li>Justifications</li>
<li>JRuby on Rails</li>
<li>Deployment Options</li>
<li>Migrations</li>
</ul></li>
<li>They are Java developers (10+ year)</li>
<li>Working to build out <span class="caps">JVM</span> dynlang support<br />
*JRuby 101. JRuby is:
<ul>
<li>Ruby (1.8ish)</li>
<li>A non-Java language for the Java platform</li>
<li>A new way to look at Ruby and the <span class="caps">JVM</span></li>
<li>Helping to expand Ruby’s reach</li>
<li>Helping the world better unstand Ruby</li>
<li>Really Cool</li>
</ul></li>
<li>JRuby is <span class="caps">NOT</span>:
<ul>
<li>An attempts to pollute or fork Ruby</li>
<li>An admission that Java sucks</li>
<li>The answer to every problem with Ruby</li>
<li>An attempt to alter Ruby or add incompatible features</li>
<li>Slow</li>
</ul></li>
<li>But it’s Java, Too</li>
</ul>
<typo:code lang="ruby">
<p>include Java<br />
import java.lang.ArrayList<br />
list = ArrayList.new</p>
</typo:code>
<ul>
<li>The rest you know
<ul>
<li>Obvious libraries pre-installed: Rubygems, Rake, Rspect</li>
<li>Mongrel supports JRuby (no remote gem)</li>
<li>Rails “just works”. Major orgs now investing in JRuby on Rails. Some folks where wondering if they “just” spawn a Ruby process.</li>
</ul></li>
<li>Justification or “Why would you do such a thing?”
<ul>
<li>Supporting the Status Quo (JRuby supports’ Ruby 1.8’s String)</li>
<li>Supports ActiveSupport::MultiByte</li>
<li>Exposing Java Unicode</li>
<li>Ruby 2.0 String on the way…</li>
</ul></li>
<li>Threading
<ul>
<li>JRuby supports Ruby’s Thread <span class="caps">API</span></li>
<li>JVMs are native-threaded (uses multiple cores)</li>
<li>JRuby Supports thread pooling</li>
</ul></li>
<li>JRuby on Rails the basics
<ul>
<li>Many gems just work</li>
<li>Rails commands just work. rails myapp, rake db:migreate</li>
<li>jruby script/server #==> WEBBrick</li>
</ul></li>
<li>Some differences
<ul>
<li>MySQL driver works.</li>
<li><span class="caps">JDBC</span>…different and faster. (database.yml needs url: and driver: com.mysql.jdbc.Driver)</li>
<li><span class="caps">JNDI</span> for connection pooling (jndi: java:comp/env/jdbc/MyAppPool)</li>
<li>Broad database support (DB2, Derby, <span class="caps">HSQLDB</span>, JavaDB, MS Access, Mimer <span class="caps">SQL</span>, MySQL, PostgreSQL,…and many more)</li>
<li>ActiveRecord-<span class="caps">JDBC</span>: as no schema management <span class="caps">API</span>. MySQL pass 100% of tests, Derby and PostgreSQL have 17 failing tests out of 1000+ tests. Others at varying levels, but coming along. Oracle supports started recently and has less than 100 failed tests for now.</li>
</ul></li>
<li>Differentiation
<ul>
<li>No Native Extensions. Require ports. Mongrel done, Hpricot done, RMagick in progress. We’re looking for porters and recommendations</li>
<li>Command-line Performance. Java is not slow…except at startup. It’s an issue for now. Don’t expect stella <span class="caps">CLI</span> performance.</li>
</ul></li>
<li>Demo
<ul>
<li>Building, running, and deploying a JRuby on Rails application</li>
</ul></li>
</ul>
<typo:code lang="ruby">
<p>tar xzf jruby.tar.gz<br />
jruby_env<br />
jruby -v<br />
jruby -S gem rails -y<br />
jruby -S gem install gem_plugin<br />
jruby -S gem install mongrel<br />
jruby -S gem install activerecord-jdbc -y<br />
cp lib/mysql.jar jruby/lib<br />
jruby script/server<br />
http://localhost:3000<br />
envirvonment.rb <br />
if RUBY_PLATFORM =! /java/<br />
require ‘jdbc_driver’ #I missed the proper code!<br />
end<br />
jruby script/generate migration entry<br />
jruby -S rake db:migrate<br />
# they continue to use the Rails generators and add standard Rails code</p>
cp -rp ../goldspike vendor/plugins
jruby -S rake war:standalone:create
<p># Assemble a .war file that deploys your Rails application as a standard J2EE application.<br />
http://localhost:8080/buggy/entries/list # Rails via J2EE</p>
</typo:code>
<ul>
<li>Thanks You..but there is more.
<ul>
<li>There is a new option.</li>
<li>jruby -S gem install GlassFish-10.0.0.0-java.gem —no-wrappers</li>
<li>glashfish command. Command line to start J2EE server.</li>
</ul></li>
<li>Migration
<ul>
<li>It can be done!</li>
<li>MySQL: works, Dearby/JavaDB: nearly 100%, others…depends.</li>
<li>Fixtures: Usually bugs are <span class="caps">YAML</span> rather than DB</li>
<li>Options: 1) use something else,. 2) Use an equivalent Java library 3) Port the library… 4)5)6) # I missed these</li>
</ul></li>
<li>Deployment
<ul>
<li>Mongrel</li>
<li>More common approach is .war file</li>
<li>A Grizzly/GlassFish v3 option.</li>
</ul></li>
<li>Demo: Calling Java libraries from JRuby</li>
</ul>RailsConf 2007 - Day 32007-05-19T00:00:00-07:00http://onrails.org/2007/05/19/railsconf-2007-day-3<h2>Bring Ruby to the Enterprise. Not the Other Way ’Round by Cyndi Mitchell (Thoughworks)</h2>
<p>Enterprise used to mean “To boldly go where no one went before”. Now it means “loose time, things that add no value, bloat-ware, incompetency, and corruption”<br />
We now have to reclaim the enterprise. Many of the people in this room and RoR planting the seed for a paradigm shift. Many now saw the light and start using RoR in the enterprise. In any case they all need new systems to communicate with old systems. <br />
If we get involved we can show them a better way. Help the Enterprise climb the learning curve faster. Thoughworks announces RubyWorks a full fledged ready to deploy Rails environment. JRuby provide for many Enterprise to make good on their existing Java investments while starting with Ruby On Rails. Lot of indicators showing that we are in the position to reclaim the Enterprise with Ruby On Rails. The core team shows the way of a better way of developing software. There is now a gap in the market in showing the Enterprise the Ruby On Rails way. “We” should be bold enough to bring Ruby On Rails to Enterprise.</p>
<p>Note: Thoughworks is a sponsor of RailsConf.</p>
<h2>Keynote by Tim Bray (Sun)</h2>
<p>Tim Bray, “Web Guy”. <br />
Tim starts to asks a few questions?</p>
<ul>
<li>“Who are you guys?”
<ul>
<li>Startup? 35%</li>
<li>Not startups? 35%</li>
<li>Service providers? 20%</li>
</ul></li>
</ul>
<ul>
<li>Very first web programming framework? 10 people.</li>
<li>Which framework are you coming from?
<ul>
<li>Java? Many.</li>
<li>Microsoft? Less</li>
<li>Php? Lots.</li>
</ul></li>
</ul>
<p>He did write lots of Ruby code that is in production, but hasn’t yet done lots with Rails.</p>
<p>Sun can give server to “worthy” open source projects. Sun also sponsors conference like this…and “Ladies and Gentlemen’s your are watching a paid commercial”. But we are putting our Money where our mouth is. Growing the Rails eco-system is good for everyone.</p>
<p>He is now showing NetBeans (pre-alpha release 6.0). You can run Rake Targets. Debugger running a .rhtml session.</p>
<p>The most visible thing Sun has done is to hire the JRuby guys. Charles Nutter comes on stage. So Tim asks him “Why JRuby”. To bring Ruby in Enterprise where Ruby is not so well accepted, wast number of existing Java libraries, <span class="caps">JVM</span> good virtual machine. Another question Charles mentions is “When to use JRuby?”. At the end of the month will come a first release candidate for JRuby 1.0.</p>
<p>He now asks Cindy from Thoughworks to explain why they use JRuby for Thoughworks Studio? She mentions that JRuby is not too disruptive for many of these Enterprises.</p>
<p>Why is Sun doing this? For quite some years sun was saying “The answer is Java. What is your question?”. Tim mentions is their business to help developers by selling them servers, the Solaris OS, Netbeans, Big Computers (2TB ram) starting at only $535000.-, Identity Management Solutions. The problem they are trying to solve, is that Sun is good a selling big boxes to bank, but they need to grow their business, and growth comes from the developers…the CEOs will follow. That’s why we love you…because we are greedy.</p>
<p>So how do we do money on free products? There is a three part mantra. 1) Adoption. If people don’t adopt your tools you won’t make money. Free removes friction to adoption. 2) Deployment. Once they have adopted you tools, they need to use it. Only once it’s deployed, customers see the value of your tools. 3) Monetization at the point of value. The hypothesis is that no serious business, will deploy any serious applications, and will not be ready to pay to support it. This will lead to greater prosperity down the road.</p>
<p>Let’s assume Rails succeeds beyond our wildest dreams. Are all our problems over? In the best possible scenario…Java will never go away, .Net will never go away, <span class="caps">PHP</span> will never go away, Cobol will never go away. The number of applications written is growing. The Network is heterogeneous, and the systems we deploy will need to cooperate. <span class="caps">DEAL</span> <span class="caps">WITH</span> IT. It’s arguably an unsolved problem, it’s a tax on our creativity. There a couple of solutions. 1. Run ruby on the Java platform. 3. The Community.</p>
<p>How do we get all these things talking to each other? The right answer is <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm"><span class="caps">REST</span></a>.</p>
<p>What’s said on Twitter during the keynote:<br />
<img src="http://onrails.org/files/20070519RailsConfTwitter.gif" border="0" height="408" width="764" alt="20070519RailsConfTwitter.gif" align="" /></p>
<h2>Custom Rails Helpers: Keeping Your Views <span class="caps">DRY</span> by Glenn Vanderburg</h2>
<p>There are Rails APIs you never heard off unless you are writing helpers.</p>
<p><b>Simple Helpers</b></p>
<typo:code lang="ruby">
<p>def sort_header(field, label=field.titleize)<br />
content_tag(:th, :class => ‘sort_header’) do<br />
link_to label, :sort => field<br />
end<br />
end</p>
</typo:code>
<p>Good for small stuff. For larger amounts use strings <<<span class="caps">EOS</span>, %{}, StringIO. Or use Biulder:XmlMarkup. render:partial.</p>
<p>Use <span class="caps">HTML</span> options<br />
<typo:code lang="ruby"><br />
def sort_header(field, label=field.titleize, html_options={})<br />
options = {:class=> ‘sort_header’).merge(html_options)<br />
content_tag(:th, :class => ‘sort_header’) do<br />
link_to label, :sort => field<br />
end<br />
end</p>
</typo:code>
<p><b>Generating Javascript</b></p>
<p>What about this?<br />
<typo:code lang="ruby"><br />
def filter_select(name, select_options)<br />
field_id =“field_#{name}”<br />
select_tag(name, build_option_tags(select_options), <br />
{:id => field_id})<br />
observe_field(field_id, :on => ‘changed’,<br />
:function => “$(‘filter_form’).submit(); return false;”<br />
end</p>
</typo:code>
<p>Javascript Helpers</p>
<ul>
<li>Rails Recipes, Recipe 2.</li>
<li>When other helpers generate javascript, use them</li>
<li>application.js</li>
</ul>
<p>Learn Javascript, learn Prototype.</p>
<typo:code lang="ruby">
<p>def filter_select(name, select_options)<br />
field_id =“field_#{name}”<br />
select_tag(name, build_option_tags(select_options), <br />
{:id => field_id})<br />
observe_field(field_id, :on => ‘changed’,<br />
:function => “MyApp.change_filter();”<br />
end</p>
</typo:code>
<p><b>Form Builders</b></p>
<p>form_for, field_for</p>
<typo:code lang="ruby">
<p>class TaggedBuilder < ActionView::Helpers::FormBuilder<br />
def text_field(label, *args)<br />
end<br />
end</p>
</typo:code>
<p>Glenn will put the slides <a href="http://wiki.oreillynet.com/wiki/railsconf2007/index.cgi?PresentationSlides">online</a>.</p>
<h2>Date Warehouses with ActiveWarehouse by Anthony Eden</h2>
<p>The talk is in line with the tutorial on</p>
<ul>
<li><a href="http://activewarehouse.rubyforge.org/">http://activewarehouse.rubyforge.org/</a> and on</li>
<li><a href="http://anthonyeden.com/2006/12/20/activewarehouse-example-with-rails-svn-logs">http://anthonyeden.com/2006/12/20/activewarehouse-example-with-rails-svn-logs</a></li>
</ul>
<ul>
<li>ActiveWarehouse::Dimension</li>
<li>ActiveWarehouse::Fact</li>
<li>ActiveWarehouse::Cube</li>
</ul>
<typo:code lang="ruby">
<p>class RevisionReportsController < ApplicationController<br />
def index<br />
<code>report = ActiveWarehouse::Report::TableReport.new(
:title => "Sales by Region",
:cube_name => :sales,
:column_dimension_name => :date,
:row_dimension_name => :store
)
render_report(</code>report)<br />
end<br />
end</p>
</typo:code>
<p><b>Dimension Mixin</b></p>
<p>acts_as_hierarchy_dimension<br />
acts_as_slowly_changing_dimension</p>
<p><b>Data Builders</b></p>
<p>rake warehouse:build_date_dimension<br />
rake warehouse:build_random_data # for testing</p>
<p><b>Role-Playing Dimensions</b></p>
<p>This uses views. ActiveRecord was extended to use views. Added migrations to views.</p>
<p>script/generate dimension_view creation_date_view</p>
<p><b>ActiveWarehouse <span class="caps">ETL</span></b></p>
<p><span class="caps">ETL</span>=Extract, Transform, Load. Or how to get data into the datawarehouse. This is a separate project installed as a gem.</p>
<p>Foreign Key Lookup Transform, Decode Transform, Type Transform, SHA1 Transform, String to Date Transform, Date to String Transform, Default Value Transform, Ordinal Transform, Custom Transform, Row Level Transform.</p>
<p>Loading. Write to multiple output, truncate tables with preprocessor, bulk load through adapters (that support it).</p>
<p><b>Who is using ActiveWarehouse</b></p>
<ul>
<li>blurb. 16 Dimension Tables, 8 Fact Tbles, Orders, User Registration, Uploads.</li>
<li>rubyforemmmultiworks.</li>
<li>Department of Defense. Used for portions of a safety data warehouse. Provided the initial genesis of the ActiveWarehouse plugin.</li>
</ul>
<p><b>What’s Next?</b></p>
<ul>
<li>Improvement in the Aggregation and Querying systems</li>
<li>Efficient Construction and Storage of Aggregates</li>
<li>Support for <span class="caps">MDX</span> for querying</li>
</ul>
<p><b>Resources</b></p>
<p>Anthony recommends the following book which highlights many of the principals applied in ActiveWarehouse:</p>
<p><a href="http://www.amazon.com/exec/obidos/ASIN/0471200247/ralphkimballc-20/104-5050702-4100704">The Data Warehouse Toolkit: The Complete Guide to Dimensional Modeling</a></p>
<h2>Open Mic</h2>
<p>(Let me know if I’ve got your names wrong!).</p>
<p><b><a href="http://masterview.org/">MasterView Template Plugin/Gem</a></b></p>
<p>By Jeff Barczewski and Deb Lewis<br />
<a href="http://rubyforge.org/projects/masterview">http://rubyforge.org/projects/masterview</a><br />
<a href="http://masterview.org/">http://masterview.org/</a></p>
<p>Generates a template and partials from an existing html design by simply adding some tags.</p>
<p><span class="caps">WYSIWYG</span> + Designer Friendly<br />
Has a plugin in and is documented</p>
<p><b><a href="http://yikesite.com/">YikeSite</a></b></p>
<p>Jeff Warrick from Canada<br />
Simple Content Management.<br />
A different approach to content management. 99% his client need to make edit at one small thing on a site. Adds an Admin and Edit button on a page and allows simply to change the content, wording, and formatting. Uses liquid template. The Admin interface allows to add, edit, and remove pages and organize them hierarchically.</p>
<p><b><a href="http://revolutionhealth.com/">revolutionhealth</a></b></p>
<p>by Eric Battin.<br />
Health portal. You can create a page from any content of the portal, or create new content. Eric shows the clipping functionality. Pretty slick. Then he shows the edit mode of a page.</p>
<p>See <a href="revolutiononrails.blogspot.com">revolutiononrails.blogspot.com</a></p>
<p><b>cnu config</b></p>
<p>Allows to overlay yaml files and access the configuration through a “dot” syntax.</p>
<p>CnuConfig.config.ConfigDemo(“url”)<br />
CnuConfig.config.moch_object.moch_method(“IL”, “Chicago”)<br />
CnuConfig.confi.RailsConf.year</p>
<p>Will be packaged as a gem and will be on Rubyforge next week.</p>
<p><b><a href="http://rubyforge.org/projects/cruisecontrolrb/">CruiseControl.rb</a></b><br />
by Alexey Verkhovsky</p>
<p>This are the step required to install and use cruisecontrol rb.</p>
<p>Download cruisecontrolrb-1.1.0<br />
cruise add MyProject —url file:///sv-repo/passing_project<br />
cruise start<br />
http://localhost:3333</p>
<p><b><a href="http://pibb.com">Group Discussion Tool</a></b><br />
By Bryan Alan. <br />
He wrote the openid plugin. The Group Discussion Tool is build around openid.<br />
<a href="http://pibb.com">http://pibb.com/</a><br />
OpenId is pretty awesome.</p>
<p><b><a href="http://divinecaroline.com/">divinecaroline</a></b><br />
A content management system. They wrote a plugin to do distributed page caching.<br />
Only works on Mac and Linux. <br />
(I didn’t get the name of the plugin)</p>
<p><b>mywaves</b></p>
<p>Share, watch, and publish video to mobile phones. Lot’s of video channels, i.e. RailsConf. You can put a channel on your blog or myspace page.</p>
<p><img src="http://onrails.org/files/20070519_mywaves.jpg" border="0" height="145" width="300" alt="20070519_mywaves.jpg" align="" /></p>
<p><b><a href="http://liquidrail.com/">The Mole Plugin</a></b></p>
<p>Fernand Galiana<br />
liquidrail.com</p>
<p>Awesome plugin allowing to determine how your application is <span class="caps">REALLY</span> used.</p>
<p><img src="http://www.liquidrail.com/assets/2007/4/15/snitch_molet.png" style="width:450px;height:350px;"/></p>
<p><b><a href="http://statisfy.net/">Statisfy.net</a></b></p>
<p>Last year he tried to demonstrate something (valuesource) but his computer didn’t work. Now he works on BountySource</p>
<p><a href="http://statisfy.net/">Statisfy.net</a> real time status usage of your site. Where people come to your application visualized on google maps.</p>Java == Poo # => true?2007-05-19T00:00:00-07:00http://onrails.org/2007/05/19/java-poo-true<p>At Tim Bray’s RailsConf keynote, he said, “Java is a 3-legged stool.” Does that mean Java is a pile of crap with three legs? I’m not sure. I’m pretty sure it’s not what he meant, but I bet some people might agree or think it has even more legs.</p>Will Marcel Molina Steal Matz's Ruby Super Powers2007-05-18T00:00:00-07:00http://onrails.org/2007/05/18/will-marcel-molina-steal-matzs-ruby-super-powers<p>I didn’t start watching <a href="http://www.nbc.com/Heroes/">Heroes</a> until after I heard <a href="http://richkilmer.blogs.com/">Rich Kilmer</a> and <a href="http://vernix.org/">Marcel Molina</a> talking about it while putting the badges together for RubyConf 2006 in Denver. Had I watched it before maybe I would have been a little scared of Marcel (<a href="http://en.wikipedia.org/wiki/Sylar">Sylar</a>), but he was very nice and didn’t <i>seem</i> like a threat to the Ruby world at all.</p>
<p>So, why be scared of Mr. Molina? You be the judge.</p>
<typo:code lang="ruby">
<p>class MarcelMolina<br />
include Heroes</p>
def <=>(other_hero)
other_hero.name == ‘Sylar’ ? 0 : 1
end
<p>end</p>
</typo:code>
<p><img src="/files/180px-Sylar3.jpg" width="92" height="116" /> == <img src="/files/marcel.jpg" width="92" height="116" /> # => true</p>RailsConf 2007 - Day 22007-05-18T00:00:00-07:00http://onrails.org/2007/05/18/railsconf-2007-day-2<p>Note: Check out the RailsConf Wiki and the <a href="http://wiki.oreillynet.com/wiki/railsconf2007/index.cgi?PresentationSlides">presentation page</a></p>
<p>Chad Fowler is starting the keynote introduction. 1600 developers are at the keynote. He makes a passionate speech about how Rails is changing how we think about software and how Rails impacted the industry. An now Rich Kilmer introduces the person that introduced him to Textmate: <span class="caps">DHH</span>.</p>
<h2>A peek at Rails 2.0</h2>
<p>Celebrating what we have</p>
<ul>
<li>> 1 million downloads</li>
<li>Hundreds of plugins</li>
<li>~10k people on rubyonrails-talk</li>
<li>He asks who is getting paid in one form or another using Rails and a large part the participants raise their hands.<br />
( Books: many Rails books in many languages. Surpassed <span class="caps">PHP</span>, Perl and Python (source O’Reilly Radar).</li>
<li>http://workingwithrails.com/ indicates over 100 countries where people do Rails.</li>
<li><span class="caps">IDE</span>: CodeGear, Textmate, NetBeans, JetBrains, Aptana</li>
</ul>
<p>Rails 2.0</p>
<ul>
<li>It’s not gonna change everything you know, it’s gonna be humble.</li>
<li>No new ‘great’ idea.</li>
<li>The experiment worked! (RESTFul resource)</li>
<li>The world of resources is a better, greener place.</li>
<li>Rails 2.0 will focus more on the <span class="caps">REST</span> convention</li>
<li>Routes</li>
</ul>
<typo:code lang="ruby">
<p>map.namespace(:admin) do |admin<br />
admin.resources :products,<br />
:collection => {:inventory => :get},<br />
:member => {:duplicte => :post},<br />
:has_many => [:tags, :images, :variants],<br />
:has_one => :seller<br />
end</p>
</typo:code>
<ul>
<li>David now demos the new scaffolding that use the resource approach of working with things.</li>
</ul>
<p>./script/generate scaffold persone name:string create_at:time</p>
<ul>
<li>He adds new format format.csv to support exporting as comma separated text.<br />
You can easily connect to this services:<br />
<typo:code lang="ruby"><br />
require ‘active_resource’<br />
class Person < ActiveResource::Base<br />
self.site = “http://localhost:3000”<br />
end<br />
p = Person.find 1<br />
</typo:code></li>
</ul>
<ul>
<li>Beyond <span class="caps">CRUD</span> you can custom methods, Person.find :all, :params => {:name => ’d’}</li>
<li>This all works today.</li>
<li>Action Web Service is no longer service with Rails 2.0. ActiveResource is.</li>
<li>Friends and allies: Ajax, <span class="caps">REST</span>, Atom, OpenID</li>
</ul>
<p><b>9 other things I like about rails 2: </b></p>
<p>1) Breakpoints are back (ruby_debug)</p>
<p>2) <span class="caps">HTTP</span> Performance</p>
<typo:code lang="ruby">
<p><!-- :cache => true
gzips all javascript and stylesheet in one file
i.e. prototype, css get zipped down to 35K from 200k
--><br />
<%= javascript_include_tag :all, :cache => true <span>> <br />
<</span>= stylesheet_link_tag :all, :cache => true %></p>
</typo:code>
<p>3) Query cache. <span class="caps">DHH</span> loves free performance</p>
<p>4) action.mime_type.renderer</p>
</typo:code>
<typo:code lang="ruby">
<p>people/index.html.erb<br />
people/index.xml.builder<br />
people/index.rss.erb<br />
people/index.atom.builder<br />
def index<br />
respond_to do |format|<br />
format.html<br />
format.xml<br />
format.rss<br />
format.atom<br />
end<br />
end</p>
</typo:code>
<p>5) config/initializers. One file per configuration in initializers folder</p>
<p>6) Sexy migrations (just nicer)<br />
<typo:code lang="ruby"><br />
create_table :people do |t|<br />
t.integer :account_id<br />
t.string :first_name, :last_name<br />
end</p>
</typo:code>
<p>7) <span class="caps">HTTP</span> Authentication. authenticate_or_request_with_http_basic</p>
<p>8) The <span class="caps">MIT</span> assumption. ./script/generate plugin now generates a default <span class="caps">MIT</span> license file.</p>
<p>9) Spring cleaning. Deprecated features of 1.2 will be removed. In-place editor will be moved to plugins.</p>
<p>That’s pretty much it. Thank you.</p>
<h2>Building Community Focused Apps with Rails by Dan Benjamin</h2>
<p>Rails is the ideal platform for Web 2.0. Fast prototyping and proof of concept. Prototype becomes the product. Conducive to collaboration with developers and designers. Dan is going to talk about <a href="http://corkd.com/">Cork’d</a>. Currently 20000 users.</p>
<p>Make a Plan.</p>
<ul>
<li>Treat your application like a product and your idea like a business. Just because it’s a good idea doesn’t mean it’s gonna be automatically successful.</li>
<li>Stay Agile. Resist big infrastructure.</li>
<li>Build the Right Team. Keep it light.</li>
<li>Determine Ownership.</li>
<li>Have a Revenue Stream (ads don’t count)</li>
<li>Focus on Simplicity. Don’t build features just because you think they are cool.</li>
<li>Don’t Release a Public Beta. They had two private betas. They learned from a handful set of people rather than from a large group.</li>
<li>Know Your Audience. Be your Audience</li>
</ul>
<p>Build the App.</p>
<ul>
<li>Think Like a Designer.</li>
<li>Consider the Fold.</li>
<li>Avoid Big Migrations. User entered data can be challenging.</li>
<li>Collaborate.</li>
<li>The Rails Layouts Makes Designers Happy.</li>
<li>Common Rails Collaboration Tools. Subversion, Capistrano, Campfire, Basecamp, Lighthouse.</li>
<li>Don’t Repeat Yourself: Use Plugins. acts_as_authenticated, attachment_fu, acts_as_taggable, exception_notification, open_id_authentication, ymlr4r geocode</li>
<li>Take “Code Vacations”</li>
</ul>
<p>Get Noticed</p>
<ul>
<li>“It’s Google’s World, We Just Live in It.”</li>
<li>Use Smart URLs. /wine/view/5748, /authors/danbenjamn</li>
<li>Leverage Markup. Google reads metatags.</li>
</ul>
<p>Recruit Members</p>
<ul>
<li>Make It Obvious and Easy to Signup</li>
<li>Ask Only for What’s Truly Necessary</li>
<li>Ask for Everything but Require (Almost) Nothing</li>
<li>Limit Non-Members</li>
</ul>
<p>Keep Them Coming Back for More</p>
<ul>
<li>Make Frequent Improvements</li>
<li>Respond Positively to Your Members</li>
<li>Create A Developer Network</li>
<li>Share Your <span class="caps">API</span></li>
<li>Find Good Partners</li>
<li>“If You Do Things Right, People Won’t Know You’ve Done Anything At All.”</li>
<li>Just Ship It</li>
</ul>
<h2>How We Used Apollo and Rails to (start to) Build an Agile Project Management App by Christopher Haupt and Chris Balley</h2>
<p>They are part of Adobe’s Consumer Hosted Applications and Online Services group. They use whatever technology is right for the job, Flex, Rails and dozens of other technologies. They use Scrum and are geographically dispersed teams, in Germany, India, US.</p>
<p>Why Did We Choose Apollo and Rails?</p>
<ul>
<li>Learning Exercise</li>
<li>Offline Support</li>
<li>Maturing Tools</li>
<li>Leverage our Rails Experience</li>
<li>Cross Platform</li>
<li>Installers</li>
</ul>
<p>Why not <span class="caps">AJAX</span>?</p>
<ul>
<li>Offline and Partially Connected</li>
<li>File System Access</li>
<li>Drag and Drop with Native OS</li>
</ul>
<p>Now they are demoing Maptacular, an Apollo applications.</p>
<p>Combining Apollo and Rails: Communication</p>
<ul>
<li>Flash Side
<ul>
<li><span class="caps">AMF</span></li>
<li><span class="caps">SOAP</span></li>
<li><span class="caps">REST</span> <== they used that</li>
</ul></li>
<li><span class="caps">HTML</span> Side
<ul>
<li><span class="caps">AJAX</span> techniques</li>
</ul></li>
<li>Hybrid
<ul>
<li>Ue <span class="caps">DOM</span> bridge to use the one you are comfortable with.</li>
</ul></li>
</ul>
<p>Combining Apollo and Rails: Quirks</p>
<ul>
<li>Flex’isms</li>
<li><span class="caps">RESET</span> can be a pain
<ul>
<li>Use _method hacks for <span class="caps">PUT</span>, <span class="caps">DELETE</span>, <span class="caps">HEAD</span></li>
<li>Pass a body on everything other than <span class="caps">GET</span></li>
</ul></li>
<li>Some <span class="caps">HTTP</span> headers can’t be used, or problematic on a <span class="caps">GET</span></li>
<li><span class="caps">HTTP</span> Status codes not accessible
<ul>
<li>Use URLoader to get <span class="caps">HTTP</span> Status Codes</li>
</ul></li>
<li>dasherize-is-unhealthy-to-your-actionscript-code</li>
<li>Migrating to newer Apollo Builds
<ul>
<li>ApolloApplication .vs. Application (for transparency)</li>
</ul></li>
</ul>
<p>Now they move on to Code Snippets. The sample code can be found on the Apollo Labs.</p>
<ul>
<li>Online/Offline (Event.NETWORK_CHANGE). Notifies if network change but doesn’t tell if network is up or not. Solution: use URLoader to ping the network (they ping google.com)</li>
<li>Video Capture, File IO, Doing your own Chrome</li>
</ul>
<p>Chris now demonstrate some community create applications.</p>RailsConf 2007 - Day 12007-05-17T00:00:00-07:00http://onrails.org/2007/05/17/railsconf-2007-day-1<p>Here we go, RailsConf 2007, has started. It’s bigger than ever, more tracks, more sessions. This is the first day where they provide full or half-day tutorials sessions. I will try to cover the different sessions I will attend so stay tuned.</p>
<p>Today I will attend: “Scaling a Rails Application from the Bottom Up.” and “Harnessing Capistrano.”</p>
<h2><b>Scaling a Rails Application from the Bottom Up. by Jason Hoffman</b></h2>
<p>Jason Hoffman, <span class="caps">CTO</span> of Joyent. Did also form Textdrive.</p>
<p>Six part presentation:</p>
<p>I. Introduction and foundation<br />
II. Where do I put stuff<br />
<span class="caps">III</span>. What stuff?<br />
IV. What do I run on this tuf?<br />
V. What are the patterns of deployment?<br />
VI. Lessons learned</p>
<p>His presentation will answer the following questions:</p>
<ul>
<li>What is a “scalalble” application?</li>
<li>What are some hardware layout?</li>
<li>Where do you get the hardware?</li>
<li>How do you pay for it?</li>
<li>Where do you put?</li>
<li>Who runs it?</li>
<li>How do you watch it?</li>
<li>What do you need relative to an application?</li>
<li>What are the commonalities of scalable web architectures?</li>
<li>What are the unique bottlenecks for Ruby on Rails applications?</li>
<li>What’s the best way to start so you make sure everything scales?</li>
<li>what are to common mistakes?</li>
</ul>
<p>Maybe it’s a little early, or I am not awake, but the talk seems a little slow. But Jason seems to do a good job at describing how the different people (developer, sysadmin, …) see scalability.</p>
<p>Ease of management is on log scale. It’s not just a Rails issue. A $5000 Dell 1850 costs $1850 to power over 3 year.</p>
<p>This is a really good presentation from a point of view of what is involved to build data center. I should have read better the <a href="http://conferences.oreillynet.com/cs/rails2007/view/e_sess/11694">description</a> of the presentation.</p>
<p>So I am going to move over to Thomas Fuchs presentation:</p>
<h2><b>Is JavaScript Overrated? Or: How I Stopped Worrying and Put Prototype and script.aculo.us to Full Use by Thomas Fuchs</b></h2>
<p>I am just tuning in to his presentation and he is showing of how to use selectors with Prototype.</p>
<p><span class="caps">DOM</span> traversal: <br />
<typo:code lang="javascript"><br />
$(‘blech’).previous(‘ul’).down(‘.somesuch’,2)<br />
$(‘homo-sapiens’).descendantOf(‘australopothecus’)</p>
</typo:code>
<p>Element methods:<br />
<typo:code lang="javascript"><br />
$(‘a_div’).update(‘blah’).show().setStyle({opacity:0.5});<br />
$(‘myform’).focusFirstElement();<br />
$(‘person-example’).serialize();<br />
Element.addMethods(‘form’) {<br />
valid: function(element) {<br />
// code to valid form<br />
}<br />
}</p>
</typo:code>
<p>What’s new in Prototype 1.5.1:</p>
<ul>
<li>speedier $$</li>
<li><span class="caps">CSS</span> 3 Selectors</li>
<li>$(‘form’).request()</li>
<li>String .includes .times .toPaddedString(8,2)</li>
<li><span class="caps">JSON</span> support i.e. new Date().toJSON();</li>
<li>$(‘blah’).firstDescendent()</li>
<li>throw $continue deprecated use “return” instead</li>
<li>Safari issues fixed</li>
<li><span class="caps">YAML</span> compatible</li>
</ul>
<p><span class="caps">DOM</span>, Events, Forms, Position:</p>
<ul>
<li>new Element(tagName, attributes);</li>
<li>$(‘blech’).insert(html|object, position)</li>
<li>$(‘blech’).wrap(‘span’);</li>
<li>$(‘country’).setValue(‘AT’);</li>
</ul>
<p>Function.prototype: curry(), wrap(), defer(), delay()<br />
Q: When is the next release of Prototype? <br />
A: When it’s ready.</p>
<p>A 10 minute break now, the Thomas is going to present Scriptaculous Effects.</p>
<p><b><a href="http://script.aculo.us/">script.aculo.us</a></b> adds advanced User Interface interaction to the <span class="caps">DOM</span>. Extracted from Real-World applications. Started with Fluxiom. The two main parts are Visual effects and Drag&Drop. Today we will only look at the Visual Effects. They are other parts such as Autocompleter, In-Place Editor, Slider control, <span class="caps">DOM</span> Builder, and Unit testing. They won’t be more advanced components.</p>
<p>Effects engine: the ideas behind the engine is timeline based animations.</p>
<p>Core Effects:</p>
<ul>
<li>Effect.Move</li>
<li>Effect.Opacity</li>
<li>Effect.Highlight</li>
<li>Effect.ScrollTo</li>
<li>Effect.Morph // 1.7+</li>
<li>Effect.Parallel</li>
</ul>
<p>Based on the Effect.Base.prototype class.<br />
Effect life cycle: intialize(), setup(), update(), finish(). Each frame calls update().</p>
<typo:code lang="javascript">
<p>Effect.DefaultOptions = {<br />
transition: Effect.Transitions.sinoidal,<br />
duration: 1.0,<br />
fps: 100,<br />
sync: false,<br />
from: 0.0,<br />
to: 1.0,<br />
delay: 0.0,<br />
queue: ‘parallel’<br />
}</p>
</typo:code>
<p>Morphing: came out with Scriptaculous 1.7.</p>
<typo:code lang="javascript">
<p>$(‘mydiv’).morph(‘font-size:20px; color:“#abcdef”);<br />
$(’mydiv’).morph(‘warning’); //limited to top level classname</p>
</typo:code>
<p>TimeLines: <br />
<typo:code lang="javascript"><br />
new Effect.Blah(‘element_2’)<br />
new Effect.Blah(‘element_2’, {duration:0.6, delay:0.3});</p>
</typo:code>
<p>You have to be careful with effects created that will run in parallel as the javascript engine are not multi-thread. Better solutions is to use queues:<br />
<typo:code lang="javascript"><br />
new Effect.Blah(‘element_1’, {queue:’end’});<br />
new Effect.Blah(‘element_2’, {queue:’front’});</p>
</typo:code>
<p>and use scope:<br />
<typo:code lang="javascript"><br />
new Effect.Blah(‘element_1’, {queue:{scope:’blech’}});<br />
new Effect.Blah(‘element_2’, {queue:{scope:‘blech’, position:’end’}});<br />
new Effect.Blah(‘element_3’, {queue:’front’});</p>
</typo:code>
<p>Utilities:<br />
<typo:code lang="javascript"><br />
Element.toggle(‘element’, ‘blind’);<br />
Element.tagifyText(element);<br />
Element.multiple(‘element’, Effect.Fade, {speed:0.05});</p>
</typo:code>
<p>Do it yourself: Thomas now shows how to create an Effect programatically.</p>
<p>Future features:</p>
<ul>
<li>Sound without Flash (it’s already in the beta release). Sound.paly(‘sword.mp3’). It uses native sound implementation with Quicktime as fallback.</li>
<li>Adjust to new Prototype features. $(‘blech’).fade(); $(‘blech’).slowlyReveal();</li>
</ul>
<p><b>Part IV: Testing</b></p>
<p>Thomas is flying through testing…</p>
<ul>
<li>assert(true)</li>
<li>assertEqual(expected, actual)</li>
<li>assertEnumEqual(expected, actual)</li>
<li>assertNotEqual(expected, actual)</li>
<li>assertMatch</li>
<li>assertIdentical</li>
<li>assertNotIdentical</li>
<li>assertType</li>
<li>assertRaise</li>
<li>assertRespondTo</li>
<li>assertVisible(element)</li>
<li>assertNotVisible(element)</li>
<li>info(message)</li>
</ul>
<p>Mostly unit testing, but some functional testing is available.<br />
Most assert take a message. I.e. assertXYZ(params, message)</p>
<ul>
<li>wait(milliseconds, method) // should be last statement in test, but can be nested.</li>
<li>rake test:javascripts (browser will popup). Done with the javascript_test plugin. Launches the web server (WEBrick), then controls the browsers (Safari, Firefox, IE), the browser then calls the web server, and list the results (<span class="caps">SUCCESS</span>, <span class="caps">FAILURE</span>, and <span class="caps">ERROR</span>)</li>
</ul>
<p>Resources:</p>
<ul>
<li><a href="http://www.prototypejs.org/">www.prototypejs.org</a></li>
<li><a href="http://wiki.script.aculo.us/scriptaculous/">wiki.script.aculo.us/scriptaculous/</a></li>
<li><a href="http://pragmaticprogrammer.com/titles/cppsu/index.html">Book: Prototype and script.aculo.us by Pragmatic Programmer</a></li>
<li><a href="http://www.manning.com/crane3/">Book: Prototype and Scriptaculous in Action by Manning</a></li>
<li><a href="http://www.oreilly.com/catalog/9780596527440/">Book: Ajax on Rails by O’Reilly</a></li>
</ul>
<h2><b>JRuby talk by Charles Nutter and Thomas Enebo</b></h2>
<p>(note taken by Robert Hall, thanks man!)</p>
<ul>
<li>1.8ish—based on Ruby 1.8.5</li>
<li>Gems 0.9.1 is pre-installed</li>
<li>Partially compiled—about 80% of Ruby code compiles…rest is run in <span class="caps">JIT</span> mode</li>
<li>Ruby 1.8 strings supported. Works with ActiveSupport::MultiByte</li>
<li>Ruby 2.0 String support coming</li>
<li>Most Ruby apps should work on JRuby <br />
—most gems just work<br />
—Red Cloth, Blue Cloth<br />
—Hpricot</li>
<li>Typical Rails commands just work</li>
<li>ports: Mongrel ported, Hpricot ported, RMajick in progress</li>
<li>Ruby thread <span class="caps">API</span> supported<br />
<del>- native-threaded 1 JRuby thread=1 system thread <br />
-</del> supports thread pooling</li>
<li>performance comparable to C Ruby impl<br />
—Rdoc has issues<br />
—<span class="caps">CLI</span> performance slow</li>
<li><span class="caps">JDBC</span> support strong<br />
—mySQL support strong<br />
—some postgres issues<br />
—some Oracle users <br />
—many others</li>
<li>ActiveRecord <span class="caps">JDBC</span></li>
<li>No native extension support</li>
<li>Goldspike—JRuby deployment tool<br />
—Rails plugin for building <span class="caps">WAR</span> files<br />
—app server agnostic <br />
—Can be deployed to Java app server as <span class="caps">WAR</span> file</li>
<li>Deployment— MOngrel supported..some issues (forking, process management doesn’t work)</li>
<li>Access to Java EE features (<span class="caps">JMS</span>, <span class="caps">JPA</span>, <span class="caps">JTA</span>)</li>
<li>Java libraries can be wrapped</li>
<li>Coming soon<br />
—A Grizzly/GlassFish V3 option <br />
—Lightweight, gem-installable like Mongrel<br />
—Concurrency, pooling mulit-app like <span class="caps">WAR</span></li>
<li>Mephisto demo</li>
<li>Main idea—- Ruby as the programming language, Java for the platform and libraries</li>
<li>Best of all worlds <br />
<del>-Ruby or Rails as the appl layer<br />
—Java libraries alone or as ported/wrapped gems<br />
—Java based services</del>-legacy app integration<br />
—The <span class="caps">JVM</span></li>
<li>Acceptable to today’s enterprise<br />
—Java to ‘them’, Ruby to you</li>
<li>Calling Java from Rails demo<br />
—<span class="caps">RSS</span> reader demo..calling Java library from Rails code</li>
<li>Tools—<br />
Textmate, Emacs, Vi(m), notepad<br />
<del>- missing some features<br />
-</del> code competion?<br />
<del>- jump to declaration? <br />
-</del> rename variables?<br />
— popup Rdoc?</li>
<li>Presenters claim Best Ruby <span class="caps">IDE</span> Available is NetBeans (milestone 9)<br />
<del>- code completion <br />
-</del> smart syntax highlightings (for Ruby code, <span class="caps">RHTML</span> files, etc)<br />
— Rdoc support</li>
<li>Demoed a cool Ruby shell like <span class="caps">IRB</span> implemented in Swing..built into NetBeans</li>
<li>Jruby 1.0 almost ready</li>
</ul>
<p><span class="caps">LUNCH</span>: will be back at 1:30pm</p>
<h2><b>Harnessing Capistrano by <a href="http://weblog.jamisbuck.org/">Jamis Buck</a></b></h2>
<p>Jamis will focus Capistrano 2.0 today. Some things will not be backward compatible with Capistrano 1.0.</p>
<p>His slides are online at <a href="http://presentations.jamisbuck.org/railsconf2007/">http://presentations.jamisbuck.org/railsconf2007/</a>.</p>The New SearchCoders Apollo Dashboard2007-05-15T00:00:00-07:00http://onrails.org/2007/05/15/the-new-searchcoders-apollo-dashboard<p><img src="http://onrails.org/files/20070514_searchcodersicons.jpg" border="0" height="172" width="497" alt="20070514_searchcodersicons.jpg" align="" /></p>
<p>The new version of SearchCoders is not just a pretty face, Tom and Robert also worked hard adding quite some neat and useful functionality like chatroom, notes and favorites. Searching is faster than ever. The new Searchcoders.com <a href="http://www.searchcoders.com/flex/">Dashboard</a> is Still the best way to find useful Flex related information on the net.</p>
<p><img src="http://onrails.org/files/20070514_searchcoders.jpg" border="0" height="332" width="320" alt="20070514_searchcoders.jpg" align="" /></p>RubyKagi2007 (日本 Ruby 会議 2007)2007-05-15T00:00:00-07:00http://onrails.org/2007/05/15/rubykagi2007-26085-26412-ruby-20250-35696-2007<p><img src="http://onrails.org/files/20070515_rubykaigilogo.gif" border="0" height="93" width="445" alt="20070515_rubykaigilogo.gif" align="" /></p>
<p>I would love to go once to Japan to attend the (now) RubyKaigi conference. This year won’t work for me…hey Lee, what about next year?</p>
<p>Find more info <a href="http://jp.rubyist.net/RubyKaigi2007/">here (in Japanese)</a> and <a href="http://translate.google.com/translate?u=http%3A%2F%2Fjp.rubyist.net%2FRubyKaigi2007%2F&langpair=ja%7Cen&hl=en&ie=UTF-8&oe=UTF-8&prev=%2Flanguage_tools">here (in Google translated English)</a></p>Sol's RailsConf 2007 picks2007-05-10T00:00:00-07:00http://onrails.org/2007/05/10/sols-railsconf-2007-picks<p>are <a href="http://www.myconfplan.com/users/solo/conferences/RailsConf2007">here</a>. See you in Portland.</p>RailsConf 2007 - Here we come!2007-05-09T00:00:00-07:00http://onrails.org/2007/05/09/railsconf-2007-here-we-come<p>I just completed a first pass at setting my schedule for RailsConf. <br />
<a href="http://myconfplan.com/users/Daniel/conferences/RailsConf2007">Check it out</a> at MyConfPlan. In any case go check out MyConfPlan which is a pretty cool Rails application.<br />
As usual I am looking forward meeting many of the people I have met last year. Also if you are from Switzerland and doing Rails work, try to hunt me down, I would love to talk to you. It’s also fun that we are going to meet <a href="http://pea2.com">Kirk</a> again, and “old” mate from Denver that is now leaving in Portland.</p>Lee's RailsConfPlan at MyConfPlan2007-05-09T00:00:00-07:00http://onrails.org/2007/05/09/lees-railsconfplan-at-myconfplan<p>Following <a href="http://onrails.org/articles/2007/05/09/railsconf-2007-here-we-come">Daniel’s</a> lead, here are the <a href="http://myconfplan.com/users/lmarlow/conferences/RailsConf2007">talks</a> that I’m thinking of attending. So far I only looked at the titles of the talks, I’m sure I’ll do some switching once I look at them more in depth. Anyway, if you decide to look Daniel up while you’re there, you might want to look me up too, so I can translate his Swiss accent for you.<br /><br /><a href="http://www.biego.com/">Chris</a>, <a href="http://www.gatelys.com/">Sol</a> and <a href="http://nicholaswright.org/blog/">Nick</a>… tag… your turn.<br /></p>Forgot Password?2007-05-09T00:00:00-07:00http://onrails.org/2007/05/09/forgot-password<p>I did it again…forgot my password. Now if everyone could offer an openid login like <a href="http://www.highrisehq.com/">Highrise</a>. This time it happened on <a href="http://myconfplan.com/">myconfplan</a>, while I was organizing my schedule for next weeks RailsConf. As I didn’t find a link to reset the password on myconfplan, I send an email to their support. <a href="http://drnicwilliams.com">Dr Nic</a> replied promptly and said he didn’t implement this yet on this wedsite, but he could manually reset the password. Well, recently I implemented that feature for MySpyder.net (one of our forthcoming web applications). So I send him some code snippets. Not sure if <a href="http://drnicwilliams.com">Dr Nic</a> will use them, but maybe some of our blog readers may be interested, so here we go.</p>
<p>They are several ways to implement a "Forgot Password? This time we choose to send out a “reset password” link that is valid for 24 hours. This link lets the user login, bypassing the standard login, and showing the change password screen.</p>
<h3>First lets add a migration.</h3>
<typo:code lang="ruby" title="Migration">
<p>class ForgotPassword < ActiveRecord::Migration<br />
def self.up<br />
add_column :users, :reset_password_code, :string<br />
add_column :users, :reset_password_code_until, :datetime<br />
end</p>
def self.down
remove_column :users, :reset_password_code
remove_column :users, :reset_password_code_until
end
<p>end</p>
</typo:code>
<h3>“Forgot password” form.</h3>
<p>Then add a “forgot password” form, allowing the user to submit the email to which the “reset password” link will be emailed. When the form is submitted, the controller creates a ‘reset password code’ that is valid for one day, and sends an email to the user.</p>
<typo:code lang="ruby" title="UserController#forgot_password">
def forgot_password
user = User.find_by_email(params[:email])
if (user)
user.reset_password_code_until = 1.day.from_now
user.reset_password_code = Digest::SHA1.hexdigest( “#{user.email}#{Time.now.to_s.split(//).sort_by {rand}.join}” )
user.save!
UserNotifier.deliver_forgot_password(user)
render :xml => “<errors><info>Reset Password link emailed to #{user.email}.</info></errors>”
else
render :xml => “<errors><error>User not found: #{params[:email]}</error></errors>”
end
end
</typo:code>
<h3>Send email with the ‘reset password’ link.</h3>
<p>When the user receives the “reset password” email and clicks the link to reset the password, the reset_password method is invoked on the controller. The user associated with the “reset_code” is found, and if the the reset_code is not yet expired the user is automatically logged-in and redirected to the account page where he can change his password. Note that by adding an expiration attribute for the code, we don’t need to run a cleanup batch process to invalidate these codes. Not in the following code we redirect to a “.swf” file. This was an early experiment where the user interface of the application was written in Flex. We are currently rewriting it to use a more traditional html and css approach.</p>
<typo:code lang="ruby" title="UserController#reset_password">
def reset_password
user = User.find_by_reset_password_code(params[:reset_code])
self.current_user = user if user && user.reset_password_code_until && Time.now < user.reset_password_code_until
redirect_to logged_in? ? “/MySpyder.swf?a=account” : “/MySpyder.swf?a=login”
end
</typo:code>
<p>The email is simply send using the following ActionMailer.</p>
<typo:code lang="ruby" title="UserNotifier">
<p>class UserNotifier < ActionMailer::Base<br />
def forgot_password(user)<br />
setup_email(user)<br />
@subject += ‘MySpyder.net – Reset Password’ <br />
@body[:url] = “http://myspyder.net/reset_password/#{user.reset_password_code}”<br />
end</p>
protected
def setup_email(user)
@recipients = “#{user.email}”
<code>from = "admin</code>myspyder.net"
@subject = "[myspyder.net] "
@sent_on = Time.now
@body[:user] = user
end
<p>end</p>
</typo:code>
<p>And the view for the UserNotifier is the following</p>
<typo:code lang="ruby" title="forgot_password.erb">
<p><%= @user.email %>,</p>
<p>You can reset your password by using the following link <%= @url %></p>
<p>Thank your for using MySpyder.net</p>
</typo:code>TextMate filetype detection for script/runner Rails scripts2007-04-20T00:00:00-07:00http://onrails.org/2007/04/20/textmate-filetype-detection-for-script-runner-rails-scripts<p>So you’re building some righteous automation for your killer web 2.0 app, placing scripts in <code>RAILS_ROOT/script</code> that you can call from cron for nightly maintenance, etc. To bootstrap your rails environment, you decide to use the shebang feature of script/runner, available since <a href="http://dev.rubyonrails.org/changeset/5189">changeset 5189</a>. When you start to edit the script in TextMate (you <strong>are</strong> using TextMate, aren’t you?) there is no syntax highlighting to be found! It’s all plain text with no colors, and none of your ever-so-helpful keyboard macros work! Frightful. Well, take a deep breath, because together, we’re going to get the filetype detection magic working for you.</p>
<p>Before we get started, it’s helpful to know how filetype detection works. TextMate does a couple of different types of filetype detection — the first is based off of the extension, so if you named your script with a <code>.rb</code> extension, you are probably wondering what in the world I’m rambling about. Dude. It just works.</p>
<p>However, if you followed the rails convention for scripts, and did not use an extension with your filename, keep reading. The second type of detection works by scanning the so called “shebang” line at the top of the script which tells the shell (and in this case TextMate) which interpreter to use to evaluate your script — this is how we will tell TextMate that script/runner really means ruby.</p>
<p>First of all, you’ll need to fire up the Bundle Editor and select “Languages” from the drop-down filter. Expand the “Rails” node, and then select the “Ruby on Rails” language. On the right side, you should see the definition being used by TextMate to detect the Ruby on Rails scope. If you have not modified your bundle, you’ll probably see that it is using a <code>fileTypes</code> to look for <code>.rxml</code> files. This is where we want to insert the following line:</p>
<p>@ firstLineMatch = ‘^#!.*(script/runner)’;@</p>
<p>Here’s a screenshot of what it should look like when you are done:<br />
<img src="http://onrails.org/files/BundleEditor-ROR.gif" alt="" /></p>
<p>Now go back to your script and enjoy all the colorized, scope-aware editing goodness that is TextMate!</p>Updated Rake Command Completion2007-04-11T00:00:00-07:00http://onrails.org/2007/04/11/updated-rake-command-completion<p>Here’s another update to a <a href="http://onrails.org/articles/2006/11/17/rake-command-completion-using-rake">previous post</a>.<br /><br /><ol><li>A bug was fixed that caused the first task to be omitted from the task list.</li><li>A new feature was added to allow rake not to be the first command on the command line. Now you get completion for both rakes in the following command: <typo:code>rake db:migrate <span class="caps">VERSION</span>=0 && rake db:migrate</typo:code><br /></li><li>Another feature for quicker rake command completion development, <sarcasm>a feature everyone has been waiting for</sarcasm>. This feature just adds the rake completion script itself to the cache dependency list, so the cache will be refreshed while you are playing with the command completion script. This should make tweaking the script much easier in the future.</li></ol>As always, <a href="http://onrails.org/files/rake-completion.rb">enjoy</a>.<br /></p>Web Snapshot - a simple Apollo Application.2007-04-05T00:00:00-07:00http://onrails.org/2007/04/05/web-snapshot-a-simple-apollo-application<p>This simple Apollo Application takes 200×150 thumbnails of a Web page.</p>
<p><b><a href="http://onrails.org/articles/2007/06/13/websnapshot-a-simple-adobe-air-application"><span class="caps">UPDATE</span>: See Web Snapshot – a simple Adobe <span class="caps">AIR</span> application</a><b/><br />
<div style="overflow:hidden"><br />
<img src="http://onrails.org/files/20070404_WebSnapshot.jpg" border="0" height="268" width="586" alt="20070404_WebSnapshot.jpg" /></p>
</div>
<p>1) Enter the <span class="caps">URL</span> of the page you want to “Snap”.<br />
2) Click the Thumbnail <br />
3) A file dialog opens and asks for the File to save.</p>
<p>Download it now: <a href="http://onrails.org/files/WebSnapshot0.1.air">WebSnapshot0.1.air</a> (right click and ‘Download Linked File’)</p>
<p>It uses the new HTMLControl that Apollo provides, which behind the scene is a full fledged web browser based on <span class="caps">KTHML</span>. Check out an extract of the source code:</p>
<typo:code>
<p>//1. Load the page (asynchronously)<br />
var html:HTMLControl = new HTMLControl();<br />
html.width = 400;<br />
html.height = 300;<br />
html.load(new URLRequest(url));</p>
<p>//2. Draw and scale the rendered html into a bitmap<br />
var snapshot:BitmapData = new BitmapData(200, 150); <br />
var matrix:Matrix = new Matrix();<br />
var scaleX:Number = 0.5;<br />
var scaleY:Number = 0.5;<br />
matrix.scale(scaleX, scaleY);<br />
snapshot.draw(htmlContent, matrix);</p>
<p>//3. Save as <span class="caps">JPEG</span><br />
var jpegEnc:JPEGEncoder = new JPEGEncoder(75); <br />
var jpegData:ByteArray = jpegEnc.encode(snapshot); <br />
var stream:FileStream = new FileStream() <br />
stream.open(file, FileMode.<span class="caps">WRITE</span>); <br />
stream.writeBytes(jpegData);<br />
stream.close();</p>
</typo:code>
<p>I found the JPEGEncoder <a href="See http://www.kaourantin.net/2005/10/more-fun-with-image-formats-in-as3.html">here</a>.</p>
<p>And Daniel Dura had a <a href="http://www.danieldura.com/archive/apollo-native-file-dialogs#more-182">trick</a> to use a native save windows.</p>
<p>Note I need to try this application on Windows…I’ll do that tomorrow.</p>
<p>Enjoy!<br />
Daniel</p>
<p><b>Update:</b>I quickly tried on Windows XP and the save doesn’t seem to work. Let me know how it works for you. Thanks.</p>
<p><b><a href="http://onrails.org/articles/2007/06/13/websnapshot-a-simple-adobe-air-application"><span class="caps">UPDATE</span>: See Web Snapshot – a simple Adobe <span class="caps">AIR</span> application</a><b/></p>RailsLogVisualizer meets Apollo.2007-03-29T00:00:00-07:00http://onrails.org/2007/03/29/railslogvisualizer-meets-apollo<p><img src="http://onrails.org/files/20070328RailsLogVisualizerLogo.gif" border="0" height="80" width="79" alt="20070328RailsLogVisualizerLogo.gif" align="right" />It’s not complete yet, but for the curious out there, here is a first and “ruff” version of the RailsLogVisualizer as a pure Apollo application. The previous version was an <span class="caps">OSX</span> application that was embedding a Ruby http server that was used to load the Rails log files, as a Flex application didn’t provide a mean to load files directly. Here comes Apollo and lifts that restriction. So I thought…let’s try to rewrite the file loading in Actionscript. Well this is my first attempt, during the port I broke a couple of features that will need more attention in the future. Also I haven’t tried to load any file bigger than 40Mb. And I haven’t implemeted the incremental loading of large files that I had with the Ruby version. Also the keyboard navigation isn’t working…so just use the mouse for now. That’s the next thing I’ll need to fix. Let me know what you find at daniel@onrails.org or just add some comments on this entry.</p>
<p>Things that broke during the port:</p>
<ul>
<li>Hourly breakdown of daily request.</li>
<li>Breakdown ofHttp methods (Get, post, delete, head).</li>
</ul>
<p>Things I’ll need to add next:</p>
<ul>
<li>Improve progress indicator during file load and data parsing.</li>
<li>Refactor interaction to allow keyboard support (basically rewrite using Cairngorm).</li>
<li>Improve the File Browser.</li>
<li>Support for RESTFull controllers (detect <em>method parameters (i.e. ?</em>method=put)).</li>
<li>Add chart of action over time.</li>
</ul>
<p>How to install:</p>
<p>1) If you haven’t yet downloaded the Apollo Runtime, get it here: <a href="http://labs.adobe.com/downloads/apolloruntime.html">Apollo runtime (8Mb)</a>.</p>
<p>2) Download the Rails Log Visualizer:<br />
<a href="http://onrails.org/files/RailsLogVisualizer0.4.air">RailsLogVisualizer0.4.air (480Kb)</a> (right click and ‘Download Linked File’). On a side note don’t click directly as the mime type on this server for .air files is not yet set. For more info see Mike Chambers <a href="http://weblogs.macromedia.com/mesh/archives/2007/03/setting_the_mim.html">entry</a> on the subject.</p>
<p>3) Follow the installation steps that Apollo provides. It’s a little strange at first as they have a custom installer.</p>Apple TV on my TV2007-03-24T00:00:00-07:00http://onrails.org/2007/03/24/apple-tv-on-my-tv<p>I picked up my Apple TV today from Fedex since I wasn’t expecting the delivery a day early. It is quite a good looking device, both physically and what it puts on the screen. The little remote might bother me a little as I’ve come to expect more from remotes since I got my Logitech Harmony remote. I wonder if Apple has included discrete codes in the device, so I can setup a macro on my remote that will turn on my receiver and start shuffling through my music. I don’t want to have to turn on my TV every time I want to listen to music.<br /><br />Anyway, time to play with it will have to wait since the Sweet 16 is on.<br /><br /><b>Update:</b> Well, 2 things I was hoping to do with the Apple TV don’t seem possible. I wanted to be able to control my music playing on the Apple TV from my laptop from anywhere in the house. The 2 ways I was thinking that would work would be by having it show up as remote speakers in iTunes for playing my local iTunes stuff, a la AirTunes, or by actually selecting the media that are on the Apple TV from the iTunes devices interface. Neither of these work. Is this a deal-breaker for me? I’m not sure yet, but playing music through my stereo without the TV on was one of the things I was expecting from the Apple TV.<br />
<br /><br /><b>Update 2:</b> So far I’ve mainly been using it for listening to music and it sounds fine, I just shut the TV off once the music starts. I don’t think it sounds better than my Archos Recorder v1 from 2002 running <a href="http://www.rockbox.org/twiki/bin/view/Main/DeviceChart">Rockbox</a> through S/<span class="caps">PDIF</span>, but the UI is nicer looking. The only video I’ve watched so far was from <a href="http://www.themerlinshow.com/">The Merlin Show</a> in hi-res, and it looked ok, better than SD but not as good as HD. I was able to hook up my Harmony remote to work reasonably well, but still discrete codes for playlists or something would make things better. These <a href="http://www.livingwithmac.com/apple-tv-and-harmony-remote">instructions</a> helped get things setup with the remote. The slide shows are nice and look great, I think they are my wife’s favorite feature so far.<br /></p>Searchcoders.com - the fastest way to search the Flexcoders group.2007-03-22T00:00:00-07:00http://onrails.org/2007/03/22/searchcoders-com-the-fastest-way-to-search-flexcoders-com<p>Tom and Robert just announced that <a href="http://www.searchcoders.com/flex/">Searchcoders.com</a> went live. I had the chance to have met Tom and Robert at the 360flex conference and they gave me access to the beta of searchcoders.com. I have used google, the yahoo groups and several other means before to search through all the messages of the <a href="http://tech.groups.yahoo.com/group/flexcoders">flexcoders group</a>, and searchcoders.com just works the best for me. This group just has so much great content and is the fastest way to solve many of the issues you may <br />
encounter once you start pushing what Flex has to offer. Thank to the community of sharing all this info and thanks to Searchcoders to make it more valuable and more accessible.</p>Best way to reset a form using Cairngorm?2007-03-16T00:00:00-07:00http://onrails.org/2007/03/16/best-way-to-reset-a-form-using-cairngorm<p>I just implemented some code that doesn’t feel quite right, but works and would like your input on the matter. A Payment Entry form will be used by the user several times in the life of a Flex application to enter different type of payments. So every time the user wants to pay, the form needs to cleared. I can see these different ways:</p>
<p>1. Ask the form to clear all it’s fields</p>
<p>2. Bind the fields to a model, and reset the model with the default fields values</p>
<p>3. Create a new instance of the form.</p>
<p>It’s a rather complex form with multiple steps (tabs) and the user can quit the form at any moment. So option 1 and 2 needs to reset not only the fields but also the state of each component used on the form. Therefore I opted for approach three which goes as follows:</p>
<p>The view contains following code that replaces the form with a new instance:</p>
<typo:code>
<p>public function clearPaymentInformation():void {<br />
var index:Number = content.getChildIndex(enterPaymentView);<br />
content.removeChild(enterPaymentView);<br />
enterPaymentView = new EnterPaymentInformation()<br />
content.addChildAt(enterPaymentView, index);<br />
}</p>
</typo:code>
<p>Now we have a PayInvoiceCommand that needs to invoke this function. That’s where what doesn’t feel right as the command has to know the view. With the newer version of Cairngorm the command gets information using a delegate, then updates the model. The view is bound to the model. But the command shouldn’t have to know the view. But for option 3 I didn’t find another way around. So I use an adapted version of the ViewLocator (as my view are not ViewHelpers) to which I register the view upon creation. Then in the command I use <br />
<typo:code><br />
WebComponentsViewLocator.getInstance().getView(“paymentView”).clearPaymentInformation();<br />
model.paymentViewState = WebComponentsModelLocator.PAYMENT_VIEW_STATE_ENTER_PAYMENT;</p>
</typo:code>
<p>Is there anyone out there that uses the same approach. If no, thats maybe a good answer that I am on the wrong track. Maybe I should issue an event from the command and have the view listen to the event. This would decouple both, but still doesn’t feel quite right. Maybe I just had a too long day. So any insight is welcome on how you deal with “reseting” forms in your Cairgorm applications. Thanks in advance.</p>
<p>Time for MotorStorm!</p>Apple TV ships March 20th?2007-03-09T00:00:00-08:00http://onrails.org/2007/03/09/apple-tv-ships-march-20th<p>I just checked my order for an Apple TV that was placed on January 10th. It now says “Ships by: Mar 20” and “Delivers by: Mar 26”<br /></p>FlexBook2007-03-07T00:00:00-08:00http://onrails.org/2007/03/07/flexbook<p><img src="http://onrails.org/files/20070306_FlexBook1.jpg" border="0" height="160" width="246" alt="20070306_FlexBook1.jpg" /><br />
<img src="http://onrails.org/files/20070306_FlexBook2.jpg" border="0" height="249" width="310" alt="20070306_FlexBook2.jpg" align="right" /></p>
<p>This is the most amazing example of a Flex component I saw. I missed the ‘Making Components’ at the 360Flex conference in favor of the E4X talk. But thankfully the E4X talk finished early and left me 15 minutes seeing the end of the Making Components talk…and I was blown away. Ely Greenfield presented how he created the FlexBook component and presented some of the important concepts behind it. I know Flex is powerful but I didn’t realize you can achieve what Ely did, so maybe this is just the start. So check out these two examples to get a fell what your browser can do for you:</p>
<p>http://demo.quietlyscheming.com/book/app.html<br />
http://demo.quietlyscheming.com/book/Anatomy.html</p>
<p>Ely also showed some Apollo application that implements paged browsing…Like Firefox on steroids!!.</p>360Flex - Day three2007-03-07T00:00:00-08:00http://onrails.org/2007/03/07/360flex-day-three-live-update<p>08:30am <strong>Last day’s Keynote by Ted Patrick</strong></p>
<p>Tom Hobbs from the Experience Design group of Adobe presents how they developed the <a href="http://www.amgentourofcalifornia.com/docroot/tourtracker2/index.html">Tour Tracker</a> a complex application tracking a cycling race with gps locations of the racers, links to Flickr feeds of the photo, video. It was done by 3 people in 6 weeks. Tom goes in detail through the iterative development they used, the team started building upfront and gradually added complexity. He presented the values the team where using to reach a great design. Great talk.</p>
<p><img src="http://onrails.org/files/20070307_TourTracker.gif" border="0" height="152" width="206" alt="20070307_TourTracker.gif" /></p>
<p>And now Ted Patrick on the <strong>“Next Flex”</strong>. He wants to talk about what Adobe and the people using Flex are working on. What he is going to show us may not ship, Adobe tries to be open about what they are working on but may decide not to deliver it or deliver it later. They want to expand the reach of RIAs to include desktop, web and offline applications. They want to make it easier for web and enterprise application developers to learn Flex. They want to invest in the platform to server the needs of enterprises and the Flex ecosystem. They want to be much more Open and transparent, they want to build the next generation of Flex with everyone that is working with it. They are two release of Flex set for this year, Moxie and Borneo. The next generation of Flex will be build on the Flash Player 9. They want to better integrate Flex with CS3 (Flash, Fireworks, Illustrator and Photoshop). He now stops and show the integration with Fireworks. In Fireworks he can drag Flex components on a <strong>Fireworks</strong> image. FW implements scale 9. Is building a UI in Fireworks. In FW he can changes the properties of a Flex components. The he can export the image a <span class="caps">MXML</span> and images. Now a designer can prototype a Flex application without using Flex right from Fireworks. The next piece of the puzzle is <strong>“Borneo”</strong>, the next version of the Flex Data Services. Integrates with LifeCycle. The team has rewritten the mx:WebService to support better <span class="caps">SOAP</span>. <strong>Moxie</strong> is the next version of the Flex <span class="caps">SDK</span> and Flex Builder with improved “Language Intelligence”, integrated Profiler, enhanced Design View, Data integration, enhanced DataGrid and Lists. He now shows a demo of it. FlexBuilder 3 now has a refactor method where a method can be renamed right from it’s use. It has also variable renaming. command-shift-j finds cross class all the uses of a given method/variable. <strong>Flex and Apollo</strong> They are working on a Apollo plugin for Eclipse. Will be release at Apollo camp on March 16th. FlexBuilder will host an Apollo Project. <strong>Flex Ecosystem</strong> Flex is more than Adobe. It’s fantastic. He now shows some examples. <span class="caps">ESRI</span>, the world is not flat! <span class="caps">ESRI</span> created a set of components to allow vector mapping to be included in a Flex app with one or two tabs. Ted now shows a demo of these components. The next demo is from Farata Systems. Their background is from the PowerBuilder days and having lots of fun with Flex. FlexBI (Business Intelligence). He shows a customized data grid and can modify the view and the data to be retrieved. The gird is grouping, sorting and totaling the data. Now onto Flexlib. Darron Schall and Doug McCune published many of their components under the <span class="caps">MIT</span> license on google code. They also created a whole environment to allow the community to contribute. They have put a demo out at http://dougmccune.com/flexlib/keynote/.</p>
<p><img src="http://onrails.org/files/20070307_Flexlib.jpg" border="0" height="152" width="206" alt="20070307_Flexlib.jpg" /></p>
<p>Last thing is <strong>Yahoo</strong>. Yahoo provides open apis to allow 3rd party developers to make their site better. At this conference Yahoo provided the AS3 apis to their different services. <strong>Flex <span class="caps">API</span> Posters</strong> Everyone on the 360Flex mailing list (at the conference or on the waiting list) will get an email and will get the Flex <span class="caps">API</span> poster. <strong>Next 360Flex</strong> Now Ted asks Tom and John who created the conference to come up on stage and he talks about the future of the conference. Tom is asking who would be interested to do another 3 day conference in August. About half of the audience responds. He also asks who would be interested in a one day event in your city, 120Flex, and who if the topics should rather be introduction or advanced. Lots of interest for the one day event and no interest in the beginner sessions. And now three quick announcements from the Ebay team. 1) they are hiring 2) they are holding their developers conference in June 11th-13th in Boston ($350 for 3days) 3) An Ebay Actionscript open source library that is released today. Allows to use ebay easier. (http://adobe.com/go/ebaylibary, will be available shortly). Tom now thanks his team has he wasn’t very productive during this conference. End of Keynote.</p>
<p>11:00am <strong>Model-Driven Integration Strategies by Joe Berkovitz</strong></p>
<p>Modeling: describing software abstractly<br/>
Integration: hooking up disparate components<br/>
Strategy: an overarching approach to a problem<br/>
Model-Driven Integration Strategy: An approach that uses abstract descriptions of drive the hookup of disparate components.<br/></p>
<p>He will mostly talk about transformation tools: Axis, xdoclet, xdoclets2, <span class="caps">XSLT</span>. He will not talk about these tools directly but about <a href="http://www.blackbento.com/hamachi/">Hamachi</a>, a generator generator. Hamachi can generate Value Object, and Cairngorm classes. Hamachi use a language neutral <span class="caps">XML</span> format. All right…I am out of this talk. If I need Hamachi I will look it up, but some guys from Adobe are about to publish a FlexBuilder plugin for Cairngorm, that’s all I would need for now.</p>
<p>05:10pm Ok it’s a wrap. I am at the airport on my way back to Denver and a little dazzled. Lot’s of Flex during the last three days. But I must admit that the Flex team created an awesome platform that showed it’s potential during this conference. It’s gonna be the year of Flex and many companies at the conference (Yahoo, Allurent, Ebay, Adobe, Userplane and others) where looking for people willing to dive into Flex. There will more Flex applications developed this year than ever before. So keep an eye open for Flex. For me it’s gonna be back to consulting work tomorrow and I have a big Flex project to “finish” for the end of the month. So I may not have time to play with all the cool new stuff I learned. I hope you enjoyed my attempt of live coverage of the event. Have fun!</p>Mapping Rails Errors to Flex Fields.2007-03-06T00:00:00-08:00http://onrails.org/2007/03/06/mapping-rails-errors-to-flex-fields<p><img src="http://onrails.org/files/20070306_signup_errors.jpg" border="0" height="164" width="528" alt="20070306_signup_errors.jpg" align="center" /></p>
<p>We extended the <a href="wheelerstreet">com.wheelerstreet.utils.ValidatorForm</a> to add support for Rails Errors. Saving a form is a two step process. First, client side validation, the Signup button only gets enabled if the form is valid from a client side point of view. Step 2, server side validation, the user press the signup button and invokes the Rails UserController#create method</p>
<typo:code>
<p>class UsersController < ApplicationController<br />
def create<br />
@user = User.new(params[:user])<br />
respond_to do |format|<br />
if @user.save<br />
self.current_user = @user<br />
format.xml { head :created }<br />
else<br />
format.xml { render :xml => @user.errors.to_xml(:dasherize => false) } end<br />
end<br />
end<br />
end</p>
</typo:code>
<p>If saving the user fails then Rails return the xml version of the errors:</p>
<typo:code>
<p>@user.errors.to_xml(:dasherize => false)</p>
</typo:code>
<p>Now we need a generic way to deal with these errors. We created the Flex RailsErrors class to manage the returned xml. And we created the RailsValidationForm that extends the com.wheelerstreet.utils.ValidatorForm. The RailsValidationForm class can be bound to a RailsErrors instance. So the result handler of the Flex Cairngorm Flex SignupCommand we just set the errors on the model locatorL</p>
<typo:code>
<p>var errors:RailsErrors = new RailsErrors(data.result as <span class="caps">XML</span>);<br />
MySpyderModelLocator.getInstance().signupErrors = errors;</p>
</typo:code>
<p>The signup.mxml page contains the following signup form</p>
<typo:code>
<mx:Canvas
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:rails="org.onrails.rails.*"
>
<mx:Panel x="162" y="64" title="Signup - Your Account Details.">
<!-- Instance of org.onrails.rails.RailsValidationForm -->
<rails:RailsValidationForm
id="submitForm"
defaultButton="{signupButton}"
validators="{validators}"
fieldMap=""
railsErrors="{MySpyderModelLocator.getInstance().signupErrors}"
x="98" y="89">
<mx:FormItem label="email">
<mx:TextInput id="email" />
</mx:FormItem>
<mx:FormItem label="Password">
<mx:TextInput id="password" displayAsPassword="true" />
</mx:FormItem>
<mx:FormItem label="Confirmation">
<mx:TextInput id="passwordConfirmation" displayAsPassword="true" />
</mx:FormItem>
<mx:Button id="signupButton" label="Signup >>" click="signup()" enabled="{MySpyderModelLocator.getInstance().signupButtonEnabled}"/>
</rails:RailsValidationForm>
</mx:Panel>
<rails:RailsErrorBox x="487" y="64" width="301" height="178"
errorMessage="errors prohibited this new account to be created"
errors="{MySpyderModelLocator.getInstance().signupErrors}"
visible="{MySpyderModelLocator.getInstance().signupErrors && MySpyderModelLocator.getInstance().signupErrors.hasErrors()}"
/>
</mx:Canvas>
</typo:code>
<p>The RailsErrorBox just displays the text of all error messages and is only visible if there are any Rails errors.</p>
<p>Now all the magic happens in the org.onrails.rails.RailsValidationForm railsErrors setter.</p>
<typo:code>
<p>public function set railsErrors(errors:RailsErrors):void {<br />
<em>railsErrors = errors;<br />
if (_railsErrors==null || !</em>railsErrors.hasErrors()) {<br />
resetErrors();<br />
} else {<br />
for each (var field:String in <em>railsErrors.fields) {<br />
if (</em>fieldMap[field]) <br />
_fieldMap[field].errorString = field + ’ ’ + _railsErrors.getFieldErrors(field).join(’, ’);<br />
} <br />
}<br />
}</p>
</typo:code>
<p>The key is to associate the Rails error message with the field is simply to set the errorString on the field.</p>
<p>I just created this code this morning at breakfast so it’s really a work in progress. For instance it doesn’t support Rails attributes that are more than one word. But this goes hand in hand with the ActiveResourceClient and can be useful I hope to others trying to integrate Rails and Flex. So we will create a Google project and post the RailsErrors and RailsValidationForm.</p>360Flex - Day two2007-03-06T00:00:00-08:00http://onrails.org/2007/03/06/360flex-day-two-live-update<p>All right, here we go again.</p>
<p>08:30am <strong>Flex Data Services by Jason Williams</strong> <span class="caps">FDS</span> is a J2EE Application that provides data synchronization between a client and a server. Provides Messaging, <span class="caps">RPC</span> Services and Data Management. All these services use service adapters on the server to get the job done. All the other services are build on top of Messaging. Jason goes through the various ways to configure these services, way to much data to blog about. Jason will post his slides online. I will point to them as soon as I gound out.</p>
<p>10:00am <strong>Flex Builder Secrets by David Zuckerman</strong> Change in plan, I won’t attend the Modules presentation as I played with Module last week and it works pretty well. So Let’s see if there are some good FlexBuilder secrets out there. If not that will give me some time to play with handling Rails Errors from Flex. I’ll blog about that shortly. David will briefly show some editing features, the will dive into hacking FlexBuilder, hacking the property inspector and use the APIs exposed by FlexBuilder. David is part of the FlexBuilder development team and is currently working on ‘Find all references’ and Refactoring support.</p>
<table>
<tr>
<td>apple-shirt-t </td>
<td> Open Type</td>
</tr>
<tr>
<td>apple </td>
<td> Turns an identifier into a ‘navigate to’ link</td>
</tr>
<tr>
<td>ctrl-o </td>
<td> Outline view </td>
</tr>
</table>
<p>David mentions’ that everything he shows now is at our risks and can damage the installation. He shows or the color syntax settings can be modified. There are defined in the Colors.xml file inside of a .jar file that is part of an eclipse plugin. Note sure that I want to mess with that stuff. Graphical Property Inspector. You can create your own customer common property inspector. This inspector is defined by by an xml file. David nows describe how to extend FlexBuilder using java. I guess that these notes won’t be to useful, so hopefully he will provide his slides.</p>
<p>01:00pm <strong><span class="caps">MXML</span> vs. AS3 by Ted Patrick</strong> His goal is that we understand <span class="caps">MXML</span> as a medium to write applications. Apparently I am the trouble maker for the bad sound with the mikes that the presenters experienced since the beginning of the conference..as my <span class="caps">EDVO</span> card may interferer with their microphones. So I will start taking notes offline and post them here after the talks are over. <span class="caps">MXML</span> gets translated to AS3, so it’s the same. <span class="caps">MXML</span> Tags are instances of AS3 classes. 100% compatible, 100% the same. To see how the translation work use the compiler flag -keep-generated-actionscript. Best way to understand inner workings and what’s going behind the scenes.</p>
<p>02:30pm <strong>E4X by Danny Patterson</strong> Danny co-authored the ActionScript 3 with Design Patterns book. He described the new <span class="caps">XML</span> related classes and showed examples for each of them: . <span class="caps">XML</span>, XMLList, QName, Namespace.</p>
<p>Filtering:</p>
<p>catalog.product.(price < 50).name,</p>
<p>or using a variable</p>
<p>var findPrice =50;<br />
catalog.product.(price < findPrice).name</p>
<p>Chained Filter:</p>
<p>catalog.product..(name.toString().length >0).(price < 50).name</p>
<p>Namespaces</p>
<typo:code>
<p>//xmlns<br />
var envelop = <soap:envelop xmlns:soap="{uri}" /><br />
envelop.body = </p>
</typo:code>
<p>04:00pm <strong>Flex and Flash Together by Jesse Warden</strong> Jesse goes fast through lots of material. <strong>Call Flash from Flex directly</strong> But he shows how to load a swf file using the SWFLoader into flex, cast the loader.content to the interface you would to use, then then Flex can call the methods you want on the Flash movie.. You can do that today with the Actionscript 3 plugin for Flash 8. <strong>addFrameScript</strong> addFrameScript(39, stop)…show a way to load dynamically code inside you application by using Embed…he uses this to build a nice Flash components that can be used straight from Flex. He makes a compelling case of using Flex and Flash together.</p>360Flex - Day one.2007-03-05T00:00:00-08:00http://onrails.org/2007/03/05/360flex-day-one-live-update<p>08:00am sitting at the Denny’s down of the Ebay conference center where the 360Flex Conference is starting. There seems to be a already a large coverage in the blog community of the 360flex conference…so I’ll be rather brief and just provide what strikes me at each of the presentation I will attend. I will update this blog entry as the conference moves on.</p>
<p>I am currently making up my mind as to which talk to attend here after is a first pass at my list.</p>
<p>08:10 All right I am at the conference. Pretty well organized the facilities and the conference room is pretty impressive…and they have Starbucks coffee. The room is mostly already full.</p>
<p><strong>Day 1</strong></p>
<p>08:30am <strong>Keynote: The Magic of Flex by Mark Anders</strong> <br />
1st Flex specific conference. Mark asks how many are Flash developers in the audience. It’s the minority, about 30 hands raised. Flex is the way to create Flash stuff in a developer friendly way. <strong><span class="caps">MXML</span></strong> Mark shows some <span class="caps">SVG</span> components and demonstrates how <span class="caps">MXML</span> ties in with Actionscript classes. <strong>Databinding</strong> He demonstrates databinding to change the gradients of an svg components without coding using. His Microsoft ghost is chasing him…his Mac froze and is now rebooting. He blames it on Powerpoint that runs Rosetta. <strong>Composition</strong> New controls can be build by composing other controls. Mark show several components that different people created such as the <a href="http://demo.quietlyscheming.com/fisheye/index.html">fisheye</a> component and an <a href="http://dougmccune.com/flex/awesomerss2/">cool RSSReader</a> that smokes. <strong>States</strong> allowing to build liquid interface declaratively. He demonstrate in FlexBuilder how to create a little Flickr Browser that has two states, the search state that just shows the search box and the result state that also displays the results. <strong>It’s Flash!</strong> Flex is powerful thanks to the underlying Flash engine. He demonstrates some Flex application that use the full power of Flash: <a href="http://picnik.com/">Picnik</a> and Buzzword from Virtual Ubiquity. <strong>ActionScript 3</strong> He now starts the new version of the Flash <span class="caps">IDE</span> and show a “Ring of Fire” rendering application and compares the AS3 and AS3 application…the crowd claps as it shows off fast AS3 is. <strong>An Exciting Future</strong> He invites Mike Downey on stage to show Apollo. Mike will show the new things you can do with Flex using Apollo to build cross-operating system applications that can do things like accessing the local files, run online/offlie, full drag-and-drop between the Desktop and the application, clipboard access and more…Mike shows Buzzword as an Apollo application. He shows gTimer, an Apollo time tracking application written by Grant Skinner. He goes on to show Maptacular which overlays a Flex app with Google Maps. The last app shown is Scout, written by Christian Cantrell that is an Html inspector ala Firebug. <strong>Flex 3</strong> Mark is now back on stage and is talking about what they are working on with Flex 3. Designer/developer workflow. Make it easier to integrate Flex with existing services and enabling richer data display and manipulation (live data). Building Apollo applications from FlexBuilder and embed Html (real browser) in a Flex application. Increase developer productivity. Timeline: First half 2007 will see the release of public labs release of Apollo and Flex 3 (“Moxie”). In the second half the first version of Apollo and Flex 3 will be release. That’s it!</p>
<p>08:55am <strong>Apollo APIs by Christian Cantrell</strong> He writes Apollo application as Apollo is being developed. Everything he talks about is subject to change. He is writing real-world usage, cool Apollo applications to provide feed back to the Apollo development team. Apollo is based on the Flash Player, and provides Flash, Flex, Javascript and Apollo APIs. <strong>NativeWindow</strong> allows to use native OS windows with Flash, Flesh or <span class="caps">HTML</span> content, supporting full transparency. He is doing all his work from FlexBuilder and will not show some demo applications. HTMLEditor, allows to edit html that shows a system chrome. Lookup application that demonstrate an Apollo window which is a Apollo look and feel chrome that provides it’s own close, maximize buttons and window scrollbars. PixelPerfect that is a pure Actionscript based application that demonstrates a custom chrome which is a transparent ruler application that allows to pixel measure your Desktop. ScreenPlay an application that has no chrome and allows to draw on the desktop and highlight anything on the Desktop. <strong>File System APIs</strong> File extends FileReference. File objects are pointers to files and directories. File APIs can be Synchronous and Asynchronous. Threading is not accessible to the developers. <strong><span class="caps">URL</span> Schemes</strong> file:, app-resource, app-storage:. Two more demos. FileBrowser, that supports full drag and drop file operations. FileComponentTest that allows to view folders in Tree, List or Grid view and is written in 47 lines of <span class="caps">MXML</span> code. <strong>HTMLControl</strong> is a display object than can display <span class="caps">HTML</span>, it’s an embedded browser (without chrome) build using Khtml (WebKit). Has loadString function to load content, adds to the URLRequest class. <strong>Script Bridging</strong> allows scripting between Actionscript and Javascript. References to object can be passed between the two environments. I.e. an Actionscript event can be attached to a Dom object. <strong>The Flex <span class="caps">HTML</span> Components</strong> Allows to add an HTMControl to a Flex container. Some more demos. Scout, the html inspector. He now use the dom tree to select an item on the google home page, then edit it and the changes are directly rendered. Assassin, an application to watch items on Amazon. He want’s to know when Halo 3 is available or when the rating changes. <strong>Shell</strong> provides access to shell or runtime facilities. I.e. when all the windows applications close then developers can decide if the application closes. Or find out which window has the focus, or close the application. <strong>Network Detection</strong> Event.NETWORK_CHANGE event to listen if the application goes online/offline. He mentions an application for Doctors that need to be offline when they do house calls but still need to have access to the application. Apollo will provide a framework around this. The important fact is not wether the application is online or not, but wether the application can access the external services is need. He now shows the <span class="caps">OCD</span> application that uses the ServiceDetector class to listens to the ServiceEvent.SERVICE_AVAILABLE and ServiceEvent.SERVICE_UNAVAILABLE events. <strong>InvokeEvent</strong> tell every time the application is invoked. Provides control to the application what to do when the run is clicked again, some application just will do nothing or bring the application in front, another may open a new tab, another may create a new window. He demos now InvokeTest and PixelPerfect to demonstrate this. A question from the audience was if you can grab pixels from the desktop. Christian mentions that they are no APIs for that and he wasn’t sure why, maybe a security constraint. <strong>Application Update <span class="caps">API</span></strong> to make updating your applications easier. The runtime allows to update the application and restart it from within the application. There is still some code left to be provided (when to update, data migrations). They currently provide a bar minimum framework for this and may build some higher level framework on top of it. <strong>Managing Multiple Displays</strong> currently doesn’t work in the latest build. Screen class. Screen.screens returns an array of Screen objects. Screen.mainScreen returns the primary screen. Screen.visibleBounds allows to properly align the screens. <strong>URLRequest changes</strong> support for arbitrary methods: <span class="caps">GET</span>, <span class="caps">POST</span>, <span class="caps">HEAD</span>, <span class="caps">PUT</span>, etc. Allows more <span class="caps">HTTP</span> header flexibility. <strong>Security</strong> A question from the audience is what about security. The answer is yes, but Christian is not providing details on the model, he just mentions that they are looking into. But he mentions that Apollo allows to write “bad” apps like in other frameworks. They will be more information on that closer to the launch of Apollo. <br />
<strong>Icons</strong> Apollo handle platform independent icon conversion. The minimum is 128×128. <strong>Installation</strong> You need to install the Apollo runtime to deploy an application. So an application cannot be deployed without the run time. <strong>Future Apollo APIs</strong> Menus, Drag&Drop, File extension registration, System notifications. That’s it!. <strong>Q&A</strong> Q:When will it be available? A: Pretty soon. (Someone in the room mentions before the 16th).</p>
<p>02:05pm <strong>Flex loves Flash? Embed and Beyond by <a href="Building Apollo Apps">Grant Skinner</a></strong> He will show us know where we are and let us make the call if Flex loves Flash. The workflow is not well integrated at the tool level for now. <strong>Embed</strong> metatag [Embed(source=…)], compiler directive “@Embed”, style directive upSkin:Embed(source=…). The Flex compiler doesn’t do a great job bringing in <span class="caps">SVG</span> it also drops annimations and as sizing issues. From a workflow point of view the issue is than when importing images into Flex the images cannot be resized and transformed if needed without going back to the original editing tool and re-exporting it. Grant now goes into the details of embed fonts. Flash bitmaps font cannot be embedded. Raw binary data can also be embedded by using mimeType=‘application/octect-stream’. Grant now goes on prepping why using Flash with Flex is a good thing by exploring 6 challenges. <strong>Challenge 1</strong> – Prepping and managing assets isn’t fun in Flex. Embed(source=“mySWF.swf”, symbol=“SymbolName”) to access Flash symbol that are in an Flash library. This allow to centralize all your assets into one Flash file. He now shows an Flash command that allows to generate a Flex class (SimpleAssetLibrary) to provide access to Flex for all the embedded Flash assets. <strong>Challenge 2</strong> Flex doesn’t have a lot of love for designers or their tools. But…Flash 9 has really good support to import Photoshop images. And preserves layers, folder names, vector assets, text and allows to map these assets in different ways. So Flash is a really good intermediary between Flex and Photoshop. <strong>Challenge 3</strong> Flex ain’t so good with fonts. Flash can help out by embedding all the fonts into Flash then using them from Flex. This does allow to use Flash bitmap fonts. It’s not quite straight forward yet as the Flash Font symbol needs to be referred to by using the system generated class name (i.e. Arial_12pt_st). To find out this font names you can iterate over the embedded font returned by Font.enumeratedFonts(false). <strong>Challenge 4</strong> Flex hates Flash ActionScript. It can be done…but I may not quote Grant correctly here. But a swf file can be embedded as an octet-stream, the loaded using a loader and access to the class can then be done using the ApplicationDomain. If we go beyond embed we can get better results by exporting your FlashCS3 application into a .swc file. And Flex can then import and use that .swc file. <strong>Challenge 5</strong> Flex is stuck up. Flex doesn’t love the Flash display symbols. Make it a child of UIComponent or wrap it in a class that extends IUIComponent. He wrote a DisplayObjectWrapper that is a generic solution for this issue. A better approach would we that Flash components developers support the IUIComponent or extend something that does (FlashSymbol, name still to be determined). <strong>Challenge 6</strong> Run-time loading of Flash content. Load Swf into Loader. ApplicationDomain.getReference to get access to the symbol, then wrap into a DisplayObject. It’s tricky to work with Icons and other aspects as an AssetClass needs to be extended. Flash v3 components will work in Flex. See his <a href="http://gskinner.com/blog">blog</a> and <a href="http://gskinner.com/talks/">talk page</a> for more info.</p>
<p>03:30pm <strong>Introduction to Apollo by Mike Chambers</strong>. After a brief introduction of what Apollo is, Mike shows some demo applications. Ascension – a sound visualizer that can load your iTunes library and visualize the playing music, load the album art from Amazon and images from Flickr regarding the album and artist. The Apollo run-time target size is between 5 and 10 Mb. Mike provides an overview of the APIs. He demonstrates now using FlexBuilder how to get started with an Apollo application. All applications start with two files, the main.mxml file that is a Flex application with the mx:ApolloApplication as root component file and an .xml application descriptor file providing additional information on how to build the Apollo application such a system icons to use, the main contain (main.mxml).</p>
<p>04:00pm <strong>Flex Apps Faster with WebORB</strong> – Well it seems that I had some issues with MarsEdit the soft I use writing these entries I lost all the coverage of the WebORB presentation and the last bit of the Apollo presentation. Mark presented the benefits of WebORB over traditional approaches using HttpServices or WebServices by demonstrating some applications which take around 6 seconds to perform 50 remote calls and the sames calls using WebORB take less than 1 seconds. Mark goes on showing the benefits of using WebORB Data Management services that allow to generate much of the plumbing required to interact between Flex and .Net, <span class="caps">PHP</span>, and later on Rub y On Rails.</p>XML Filtering Predicate2007-02-27T00:00:00-08:00http://onrails.org/2007/02/27/xml-filtering-predicate<p>I need to filter some <span class="caps">XML</span> data based on several conditions. I found the following article “”http://www.darronschall.com/weblog/archives/000214.cfm">E4X: Predicate Filtering with Regular Expressions</a>" from Darron that provides a nice overview of filtering using e4x. I haven’t found any more detailed information on using predicates so I checked out the <a href="http://www.ecma-international.org/publications/standards/Ecma-357.htm">ECMAScript for <span class="caps">XML</span> <br />
(E4X) Specification 2nd edition</a>. See page 52 for details. But in short the filter can be an expression and use && and ||, the logical and and or.</p>
<typo:code>
<p>filtered = list.item.( /^4567.<strong>/.test( number ) || /^D.</strong>/.test( name ) ); </typo:code></p>
<p>Here is the full test case:</p>
<typo:code>
<p>package tests.actionscript<br />
{</p>
<p>import flexunit.framework.*;</p>
<p>public class TestXml extends TestCase<br />
{</p>
<p>public function testXMLFiltering():void {<br />
var list:<span class="caps">XML</span> = <list> <br />
<item><br />
<name>Kamesh</name><br />
<number>12345</number></p>
</item>
<item>
<name>Daniel</name>
<number>12345</number>
</item>
<item>
<name>Robin</name>
<number>12345</number>
</item>
<item>
<name>George</name>
<number>4567</number>
</item>
<item>
<name>Adam</name>
<number>4567</number>
</item>
<item>
<name>Dean</name>
<number>4567</number>
<policy>yes</policy>
</item>
</list>
<p>var filtered:XMLList = list.item.( /^D.<strong>/.test( name ) ); Assert.assertEquals(2, new XMLListCollection(filtered).length);<br />
filtered = list.item.( /^4567.</strong>/.test( number ) ); <br />
Assert.assertEquals(3, new XMLListCollection(filtered).length);</p>
<p>filtered = list.item.( /^4567.<strong>/.test( number ) && /^D.</strong>/.test( name ) ); <br />
Assert.assertEquals(1, new XMLListCollection(filtered).length);</p>
<p>filtered = list.item.( /^4567.<strong>/.test( number ) || /^D.</strong>/.test( name ) ); <br />
Assert.assertEquals(4, new XMLListCollection(filtered).length);</p>
<p>}</p>
<p>} // class</p>
<p>} // package</p>
</typo:code>Flex introspection API: describeType(value:*):XML2007-02-24T00:00:00-08:00http://onrails.org/2007/02/24/flex-introspection-api-describetype-value-xml<p>I am playing with the mx.automation framework provided by Flex. For that I need to associate each control with it’s automation implementation. More on that on a subsequent blog entry. But it some case I need to find the super class of a class</p>
<p>Let’s take the following three classes:</p>
<typo:code>
<p>class A {}<br />
class B extends A {}<br />
class Tab extends Button {}</p>
</typo:code>
<p>Now we can create the following function:</p>
<typo:code>
<p>import flash.utils.describeType;<br />
private function superClass(clazz:Class):String {<br />
return describeType(clazz).factory.extendsClass<sup class="footnote" id="fnr0"><a href="#fn0">0</a></sup>.@type;<br />
}</p>
</typo:code>
<p>Let run the following code</p>
<typo:code>
<p>trace(“A super class:”<ins>superClass(A));<br />
trace(“B super class:”</ins>superClass(B));<br />
trace(“Tab super class:”+superClass(Tab));</p>
</typo:code>
<p>And we get the following output:</p>
<typo:code>
<p>A super class:Object<br />
B super class:com.nouvelles_solutions::A<br />
Tab super class:mx.controls::Button</p>
</typo:code>
<p>Let me know if there is an easier way.</p>
<p>The build in <a href="http://livedocs.adobe.com/flex/2/langref/flash/utils/package.html#describeType()">describeType</a> function takes a class as parameter and return an <span class="caps">XML</span> definition of a class. For example describeType(B) returns the following:</p>
<typo:code>
<type name="com.nouvelles_solutions::B" base="Class" isDynamic="true" isFinal="true" isStatic="true">
<extendsClass type="Class"/>
<extendsClass type="Object"/>
<accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
<factory type="com.nouvelles_solutions::B">
<extendsClass type="com.nouvelles_solutions::A"/>
<extendsClass type="Object"/>
<method name="a" declaredBy="com.nouvelles_solutions::B" returnType="void">
<parameter index="1" type="String" optional="false"/>
</method>
</factory>
</type>
</typo:code>
<p>Pretty cool.</p>Cairngorm Generators2007-02-21T00:00:00-08:00http://onrails.org/2007/02/21/cairngorm-generators<p>I looked into <a href="http://labs.adobe.com/wiki/index.php/Cairngorm">Cairngorm</a> a while ago (version 0.95 I believe, pre-ModelLocator area) and didn’t like the fact that you couldn’t use Flex bindings at that time. I recently gave it a second look I liked what I saw. Using Cairngorm is at first very verbose but it provides you with a clear way of organizing your code, which is very beneficial on larger projects. Cairngorm is well documented and there are several nice examples available. Also checkout <a href="http://www.cairngormdocs.org/">http://www.cairngormdocs.org/</a>. So yesterday introduced Cairgorm on two Flex projects I am working on.</p>
<p>The first project is a larger Flex 1.5 project (65 actionscript classes, 75 Data transfer object, >100 Mxml views) that I need to migrate to Flex 2.0. I though “great time to start with Cairngorm”. So the first step was to look at all the user gestures for all the screens and create a list of events, map these events to commands, create 3 delegates and services to handle all the remote calls. On paper that was pretty fast to do, but I didn’t want to create all the Cairngorm supporting class by hand. Handily I found the following generator that is a <span class="caps">PHP</span> application:</p>
<block>
<p><a href="http://www.ericfeminella.com/blog/2007/01/04/introducing-cairngen/">Cairngen</a></p>
</block>
<p><br/>
It targets currently only Cairngorm 2.0 and not the newer Cairngorm 2.1. So after generate the supporting classes I had to manually do some changes. But thanks for this tool.</p>
<p>The second project is a smaller Flex application backed by a Ruby on Rails server. And I found the following Ruby on Rails Cairngorm generators at http://code.google.com/p/cairngorm-rails-generator/</p>
<p>Simply copy the generators to your “/vendor/generators” folder, the generators folder will then contain the following generators:</p>
<typo:code>
<p>cairngorm<br />
command<br />
delegate<br />
event<br />
vo<br />
worbservice</p>
</typo:code>
<p>Note there are several places in Rails you can set generators, but that did the trick for me. The I created a “src” folder in my Rails root folder and issues the following commands:</p>
<p>Then you can use these different generator commands to build the structure you require, the events, commands, delegates and more.<br />
<typo:code><br />
./script/generate cairngorm org/onrails/myspyder <br />
./script/generate delegate org/onrails/myspyder server<br />
./script/generate command org/onrails/myspyder show_page_watch server<br />
./script/generate event org/onrails/myspyder show_page_watch</p>
</typo:code>
<p>I issued the generate script for each of the commands that application needs to support. The main controller now looks as follows (still very early in the development phase)</p>
<typo:code>
<p>package org.onrails.myspyder.control<br />
{<br />
import com.adobe.cairngorm.control.FrontController;<br />
import com.adobe.cairngorm.control.CairngormEventDispatcher;<br />
import org.onrails.myspyder.control.<strong>;<br />
import org.onrails.myspyder.command.</strong>;</p>
<p>public class MySpyderController extends FrontController<br />
{<br />
public function MySpyderController()<br />
{<br />
initialiseCommands();<br />
}</p>
<p>public function initialiseCommands() : void<br />
{<br />
// Application Tabs<br />
addCommand( ShowAccountEvent.EVENT_SHOW_ACCOUNT, ShowAccountCommand );<br />
addCommand( ShowPagesEvent.EVENT_SHOW_PAGES, ShowPagesCommand );<br />
addCommand( ShowSettingsEvent.EVENT_SHOW_SETTINGS, ShowSettingsCommand );</p>
<p>// Page List<br />
addCommand( ReloadPagesEvent.EVENT_RELOAD_PAGES, ReloadPagesCommand );<br />
addCommand( AddPageEvent.EVENT_ADD_PAGE, AddPageCommand );<br />
addCommand( ReloadPageEvent.EVENT_RELOAD_PAGE, ReloadPageCommand );<br />
addCommand( RemovePageEvent.EVENT_REMOVE_PAGE, RemovePageCommand );<br />
addCommand( SavePageEvent.EVENT_SAVE_PAGE, SavePageCommand );</p>
<p>// Page Details<br />
addCommand( ShowPageWatchEvent.EVENT_SHOW_PAGE_WATCH, ShowPageWatchCommand );<br />
addCommand( ShowPageWatchResultEvent.EVENT_SHOW_PAGE_WATCH_RESULT, ShowPageWatchResultCommand );</p>
<p>// Html Section<br />
addCommand( ShowOriginalPageEvent.EVENT_SHOW_ORIGINAL_PAGE, ShowOriginalPageCommand );<br />
addCommand( ShowPageSectionEvent.EVENT_SHOW_PAGE_SECTION, ShowPageSectionCommand );<br />
addCommand( SelectPageSectionEvent.EVENT_SELECT_PAGE_SECTION, SelectPageSectionCommand );</p>
<p>}</p>
<p>}</p>
<p>}</p>
</typo:code>
<p>Let me know your experience with Flex and Cairngorm.</p>RESTFul Rails from Flex.2007-02-10T00:00:00-08:00http://onrails.org/2007/02/10/restful-rails-from-flex<p>As part of the “MySpyder” project I am currently working on we want a Flex front-end to access a RESTFul Ruby on Rails service. You can read more on RESTFul and ActiveResource on <a href="http://www.loudthinking.com/arc/000593.html">David’s blog</a>, on the <a href="http://weblog.rubyonrails.org/2006/11/23/rails-1-2-release-candidate-1">“release notes”</a> of Rails 1.2, PeepCode as an excellent <a href="http://peepcode.com/products/restful-rails">screencast</a> (not free) on the subject, and many other places.<br />
<p/><br />
In short using the RESTFul approach allows to expose and manipulate a Rails model via a predefined set of standard Http requests. For example we have an ActiveRecord named Watch which can be manipulated via the following requests:</p>
<table>
<tr>
<th> command </th>
<th> url </th>
</tr>
<tr>
<td> index </td>
<td># <span class="caps">GET</span> /watches.xml</td>
</tr>
<tr>
<td> show </td>
<td># <span class="caps">GET</span> /watches/1.xml</td>
</tr>
<tr>
<td> new </td>
<td># <span class="caps">GET</span> /watches/new</td>
</tr>
<tr>
<td> create </td>
<td># <span class="caps">POST</span> /watches.xml</td>
</tr>
<tr>
<td> update </td>
<td># <span class="caps">PUT</span> /watches/1.xml</td>
</tr>
<tr>
<td> delete </td>
<td># <span class="caps">DELETE</span> /watches/1.xml</td>
</tr>
</table>
<p/>
<p/>
<p>This allows for standard <span class="caps">CRUD</span> operations. Note rest supports also custom operations and <span class="caps">CRUD</span> operations on nested resources (such as a has_many relationship). We won’t address them in the article, but I will certainly need them later in the project.<br />
<p/> <br />
The Rails application can determined what format to return based on the content type or the extension of the url. We are only interested in xml for the moment.<br />
<p/> <br />
Some of the advantages of a RESTFul Rails application are that it provides a standard way to organize your controllers, as you will see just in a moment because the controllers are standard most of the code can easily be generated, and because the <span class="caps">URL</span> to access the application are standard we can now provide some standard utility class to access a RESTFul server. Rails provides an ActiveResource client class, and I haven’t found one yet for Flex. So I started to write one which I will show here after. Now please contact me or add some comments to this blog if you find anything similar or if you want to help me out writing this class. Another cool feature of writing RESTFul Rails controllers is that you get an <span class="caps">API</span> for your application nearly for free. This is the main reason we went down that direction.<br />
<p/><br />
Assuming we have an ActiveRecord named Watch we can now generate a RESTFul Ruby on Rails controller issuing the following command<br />
<typo:code><br />
./script/generate scaffold_resource watch</p>
</typo:code>
<p>Our server now supports RESTFul http requests.<br />
<p/><br />
Now wouldn’t it be nice if we could access the server data from Flex in the following manner:<br />
<typo:code><br />
import mx.rpc.AsyncToken;<br />
import org.onrails.ActiveResourceClient;</p>
<p>var watches:ActiveResourceClient = new ActiveResourceClient();<br />
watches.defineResource(“http://localhost:3000”, “watches”, resultHandler, faultHandler);</p>
<p>// Note that all the calls are performed in parallel and asynchronously.<br />
watches.list()<br />
watches.show(8)</p>
<p>// create <br />
var data:<span class="caps">XML</span> = <watch><br />
<url>www.picnik.com</url><br />
<xpath></xpath><br />
<frequency>10080</frequency></p>
</watch>
<p>watches.create(data)</p>
<p>// update <br />
data = <watch><br />
<id>8</id><br />
<frequency>10080</frequency></p>
</watch>
<p>data.frequency = 1440;<br />
watches.update(data)</p>
<p>// delete<br />
watches.deleteItem(8)</p>
</typo:code>
<p>Now we can. I started to write the ActiveResourceClient actionscript class to allow this. It’s attached at the end of the article. Now, this is a first try I’ve created this morning. So please be critical and let’s improve it together, or even better if you have one or know one that’s way better please point me where I can get it.<br />
<p/><br />
To use the ActiveResourceClient just put the ActiveResourceClient.mxml file into the org.onrails folder in your Flex project. Note that you can provide a default result handler and fault handler or set one handler for each specific call, i.e. the watches.create returns an AsyncToken where a dedicated handler can be specified just to handle the result of the creation.<br />
<p/><br />
Download: <a href="http://onrails.org/files/20070209_ActiveResourceClient1.mxml">ActiveResourceClient.mxml</a> (renamed file to ActiveResourceClient.mxml)<br />
<p/><br />
Enjoy,<br />
Daniel Wanja.</p>
Welcome to MXNA readers.2007-02-08T00:00:00-08:00http://onrails.org/2007/02/08/welcome-to-mxna-readers<a href="http://onrails.org/">OnRails.org</a> has been added to Adobe's xml news aggregator. You may wonder why a Ruby on Rails blog on Adobe's aggregator and what my involvement with Flex is. Read my <a href="http://onrails.org/articles/2007/02/07/certified-flex-2-0-developer">previous</a> post to see why I believe Flex and Rails are a great match.
<p/>
I used Flex since it was called Royale and develop 2 Flex application for customers that are currently in production. I am also currently working on three new projects that involve Flex, two off them are using Ruby on Rails as back end and one uses java. The java project is still using Flex 1.5. One is for <a href="http://onrails.org/articles/2007/02/07/sneak-peek-digital-seed-an-elearning-application-build-ruby-on-rails-and-flex">Digital Seed</a> and another is code named "MySpyder" for now and is just in it's infancy.
<p/>
I used to have a blog call f2ee.com (I gave away the domain name a while ago) named Flex+Flash Enterprise Edition which was solely focus on Flex. The only reminiscence left is on the <a href="http://web.archive.org/web/20050324150322/www.f2ee.com/blojsom/blog/default/">wayback machine</a> and two compiled demos, one <a href="http://web.archive.org/web/20050413030138/f2ee.com/flex15/portoflioReader/test2.swf">PortfolioReader</a> and some <a href="http://web.archive.org/web/20050413000233/f2ee.com/flex15/uiPatterns/t101_formView.swf">Scafolding Demo</a> using Flex. I don't even think I know where the source code of these demos is. Early 2005, I have also created with Lee <a href="http://flexonrails.com/">Flex::OnRails</a> (don't use it, use WebORB) a framework to integrate Flex (and Flash) with Ruby using AMF4R.
<p/>
More recently I open sourced the <a href="http://web.archive.org/web/20050413000233/f2ee.com/flex15/uiPatterns/t101_formView.swf">RailsLogVisualizer</a> on rubyforge. This is a Flex a desktop application for OSX (I wish <a href="http://labs.adobe.com/wiki/index.php/Apollo">Apollo</a> was out) with a embedded Ruby server (not Rails).
<p/>
On this blog I wrote several entries related to Flash and Flex, like <a href="http://onrails.org/articles/2005/07/31/dvdreleases-integrating-flash-with-ruby-on-rails">Integrating Flash with Ruby on Rails</a> and <a href="http://onrails.org/articles/2006/10/29/part-1-using-weborb-to-access-activerecords-from-a-flex-application">Using WebORB to access ActiveRecords from a Flex application</a>.
<p/>
Next month I'll be going to the <a href="ttp://360flex.org">360flex</a> conference and I'll be blogging on the Flex Data Services related presentations.
Welcome!
Daniel Wanja.
Sneak Peek: Digital Seed: - an eLearning Application build Ruby on Rails and Flex.2007-02-07T00:00:00-08:00http://onrails.org/2007/02/07/sneak-peek-digital-seed-an-elearning-application-build-ruby-on-rails-and-flexLast year Sean and Greg asked us to join one of their venture as Ruby on Rails developers. <a href="http://www.doloresjoya.com/">Dolores</a> joined as designer. Like Sean <a href="http://voisen.org/archives/2007/02/06/digital-seed-a-sneak-preview/">describes it</a> "Digital Seed is a Flash and Ruby on Rails application that has been designed to allow learning and training companies to more easily deliver their “soft skills” training (leadership, management, communications, etc.) in a multimedia-rich online learning environment.". This is a really fun project to work on. Sean put up a 10 minute <a href="http://www.digital-seed.com/">screencast</a>.
<p/>
<p/>
<img src="http://onrails.org/files/20070206-digital-seed.png" border="0" alt="20070206-digital-seed.png" align="right" />
<p/>
Certified Flex 2.0 Developer.2007-02-07T00:00:00-08:00http://onrails.org/2007/02/07/certified-flex-2-0-developerLast week I passed Adobe's Flex 2 Developer Exam. Now what's that got to with Rails. Like you may have seen in my <a href="http://onrails.org/articles/2007/02/07/sneak-peek-digital-seed-an-elearning-application-build-ruby-on-rails-and-flex">previous post</a> I like both technologies, Flex and Ruby on Rails, and I see the strength of both coming together and allowing to build some really cool applications. Now <a href="http://www.themidnightcoders.com/weborb/rubyonrails/index.htm">WebORB for Ruby on Rails</a> will play a big element in tying both together. WebORB is not the only way to build a Flex app on top of a Ruby on Rails server, but it provides an efficient mechanism to transfer data between the UI and the server. Beginning of 2005 with Lee we wrote <a href="http://flexonrails.com/">Flex::OnRails</a>, a now "deprecated" (as in don't even try to use it) framework, that was build on top of AMF4R. At that time combining Flex and Rails was an odd match, due to the pure enterprise nature of Flex with it's very high price sticker. Now that Flex is free, I can see many projects benefiting from integrating both. It is true that many web sites don't need a Rich User interfaces that go beyond what can be achieve with javascript. There are many javascript based websites that are incredible. See <a href="http://www.fluxiom.com/">http://www.fluxiom.com/</a> or <a href="http://wufoo.com/">http://wufoo.com/</a> as two refined examples. However with Flex it's often faster to build an application than with html and javascript, the applications often perform better, are easier to skin for a developer, the code is more readable and can support very large projects. Don't take me wrong, I love the <a href="http://www.prototypejs.org/">Prototype</a> library and <a href="http://script.aculo.us/">Scriptaculous</a> is really cool, and I will do many more "pure" Ruby on Rails projects, but at least now there is a serious alternative that I will consider in many scenarios.
<p/>
Now before you ask why did I even bother doing a certification, let me answer it. The first reason is that it forces me to read and study material that I would never have the patience to read otherwise as there is always too many cool things to try out. Now everyone has it's own style of learning. I started Rails by reading all the rdoc that was available and I also love to read the source code. The second reasons is marketing, and this worked really well for me in the past and opened several doors. Personally, I wouldn't value a developer by it's certification but rather by the projects he worked on, the code he writes and it's personality.
<p/>
I haven't found much information out there on the Flex certification which is pretty new . The <a href="http://weblogs.macromedia.com/flexteam/archives/Exam_Guide_Flex2.pdf">Exam Preparation Guide</a> by Adobe provides an overview and there is a more <a href="http://www.donathgroup.com/pdf/Flex20Blueprint.pdf">detailed version</a> on the net which is not the official one. I found lot's of information in <a href="http://livedocs.macromedia.com/flex/201/">Adobe's online documentation</a> and in the <a href="http://www.amazon.com/Adobe-Flex-2-Training-Source/dp/032142316X">Flex 2, Training from the source</a> book.
<p/>
So be ready to hear a little more on Flex and Rails on this blog.
RailsConf 2007 registration is open!2007-02-02T00:00:00-08:00http://onrails.org/2007/02/02/railsconf-2007-registration-starts-february-2ndUPDATED: <a href="http://conferences.oreillynet.com/pub/w/51/register.html">REGISTER NOW!</a>
I just received notification that my proposal for a talk at RailsConf was declined. The subject was of course, "Flex On Rails - Enterprise Data Manipulation.". I hope that my friend <a href="http://thillerson.wordpress.com/">Tony</a> which made a proposal on a similar subject has been accepted. He is an excellent teacher. In addition the notification indicated that the registration starts tomorrow. So get ready!
Slicehost made us rich!2007-02-01T00:00:00-08:00http://onrails.org/2007/02/01/slicehost-made-us-richActually, I guess they made us less poor. Last month a bunch of our referrals finally paid off, saving us 70% of our usual monthly fee! Thanks go to Kevin, Richard, Marty, John, Christopher, Brandon, Zachary, Piotr, and Jesse!<br /><br />Why haven't we written much about <a href="http://www.slicehost.com/">Slicehost</a> in the 6 months we've been hosting on them? Because it just works. We just set up our apps and let them run.<br /><br />If you'd like to be in our next thank you note, use this <a href="https://manage.slicehost.com/customers/signup?referrer=629092">link</a> when signing up for your slice.<br /><br />Thanks again, referrals and Slicehost.<br />
RailsConf registration starts 1st week of Februrary. So get ready!2007-02-01T00:00:00-08:00http://onrails.org/2007/02/01/railsconf-registration-start-1st-week-of-februrary-so-get-readyThe conference Wiki <a href="http://wiki.oreillynet.com/wiki/railsconf2007/index.cgi?WhenWillRegOpen">indicates</a> that the registration starts the first week of February. Chad just <a href="http://chadfowler.com/2007/2/1/railsconf-registration">notified</a> the community that it's coming soon. I speculate the registration opens tomorrow, February 1st. Rumored to be around $800.- and having more seats than the 700 of last year, it may take a little longer to sell the conference out this time. Let's see. In any case get ready!
New Rails Group in Seattle2007-02-01T00:00:00-08:00http://onrails.org/2007/02/01/new-rails-group-in-seattleFor those in or near Seattle you might want to check out the new <a href="http://www.seattleonrails.org/">Rails group</a> that is starting this month. It is sponsored by <a href="http://www.engineyard.com/">Engine Yard</a> and my friend's company, <a href="http://www.biego.com/">Biego</a>. The first meeting is February 13th at 6pm at the Greenlake Public Library. Too bad it wasn't last week when I was in Seattle for a few days, I would have liked to seen what the Ruby community is like there.<br />
Does a good idea make a good business?2007-02-01T00:00:00-08:00http://onrails.org/2007/02/01/does-a-good-idea-make-a-good-business<p>On top of our Ruby on Rails consulting work we would like to create a small internet “service” business. Something like <a href="http://time.onrails.org/">time.onrails.org</a> but more fleshed out and supporting paying customers. We are bringing on board Solomon White, which is an awesome Ruby on Rails developers, to help out. So the other day we met and threw out some ideas of project we would consider doing. I think we came with a bunch of great ideas that each on their own could support a nice business or at least would be fun to develop. Often the feeling is that sharing these ideas would give away the “magic” ingredients that would make the new venture a success, that competition would outrun us and they will be first and take the whole market. I don’t believe so. A very close friend created a spectacular Java/.Net integration framework. He is adamant about not revealing too much on how he created it or even that he created it. The result is that potential customers don’t “just” find him as they don’t know that a solution to their problem is out there, and he must convince them really hard that he has the solution, and sometimes that they have a problem. In other scenarios a ‘surprise’ announcement, like Apple masters so well, has certainly a great impact as that creates lot’s of buzz on the net and in the news. The reality is that we don’t have Apples audience and no one is expecting a ‘surprise’ from us. I don’t think that they are not many great ideas worth keeping secret Rather find a problem or need and make sure you create an awesome solution addressing it. While you create it, talk about it, spread the word, gather feedback, talk about the technical challenges you encounter, feel the interest that’s out there. Then deliver. And deliver something exceptional …sounds familiar? Well that concept is not invented here, but if we shine at taking one of “our” ideas, and providing an exceptional implementation I believe we can attract many users and create a nice business out of it.</p>
<p>So the steps in the process becomes something like this:</p>
<p>1. Investigate ideas (that’s where we are at)<br />
2. Choose idea.<br />
3. Define project<br />
4. Implement and spread the word.<br />
6. Go live<br />
7. Adapt and Improve</p>
<p>Currently we are in the “investigation” phase for several of these ideas. In other words we are coding and having fun and testing out different things. So here is the list of our killers ideas (in no specific order):</p>
<p><b>RailsLogVisualer plug-in</b>: Realtime and aggregated log visualization of your Rails application. At the end of last year I wrote an offline <a href="http://railslogvislzr.rubyforge.org/">Rails Log Visualizer</a>. It’s pretty basic but provides some interesting information about the different applications we have in production. While writing it I realized that it would not be too difficult to have a plugin that would collect and aggregate request data and be able to provide information on the specific controllers and actions of the application. Of course it would require to support clusters of Rails applications. This plugin would provide a nice drill-down approach to the log data analysis which differs from a more traditional log analysis approach. For now, check out <a href="http://nubyonrails.com/articles/2007/01/03/a-hodel-3000-compliant-logger-for-the-rest-of-us">Geoffrey’s article</a> on how to add Rails support to <a href="http://haveamint.com/">Mint</a> for a nice way to analyze your log data on a deployed server.</p>
<p><b>ScrumPlan</b>: An Agile Project management tool. I still do tons of enterprise work, and I really like how Scrum brings teams together. Scrum is very simple and a spreadsheet can be sufficient to get started, but I see the need for a simple dedicated tool to support the different activities that is simpler, more efficient and elegant than the existing tools out there. Lee is not too hot on this idea as we don’t use Scrum on our small projects.</p>
<p><b>FlexTester</b>: An automation/regression tool for Flex. A large part of this testing tools would be in Flex, but the tool would have a server side part that is written in Ruby on Rails to keeps track of tests runs, to drive continuous integration and so forth. Flex is not directly related to Rails but I also do a lot of Flex work. I just think it’s a very nice way to create an UI, although in many case <span class="caps">RJS</span> does the trick as nicely and is “more” conventional. Flex is appropriate for enterprise applications (with many screens, many developers, lots’ of functionality) and Adobe just added some framework level way to record and playback user events (see the <a href="http://livedocs.macromedia.com/flex/201/langref/mx/automation/package-detail.html">mx.automation package</a>). There is currently one very expensive tool out there to create regression tests for Flex. Another more affordable one would be welcome. I started playing with the mx.automation framework and I am evaluating the effort implementing such a tool.</p>
<p><b>TimeOnRails 2</b>: We have several hundred registered users (858 today) for time on rails and many use it on a daily basis. We received great feedback and also improvement requests. We use it our-selves on a daily basis and see many ways we want to improve and make it even more useful, especially on projects with multiple team members. Rather than just fixing the current code based which was implemented during the pre-RESTFull area, we want to rewrite it from the ground up. Note if we don’t select that idea, I will need to fix promptly several small issues on time.onrails.org.</p>
<p><b>RailsCloud</b>: Rails hosting on a cloud. Ways to deploy or scale you Rails environment at the click of a button…This would leverage <a href="aws.amazon.com/ec2">Amazon’s EC2</a>.</p>
<p><b>S3Backup</b>: Backup to S3 with a twist!</p>
<p><b>MySyder</b>: The last year we worked in the eCommerce field. It’s pretty amazing what’s going on in this field, and there is the need to provide better tools for vendor and online stores. As part of “investigating” this idea we defined a subset of functionality related to “watching specific html pages” that we can turn into an online service or product by it’s self.</p>
<p>As you see we’ve got many ideas. I like Solomon’s way of looking at these ideas…“Which one we do first?” … More on that in the future.</p>Rails 1.2.1 released? - Answer: yes2007-01-18T00:00:00-08:00http://onrails.org/2007/01/18/rails-1-2-1-releasedIt looks like Rails 1.2.1 is out, but I haven't seen an announcement yet (nor one for 1.2.0). Changeset <a href="http://dev.rubyonrails.org/changeset/5990">5990</a> created a tag for 1.2.1 and the gem is on rubyforge already. Maybe it's a good time to freeze those apps to a release version instead of riding on edge all the time.<br /><br />Happy Railing!<br /><br /><b>Update:</b> The <a href="http://weblog.rubyonrails.com/2007/1/19/rails-1-2-rest-admiration-http-lovefest-and-utf-8-celebrations">announcement</a> came not too long after my post.<br />
Onrails.org moved to Slicehost.2007-01-13T00:00:00-08:00http://onrails.org/2007/01/13/onrails-org-moved-to-slicehostI wanted to move this blog to Mediatemple as I liked their concept of a Ruby on Rails Container. After signing up and following the instructions I realized that Lee did such a good job of setting up time.onrails.org on Slicehost, and we are really impressed with the performance of the servers, that it was even easier for us to just move this blog to slicehost. Some nice aspect of Mediatemple are that they provide an https connection included with their base price, but I didn't like that the default Ruby version was 1.8.2. and not 1.8.4 and MySQL was 4.1.11 and no 5.
Happy New Year!2006-12-27T00:00:00-08:00http://onrails.org/2006/12/27/happy-new-yearA bit early? Just a couple of days. I just wanted to wish to all the readers of onrails.org and all the users of time.onrails.org and very nice holiday. Having some out of town friends and family over, I won't be checking too much my email nor doing too much development the next few days. I'll be heading up the mountains and do some snowboarding. What a Rails year it was! Thank you for my main customer Gatelys and specially their technical director Solomon White that allowed us to write some kick-ass Rails application during 2006, that was a fun ride. So what's in store for 2007? Nothing is finalized yet, so stay tuned for the first half of January as we may start reporting on some new projects. Also with Lee, we will tackle a new 'side' project using Rails. We will drive it further and build a viable business around it. Like for time.onrails.org we will report our progress on this blog. I will also continue investigating using Flex with Rails as it's a pretty powerful match and opens doors to some really cool applications. I will checkout deeper the Streamlined framework. And of course I will attend a couple of conferences like <a href="http://360flex.org">360flex</a>, <a href="http://conferences.oreillynet.com/rails/">RailsConf</a> and <a href="http://www.rubyconf.org/">RubyConf</a>. We will try out other hosting services (I just signed up with MediaTemple). We will continue to closely follow the evolution of Edge Rails, specially the ActiveResources. So, stay tuned and see you next year for some more Ruby On Rails.
Blizzard `06 - Day 22006-12-21T00:00:00-08:00http://onrails.org/2006/12/21/blizzard-06-day-2I think we have about 2 feet of snow now. The neighborhood has been out in full force shoveling driveways and sidewalks so the dogs can all play together.<br /><br />The big dogs came out:<br /><img src="http://onrails.org/files/Last_Roll_-_32.jpg" /><br /><br />And the small ones, too:<br /><img src="http://onrails.org/files/Last_Roll_-_22.jpg" /><br /><img src="http://onrails.org/files/Last_Roll_-_28.jpg" /><br /><br />Our beagle even had to pull me out of a drift:<br /><img src="http://onrails.org/files/Last_Roll_-_40.jpg" /><br /><br />Time for lunch and some hot chocolate.<br />
Rails on Snow2006-12-20T00:00:00-08:00http://onrails.org/2006/12/20/rails-on-snowIn case you haven't heard, we're getting a "little" snow today in Colorado. We have 3-4 foot drifts in the middle of our back yard. Most flights out of the Denver Internation Airport have been cancelled, but the Rails coding never stops.<br /><br /><img src="http://onrails.org/files/0.jpg" /><br /><br />It's not too cold, but the wind blew snow in through our dog door. Our poor beagle is having a hard time trying to find a place to do his business.<br /><br /><img src="http://onrails.org/files/2.jpg" /><br /><br />Anyway... back to unit tests.<br />
RailsLogVisualizer: now open source and 6 x faster.2006-11-29T00:00:00-08:00http://onrails.org/2006/11/29/railslogvisualizer-now-open-source-and-6-x-fasterI moved the RailsLogAnalyzer to RubyForge and as there was already a project on RubyForge with the same name, so I renamed it to <a href="http://railslogvislzr.rubyforge.org/">RailsLogVisualizer</a>. So <b>RailsLogVisualizer</b> it is. Version 0.3 provide a drastic speed improvement over version 0.2. If you are curious or adventurous you can browse the <a href="http://rubyforge.org/viewvc/?root=railslogvislzr">source code</a> on RubyForge.
<br/>
The Project Home Page is <a href="http://railslogvislzr.rubyforge.org/">http://railslogvislzr.rubyforge.org/</a><br/>
The project is at <a href="http://rubyforge.org/projects/railslogvislzr/">http://rubyforge.org/projects/railslogvislzr/</a><br/>
Enjoy!
The Rails Edge Conference in Denver - Day 32006-11-18T00:00:00-08:00http://onrails.org/2006/11/18/the-rails-edge-conference-in-denver-day-3<p>I am a bit late (20minutes) to the conference as I had an iChat with my nieces that turned 3 today. <br/></p>
<p><b><span class="caps">THE</span> <span class="caps">RAILS</span> <span class="caps">TIMES</span> by Mike Clark and Bruce Williams</b><br /></p>
<p>So I seems I haven’t missed to much so far. Mike Clark and Bruce Williams are presenting what’s new in Rails. They call it it “<span class="caps">THE</span> <span class="caps">RAILS</span> <span class="caps">TIMES</span>”, and the first slide is a news paper front page. <br />
<ul><br />
<li><span class="caps">HABTM</span> Ousted in favor of Rich Models using has_many :through. </li><br />
<li>Many deprecations telling you how to prepare for Rails 2.0. </li><br />
<li>Routes get named.</li><br />
<li>Extra: Ruby generates javascript. <i> page[:tags].reload # reload <em>tags.rhtml partial.</i></li><br />
<li>Serial(ization) Killers At Large: <span class="caps">YARML</span>, <span class="caps">XML</span>, <span class="caps">JSON</span></li><br />
<li><span class="caps">RSS</span> is the next big thing: <i>render_rss_feed_for(@people, options)</i></li><br />
<li>The future is <span class="caps">CRUD</span>: <i>ruby script/generate scaffold_resource article</i>. <i>map.resources :articles</i></li><br />
<li>Conventions Flourish: see simply_helpful. <i>form_for @person do end </i></li><br />
<li><span class="caps">BULLTIN</span>: Apps respond-to Clients: <i>respond_to do |format| format.html, format.js, format.xml, format.yaml</i>. Custom format can also be added.</li><br />
<li><span class="caps">CORBA</span>? <span class="caps">RMI</span>? No, ActiveResource!: <i>class Person < ActiveResource::Base</i></li><br />
<li>Security Alert! Parameter Filtering – <i>filter_parameter</em>logging :password, :login, :user</i></li> <br />
<li>Installation Typo Triggers Global App Meltdown:<i> rake rails:freeze:gems</i></li><br />
<li>Manking Attacked by Mongrel: <i>gem install mongrel</i></li><br />
<li>Tomorrow’s Edition? : Rails 2.0? <span class="caps">REST</span>? </li></p>
</ul>
<p/>
<p><b>The Meaning of <span class="caps">CRUD</span> by Chad Fowler</b><br /></p>
<p>This is an awsome talk where Chad is going into the impact that a RESTFul approach has on your development and how to write your application using the new named routes and RESTfull controllers.</p>
<p/>
<p><b><a href="http://streamlinedframework.com/">Streamlined</a> by Justin Gehtland</b><br />
Justin goes through many of the options on how to manipulate declaratively a Streamlined driven UI.</p>
<p>Road map:</p>
<ul>
<li>0.0.6 new look (soon)</li>
<li>0.0.7 control types for fields</li>
<li>0.0.8 plugin instead of generator</li>
<li>0.1 99% rcov, compatibility</li>
</ul>
<p>Features to look for</p>
<ul>
<li>visual configuration</li>
<li>declarative tabbed ui 0.0.8?</li>
<li>generated columns sortable</li>
<li>context specific ui (different for list, show , edit…)</li>
<li>rich text editor (TinyMCE)</li>
</ul>
<p/>
<p><b>Deployment by James Duncan Davidson</b><br /></p>
<p><b>Start Early</b> deploying your applications. Find all the “interesting” deployment problems up front. You’ll know how to do it when the times comes. You’ll get into the deployment rhythm.</p>
<p><b>How to do it:</b> not using WEBrick, <span class="caps">CGI</span>, FastCGI…but proxy to Mongrel (ya-huh!). Front End use Apache, Lighttpd, Pound, Pen, or hardware load balancer. Use Capistrano. <b>The Golden Path</b> assumes Capistrano, Unix (<span class="caps">NOT</span> Windows), subversion. Apache 2.2.x (myproxy balance), Ruby Termios Library, MySQL 5. Duncan then went on to a live demo, connected to his Subversion repository in Portland using the Hotels network deploying to an EC2 (Amazon Elastic Computing Cloud) . So pretty gutsy demo but the demo went on pretty well.</p>
<p/>
<p><b><span class="caps">CONFERENCE</span> <span class="caps">CONCLUSION</span>!</b><br/>
Awesome conference, well worth the money. Not only was it well organized but the talks where just loaded of useful information. Thanks to all the presenters!</p>The Rails Edge Conference in Denver - Day 22006-11-17T00:00:00-08:00http://onrails.org/2006/11/17/the-rails-edge-conference-in-denver-day-2He we go again, day 2 is starting.
<p/>
<b>Rails the right tool for the job? by Mike Clark.</b><br/>
Mike will address the following aspects of Rails:Sweet spots, Honey Pots, Tar Pits. Rails is a full-stack web framework, no need to choose the different parts of the stack it's ready to go from the start. It's Quick and Clean, like Martin Fowler would say. Mike adds quicker than J2EE and cleaner than PHP. <b>The sweet spot</b>: database backed web applications, green-field development, open-minded team, following the rails way.
<b>Honey Pots</b> is when you get into Rails because it's sweet, but then you get stuck. In other words the not so sweet spots: Legacy, Internationalization, messaging systems, heavy use of threading.<b>Tar Pits</b> two phase commits, off the shelf components, obfuscation, client installations, corporate standards.
<p/>
<b>Active Record Demystified by Marcel Molina Jr.</b><br />
An in-depth tour of connection adapters, ActiveRecord::Base#save, and ActiveRecord::Base.find. <br/>
<p/>
<b>Building UI Frameworks by Bruce Williams.</b><br />
Bruce worked on a large system with many views. Views are tedious and are time consuming to develop and took a large portion of the development of the 90000 Ruby code application they wrote. I will not talk about components, engines, markaby. Bruce will shares some of his frustrations and challenges. Views are hard to read, are hard to learn (ruby, rails, html, css, javascript+prototype). He extensively explain the difficulties that are faced when doing view development and mentions that it's all about <b>Pain Management.</b>. He continues by showing some examples and concepts to ease that pain by using simply_helpful plugin, DSL for controllers, and block helpers than render partials.
<p/>
<b>Rake Your Secret Weapon by Jim Weirich.</b><br />
<p/>
<b>Burried Treasure by Dave Thomas</b><br />
Tips and Tricks for Ruby & Rails Development. Dave goes through these following Rails goodies:
<ul>
<li>with_scope</li>
<li>with_options</li>
<li>returning</li>
<li>&:xx - The Blockinator %w{ cat dog }(&:upcase) or users.map(&:name)</li>
<li>Lookup Constants</li>
<li>Formatting dates and number</li>
<li>Enumerable extensions (i.e. group_by)</li>
<li>Arrays: in_groups_of, to_sentence</li>
<li>Strings: at, from , to, first, last, each_char</li>
<li>Subversion integration: script/generate model mymodel <b>--svn</b> (adds it automatically to subversion)</li>
<li>The Console: app.get, app.response, helper, irb for default object, ActiveRecord::Base.logger = Logger.new STDOUT</li>
<li>Routing: >>irb ActionController::Routing::Routes; puts routes</li>
<li>TextMate: ctrl-h on a method to shows the rdoc. ctrl-shift-apple-s on an ActiveRecord shows the schema information. Code Completion. </li>
</ul>
Rake Command Completion Using Rake2006-11-17T00:00:00-08:00http://onrails.org/2006/11/17/rake-command-completion-using-rake<p>This is an update of a <a href="http://onrails.org/articles/2006/08/30/namespaces-and-rake-command-completion">previous</a> post.</p>
<p>I just watched <a href="http://onestepback.org/">Jim Weirich's</a> talk on <a href="http://rake.rubyforge.org/">Rake</a> at the <a href="http://pragmaticstudio.com/therailsedge/denver.html">Rails Edge Studio</a> and decided to update the command completion script to use Rake itself for caching the tasks. <a href="http://errtheblog.com/post/33">Err the Blog</a> did an update on my script last month to include caching for a nice speedup, so I took that and made sure the cache is regenerated when the Rakefile or any rake tasks found in your rails app have been updated. I added this with just some straight ruby code, but Jim's talk made me realize that this type of thing is exactly is what rake is for. So, here is the updated version:</p>
<typo:code lang="ruby">
#!/usr/bin/env ruby
# Complete rake tasks script for bash
# Save it somewhere and then add
# complete -C path/to/script -o default rake
# to your ~/.bashrc
# Nicholas Seckar <nseckar@gmail.com>
# Saimon Moore <saimon@webtypes.com>
# http://www.webtypes.com/2006/03/31/rake-completion-script-that-handles-namespaces
# http://errtheblog.com/post/33
exit 0 unless File.file?(File.join(Dir.pwd, 'Rakefile'))
require 'rubygems'
require 'rake'
DOTCACHE = File.join(File.expand_path('~'), ".rake_task_cache" , Dir.pwd.hash.to_s)
RAKE_FILES = FileList[ __FILE__, 'Rakefile', 'lib/tasks/**/*.rake', 'vendor/plugins/*/tasks/**/*.rake']
file DOTCACHE => RAKE_FILES do
tasks = `rake --silent --tasks`.split("\n").map { |line| line.split[1] }
require 'fileutils'
dirname = File.dirname(DOTCACHE)
FileUtils.mkdir_p(dirname) unless File.exists?(dirname)
File.open(DOTCACHE, 'w') { |f| f.puts tasks }
end
Rake::Task[DOTCACHE].invoke
tasks = File.read(DOTCACHE)
exit 0 unless /\brake\b/ =~ ENV["COMP_LINE"]
after_match = $'
task_match = (after_match.empty? || after_match =~ /\s$/) ? nil : after_match.split.last
tasks = tasks.select { |t| /^#{Regexp.escape task_match}/ =~ t } if task_match
# handle namespaces
if task_match =~ /^([-\w:]+:)/
upto_last_colon = $1
after_match = $'
tasks = tasks.map { |t| (t =~ /^#{Regexp.escape upto_last_colon}([-\w:]+)$/) ? "#{$1}" : t }
end
puts tasks
exit 0
</typo:code>
<p><strong>Update:</strong> I fixed the bug that <a href="http://onrails.org/articles/2006/11/17/rake-command-completion-using-rake#comment-227">janfri</a> pointed out. The bug caused the first task to be missed. I also changed it so it won't abort if rake isn't the first command on the command line. This will allow stringing multiple commands together. For instance:</p>
<typo:code>
rake db:migrate VERSION=0 && rake db:migrate
</typo:code>
<p><a href="http://onrails.org/files/rake-completion.rb">Enjoy</a></p>
The Rails Edge Conference in Denver - Day 12006-11-16T00:00:00-08:00http://onrails.org/2006/11/16/the-rails-edge-conference-in-denverThe <a href="http://pragmaticstudio.com/therailsedge/">conference</a> just started 30 minutes ago. I will write down some notes as it moves ahead. On a side note, Chad has a cool t-shirt saying "<strike>Rails</strike> Ruby - Programmer Friendly, Enterprise Ready"...way to go, enterprise here we come.
<p/>
<b>Meta Programming Ruby by Dave Thomas.</b><br/>
Extending Ruby for Fun and Profit.<br/>
Meta programming allows to extend the language by writing code that writes code. This talk is about understanding how it works, but mostly it's to allow us (the attendees) to start writing our own extensions. Dave goes through these four aspects of Ruby that enable meta programming: classes are open, definitions are active, all method calls have a receiver, classes are objects.
<p/>
<b>Ruby Idioms for Rails Programmers by Stuart Halloway</b><br />
Implicit vs. Explicit - Stuart takes a Java/Struts example and refactors it to a Rails example showing along the way the explicit parts that should be implicit as they don't have anything to do with the business logic you are trying to implement. Basically he moves a 20 lines java method down to 1 lines of ruby. This was very revealing, but let's not start a java .vs. rails debate here ;-) <br />
Add Context to Instances - Ruby allows to modify objects to represent context. For instance active records contain the errors context that are triggered during saves, also active record contains wether it's a new record. So breaking apart from a "pure" object model, in Rails these contexts are injected into the objects, this simplifies greatly the development concepts. For example you have on instance of Person that is valid and not new. In java these concepts are broken down in separate concepts but you end up with DAOs, validators, business object, which all need to be tied together. In short Rails is less "pure" but simpler.<br />
Personalized Object Model - Augmentations by methods on demand (method_missing). sample platter (Symbol#to_proc, Object#with_options, and hundreds more). Domain-Specific Encapsulation - Stuart now describes how Rails provides some domain specific encapsulation to hide some of the internals of your application, i.e. hide_action, add_variables_to_assigns.<br />
Stuart warns us that he feels strongly about the topics he will cover now, but they may be controversial. Poor Composition Disrupts Flow - Stuart refers to the Smalltalk best practice book (p22, Kent Beck) which states "...keep all the operations at the same level of abstractions...". He diggs through some method examples form Edge Rails that could be 'improved'. <br />
His presentation can be found at codecite.com
<p/>
<b>Rails Reflection by Chad Fowler</b><br/>
Chad is presenting some of the findings of the project he workd for at Naviance. He started showing of a movie of a tool they (him and Bruce Williams) wrote to dynamically and visually create ActiveRecords and add data to it, then be able to export the fixtures. Why use Rails reflection? learn how rails work, simplify maintenance, make Rails do that Rails doesn't do well.<br />
Chad will go throught some of the reflection possibilities that Rails offer that allowed him to build the tool he just demonstrated.<br />
Active Record Reflection - schema, relationships, callback and errors. Some ActiveRecord reflection examples:
<pre>
ActiveRecord::Base.connection.tables.length
User.column_names
User.reflections.keys
</pre>
Some nifty trick to run migration code from irb is when you execute the following from irb:
<pre>
>>irb ActiveRecord::Base.connection
</pre>
Now the receiver class (in irb) is the connection which supports migration calls like add_column, drop_table, and so on.
<p/>
Action Controller Reflection - Requests, Filters, Routes. <br/>
<pre>
self.class.before_filters
self.class.after_filters
self.class.included_actions
self.class.excluded_actions
ActionController:Routing::Routes.routes
</pre>
Chad concludes with the fact that these technique should be used only where appropriate and that many applications don't need such a level of programming.
<p/>
<p/>
<b>Ruby Design Patterns by Jim Weirich</b><br/>
A design pattern is a solution to a problem in a context.<br />
Jim goes in detail through some Ruby implementation of these standard patterns: Template Method Pattern, Strategy Pattern, Singleton Pattern. He also presents the Blank Slate Pattern he used while creating the XmlBuilder library.<br />
The ruby way:<br/>
<pre>
Singleton Pattern => include Singleton
Observer Pattern => include Observable
Iterator Pattern => include Enumerable
Factory Pattern => ClassName.new
Proxy Pattern => method_missing
Visitor Pattern => Open classes
</pre>
Jim refers to a paper from Peter Norvig from 1996 where he categorize patterns as being Invisible, Formal, and Informal for different languages and mentions that some dynamic languages have fewer restrictions and often don't require explicit patterns or have simpler implementations.
<p/>
<p/>
<b>ActionPack Demystified by Marcel Molina Jr.</b><br/>
ActionPack = ActionController + ActionView<br/>
Marcel is going through the internals of ActionPack and will cover lot's of code. So I am not sure how much I will be able to write down...I may try to follow his talk :-). Looking at the internals are useful to understand the larger story of what's going with your application and Rails is a good example of how to write Ruby code or is a good help how to extend Rails.<br/> Yes, he really presents lots of interesting stuff, so I'll better sit back and follow. Right now he is explaining the compilation of the templates and going through the implementation of compile_and_render_template. Marcel want's to see how he feels about presenting this and looks for motivation to re-implement it.
<p/>
<p/>
<b>Ajax on Rails by Justin Gehtland.</b><br/>
This talk is about Ajax or the cool crap you can actually see. No meta programming. Justin will walk us through Prototype support in Rails, Scriptaculous Helpers, and Javascript generation.
<p/>
That concludes the talks for the day. After dinner there will application presentations by the attendees.
<p/>
<b>The evening presentations where really cool</b><br/>
<a href="http://onrails.org/articles/2006/11/15/railsloganalyzer-v0-2-for-osx-faster-better">Rails Log Analyzer</a> by Daniel Wanja. Yes, I presented the new version of the log analyzer. <br/>
<a href="http://time.onrails.org">Time.onrails.org</a> by Lee Marlow. A time management application Lee and I worked on.<br/>
<a href="mediapulse.com">iDeal</a> by Brian Spaid from mediapulse.com. A tool to quickly create websites and track user activity. This tool is used by them internally and not yet public.<br/>
<a href="http://visible-assets.com">RFID Tracking Software</a> by Steve Mui. A cool rails application that allows real time asset tracking. The demo Steve presented was for an hospital that is tracking assets worth over $5000 (i.e. artificial knee) and Hospital workers. The software can track if the assets are in stock, see for specific rooms (i.e. operation room) when assets enter/leave the room. They have rfid scanners that track rfids and log their presence every couple of seconds to a Postgress database. The rails application then summarize and visualize all this data.<br/>
<a href="http://loopnote.com/">http://loopnote.com/</a> by Martin May. A topic based notification application. You can register to a topic and be notified whenever the topic maintainer notifies you of a change. Notification is by rss, email, text message. You can create your own topics. Besides be nicely designed I believe that this is going to be a pretty popular application. It's not open to the public yet, but the demo was impressive.<br/>
<a href="showerinabox.com">showerinabox.com</a> by Leslie A Hensley. A funny application allowing to plan a bridal shower and print out some customized bridal shower games. All in Ruby on Rails, using PDFWriter.<br/>
Ruby binding2006-11-16T00:00:00-08:00http://onrails.org/2006/11/16/ruby-bindingWhat is <code>binding</code>? It basically holds the current state of the application... it knows what <code>self</code> is (or was when <code>binding</code> was invoked). What else does it know? I'm not sure, it's something I'd like to investigate further. Can the binding be interrogated? Can it be manipulated?
Let me know if you have good pointers to info about it. I'll check Pickaxe when I get home.
Module Tidbits2006-11-16T00:00:00-08:00http://onrails.org/2006/11/16/module-tidbitsI always forget what including versus extending a Module, so here's a little reminder for myself.
<typo:code>
module UsefulMethods
def some_cool_thing
1 + 1 == 0
end
end
class IncludeUsefulInstanceMethods
include UsefulMethods
end
class IncludeUsefullClassMethods
extend UsefulMethods
end
puts IncludeUsefulInstanceMethods.new.some_cool_thing # => false
puts IncludeUsefullClassMethods.some_cool_thing # => false
</typo:code>
So, including a module basically shoves the module's methods into the class as instance methods, while extending a module puts them in as class methods.
That's it. By the way, this was inspired by Dave Thomas' metaprogramming talk at the Rails Edge Studio in Denver.
RailsLogAnalyzer v0.2 for OSX - Faster, Better2006-11-15T00:00:00-08:00http://onrails.org/2006/11/15/railsloganalyzer-v0-2-for-osx-faster-betterVersion 0.2 of the RailsLogAnalyzer is still a development version but a great improvement over my first prototype. This version has been rewritten from the ground up and doesn't use a database to store intermediate log file aggreation.
<img src="http://onrails.org/files/RailsLogAnalyzerActionView.gif" border="0" height="396" width="564" alt="RailsLogAnalyzerActionView.gif" align="right" />
<p/>
<b>Analyzing your log file data.</b>
Once the log file is loaded you will see a breakdown of your requests by year, month, and day.
Click on the year, month, or day to see the controllers invocations during that period.
Click on the controller in the chart to see the method invocations during the selected period.
The method are further broken down based on their http methods (get, post, delete, ...).
Note: loading a 10Mb production log file with 30000 requests takes about 10 seconds on my MacBook Pro.
loading a 250Mb production log file with 530000 requests takes about 2 minutes.
loading a 4.5Gb production log file with 11 million request takes about 45 minutes.
The data is loaded in memory and must be reloaded once the application is closed.
Download it here <a href="http://onrails.org/files/RailsLogAnalyzer_0.2.dmg">RailsLogAnalyzer_0.2.dmg (487KB)</a> and let me know your findings at daniel@onrails.org
Part 1: Using WebORB to access ActiveRecords from a Flex application.2006-10-29T00:00:00-07:00http://onrails.org/2006/10/29/part-1-using-weborb-to-access-activerecords-from-a-flex-application<p>On Friday I started for a customer an investigation in providing a Flex front-end for an Ruby on Rails backend using WebORB. In parallel I will push this investigation further for myself in order to find a nice mechanisms to support <span class="caps">CRUD</span> operations with relationship support using WebORB. Over the next couple of weeks I will write some of my findings on this blog. So this week-end I started to put in place an environment where I can unit test the interaction between Flex and Ruby on Rails using WebORB. In this first part I will show how to extend WebORB to perform a deep find, how to write a Flex unit test to test asynchronous remote calls, and how to use Ruby on Rails fixtures for the Flex unit tests.<br />
<p/><br />
This is an extract of the ‘final’ version of the Flex unit test (as of Part 1 of the article). The full version is at the end of the article. <br />
<typo:code><br />
public function testGetFirstCustomer():void {<br />
var activeRecordService:RemoteObject = getActiveRecordService(onGetFirstCustomerResult); <br />
create_fixtures([“customers”, “addresses”, “orders”, “items”], doGetCustomerFirstCustomer, activeRecordService);<br />
} <br />
private function doGetCustomerFirstCustomer(activeRecordService:Object):void {<br />
var options:Object = {’include’:[‘bill_to_address’, {’orders’:’items’}]};<br />
activeRecordService.get(“Customer”, 1, options); <br />
}<br />
private function onGetFirstCustomerResult(event:Event, token:Object=null):void <br />
{<br />
assertTrue(event.toString(), event is ResultEvent); // First param is message.<br />
var customer:Object = ResultEvent(event).result;<br />
assertEquals(“Daniel”, customer.name);<br />
assertEquals(“Littleton”, customer.bill_to_address.city);<br />
assertEquals(2, customer.orders.length); // 2 order<br />
assertEquals(3, customer.orders<sup class="footnote" id="fnr0"><a href="#fn0">0</a></sup>.items.length); // the first has 3 items<br />
assertEquals(“Remote Control”, customer.orders<sup class="footnote" id="fnr0"><a href="#fn0">0</a></sup>.items<sup class="footnote" id="fnr2"><a href="#fn2">2</a></sup>.product); <br />
}</p>
</typo:code>RubyConf 2006 - Day 32006-10-22T00:00:00-07:00http://onrails.org/2006/10/22/rubyconf-2006-day-3Here we go again. Let's how long my battery is going to last today.
<table>
<tr><td><a href="http://codefluency.com/">Bruce Williams </a>posted the cool RubyConf 2006 logo on his <a href="http://codefluency.com/">blog</a>. </td></tr>
<tr><td><img src="http://onrails.org/files/rubyconf2006-140x85.png" border="0" height="85" width="140" alt="rubyconf2006-140x85.png" align="center" />
</td></tr>
<tr><td>9am: Streamlined, Justin Gehtland</td></tr>
<tr><td>Why Streamlined? Remove repetitiveness in web development mostly for back-end type of application. Streamlined is build on top of Ruby on Rails. Build from their needs to build client applications. Goal to bring declarative goodness of ActiveRecord to the view layer. Streamlines is not a code generator like scaffolding. He now moves on to demo an application build with the framework. Streamlined support nicely relationship management. By default a new <i>streamlined</i> folder is add at the same level than the controllers, views, and models level. The streamline folder contains StreamlinedUI class allowing the modify declaratively the default behavior and representation of the views. Note that Justing presents the new css look and feel that Streamlined supports, named 'grail', which looks way better than the prior default look and feel. The default behavior uses Ajax, this can be turned off. No views are generate by default, they are dynamically rendered. For customization that goes beyond the features provided by Streamlined, a view can be generated and customized at will and will then be used instead of the generic view. Supports the acts_as_authenticated plugin, and provides user preferences. Justin now shows some upcoming features, like model specific behavior, layer specific field, tabbed views, multiple windowing toolkits, visual configuration.
</td></tr>
<tr><td>YARV: on Rails? by Koichi SASADA </td></tr>
<tr><td>He starts with a tour on how Ruby activities in Japaon, from the RubyConf, to books and magazines. Japanese are very enthusiastic about Ruby. He mentions the <a href="http://translate.google.com/translate?u=http%3A%2F%2Fjp.rubyist.net%2Fmagazine%2F&langpair=ja%7Cen&hl=en&ie=UTF-8&oe=UTF-8&prev=%2Flanguage_tools">Rubyist magazine</a> (this is the link to the google translated version). He now moves on to YARV (Yet Another Ruby Vm). Which is going to be the new interpreter, which will have several advantages and optimizations. The demo continues buy showing a Rails application running on Yarv. YARV passes most of tests, but make 'test/test-all' still reports some errors. He demystifies some of the myth related to yard and mentions that Yarv is not a Silver Bullet. It doesn't make all programs 50 times faster, nor makes you slim and rich. The whole presentation is pretty funny. </td></tr>
<tr><td>You got your Ruby in my CLR!, by John Lam</td></tr>
<tr><td>no comments for that one...I was heads down coding...</td></tr>
<tr><td>USS Ruby</td></tr>
<tr><td>Where Star Treck joins Ruby. A one man act, somebody is taping this...I gotta find that link, it's too funny.</td></tr>
<tr><td>Summer of Code 2006 - Google & Ruby Central, Inc.</td></tr>
<tr><td>Austin Zigler was one mentor of the summer of code. He presents the principles of the Summer of code. 17 volunteers reviewed 96 applications for projects. 84 projects where eligible. 25 found a mentor, and google accepted 10. 3 of projects will be presented here. Ariel, A Ruby Information Extraction Library, train a program how to scan web pages. Root Port, Makerf, .....<br/>
<strong>1.</strong> Gregory Brown presents his project, Ruby Reports (<a href="http://ruport.infogami.com/">ruport</a>). Plays also nice with Rails via acts_as_reportable. Gregory is not a Rails programmer, but wanted to get a plugin out there and let it grow.
<pre>
class ChunkyBacon < ActiveRecord::Base
acts_as_reportable
end
class MyReport < Ruport::Report
prepare do
@table = ChunkyBacon.report_table(:all)
end
generate do
@table.to_s
end
end
</pre>
There are many features like graph generation, pdf support for Ruport, so check it out.<br/>
<strong>2.</strong> Rockin' the Pcoket - Ruby on Phones, by Jeff Hughes. He is just another Ruby Hacker that likes phones. He went with Symbian, Nokia mostly. Based on Python for Symbian open source project. Perl did it too. His motivation where that the phone is the ideal platform, every body has one, it's always connected, but where is Ruby. 2 weeks just to get it to compile. Another 2 weeks for linking. He is new to Ruby internal, in one summer he came out with a working prototype. Today, the core interpreter, a simple and basic file io. Future development: GUI, Symbian modules (socket, bluetooth, messaging). Matz is very excited about this project. See<a href="http://ruby-symbian.rubyforge.org/"> http://ruby-symbian.rubyforge.org/</a>
<br/>
<strong>3.</strong> Jason Morisson - <a href="soc.jayunit.net">Type inference & Code Completion for RDT</a> Well, I didn't follow this talk as I was talking with Laurent Sansonetti about RubyOSA as I am waiting eagerly for the WebKit bindings.
</td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
</table>
<strong>That's all Folks. Another great Ruby conference is under wrap.</strong>
RubyConf 2006 - Day 22006-10-21T00:00:00-07:00http://onrails.org/2006/10/21/rubyconf-2006-day-2<table>
<tr><td>9am - Open Classes, Open Companies,by Nathaniel Talbott </td></tr>
<tr><td>
In this talk Nathaniel reflects upon how features of the Ruby language that make it so efficient can be applied to business. Duck Typing, Interpreted language, Flexibility, Succinctness, Reflection, Open classes. It's a great way to present business concepts to a bunch of Ruby developers. Obie also wrote down some <a href="http://jroller.com/page/obie?entry=nathaniel_talbott_open_classes_open">notes</a>.
</td></tr>
<tr><td>10am - Mac OS X and Ruby, by Laurent Sansonetti</td></tr>
<tr><td>Laurent is from Apple. Author of 5 Ruby libraries and maintains Ruby inside of OSX. For OSX Leopard, Ruby will be bundled as an OSX framework (Ruby.framework). Support 64bit, universal binary. IRB history support and line editing. Bundle gems (Rake, Rails, Mongrel, Capistrano, Libxml2, SQLit3, DNSDD,...). Ruby can control scriptable applications.
<pre>
1. RubyAEOSA: app = OSX:AEDesc.application('iTunes')
2. Applescript using RubyAEOSA: result = OSX.do_osascript "tel application 'iTunes'...
3. RubyOSA: new project since June 2006. puts OSA.app('iTunes').current_track.name
</pre>
RubyOSA is the successor of RubyAEOSA, and is simpler to use and still efficient.
<pre>
require 'rbosa'
itunes = OSA.app('iTunes')
itunes.play
# Let increase the volume...
100.times { |i| itunes.sound_volume = i; sleep 0.1 }
</pre>
He will release version 0.1.0 today, it will be available as a gem.<br/>
Now onto Cocoa. RubyCocoa, is not Cocoa specific can be used to bridge Ruby with Objective-C code. Is widely used in free and commercials products. Laurent now demos a small Cocoa application written using XCode, in Ruby, to select and control songs in iTunes.
</td></tr>
<tr><td>Rinda in the real world, by Glenn Vanderbug</td></tr>
<tr><td>Rinda is based on Linda, a distributed coordination system. Similar to JavaSpaces. Communication based on Drb.</td></tr>
<tr><td>Lightning Talks</td></tr>
<tr><td>Josh Susser having the flu, his session has been replaced by 9 x 5 minutes presentations.<br/>
1. kylemaxwell.com - I missed this presentation.<br/>
2. Ara T. Howard - ruby queue. Ruby based linux clustering solution used at NORA. nfs priority queue sqlite ruby.<br/>
3. Ben Bleything Shell-Style history for irb (in 75 lines). See at <a href="http://blog.bleything.net/">blog.bleything.net</a><br/>
4. Andre Louis - wifi.earthcode.com. A community Wifi Cafe Listings allowing to enter cafes and ratings for working condition. Great site for the Rails developer on the go. Currently listing more than 1000 entries. With a open source zoom control for google maps.<br/>
5. Ryan Davis - Hoe. A tool to compliment rake.<br/>
6. Daniel Burger - Win32Util project. Memory Mapped IO on Windows with Ruby.<br/>
7. Aaron Patterson, <a href="http://tenderlovemaking.com/">http://tenderlovemaking.com</a> (despite the site url, can be viewed at work). The presentation is named "I saw the sign" - Control a electrical sign panel from Ruby.<br/>
8. Charles Nutter - JRuby - presents the functionality of JRuby (0.9.1)<br/>
9. Charles Queen, James Grey - Heartbeat. Deploy your application from a web page. Using Capistrano and Rake tasks. see <a href="http://highgroove.com/">http://highgroove.com/</a><br/>
10.Bryan Takita - <a href="http://rubyforge.org/projects/fjson/">FJSON</a>, Fast JSON.<br/>
</td></tr>
<tr><td>Web 2.0 Beyond the Browser, by Rich Kilmer</td></tr>
<tr><td>Rich is presenting a Ruby based desktop runtime with a Rails based central service, named Indi. The UI is build in Flash.</td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
</table>
Lot's of good information can be found on these blogs:
<ul>
<li><a href="http://blog.nicksieger.com/">http://blog.nicksieger.com/</a></li>
<li><a href="http://www.halostatue.ca">http://www.halostatue.ca</a></li>
</ul>
RubyConf 2006 - Day 12006-10-20T00:00:00-07:00http://onrails.org/2006/10/20/rubyconf-2006<table>
<tr><td>Thursday night the crew (Chad, Rich, ..) preparing the name tags.</td></tr>
<tr><td><img src="http://onrails.org/files/nametags.jpg" border="0" height="166" width="208" alt="nametags.jpg" align="right" />
<img src="http://onrails.org/files/nametags2.jpg" border="0" height="166" width="208" alt="nametags2.jpg" align="right" /></td></tr>
<tr><td>It's starting stay tunned.</td></tr>
<tr><td><img src="http://onrails.org/files/RubyConfDenverLogo.jpg" border="0" height="102" width="153" alt="RubyConfDenverLogo.jpg" align="right" /></td></tr>
<tr><td>8:57am The room is pretty full.</td></tr>
<tr><td><img src="http://onrails.org/files/starting.jpg" border="0" height="180" width="240" alt="starting.jpg" align="right" /></td></tr>
<tr><td>RubyConf T-Shirt && Lee</td></tr>
<tr><td><img src="http://onrails.org/files/lee.jpg" border="0" height="180" width="240" alt="lee.jpg" align="right" /><br/>T-Shirt design by Bruce Williams.</td></tr>
<tr><td>Erlang: The Movie</td></tr>
<tr><td>We are in advance on the schedule, so Rich Kilmer decided to show a video on scripting languages that is in the same vain as DHH's webcast that really brought TextMate and Ruby on Rails into limelight. You can see it on youtube
<a href="http://video.google.com/videoplay?docid=-5830318882717959520">here</a>. Erlang is 10x more productive, 7x shorter programs. :-)</td></tr>
<tr><td>10am: The History of Ruby, by Masayoshi Takahashi</td></tr>
<tr><td>Why is Takahashi presenting The History of Ruby and not "matz"? Because Matz loves the Ruby, not the history of Ruby. By the way Masayoshi is the inventor of the <a href="http://presentationzen.blogs.com/presentationzen/2005/09/living_large_ta.html"> Takahashi "Method"</a><br/>
This presentation is a detailed and well informed recollection of how the Ruby community was created and spread from Japan to the rest of the world. Here are Lee's notes that will give you an idea but don't give justice to the presentation it self:<br/>
<pre>
History of Ruby - Masayoshi Takahashi (from the Takahashi Method)
- 5 periods of Ruby history
- Pre-history
- Feburary 24, 1993 - "Ruby" name proposed by Keiju
- Ancient Age
- Ruby 0.95 released December 21, 1995
- "Rubyist" first used August 9, 1996
- Middle Age
- Ruby spread in Japan since all the developers spoke
Japanese, developers could learn English (for other
languages) or learn Ruby
- Modern Age
- Ruby outside Japan
- 2/16/2002 - English ML volume overtook Japanese ML
- Contemporary Age (Rails Age)
- RoR - The killer application on Ruby
</pre>
</td></tr>
<tr><td>11am: Sydney & Rubinius - An experiment in improving, by Evan Phoenix (a.k.a Evan Webb)</td></tr>
<tr><td>
<pre>
- Current interpreter: dump truck - reliable, sometimes slow,
can throw everything in it
- YARV: fire engine - shiny and fast
- Rubinius: Dune buggy - fun but you'll get sand in your eyes
- Simple == Powerful
- Sydney
- What was it?
- giant patch to 1.8.2
- reentrant and threadsafe
- Hit dead end
- Rubinius
- Prototype A
- ported most of Smalltalk blue book to Ruby
- worked but slow
- Prototype B
- implemented bytecode interpreter and compiler
- Prototype S
- hand translation of proto-B into C code
- Evan has a nice conversational style to his talk
- SegfaultProtection
- protects extensions from crashing
- turns a segfault into a raised exception
- Bytecode interpreter architected via TDD
</pre>
</td></tr>
<tr><td>1:30pm Programming Graphics with Ruby, by Geoffrey Grosenbach</td></tr>
<tr><td>The presentation went through many visual examples, showed the code behind some of them. The presenter mentioned the following libraries: Scruffy - generates SVG, gnuplot, mrplot, asset_compiler from Jeremy Voorhis - Rake tasks for image manipulation, and his own library Gruff (which is pretty cool), sparkline. He went on showing how the different screencast headers on peopcode.com are generated using RMagick.</td></tr>
<tr><td>2pm: Life After mkmf, Kevin Clark</td></tr>
<tr><td>Iron Mongrel: Fuzzing, Auditing, Thrashing, Risk and The Ways Of Mongrel Destruction, Zed Shaw</td></tr>
<tr><td>More notes to come, my neighbor at the conference and former colleague Tom is taking good notes...I will point to his blog as soon as he gets a network connection. Also check out <a href="http://www.nicholaswright.org/blog/articles/2006/10/20/rubyconf-2006-day-1-part-1">Nick Blogs</a>. We gave him so much crap after RailsConf where he was bragging about how much he would blog on it and didn't do any writing that he is currently trying to prove us wrong, but provides some good information.</td></tr>
<tr><td>7:30pm - Yukihiro "matz" Matsumoto Roundtable</td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
</table>
Note that as you notice the picture are taken with a phone or photobooth.
From RubyConf 2005 to RubyConf 20062006-10-18T00:00:00-07:00http://onrails.org/2006/10/18/from-rubyconf-2005-to-rubyconf-2006RubyConf is a great point in time to have a retrospective on the past year. And what at year it was.
<p>
<style>
.timeline table {
_border:none;
padding: 5px;
}
.timeline td {
border-left: 1px solid #dcdcdc;
}
.timeline th {
text-align: right;
vertical-align: top;
white-space:nowrap;
}
</style>
<table class="timeline" >
<tr>
<th>2005 October</th>
<td>Started my first paid Ruby On Rails consulting gig to create an eCommerce platform for <strong>Gatelys</strong>. </td>
</tr>
<tr>
<th>October 14th-16th</th>
<td><strong>RubyConf 2005</strong> in San Diego, very technical. The creator and some of the key players in making Ruby were there: Yukihiro "<strong>matz</strong>" Matsumoto, Akira Tanaka, Koichi Sasada... While at the conference I started implementing <strong>time.onrails.org</strong> and started using it internally to log all my consulting time.</td>
</tr>
<tr>
<th>October 19th</th>
<td>Lee and I launched <strong>AutumnRidersTees.com</strong>, our first Ruby on Rails online eCommerce website, created for Lee's dad.</td>
</tr>
<tr>
<th>2006</th>
<td> </td>
</tr>
<tr>
<th>March</th>
<td>Gatelys deploys internally the order fulfillment section of their eCommerce Platform.</td>
</tr>
<tr>
<th>April</th>
<td>Based on the success off the first part of the eCommerce platform at Gatelys they asked me to work full time on their project. <strong>27th of April: </strong>deployed www.nationaltabletennis.com, the first public facing part of the application went life. Since October I also had spend about 50 development hours on time.onrails.org and thought it was getting pretty usable. So on the <strong>13th of April</strong>, I launched time.onrails.org.</td>
</tr>
<tr>
<th>June</th>
<td>Started working on <strong><a href="http://voisen.org/archives/2006/08/28/maestro-documenting-a-web-20-startup/">Maestro</a></strong>, a new kind of multimedia-based learning platform written in Ruby on Rails. At that point I was over committed with all the different gigs I said yes to. Hopefully I learned a lesson from that. However Maestro was fun and invigorating to work on and you saw it in the results. We spend about 30 hours each in June with Lee and where able to put together an impressive Application under the lead of Sean Voisen. Rails really rocks. <strong>June 21th</strong>: my birthday and <strong>RailsConf 2006</strong>. It was impressive to see how positive the spirit of everyone was at that conference. More than 700 people attended, the rooms where packed, the presentations where just awesome.</td>
</tr>
<tr>
<th>September</th>
<td>Integrated time.onrails.org with <strong>Blinksale</strong> using their <strong>RESTFull</strong> API.</td>
</tr>
<tr>
<th>October</th>
<td><p><strong>Time.onrails.org</strong> has now 475 registered users, I estimate around 100 active users. Thanks to everyone who tried the application out, and especially for the users that provided feedback. I started working on the next version, it is a complete rewrite, but will stay as easy to use, with several valuable new features. <strong>Gatelys</strong> deploys Gatelys.com, their flagship store using the eCommerce platform. More than 13 of their high volume stores are now powered by Ruby on Rails. I can tell you, Rails scales. <strong>RubyConf 2006</strong> is in just two days. I hope I'll see you there...I am the other Denver Ruby on Rails developer with a French accent. Swiss-French accent to be more precise. </p>
<p align="center"><strong>See you at RubyConf! </strong></p></td>
</tr>
</table>
Time.onrails.org now with Blinksale integration.2006-10-05T00:00:00-07:00http://onrails.org/2006/10/05/time-onrails-org-now-with-blinksale-integration<p>Blinksale is the easiest way to send invoices online. Now time.onrails.org is the easiest way to create Blinksale invoices. Check <a href="http://time.onrails.org/doc/blinksale/blinksale.html">http://time.onrails.org/doc/blinksale/blinksale.html</a> for more details.</p>Blinksale API2006-10-02T00:00:00-07:00http://onrails.org/2006/10/02/blinksale-api<p>Today Blinksale published it’s data <span class="caps">API</span>. See <a href="http://www.blinksale.com/api/">http://www.blinksale.com/api</a> for the details.</p>
<p>It’s good news for time.onrails.org as now we can use the api to generate a draft Blinksale invoice with one click. I have started coding the integration and expect to release it once I have completed extensive testing.</p>
<p>In short, time.onrails.org interacts in the following way with Blinksale:</p>
<ol>
<li>get list of client names</li>
<li>get highest invoice number</li>
<li>create invoice</li>
</ol>
<p>Let’s have a peek at how this is implemented.</p>
<p><strong>Accessing Blinksale</strong></p>
<p>A <em>Blinksale</em> class is provided to interact with your Blinksale data. You need to provide your blinksale id, username, and password.</p>
<typo:code>
<p>@blinksale = Blinksale.new ‘blinksaleid’, ‘username’, ‘password’</p>
</typo:code>
<p>In time.onrails.org we will let you define your Blinksale credentials once to avoid having to retype them each time you create an invoice. Storing the password is optional, and if not provided it will be prompted each time. A <em>use_ssl</em> flag can also be specified if you have a paid Blinksale subscription. This is of course recommended for security reasons.</p>
<p><strong>Get the list of clients</strong></p>
<typo:code>
<p>clients = @blinksale.clients<br />
names = clients.collect { |c| c.name }</p>
</typo:code>
<p><strong>Get the highest invoice number</strong></p>
<typo:code>
<p>invoices = @blinksale.invoices<br />
invoices.collect{|invoice| invoice.number}.max</p>
</typo:code>
<p><strong>Create An Invoice</strong></p>
<typo:code>
<p>invoice_data = BlinksaleGenerator.to_xml(<span class="caps">INVOICE</span>)<br />
new_invoice = @blinksale.invoices.new invoice_data<br />
new_invoice.save</p>
</typo:code>
<p>BlinksaleGenerator is a time.onrails.org class that helps creating the following ‘invoice’ xml.</p>
<pre>
<?xml version="1.0" encoding="UTF-8"?>
<invoice>
<client>http://#{blinksaleid}.blinksale.com/clients/#{@client_id}</client>
<number>34</number>
<date>2006-09-27</date>
<terms>30</terms>
<currency>USD</currency>
<lines>
<line>
<name>Consulting</name>
<quantity>2.0</quantity>
<kind>Hours</kind>
<unit_price>150.00</unit_price>
<taxed>false</taxed>
</line>
</lines>
</invoice>
</pre>
<p>The integration is pretty straight forward. Don’t you think? Thanks Scott and your team for this cool application. To find out more on the blinksale api see the online documentation at <a href="http://www.blinksale.com/api">http://www.blinksale.com/api</a></p>UPDATED: time.onrails.org - new features, fast server.2006-09-05T00:00:00-07:00http://onrails.org/2006/09/05/updated-time-onrails-org-new-features-fast-serverTime.onrails.org, the simplest and most efficient time tracking application out there, just got better! <br/>
<br/>
<b>Speed:</b> We moved it to a new server. The application is now really responsive!<br/>
<b>More Projects:</b> We also took the opportunity to extend the number of projects you can manage from 4 to 12 projects and sections from 12 to 52.<br/>
<b>Sorting and Filtering:</b> Added new functionality like project reordering and filtering.<br/>
<b>Project Sharing:</b> You can now share a read-only view of your projects for your customers or coworkers.<br/>
<br/>
So, no time to loose, <a href="http://time.onrails.org">go try it out</a> and let us know what you think.
Contract to hire UI Designer for Rails Project2006-09-02T00:00:00-07:00http://onrails.org/2006/09/02/contract-to-hire-ui-designer-for-rails-projectNo we are not turning into a job board or "placement" company. We are just lucky to work with some pretty brilliant people on some pretty cool Rails project that are taking off. So, one of my customers is looking for a UI and Flash Designer. You can find more info regarding the position here (http://voisen.org/archives/2006/08/28/hiring-ui-and-flash-designer/). You can also find some background and insight on this project here (http://voisen.org/archives/2006/08/28/maestro-documenting-a-web-20-startup/) and here (http://voisen.org/archives/2006/07/19/summer-of-rails/). In brief, it's a pretty cool eLearning project that will really shine through it's content that will be amplified by a discreet and powerful web presence. All that driven and based on Ruby on Rails.
<p/>
So if you are exceptional UI designer send your resume and portfolio to sean (- at -) eluminate (- dot -) net.
Namespaces and Rake Command Completion2006-08-30T00:00:00-07:00http://onrails.org/2006/08/30/namespaces-and-rake-command-completion<strong>Update:</strong> <a href="http://onrails.org/articles/2006/11/17/rake-command-completion-using-rake">Now using rake and caching</a>
<p>I got some basic rake command line completion working today using Jon Baer’s <a href="http://weblog.rubyonrails.org/2006/3/9/fast-rake-task-completion-for-zsh#comment-2361">comment</a>. Very simple, very easy:</p>
<typo:code>
complete -W '`rake—silent—tasks | cut -d ††-f 2`' -o default rake
</typo:code>
<p>However this didn’t work for the namespaced tasks in a rails app like <code>rake test:units</code>. Searching a little further I found a reference to some code <a href="http://i.conio.net/rake-completion.rb">Nicholas Seckar</a> wrote on <a href="http://project.ioni.st/post/212">project.ioni.st</a>. This used ruby to find the possible tasks for command completion. This looked promising, but it still didn’t work for namespaced tasks. A little more googling led me to what looked like the perfect link: <a href="http://www.webtypes.com/2006/03/31/rake-completion-script-that-handles-namespaces">Rake-completion script that handles namespaces</a>. Alas, it only handled one level of namespacing. It worked nicely for <code>rake test:units</code>, but <code>rake tmp:ses<TAB></code> would complete to <code>rake tmp:clear</code> instead of <code>rake tmp:sessions:clear</code>. Also, <code>rake test:units <TAB></code> would complete to <code>rake test:units units</code> instead of giving me all the tasks again, just in case you want to run multiple tasks form the command line.</p>
<p>So, now what? Stand on the shoulders of others, naturally. Here is what I’m using now that handles multiple namespaces and multiple tasks per command line:</p>
<typo:code lang="ruby">
#!/usr/bin/env ruby
# Complete rake tasks script for bash
# Save it somewhere and then add
# complete -C path/to/script -o default rake
# to your ~/.bashrc
# Nicholas Seckar <nseckar@gmail.com>
# Saimon Moore <saimon@webtypes.com>
# http://www.webtypes.com/2006/03/31/rake-completion-script-that-handles-namespaces
exit 0 unless File.file?(File.join(Dir.pwd, 'Rakefile'))
exit 0 unless /^rake\b/ =~ ENV["COMP_LINE"]
after_match = $'
task_match = (after_match.empty? || after_match =~ /\s$/) ? nil : after_match.split.last
tasks = `rake --silent --tasks`.split("\n")[1..-1].collect {|line| line.split[1]}
tasks = tasks.select {|t| /^#{Regexp.escape task_match}/ =~ t} if task_match
# handle namespaces
if task_match =~ /^([-\w:]+:)/
upto_last_colon = $1
after_match = $'
tasks = tasks.collect { |t| (t =~ /^#{Regexp.escape upto_last_colon}([-\w:]+)$/) ? "#{$1}" : t }
end
puts tasks
exit 0
</typo:code>
<p><a href="http://onrails.org/files/rake-completion.rb">Enjoy</a></p>
Full time Ruby On Rails Job in Denver.2006-08-18T00:00:00-07:00http://onrails.org/2006/08/18/full-time-ruby-on-rails-job-in-denver<p>One of my customers in Denver is looking for an experienced full-time Rails developer. The company is called , Gatelys/Etail Source. You will be part of a small, experienced, and agile development team that has developed three pretty cool Rails eCommerce applications. This is the posting they published on the job board of 37signals (http://jobs.37signals.com/jobs/323):</p>
<p class="meta">
<p><b>Description</b><br />

Small (but quickly growing) eCommerce startup seeks enthusiastic full-time senior-level Rails developer / system engineer. Special focus on performance optimization and tuning. Denver area resident preferred, but not mandatory. Salary will be competitive, depending on qualifications.<br/>
<b>To apply</b><br />

Send resume and salary requirements to jobs@gatelys.com, attention Solomon.</p>
</p>Short circuiting partials2006-08-15T00:00:00-07:00http://onrails.org/2006/08/15/short-circuiting-partialsI tend to think of partials as mini-components. I don't like it when the page using the partial "knows" too much about what's in the partial. For instance, if your partial displays a collection of things but shouldn't display anything if the collection is empty, then you'll usually see something like this:
<typo:code>
outer page stuff...
<% unless some_object.has_many_things.empty? %>
<h3>My collection of stuff</h3>
<%= render :partial => 'my_partial', :locals => { :collection_of_stuff => some_object.has_many_things } %>
<% end %>
more outer page stuff...
</typo:code>
The outer page has to know which collection of things the partial is going to use and performs some display logic around that. Shouldn't this all be contained in the partial? The outer page should just know that it is going to use a partial and that's it. So our outer page will look like this:
<typo:code>
outer page stuff...
<%= render :partial => 'my_partial', :locals => { :some_object => some_object } %>
more outer page stuff...
</typo:code>
Now it looks like a self-contained component. Good. Of course, we now have to put that outer display logic in the partial.
<typo:code>
<% unless some_object.has_many_things.empty? %>
<h3>My collection of stuff</h3>
<% some_object.has_many_things.each do |o| %>
do some stuff with <%= o %>
<% end %>
<% end %>
</typo:code>
Now the messy part is the big <code>unless</code> block around the whole partial. I'd like to just short circuit the whole page if there's nothing to display, similar to what I do in normal methods:
<typo:code>
def do_something(some_arg)
return nil unless some_arg
do_something_cool_with_some_arg
end
</typo:code>
Can it be as simple as putting a <code>return</code> statement in our partial? It turns out, yes, it is that easy.
<typo:code>
<% return if some_object.has_many_things.empty? %>
<h3>My collection of stuff</h3>
<% some_object.has_many_things.each do |o| %>
do some stuff with <%= o %>
<% end %>
</typo:code>
Wow! One whole line shorter. It doesn't look like much in this small contrived example, but I think it makes the purpose of the partial clearer and doesn't clutter up the calling page. Give it a shot.
Dreamhost out, Slicehost in.2006-08-04T00:00:00-07:00http://onrails.org/2006/08/04/dreamhost-out-slicehost-in<p>I must say I like Dreamhost but we had too much downtime recently. Even if we offer time.onrails.org for free it must be up and running when the users need it. This is especially true for a time management application. When you are done with your workday, one click and go home. Lee and I are using time.onrails.org daily for all of our customer projects and recently it has been down once too many time. In addition it’s getting really slow, but then again with a $9 a month shared host plan, I must admit we went already a long way. So time to move on and find a better solution.</p>
<p>We went the last two days on the search for a new hosting provider that would provide dedicated or virtual private servers. There is lots of offerings out there and good information. Lee stumble upon slicehost.com and liked the idea of a small hosting company, that diggs Ruby on Rails, and is about to be launched. They are small and hopefully will work hard to make it. I was not too convinced so we decided to contact them, and had a nice chat with them over their campfire support room. See the <a href="http://onrails.org/files/20060804_slicehost.html" >campfire transcript</a>. I gave them a hard-time, but they provided us with lots of good information. Check them out if you want to find out what’s going on at <a href="http://slicehost.com/">slicehost</a></p>
<p>Transcript: <a href="http://onrails.org/files/20060804_slicehost.html">http://onrails.org/files/20060804_slicehost.html</a></p>
<p>So time.onrails.org users, thank for your patience. In the next month we will move over our application to a way faster environment.</p>
<p><strong>Update:</strong> time.onrails.org has been moved. If you sign up with slicehost because of us, feel free to say we referred you. :) Just use this <a href="https://manage.slicehost.com/customers/signup?refferer=629092">referrel link</a>.</p>RailsLogAnalyzer – help wanted2006-08-03T00:00:00-07:00http://onrails.org/2006/08/03/railsloganalyzer-–-help-wanted<p>I need some Mac users to test and give feed back on a very early version of the RailsLogAnalyzer. This app is an <span class="caps">OSX</span> app and not deployed on a server, so I would like to find out the obvious bug that may occur on different Macs. I tried it on my own MacBook Pro, G5 server, and on an old PowerBook G4. But then again the people most likely to use it are Rails developers that may have differences in their environment.</p>
<p>So if you like to take risks :-), understand the basic structure of a Rails app, have a production.log you want to analyze, and are not afraid of some scary bugs then read on…</p>RailsAnalyzer - visualize your Ruby on Rails production log2006-08-03T00:00:00-07:00http://onrails.org/2006/08/03/Download Application:<br/>
<a href="http://onrails.org/pages/RailsLogAnalyzerUserGuide.html" target="_blank">User Guide</a>
Two new eCommerce sites driven by Ruby on Rails.2006-07-27T00:00:00-07:00http://onrails.org/2006/07/27/two-new-ecommerce-site-driven-by-ruby-on-railsWhile I was zipping a drink at the pool in Spain and visiting friends and family in Switzerland, the team at Gatelys.com was busy designing and configuring two new ecommerce stores using the Rails eCommerce platform I worked on while a Gatelys. And they have many more ecommerce sites to come.<p/>
<a href="http://sleekspaces.com" >www.sleekspaces.com</a> and
<a href="http://raysgolfshop.com" >www.raysgolfshop.com</a>
<p/>
Rails is open for some serious business. <p/>
Note that most of the logos, graphics and layouts are done by Lomax which is the best graphic designer I know. Now if only I could find a way to hire him away :-)
<p/>
<a href="http://sleekspaces.com" >
<img src="/files/20060727_sleekspaces.com.gif" /></a>
<a href="http://raysgolfshop.com" ><img src="/files/20060727_raygolfshop.jpg" /></a>
<p/><p/>
This complements www.nationaltabletennis.com that was launched a couple of months ago:<p/>
<a href="http://www.nationaltabletennis.com" ><img src="/files/20060727_ntt.gif" /></a>
Fowler on RubyGems2006-07-20T00:00:00-07:00http://onrails.org/2006/07/20/fowler-on-rubygems<p>Since Daniel came back from Europe, I figured I’d finally pick up his slack and write an entry. :)</p>
<hr />
<p>Last night I went to the <a href="http://rubyforge.org/projects/bdrg/">Boulder-Denver Ruby Group</a> where Chad Fowler spoke about all things <a href="http://docs.rubygems.org/">RubyGems</a>. It was a laid back talk with a recap of gems past, present and future. Pre-RubyConf 2003 the ruby-talk list would get peppered with questions like <quote>“Where is Ruby’s <span class="caps">CPAN</span>?”</quote> <p>At RubyConf 2003, when put on the spot by <a href="http://dablog.rubypal.com/">David A. Black</a> about the topic, <a href="http://en.wikipedia.org/wiki/Yukihiro_Matsumoto">Matz</a> basically said <quote>"if you build it, it will be included in ruby core.</quote> That led <a href="http://www.onestepback.org/">Jim Weirich</a>, <a href="http://richkilmer.blogs.com/">Rich Kilmer</a>, Black, and Fowler to spend the next night coding what would become the RubyGems. They even demo-ed it at the conference. It has grown quite a bit since then and now could be called the de facto standard for library distribution in Ruby.</p>
</p>
<p>The latest version of RubyGems is 0.9.0, which has some not so minor scalability improvements. To get the latest version simple run <code>gem update --system</code>. Since RubyGems isn’t in core yet, you still need to <code>require 'rubygems'</code> or set your <code>RUBYOPT</code> environment variable to <code>rubygems</code>. There is another way when starting ruby you can pass it the <code>-rubygems</code> argument. <quote>“But you said it wasn’t in <em>core</em>… if it’s not in core, why does it have it’s own argument for the ruby interpreter?”"</quote> <p>It’s true, it’s not in core. This is actually just a little trick by Chad et al to make it look it is part of ruby. The <code>-r</code> argument tell ruby to require whatever parameter follows, so the gem crowd made an <code>ubygems.rb</code> file that only has one line of code in it … <typo:code lang="ruby">require ‘rubygems’</typo:code> … and from that comes <code>ruby -rubygems</code>.</p>
</p>
<p>Bundled with gems is its own <code>gem_server</code>. Firing this up starts up a WebBrick server on port 8808 by default. Going to <a href="http://localhost:8808">http://localhost:8808</a> will then display all of the gems you have installed and even link to the rdoc installed locally if it exists and to the docs on the web. It also can serve gems if you wish. This means other machines could point to your gem_server and install any of the gems that you have installed. You do this with the <code>--source</code> argument. Others could search what gems you have by running <code>gem search -r --source http://your_machine:8808 search_string</code>. There is even a tool <code>index_gem_repository.rb</code> that will create a directory that can be served by apache as a gem server, in case you want something a little beefier than webrick.</p>
<p>One interesting idea that Chad mentioned was making a meta-gem for your projects. All the gem would declare is its dependencies on the other gems that your project needs. That way when setting up a new machine you can just install your meta-gem from your gem_server and then it will automatically install all the necessary gems. <strong>Pretty cool.</strong></p>
<p>Chad did a good job of describing how gems came to be and guiding us through some of the code with some nice anecdotes along the way.</p>
<hr />
<p>P.S. The coolest part of the night was I’m going to be a volunteer at RubyConf `06! Chad was quick to warn me that there is no glamour involved. Oh well, I’m excited anyway.</p>Pickin' up the slack2006-06-28T00:00:00-07:00http://onrails.org/2006/06/28/pickin-up-the-slackI guess I'll have to try to pick up the slack while Daniel's trekking around Europe. In case you don't know, I'm the guy named Lee that Daniel mentions from time to time.
Hopefully, I'll be able to fill some space here with some useful tidbits about Rails, Ferret, and whatever else looks interesting.
Have a great vacation, Daniel. We'll leave the light on for ya.
June - Rails Month2006-06-28T00:00:00-07:00http://onrails.org/2006/06/28/june-rails-monthJune was one of these 'Rails' month...With Lee we took on a new Rails project in the e-learning arena for some people with some really cool ideas. They wanted a html prototype at the end of the month, and overly optimistic as I am, I said why just a prototype, let's build the real thing. And we did. Now there is more to the application before it can go life than what we just build, but we managed to go from concept to a real working front-end in an extremely short time. Wired frame UI, intense object modeling discussions, html prototype, then build it with Rails. Rails just get's out of your way and let's you build a web application as fast as your brain allows :-) We where really surprised how fast a great application can be build. This was only part time, as my main project is working on gatelys.com new ecommerce platform. An astonishing Rails application. I also worked a little on RailsLogAnalyzer, a 'Rails production log' visualization application using Rails and Flex on OSX. But for that one I will wait that the Flash Player 9 is out for OSX Intel. Then RailsConf 2006. That was awesome, meeting 700 Rails enthusiasts, the Rails core team, and many Rails developers from the Denver area. I can just say: "Rails has a bright future!". But now is time for me to sit back, relax. I'll be on vacations for most of July. So see you then!
Streamlined - Will ROCK the Rails World2006-06-24T00:00:00-07:00http://onrails.org/2006/06/24/streamlined-will-rock-the-rails-world<a href="http://streamlined.relevancellc.com/">Streamlined</a> is an open source framework for quickly creating data-centric applications with Ruby on Rails.
Today Justin Gehtland announced during his 'Ajax on Rails' talk that Streamlined will be released at OSCON in July. I can best describe Streamlined as 'dynamic scaffolding' done right. Streamlined is a model driven way of generating data centric UI's. Justin demoed how to create and modify a data entry application. It provides search, crud functionality, support relationship between model, and way more. The framework adheres to the convention over configuration approach and provides a default behavior of the application than can easily be refined and enhanced. As opposed to scaffolding it doesn't generate code for the controller but provides a basic behavior. This will <strong>ROCK</strong> the software development world and accelerate many projects.
<p/>
<strong>From the Streamlined website:</strong>
<br/>
In the Abendsen release, Streamlined has been focused on solving the problems of our customers and our internal projects. Right now, Streamlined is focused on:
<ul>
<li>Generator for churning out the initial views and configuration</li>
<li>A declarative DSL for managing views, including relationship management, field selection, etc.</li>
<li>Full Ajax-enabled management views with sorting, paging and live search (with configurable field-inclusion)</li>
<li>A criteria query extension to Active Record</li>
<li>Context-sensitive help</li>
<li>An extensible component system for representing relationships at runtime</li>
<li>Export to xml/csv</li>
<li>REST-ful web service layer around all models</li>
<li>Atom support</li>
<li>Auto user-management and inclusion of declarative role-based authorization</li>
<li>Choice of layouts (Yahoo Grids or CSS Framework)</li>
<li>Theme support</li>
<li>Includes Javawin for in-browser windowing</li>
</ul>
<br/>
This is the feature set we'll release at OSCON in July.
RailsConf 2006 - Here we come!2006-06-20T00:00:00-07:00http://onrails.org/2006/06/20/railsconf-2006-here-we-comeLooking forward meeting you all in Chicago! There will be tons of great presentations, here is my selection:
<p/>
<table>
<tr><th>Friday </th></tr>
<tr><td> 10:45 </td><td> Introduction to Capistrano </td></tr>
<tr><td/><td> Mike Clark is just a great presenter </td></tr>
<tr><td> 13:15 </td><td> ?? </td></tr>
<tr><td/><td> Not sure yet </td></tr>
<tr><td> 14:30 </td><td> Monitoring Rails Applications in Production Environments </td></tr>
<tr><td/><td> Too important to skim that one </td></tr>
<tr><td> 15:45 </td><td> Sneaking Rails into the (legacy) system </td></tr>
<tr><td/><td> or Goeffrey's Rails Deployment on Shared Hosts</td></tr>
<tr><th> Saturday </th></tr>
<tr><td> 09:00 </td><td> Ajax on Rails </td></tr>
<tr><td/><td> Let's see what the 'man' has to say </td></tr>
<tr><td> 10:15 </td><td> Lessons from Blinksale and IconBuffet </td></tr>
<tr><td/><td> I am eagerly waiting for some information on the Blinksale API </td></tr>
<tr><td> 11:30 </td><td> Lucene Eye for the Ruby Guy </td></tr>
<tr><td/><td> We are using successfully Ferret, but Lee did all the programming, so it's time I do some catching up </td></tr>
<tr><td> 14:45 </td><td> Testing Migrations </td></tr>
<tr><td/><td> I hesitate between this and the two other talks, but I got bit a couple of time with migrations. So any good advice is welcome. </td></tr>
<tr><th> Sunday </th></tr>
<tr><td> 9:00 </td><td> Beyond DHTML: Introducing Laszlo on Rails </td></tr>
<tr><td/><td> I am big fan of Flex and Laszlo, now that Laszlo can generate DHTML, let's see what Mike has to say. </td></tr>
<tr><td> 10:15 </td><td> Just the Facts (and Dimensions) -- using Rails with your OLAP data model </td>
</tr>
<tr><td/><td> I had the chance of beeing part of a team that pionered the field before it was called that (back in 1987). And now I need to do some more data analysis for the soon to be releases OSX RailsLogAnalyser application (Flex+Rails). Looking forward to this talk. </td></tr>
<tr><td> 11:30 </td><td> Rails Takes on the Enterprise with SOA </td></tr>
<tr><td/><td> Rails is a tuff sell to the enterprise. They invested to much into Java and .Net, so even if Rails is often a good fit, it's not even considered. So any additional ammunition to enter existing enterprises is welcome</td></tr>
</table>
Derailed - Denver Ruby On Rails User Group. June 15th.2006-06-15T00:00:00-07:00http://onrails.org/2006/06/15/derailed-denver-ruby-on-rails-user-group-june-15th19:15 Doug Fales presentation: <strong>Rails by the Waypoints: Integrating a GPS Unit and a Digital Camera in the Era of the Mashup</strong>.
<p>
Doug will present this talk at RubyConf next week, so this is kind of a dry run for him in front of 25 people at the Derailed (Denver Ruby On Rails User Group) before the big event. About 5 other people from the attendance will also attend RailsConf. Cool, Denver is in force. Doug explained how he came to Rails and integrating it with GPS data, Flicker and Google maps...that's what happens when you got the crazy idea of running long distances in the middle of no where. Check out <a href="http://walkingboss.org/">http://walkingboss.org/</a> in the next month as he will release a first public version of his application. In short, you can map your walking track recorded by a gps onto a google map and also upload and link your photos to the track based on the photos time-stamps. Doug now moves onto the "What I learned" writing this application. Site note: the funny thing is that besides Ara, everyone in the attendance uses a Mac. Ok, back to the presentation. Doug sees Ruby on Rails as the glue between the data and the client-side of the application. Another challenge was writing the GPS data mangling libraries. He describes how Ruby helped writing different blocks of functionalities (Search using the Ferret gem and acts_as_ferret, the data models, tagging, ...). He then describes the cost of development, where Rails offers you lots for free. Finally, he concludes with comments on how rails allows for creativity by solving lots of mundane problems for you and allowing for to keep your momentum.
<p>
20:15 Now onto to Ara Howard's presentation: <strong>Meta Programming</strong>
<p>
Ara is usually more involved with the Boulder Ruby User Group. He is a Ruby person first, then a Rails person. He got into Ruby about six years ago, and works in all manner of application domains and is specialized in data mangling (not directly his words). He defines Meta-programming as being code that writes code. That can be at compile time or a run time. You can have reflexive meta programming where a language can be used to generate output in the same language. Ruby is a very good meta-programming language and Rails makes heavy use of meta-programming. Rather than going paraphrasing Ara, I would certainly be incorrect as he is covering lot's of ground, check out his <a href="http://fortytwo.merseine.nu/presentations/metaprogramming/slideshow.fcgi?n=0">slides</a> (this link is to his desktop, you can also find the slides at <a href="http://codeforpeople.com/">http://codeforpeople.com</a>). Note that just the slides won't provide enough background as the narration Ara provides and the code examples augments greatly these slides. So try to catch one of his talks if you can. The nice part of his presentation is that he is presenting advanced aspects of Ruby, the languages, that may be more obscures to people like me that dived into Ruby via Rails. Ruby provides lots of hooks for meta programming like module_eval, class_eval, instance_eval, define_method, eval (being evil).
<p>
<p>
Two excellent presentations. Thank guys! Now onto Rock Bottom for a beer.
Geoip data2006-06-01T00:00:00-07:00http://onrails.org/2006/06/01/geoip-dataAs part of the Rails Log Analyzer I want to show where, geographically speaking, the different users come from. The following 'ingredients' were required to achieve this:
<ul>
<li>The geoip gem by Clifford Heat</li>
<li>The GeoLiteCity.dat file download from http://www.maxmind.com/app/geolitecity</li>
<li>A vectorial world map in Flash from http://www.fabiovisentin.com/world_map/vectorial_world_map.asp</li>
<li>And the Flex mx:BubbleChart component</li>
</ul>
The result is the following
<p>
<img src="http://onrails.org/files/20060601_geoip1.gif" border="0" height="254" width="398" alt="20060601_geoip.gif" />
</p>
<p>
Note there are still some technical hurdles to overcome with the bubble chart as it behaves unexpectedly when setting the radius of the bubbles and the scaling of the world map as the background of the chart can not be precisely controlled. Also the world map needs to be zoomed in a little to make the graph more readable as not too much activity is going on at the south pole.
<p>
So now lets look at some code extracts.
<p>
<strong>Getting the geoip information [ruby]</strong>
<p>
When parsing the log we retrieve the city information related to an ip address
<typo:code lang="ruby">
require 'geoip'
geo_ip = GeoIP.new("#{RAILS_ROOT}/data/GeoLiteCity.dat")
parser.items.each_with_index do |item, index|
geo_info = geo_ip.city(item['ip'])
...
end
</typo:code>
The _city_ method returns the following array
<pre>
[ hostname, # 0 - Requested hostname
ip, # 1- Ip address as dotted quad
CountryCode[code], # 2 - ISO3166-1 code
CountryCode3[code], # 3 - ISO3166-2 code
CountryName[code], # 4 - Country name, per IS03166
CountryContinent[code],# 5 - Continent code.
region, # 6 - Region name
city, # 7 - City name
postal_code, # 8 - Postal code
latitude, # 9 - Latitude
longitude, # 10 - Longitude
]
</pre>
<p>
<strong>Generating the geo data series [ruby]</strong>
The log file data is stored in sqlite database for ease of querying and aggregation. <i>This will also allow to wrap the application as a packaged OSX application with the database embedded in the application.</i> The following called is invoked by the controller that simply return the result of the query to the Flex application.
<typo:code lang="ruby">
def Hit.sqlite_data(from_date, to_date)
result = {}
query = { :name => "geoip",
:sql => "select count(*) as count, latitude, longitude, city, state, country from hits where #{scope} group by 2,3 order by 1 desc",
:column_names => ['count', 'latitude', 'longitude', 'city', 'state', 'county']
}
result[query[:name]] = Hit.geoip_serie(data, query[:name],query[:column_names], result[:hit_count][:data][0][0].to_f)
result
end
def Hit.geoip_serie(serie, title, column_names, total_count)
result = {:title => title}
data = []
serie.each do |item|
row = {'count' => (item[0].to_f / total_count)*100,
'latitude' => item[1],
'longitude' => item[2],
'city' => item[3],
'state' => item[4],
'country' => item[5],
}
row['count'] = 3 #if row['count'] < 1
#row['count'] = 5 if row['count'] > 5
data << row
end
result[:data] = data
result
end
</typo:code>
<p>
<strong>Rendering the series [flex]</strong>
<p>
As seen in a previous article on how to exchange data between Flex and a Rails application using JSON, the server returns the data as a string that is simply transformed to an actionscript object using JSON.decode. This object is then passed to a custom component named BubbleSerieChart (I know, I find a more descriptive name)
<typo:code lang="ruby" title="Passing the series to a custom Flex component">
<local:BubbleSerieChart time_serie="{geoip}" serie_name="GeoIP" />
</typo:code>
<typo:code lang="ruby" title="The full source of the custom component.">
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
title="{serie_name}" height="100%" width="100%">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
[Bindable]
public var time_serie:Object;
[Bindable]
public var serie_name:String;
private function getLabel(item:Object, field:String, index:uint, percentValue:Number):String
{
return item.key;
}
]]>
</mx:Script>
<mx:BubbleChart id="chart" dataProvider="{time_serie}" showDataTips="true" width="100%" height="100%" >
<mx:backgroundElements>
<mx:Array>
<mx:Image source="@Embed('political_world_map_grey.swf')" />
</mx:Array>
</mx:backgroundElements>
<mx:horizontalAxis>
<mx:LinearAxis minimum="-180" maximum="180" />
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:LinearAxis minimum="-90" maximum="90"/>
</mx:verticalAxis>
<mx:series>
<mx:Array>
<mx:BubbleSeries xField="longitude" yField="latitude" radiusField="count" maxRadius="5"/>
</mx:Array>
</mx:series>
</mx:BubbleChart>
</mx:Panel>
</typo:code>
Rails Log Analyzer - Rails and Flex with JSON2006-05-15T00:00:00-07:00http://onrails.org/2006/05/15/rails-log-analyzer-rails-and-flex-with-json<img src="/files/20060515_railsloganalyzer.gif" alt="" />
<p>I started to write a small Rails Log Analyzer that provides some insight on how a given application is used. I’ve just spent three hours so far, so not too much to show, but I have found the integration of Flex with Rails for read-only purpose of the different time series pretty straight forward.</p>
<h2>In two words…</h2>
<p><span class="caps">RAILS</span>: data.to_json</p>
<p><span class="caps">FLEX</span>: <span class="caps">JSON</span>.decode(String(srv.lastResult));</p>
<h2>On the Rails side</h2>
<p>The controller simply transforms the Hash return by the model into a json textual representation.</p>
<typo:code lang="ruby" title="the controller">
<p>class DataController < ApplicationController</p>
def overview
render :text => Hit.overview_data.to_json
end
<p>end</p>
</typo:code>
<p>This is an extract of the method that returns a Hash that contains the time series in an Array.</p>
<typo:code lang="ruby" title="the model">
<p>def Hit.overview_data<br />
result = {}<br />
result[:header] = {:period => {:start => Hit.minimum(:time).to_s(:db), :end => Hit.maximum(:time).to_s(:db)}}<br />
result[:sessions_series] =<br />
{:by_day => Hit.data_serie(Hit.count(:session, :group => :day, :conditions => ‘controller <> “HeartbeatController”’), “sessions by day”) }<br />
result<br />
end</p>
</typo:code>
<h2>On the Flex side</h2>
<typo:code title="the view">
import com.macromedia.serialization.json.*;
private function resultHandler(event:ResultEvent) : void
{
status = “Loaded. Parsing data…”;
var result:Object = <span class="caps">JSON</span>.decode(String(srv.lastResult));
header = result.header;
ts = getSerie(result.sessions_series.by_day.data);
}
<mx:HTTPService id="srv" url="http://10.37.129.2:3000/data/overview" result="resultHandler(event)" />
</typo:code>
<p>The service is invoked by the following actionscript call</p>
<typo:code lang="ruby">
<p>srv.send()</p>
</typo:code>
<p><span class="caps">JSON</span> doesn’t support Date objects out of the box, but it’s a nice way to exchange complex data such a Hash and Map between Rails and Flex.</p>Update: time.onrails.org. Add Notes to your time entries!2006-05-08T00:00:00-07:00http://onrails.org/2006/05/08/update-time-onrails-org-add-notes-to-your-time-entries<style>
.new {
background-color: yellow;
color: rgb(0, 0, 0);
<p>}</p>
</style>
<p><span class="new" >Updated</span> time.onrails.org</p>
<p>The new functionality is <br />
<ul><br />
<li>Add notes to your time entries. You can now add notes from the Dashboard or your project pages.</li> <br />
<li>Improved <span class="caps">CSV</span> export.</li></p>
</ul>
<p>Some functionality I am considering next:<br />
<ul><br />
<li>fixing the rendering in Internet Explorer. I just saw this bug since I installed Parallels on my MacBook pro. </li><br />
<li>Blinksale integration, I started to write the UI to submit a time section to generate an invoice via Blinksale, but I am still waiting to get access to the api. Unfortunatly I didn’t make to the beta of the <span class="caps">API</span>. I even tried to convince Josh Williams from Firewheel Design, to let me in on it, but without success. Thanks Josh for the quick response anyhow!</li></p>
</ul>remote_function :with2006-05-01T00:00:00-07:00http://onrails.org/2006/05/01/remote_function-with<typo:code lang="ruby">
<p><%= select_tag “content_type”, options_for_select(content_type_options),<br />
{ :onchange => <br />
remote_function(<br />
:url => {:action => ’filter_by_content’}, <br />
:with => ‘Form.Element.serialize(this)’) } %></p>
</typo:code>
<p>The above code allows to submit via javascript the selected value of a combo box. The remote call is triggered via the <em>onchange</em> event handler of the select tag. Notice the parameters to the remote function call <strong>:url</strong>, as usual, but also the <strong>:with</strong> parameter. The <strong>:with</strong> option can be very useful if you need more control on what data needs to be sent to the server. In this case we use Form.Element.serialize that url encodes all the parameters found in a given div (doesn’t need to be a form). In this case the <em>content_type=snippet</em> is passed to the server.</p>An eCommerce platform in Ruby on Rails2006-04-27T00:00:00-07:00http://onrails.org/2006/04/27/an-ecommerce-platform-in-ruby-on-rails<p>I have the chance to be part of an amazing team since last October that created a new generation of eCommerce platform using Ruby on Rails that will power hundreds of high profile ecommerce websites. The first website powered by this platform is</p>
<p><a href="http://www.nationaltabletennis.com">www.nationaltabletennis.com</a></p>
<p>Gately’s, the company behind this development had the foresight one year ago to start the development from scratch of the three major applications forming the platform…using Ruby on Rails. This decision was driven by their technical director, Solomon White, who saw the potential of Rails that not many realized at that time and decided to form a top notch team. The three applications are order management, store builder, and the storefront engine. The storefront engine can drive multiple stores. You can get an idea of what such a store looks a like at <a href="http://www.nationaltabletennis.com">www.nationaltabletennis.com</a>. However most of the development went into the two back-end applications, that not only look amazing, but offers possibilities that will make news in the future.</p>
<p>Each of the three components of the platform consist of a large application by it-self. The storefront and the store builder are new applications and the order management replaces an older php applications. Together these applications have well over one hundred model classes. This is just to give an idea of the scale of the applications.</p>
<p>Now, the question is how well is Ruby On Rails adapted for larger scale development with a team of 5 developers and 1 designer?</p>
<p>Ruby On Rails kicks ass.</p>
<p>The many decisions that the Rails environment takes for you allows you to concentrate on what is important, like business logic, user interaction, quality. You spend very little time in the plumming of the application asking yourself where things should go or what artifacts should be used. Rails did these descisions for you. In addition, the different ways you have to exercise immediately a code change without any delay, by the console, through unit tests, or via a page refresh provides a dynamism to the development cycle that cannot be described in words but needs to be experienced. You can perform a quantity of changes in an hour that cannot be done in other environments like java. Not only code changes, but with the database migrations you can go back and forth between different data model structures, just to experiment. You start not just coding the first thing you decided on, but you start going in a “Oh, let’s try this” mode. Not all is shiny however. We had some difficulties sharing code between the three systems that had common model, views, and controllers. This was for the access rights. For some mysterious reasons I didn’t feel using the Plugins Engine that specifically addresses this problem. So I started to role-my-own, lighter version of a plugin engine, which works but is still causing some headaches from time to time. On the other hand, using the plugin architecture to share common code that doesn’t rely on views, is a simple and great solution. Furthermore to integrate the three applications we used secured, RESTfull http requests. This approach is so much simpler than webservices and with Rails you can modify the two applications that needs interaction in parallel, refining the interaction protocol, again seeing the results of any change immediately.</p>
<p>There is way more to describe, but as a former Java Enterprise developer and a former Microsoft Solution Developer, I can say that Ruby On Rails just kicks ass and leaves these other environments in the shadow.</p>
<p>If you are starting a new enterprise or web development project, you got to consider Ruby on Rails!</p>Update: time.onrails.org. Capistrano Rocks!2006-04-19T00:00:00-07:00http://onrails.org/2006/04/19/update-time-onrails-org-capistrano-rocks<style>
.new {
background-color: yellow;
color: rgb(0, 0, 0);
<p>}</p>
</style>
<p><span class="new" >Updated</span> time.onrails.org</p>
<p>The new functionality is <br />
<ul><br />
<li>A first version of data export to text, csv, and xml. See the export icons in the bottom right of the projects and dashboard page.</li><br />
<li>A mini system message board. So we can leave you a message, i.e. for planned system maintenance downtime, or to announce new functionality.</li><br />
<li>The latest version of the <a href="http://nubyonrails.com/pages/gruff">Gruff Graphs</a></li></p>
</ul>
<p>I realized that data export needs some more work as in Safari the xml doesn’t appear unless you do a view source and the csv doesn’t load Microsoft Excel directly nor adds a default .csv extension to the generated data.</p>
<p>We will deploy new functionality or fixes issues once a week if possible. Note that we are going to keep this application simple, but any suggestion is welcome. Contact us at <a href="mailto:time@onrails.org">time@onrails.org</a>.</p>
<p>I deployed the application using Capistrano. It is pretty stressless and consists of the following steps:<br />
<pre><br />
rake remote:disable_web<br />
rake remote:deploy_with_migrations<br />
rake remote:enable_web<br />
</pre></p>
<p>In this case we had a database migration, the new ‘messages’ table.</p>
<p>The only issue that persists is that the application doesn’t start right away after the deployment and seems to hang for about 10 minutes before comming back to life. The application is hosted on Dreamhost and we don’t have full control on how the displatch.fcgi processes are launched.</p>
<p>It’s now up and running, so enjoy!</p>render :update to |page|2006-04-18T00:00:00-07:00http://onrails.org/2006/04/18/render-update-to-page<p>In the following test I was checkeing out of the javascript that is generated using the render :update call. Note that using a functional test is also a nice way to explore some of the prototype_helper functionality.</p>
<pre>
page.call 'mycall', 'a', 2, 3 # --> mycall("a", 2, 3);'
page.my_class.my_method 'a', 12 # --> MyClass.myMethod("a", 12);
</pre>
<p>Now one issue I had was figuring out how to pass a javascript variable to a javascript call. I.e. mycall(p1, p2). The only way I found it so to use the page << method. After a little hacking I managed to pass javascript variables to a method using the page.call. See the use of the JsArugmentList class here after. Note it does get’s a little cluttered and the page << remains easier to read. Please let me know if you find a more elegant way to achieve this.</p>
<typo:code lang="ruby" linenumber="true" title="rjs_test.rb">
<p>require File.dirname(<i><span class="caps">FILE</span></i>) + ‘/../test_helper’</p>
<ol>
<li>Little hack to allow passing javascript variables as argument to page.call<br />
class JsArgumentList<br />
def initialize(*arguments)<br />
@arguments = arguments<br />
end<br />
def to_json<br />
@arguments.join ’, ’<br />
end<br />
end</li>
</ol>
<p>class RjsController < ActionController::Base<br />
def rescue_action(e) raise e end;</p>
<ol>
<li>See prototype_helper.rb for implementation of the ‘page’ methods.<br />
def page_call<br />
render :update do |page|<br />
page.call ‘mycall’, ‘a’, 2, 3<br />
page.assign ‘p1’, ‘str1’<br />
page << ‘mycall(p1, p2);’ <br />
page.call ‘mycall’, JsArgumentList.new(:p1,:p2) #equivalent to previous line<br />
page.my_class.my_method ‘a’, 12 <br />
end<br />
end<br />
end</li>
</ol>
<p>class RjsControllerTest < Test::Unit::TestCase<br />
def setup<br />
@controller = RjsController.new<br />
@request = ActionController::TestRequest.new<br />
@response = ActionController::TestResponse.new<br />
end<br />
def test_page_call<br />
get :page_call<br />
javascript = @response.body.split(“\n”)<br />
assert_equal ‘mycall(“a”, 2, 3);’, javascript<sup class="footnote" id="fnr0"><a href="#fn0">0</a></sup><br />
assert_equal ‘p1 = “str1”;’, javascript<sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup><br />
assert_equal ‘mycall(p1, p2);’, javascript<sup class="footnote" id="fnr2"><a href="#fn2">2</a></sup><br />
assert_equal ‘mycall(p1, p2);’, javascript<sup class="footnote" id="fnr3"><a href="#fn3">3</a></sup><br />
assert_equal ‘MyClass.myMethod(“a”, 12);’, javascript<sup class="footnote" id="fnr4"><a href="#fn4">4</a></sup><br />
end<br />
end</p>
</typo:code>Graphs with Gruff (followup)2006-04-14T00:00:00-07:00http://onrails.org/2006/04/14/graphs-with-gruff-followup<p><a href="http://onrails.org/articles/2006/02/20/graphs-with-gruff#comments">The solution from the source</a> ;-) I checked it out and it now works as advertised, just add g.minimum_value = 0 to the Gruff::Bar before rendering it (g.to_blob).</p>
<p>Note that axis starting at zero.</p>
<table>
<tr>
<td> Without the minimum_value </td>
<td> With the minimum_value set to zero </td>
</tr>
<tr>
<td> <img src="/files/20060414_gruff_before_sm.gif" alt="" /> </td>
<td> <img src="/files/20060414_gruff_after_sm.gif" alt="" /> </td>
</tr>
</table> LAUNCH time.onrails.org, time tracking made simple!2006-04-13T00:00:00-07:00http://onrails.org/2006/04/13/new-background-color-yellow-color-rgb-0-0-0-launch-time-onrails-org-time-tracking-made-simple<p><img src="/files/launch_timeonrails.gif" alt="" /></p>
<p>We call it <a href="http://time.onrails.org">time.onrails.org</a>. It’s a new <span class="caps">FREE</span> online time tracking product for the consultant and programmer that bills by the hour or works on multiple projects.</p>
<p>We (Lee and I) have been using it for awhile now to track our Rails consulting work. It’s really the fastest way to count your hours across multiple projects. And we tried many of the solutions out there.</p>
<p>See <a href="http://time.onrails.org">time.onrails.org</a> for an overview or go straight to <a href="http://time.onrails.org/account/signup">signup</a> and be up and running in 5 seconds.</p>
<p>Let us know what you think at time@onrails.org.</p>
<p>Enjoy! <br />
Daniel</p>CSS Transparent Rollovers2006-04-10T00:00:00-07:00http://onrails.org/2006/04/10/css-rollovers<p>I was trying to implement some rollover effects when I stumbled over this article at <a href="http://www.mandarindesign.com/opacity.html">mandarindesign</a>. I wrapped this functionality in the helper here after</p>
<typo:code lang="xml" linenumber="true" title="The css">
<style type="text/css">
<p><!--
div.transOFF {width: 100%; background-color: silver; border:1px solid black;}
div.transON {width: 100%; background-color: silver;opacity:.50;filter: alpha(opacity=50); -moz-opacity: 0.5; }
--></p>
</style>
</typo:code>
<typo:code lang="ruby" linenumber="true" title="The rhtml template">
<table width="200" border="0" style="border:1px solid black;">
<tr>
<td>Project</td>
<td>Dashboard</td>
<td>Charts</td>
</tr>
<tr>
<td><%= rollover_image(‘/images/index/project_icon.png’, true) %></td>
<td><%= rollover_image(‘/images/index/dashboard_icon.png’) %></td>
<td><%= rollover_image(‘/images/index/graph_icon.png’) %></td>
</tr>
</table>
</typo:code>
<typo:code lang="ruby" linenumber="true" title="The Helper">
def rollover_image(src, over=false)
transON, transOFF = over ? [‘transOFF’, ‘transON’] : [‘transON’, ‘transOFF’]
content_tag “div”,
image_tag(src, :onmouseover => “this.className=‘#{transOFF}’”, :onmouseout => “this.className=‘#{transON}’” ),
:class => transON,
:onmouseover => “this.className=‘#{transOFF}’”,
:onmouseout => “this.className=‘#{transON}’”
end
</typo:code>
<style type="text/css">
<p><!--
div.transOFF {width: 100%; background-color: silver; border:1px solid black;}
div.transON {width: 100%; background-color: silver;opacity:.50;filter: alpha(opacity=50); -moz-opacity: 0.5; }
--></p>
</style>
<table width="200" border="0" style="border: 1px solid black;">
<tbody>
<tr>
<td style="">
<p>Project</p>
</td>
<td style="">
<p>Dashboard</p>
</td>
<td>
<p>Charts</p>
</td>
</tr>
<tr>
<td style="">
<div onmouseover="this.className='transON'" onmouseout="this.className='transOFF'" class="transOFF">
<p><img src="/files/project_icon.png?1144723836" onmouseover="this.className='transON'" onmouseout="this.className='transOFF'" alt="Project_icon" class="transOFF" style=""/></p>
</div>
</td>
<td style="">
<div onmouseover="this.className='transOFF'" onmouseout="this.className='transON'" class="transON" style="">
<p><img src="/files/dashboard_icon.png?1144723723" onmouseover="this.className='transOFF'" onmouseout="this.className='transON'" alt="Dashboard_icon" class="transON" style=""/></p>
</div>
</td>
<td>
<div onmouseover="this.className='transOFF'" onmouseout="this.className='transON'" class="transON">
<p><img src="/files/graph_icon.png?1144723748" onmouseover="this.className='transOFF'" onmouseout="this.className='transON'" alt="Graph_icon" class="transON"/></p>
</div>
</td>
</tr>
</tbody>
</table>Managing Rails Plugins dependencies2006-03-04T00:00:00-08:00http://onrails.org/2006/03/04/managing-rails-plugins-dependencies<p>Rails has a nice plugin system allowing to add common code to a project. A plugin should really be independent from any other plugins. But we also use plugins to share code among different projects we are working on and our code depends on existing plugins. The Rails development team want’s to keep the plugin system simple and didn’t provide an explicit way to handle these dependencies, which I believe is a good decision. There is a solution. Simply name the plugins in order off the dependencies you have. Let’s assume you want to add “my_very_own_plugin” plugin that depends on the enumation_mixin, then simply organize the /vendor/plugins folder as follows, et Voila!:.</p>
<pre>
/myrailsapp
/vendor
/plugins
/01_acts_as_taggable
/01_enumations_mixin
/01_acts_as_versioned
/02_my_very_own_plugin
</pre>
<p>If we look at the Rails::Initializer we can see why this works. Note, this is only an extract of the full class that Rails provides to bootstrap your rails applicaton. The sort on line 4 here after allows this trick.</p>
<typo:code lang="ruby" linenumber="true" >
<p>module Rails<br />
class Initializer<br />
def load_plugins<br />
find_plugins(configuration.plugin_paths).sort.each { |path| load_plugin path }<br />
$LOAD_PATH.uniq!<br />
end<br />
end<br />
end</p>
</typo:code>Graphs with Gruff2006-02-20T00:00:00-08:00http://onrails.org/2006/02/20/graphs-with-gruff<table>
<tr>
<td><img src="http://static.flickr.com/41/102254185_44b05dcd34.jpg?v=0" alt="" /></td>
<td valign="top"><typo:code lang="ruby" ><br />
class GraphController < BaseTimeController<br />
def pages<br />
g = Gruff::Pie.new(“500×350”)<br />
g.title = “All Pages” <br />
@current_user.pages.each do |page|<br />
g.data(page.title, [page.total]) <br />
end<br />
send_data(g.to_blob, <br />
:disposition => ‘inline’, <br />
:type => ‘image/png’, <br />
:filename => “timers.png”)<br />
end<br />
end</typo:code>
<p>Pretty easy! Wasn’t it. Note the code above shows only the first of the graphs. Now if only I could find out how to set the minimum of the Bar chart to 0 instead of the minimum of the serie. Any help is appreciated?</p>
</td>
</table>A source code browser2006-02-20T00:00:00-08:00http://onrails.org/2006/02/20/a-source-code-browser<p><a href="http://source.onrails.org/repository/browse//BrowseSource">Browse::Source</a> is a simple source code browsing application. It’s 100% based on Collaboa, it’s mostly the source code browser functionality but uses the file system rather than connecting to subversion.</p>
<p>I recently got a request from Justin to have access to some ‘old’ rails code (<a href="http://flexonrails.com/">flexonrails</a>) we wrote a while ago, and also Todd asked for the source code of <a href="http://www.autumnriderstees.com/">autumnriders</a>. <br />
So I tried <a href="http://collaboa.org/">Collaboa</a> but it requires to compile subversion from the source in order to have swig-rb. So I extracted the source code browser from Collaboa and removed the dependency on swig-rb. Now if all you need is to add simple source code browsing…then Browse::Source is what you need.</p>
<p>Well, we haven’t posted yet the two code bases mentionned above, but have a look at the source code browser source code <a href="http://source.onrails.org/repository/browse//BrowseSource">Browse::Source</a></p>Auto-login2006-02-18T00:00:00-08:00http://onrails.org/2006/02/18/auto-login<p>One of my midnight Rails projects is a “time tracking” application for which I needed auto-login. You know, the “Remember me” check box so that you don’t have to login each time you visit the application. I found a nice article written by Matt McCray describing how this was implemented for TaskThis.com at http://www.mattmccray.com/archives/category/software/rails/taskthis/. Even further he provides the full source code for the application. I didn’t take directly his auto_login.rb module but was greatly inspired by it. I also used the <em>Login Engine Plugin</em> that was not providing this feature, maybe this changed, so it could be simpler, but how simple implementing the auto-login can be. Note these are not the full classes just pertinent code extracts.</p>
<p><strong>1. Remember me</strong></p>
<p>When the user login and checks the “Remember me” checkbox, the :save_login parameter is set, the User instance remember_me method invoked and the :auth_token cookie set.</p>
<typo:code lang="ruby">
<p>class AccountController < ApplicationController<br />
def login<br />
case <code>request.method
when :post
if @session[:user] = User.authenticate(</code>params[:user_login], @params[:user_password])<br />
flash[‘notice’] = “Login successful”<br />
if @params[:save_login] == “1”<br />
@session[:user].remember_me<br />
cookies[:auth_token] = { :value => @session[:user].remember_token , :expires => @session[:user].remember_token_expires }<br />
end<br />
redirect_back_or_default :controller => “time”<br />
else<br />
flash.now[‘notice’] = “Login unsuccessful”<br />
@login = @params[:user_login]<br />
end<br />
end<br />
end</p>
def logout
@session[:user].forget_me if @session[:user]
@session[:user] = nil
cookies.delete :auth_token
end
<p>end</p>
</typo:code>
<p><strong>2. login_from_cookie</strong></p>
<p>The next time the user visits the website the “login_from_cookie” filter is triggered. This method checks that the user is not logged in and that the :auth_token cookie is set. If that’s the case the user matching the :auth_token is searched and the token_expiration verified the the user is automatically logged in. Et voila!<br />
I guess auto_login would be more appropriate as method name.</p>
<typo:code lang="ruby">
<p>class ApplicationController < ActionController::Base<br />
before_filter :login_from_cookie<br />
def login_from_cookie<br />
return unless cookies[:auth_token] && @session[:user].nil?<br />
user = User.find_by_remember_token(cookies[:auth_token]) <br />
if user && !user.remember_token_expires.nil? && Time.now < user.remember_token_expires <br />
@session[:user] = user<br />
end<br />
end<br />
end</p>
</typo:code>
<p><strong>3. the User class</strong></p>
<p>The User class has two methods to set and remove the token from the database. It’s pretty secure as from the token the user cannot be identified without having the salt, the email, and the token expiration, which is most unlikely to be recreated. It could be even more secure by just encrypting some random unique identifier. The only issue I encountered was that the user class always forces the password validation and encryption when saving. For now I just bypass validation and encryption when setting and clearing the remember_me token.</p>
<typo:code lang="ruby">
<p>class User < ActiveRecord::Base<br />
def remember_me<br />
self.remember_token_expires = 2.weeks.from_now<br />
self.remember_token = Digest::SHA1.hexdigest(“#{salt}—#{self.email}—#{self.remember_token_expires}”)<br />
self.password = "" # This bypasses password encryption, thus leaving password intact<br />
self.save_with_validation(false)<br />
end</p>
def forget_me
self.remember_token_expires = nil
self.remember_token = nil
self.password = "" # This bypasses password encryption, thus leaving password intact
self.save_with_validation(false)
end
<p>end</p>
</typo:code>inline RJS2006-01-20T00:00:00-08:00http://onrails.org/2006/01/20/inline-rjs<p>In my previous article I was playing with <span class="caps">RJS</span> templates and finding easy way to generate them. Well Thomas just posted some new goodies see http://mir.aculo.us/articles/2006/01/21/new-inline-rjs-for-rails. For quick updates no need to have a separte .rjs file.</p>
<typo:code lang="ruby">
<p>class UserController < ApplicationController <br />
def refresh <br />
render :update do |page| <br />
page.replace_html(‘user_list’, <br />
:partial => ‘user’, :collection => @users) <br />
page.visual_effect :highlight, ‘user_list’ <br />
end <br />
end <br />
end</p>
</typo:code>.rjs and link_to_function2006-01-12T00:00:00-08:00http://onrails.org/2006/01/12/rjs-and-link_to_function<p>A neat little trick is that .rjs templates can be used to generate local javascript functions and be invoked without doing a server roundtrip.</p>
<p><strong>playground_controller.rb</strong><br />
<typo:code lang="ruby"><br />
class PlaygroundController < ApplicationController<br />
def rjs<br />
response.headers[‘content-type’] = ‘text/html’<br />
end<br />
end</p>
</typo:code>
<p><strong>rjs.rhtml</strong><br />
<typo:code lang="ruby"><br />
<html><br />
<head><br />
<%= javascript_include_tag :defaults %></p>
</head>
<body>
<h1 id='header'>Javascript function test</h1>
<p><%= link_to_function(‘Add’, ‘add_item()’ ) -%> | <br />
<%= link_to_function(‘Clear’, ‘clear_list()’) <span>><br />
<ul id='list' /><br />
<script type='text/javascript'><br />
<</span>= render :partial => ‘functions’, :type => ‘rjs’ <span>><br />
</script><br />
<script type='text/javascript'><br />
<</span>= # Note: following javascript is run when the page is loaded.<br />
update_page do |page|<br />
3.times { page.call ‘add_item’ }<br />
end<br />
%><br />
</script></p>
</body>
</html>
</typo:code>
<p>The <em>rjs</em> method in the <em>PlaygroundController</em> set’s the content-type as we perform a render of an rjs from within a .rhtml and this seems to change the content-type, so we need to reset it.</p>
<p><strong>_function.rjs</strong><br />
<typo:code lang="ruby"><br />
page << ‘function add_item() {’<br />
page.insert_html :bottom, ‘list’, content_tag(‘li’, ‘item’, :id => ‘list_item’ )<br />
page.visual_effect :highlight, ‘list’, :duration => 3<br />
page << ‘}’</p>
<p>page << ‘function clear_list() {’<br />
page.replace_html :list, ""<br />
page.visual_effect :highlight, ‘list’, :duration => 3<br />
page << ‘}’</p>
</typo:code>
<p>In the partial <em>function.rjs we insert the function declaration before writing to the page object. This allows us to invoke the add</em>item _ and clear_list _ methods using the link_to_function _ from in the .rhtml file. Note also in the .rhtml file we invoke directly the update_page method to insert three calls to add_item().</p>
<p><strong>The generated html files looks like this</strong></p>
<typo:code lang="ruby">
<html>
<head>
<script src="/javascripts/prototype.js" type="text/javascript"></script>
<script src="/javascripts/effects.js" type="text/javascript"></script><script src="/javascripts/dragdrop.js" type="text/javascript"></script><script src="/javascripts/controls.js" type="text/javascript"></script><p></p>
</head>
<body>
<h1 id='header'>Javascript function test</h1>
<p><a href="#" onclick="add_item(); return false;">Add</a> | <br />
<a href="#" onclick="clear_list(); return false;">Clear</a><br />
<ul id='list' /><br />
<script type='text/javascript'>
function add_item() {
new Insertion.Bottom("list", "<li id=\"list_item\">item</li>");
new Effect.Highlight('list',{duration:3});
}
function clear_list() {
Element.update("list", "");
new Effect.Highlight('list',{duration:3});
}
</script>
<script type='text/javascript'>
add_item();
add_item();
add_item();
</script></p>
</body>
</html>
</typo:code>Xml Builder2006-01-10T00:00:00-08:00http://onrails.org/2006/01/10/xml-builder<p>I created the new <em>Playground</em> category on this blog to expose various aspects regarding Ruby On Rails that I am exploring. It may raise more questions than provide answers, but in any case don’t hesitate to jump in and add your 2 cents.</p>
<p>The <em>xml_builder</em> method here after uses the <em>render_to_string method to create some xml structure. The xml</em>string could as well have been in a separate .rxml file and and a simple <em>render</em> statement instead of <em>render_as_string</em> could have saved one line of code. But hey, that’s what the playground is for!</p>
<typo:code lang="ruby">
<p>class PlaygroundController < ApplicationController</p>
def xml_builder
xml_string = <<-XML_END
xml.test do
xml.language(name)
xml.description(“Rocks!”)
end
XML_END
result = render_to_string(:inline => xml_string, :locals => { :name => ’Ruby’}, :type => :rxml)
render_text result
end
<p>end</p>
</typo:code>
<p>The output: <br />
<typo:code lang="xml"><br />
<test><br />
<language>Ruby</language><br />
<description>Rocks!</description></p>
</test>
</typo:code>Flex vs. ROR2006-01-09T00:00:00-08:00http://onrails.org/2006/01/09/flex-vs-ror<p><strong>Ed just asked me:</strong> "Why, ultimately would you say <span class="caps">ROR</span> is better than Flex? There’s a great debate at the moment.</p>
<p><strong>My <em>swiss</em> style answer:</strong> "This is a very interresting question. I effectively use<br />
both technologies with different customers on different projects. And<br />
I like both, they have different strength. Flex 1.5 answers only the<br />
UI question and doesn’t help with the persistence side of a project.<br />
Flex 2.0 will provides some answers to the persistence integration<br />
with their Enterprise Services. Flex is really awesome to build a<br />
custom UI. Rails on the other hand provides lots of power if you have<br />
control on the database schema and is a full “web” stack. It provides<br />
a nice framework to build the views and provides some pretty powerfull<br />
ways to create dynamic html pages. Rails can we very productive. So in<br />
other words, I don’t prefer one over the other. It really depends on<br />
the specifics of the problem to be solved, the technical expertise of<br />
a customer and the future direction a customer wants to go to define<br />
if one technology is more appropriate than another."</p>I'd rather be on RAILS.2005-12-09T00:00:00-08:00http://onrails.org/2005/12/09/id-rather-be-on-rails<p>This statement is pretty true right now, Rails is just a pleasant development environment. Mike Clark left this sticker at my desk at one of the places I am currently doing a Rails project at.</p>
<p><img src="http://static.flickr.com/20/71974492_e856007f89.jpg" alt="" /></p>
<p>For another client I am doing a Flex project and work with many great java developers. I thought I would put the sticker in a visible spot and see their reactions. Well, it didn’t fail, some of the comments where pretty funny. Here they go:</p>
<ul>
<li>That’s a big statement.</li>
<li>We’ll run you out on a rail.</li>
<li>So you would rather be on rails, hein?</li>
<li>HuHan!</li>
<li>You really are a geek.</li>
<li>Where did you get it? You didn’t get one for me?</li>
<li>He’s a convert.</li>
<li>You are pushing the Ruby stuff today!</li>
<li>It looks like it should have a Lenin on it.</li>
<li>I’d rather be fishing.</li>
</ul>
<p>The “Lenin” one I didn’t totally get, even after a long discussion, but I sounded pretty funny to me. As you see, give me a sticker and will say good things about you. No, that’s not the case, I just think Mike Clark and Dave Thomas are putting a very compelling training together, and with these two guys you will learn more in three days than you would ever in any other places. Check out <a href="http://pragmaticstudio.com">http://pragmaticstudio.com</a> and their new Rails Studio, coming to Denver in January.</p>An on-line store build with Ruby on Rails2005-12-03T00:00:00-08:00http://onrails.org/2005/12/03/an-on-line-store-build-with-ruby-on-rails<p>In this non-technical article I wanted to share my impressions of writing an online store with Ruby on Rails. <a href="http://www.autumnriderstees.com/">http://www.autumnriderstees.com/</a></p>
<h2>Background</h2>
<p>On September 9th Lee’s dad mentioned that he would receive a stock of new quality designer T-shirts with funny bikers logos on September the 22nd and asked Lee if he could setup an on-line store. Lee asked me if I could help out writing it in Ruby on Rails and if I thought it was feasible. Hey, I just finished “Agile Web Development with Rails”, how hard could it be, the book contains everything we need. So “heck, yea, we can do it”. So Lee told his dad: “Sure, we’ll do”. Well, it took us just a little longer, not much thought, considering we just met once a week for a month, and two weekends. But considering that Lee just started a new Rails gig, me just being father for the second time and a little sleep depraved, we manage to go-life on October the 16th at RubyConf 2005. First Ruby and Rails is really cool, Dave Thomas books are invaluable in many aspects, not the least being that the most of the order processing part of the application is taken straight from book.</p>RubyConf 2005 and RubyWeek2005-10-16T00:00:00-07:00http://onrails.org/2005/10/16/rubyconf-2005-and-rubyweek<p>RubyConf 2005 and RubyWeek</p>
<p>What a Ruby Week. I am on the plane back to Denver from the Ruby Conference 2005 that just finished in San Diego. On the beginning of the week I started a new part-time job working on a Ruby on Rails application. On Thursday I flew to San Diego for the conference. <em>Later</em> that evening, with Lee we fleshed out the latest bug of our first on-line Rails application, and put it in production. If you are a Biker and like funny shirts, check out <a href="http://www.autumnriderstees.com">AutumnRidersTees.com</a>. It’s a <em>very</em> small on-line shirt Store. Thank you Dave Thomas for your book on Rails, it was also a nice kick-start for our application, especially the non-public/administrative side of the site. On Friday the conference started, and what a conference, about two hundreds geeks and Ruby fans, inclusive many of the key players that create Ruby, Rails, and many of the awesome frameworks we are using everyday. It’s funny to put a face on who is behind these frameworks. For more info on the speakers checkout the <a href="http://www.rubycentral.org/conference/agenda.html">agenda</a>. Matz,the creator of Ruby, and ko1, the writer of the upcoming RubyVM, presented their views on the future of Ruby. I am not sure if this comes from the Japanese culture, but the elegance, simplicity and power, that radiates from the existing and forthcoming releases, made me want to to study this country. About 15 of the attendees came from Japan. It’s interesting how the community still feels small and is so open (and fun) when attending the conference especially when you realize the potential of Ruby and the power meta programming provides by creating domain specific languages. Rails is an example of that puts that power to good use. Speaking of Rails, David Heinemeier Hannsson, provided a nice <em>state of the union</em> for Rails and a hands-on workshop (he worked, we watched) of the forthcoming Rails 1.0 functionality. Rails was the trigger for me to dive into Ruby, and what is coming out will impress many java shops. SwitchTower to deploy applications from a single server to large clusters. Gauge to monitor your application and see what’s going on, live, on your servers. So many other improvements that are just <em>practical</em>. <a href="http://convergentarts.com/articles/2005/10/16/rubyconf-rails-turns-rc-1">Tom</a> took quite some notes of that presentation. Before the Rails talks I also enjoyed an interesting talk of domain specific languages in general by Jim Weirich followed by a Karlin Fox’s talk on how to create a user oriented specification and testing languages using “english” thus allowing a non-programmer user or business analyst to express the expected behavior of the application. The amazing part is that this domain specific language is implemented using Ruby and results in runnable unit test that excerse the user interface.</p>
<p>A great conference and a great Ruby week.</p>dvds.onrails.org - Integrating Flash and Ruby On Rails2005-10-09T00:00:00-07:00http://onrails.org/2005/10/09/<h1>dvds.onrails.org</h1>
<style>
pre {font-family:"Courier New", Courier, Arial; font-size: 12px;}
.operator {color: #000000;}
.keyword {color: #993300;}
.identifier {color: #000087;}
.properties {color: #000087;}
.identifier2 {color : #000087;}
.linecomment, .blockcomment {color: #808080;}
.string {color: #0000FF;}
</style>
<style type="text/css">
<!--
p.MsoNormal {
margin:0in;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:Times;
}
-->
</style>
The purpose of the DvdReleases demo application is to investigate some of the possibilities to integrate a Flash Component with a Ruby On Rails application.</p>
<p>We will describe:</p>
<ul>
<li>Enabling flash and javascript integration</li>
<li>Embedding the FlashTag in the .rhtml file. </li>
<li>passing initial values to a Flash component from an ActiveView.</li>
<li>embedding multiple Flash components in a .rhtml file.</li>
<li>Invoking remotly an ActionController from a Flash component.</li>
<li>Calling a javascript function from a Flash component.</li>
</ul>
<p>The application is quite simple and provides a list of dvd releases allowing to rate from 1 to 5 the individual dvds. The data has been downloaded from <a href="http://hometheaterinfo.com/dvdlist.htm">http://hometheaterinfo.com/dvdlist.htm</a>. As this is only a demo, you can vote several times. So, which is your favorites Dvd title?</p>
<h2>Enabling flash and javascript integration for you Ruby on Rails application. </h2>
<p>Macromedia provided the <a href="http://weblogs.macromedia.com/flashjavascript/">Flash/Javascript Integration Kit </a>a javascript library to embeded Flash with an .rhtml and javascript page.</p>
<ol>
<li><a href="http://weblogs.macromedia.com/flashjavascript/downloads/FlashJavascriptGateway.zip">download</a> the integration kit.</li>
<li>copy <em>JavaScriptFlashGateway.js</em> to rails <em>public/javascript</em> folder.</li>
<li>copy <em>JavaScriptFlashGateway.swf</em> to the <em>public</em> folder of your rails app.</li>
<li>copy your component, <em>RateMovie.swf </em>in our case, to the <em>public</em> folder of your rails app.
</li>
</ol>
<p>Then in your .rhtml view (list.rhtml in our example) add to the <head> section the following line to enable the Flash Javascript gateway: </p>
<blockquote>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <%= javascript_include_tag </span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">"JavaScriptFlashGateway"</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> %></span><span style="font-size:10.0pt;"></span></p>
</blockquote>
<h2>Embedding the FlashTag in the .rhtml file</h2>
<p>Then declare the following javascript code to the list.rhtml file. </p>
<blockquote>
<p><span style="font-family:Monaco;font-size:10.0pt;color:#891315;"> <script type="text/javascript"></span><span style="font-family:Monaco;font-size:10.0pt;color:black;"></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> var uid = new Date().getTime(); // uniq</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> function insertFlashComponent(dvd_id, vote, average) { </span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> var tag = new FlashTag('../RateMovie.swf', </span><span style="font-family:Monaco;font-size:10.0pt;color:blue;">137</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">, </span><span style="font-family:Monaco;font-size:10.0pt;color:blue;">50</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">); // last two arguments are height and width</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> tag.setFlashvars('lcId='+uid+'</span><span style="font-family:Monaco;font-size:10.0pt;color:blue;">&dvdid='+dvd_id+'&dvdvotes='+vote+'&dvdaverage='+average+'');</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> tag.write(document);</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> }</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> function hightlightVote(dvd_id) {</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> new Effect.Highlight('flashdiv'+dvd_id);</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> }</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;"></script></span><span style="font-family:Monaco;font-size:10.0pt;color:black;"></span></p>
</blockquote>
<p>The <em>insertFlashComponent </em>javascript method write the FlashTag dynamically to the html document when invoked.</p>
<h2>Passing initial values to a Flash component from an ActiveView.</h2>
<p>The <em>insertFlashComponent</em> method takes the initial parameters of the Flash component. </p>
<blockquote>
<p><span class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <strong>insertFlashComponent(<%= dvd_id %>, <%= dvd_vote %>, <%= dvd_average %>);</strong></span></span></p>
</blockquote>These parameters can now be access from flash from the _root object as follows:
<blockquote>
<pre><span class="identifier">_root</span>.dvdid, <span class="identifier">_root</span>.dvdvotes, <span class="identifier">_root</span>.dvdaverage
</pre>
</blockquote>
<h2>Embedding multiple Flash components in a .rhtml file.</h2>
<p>This is how each of the Dvds selected by the ActionController is displayed in the table body </p>
<blockquote>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"><tbody></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"><% </span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">for</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> dvd </span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">in</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> @dvds %></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <tr></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <% </span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">for</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> column </span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">in</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> Dvd.content_columns[0,</span><span style="font-family:Monaco;font-size:10.0pt;color:blue;">3</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">] %></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <td><div id=</span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">"flashdiv<%= dvd.id %>"</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">><%=h dvd.send(column.name) %></div></td></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <% </span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">end</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> %></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <td></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <script type=</span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">"text/javascript"</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <% dvd_id = dvd.id</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> dvd_vote = dvd.vote!=</span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">nil</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> ? dvd.vote.votes : </span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">"0"</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> dvd_average = dvd.vote!=</span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">nil</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> ? dvd.vote.average : </span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">"null"</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> %></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <strong>insertFlashComponent(<%= dvd_id %>, <%= dvd_vote %>, <%= dvd_average %>);</strong></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </script> </span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </td></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> <td><div id=</span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">"mydiv<%= dvd.id %>"</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">> <%= link_to_remote(</span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">"show"</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">, </span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> :update => </span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">"mydiv#{dvd.id}"</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">, </span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> :url => { :action => </span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">'show_in_place'</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">, :id => dvd.id }) %></div></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </td></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </tr></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"><% </span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">end</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> %></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </tbody></span></p>
</blockquote>
<h2>Invoking remotly an ActionController from a Flash component.</h2>
<p>Now let's look at the Flash Component that allows you to rate your favorite Dvd. </p>
<p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" width="136" height="49">
<param name="movie" value="http://dvds.onrails.org/RateMovie.swf">
<param name="quality" value="high">
<embed src="http://dvds.onrails.org/RateMovie.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="136" height="49"></embed>
</object>
</p>
<p>Initially the components show the current number of votes and the average of all votes. When moving the mouse over, it tracks if you rating the moving from 1 to 5. On release of the mouse button it sends your vote to the ActionController.</p>
<p>The component is an instance of <em>VotePanelClass </em>Actionscript class. The code extract here after shows how the initial values passed to the javascript <em>insertFlashComponent</em> can be retrieve from the Flash component by using the _root.dvdid, _root.dvdvotes, and _root.dvdaverage variables. </p>
<blockquote>
<pre><span class="keyword">class</span> VotePanelClass <span class="keyword">extends</span> <span class="identifier2">MovieClip</span> {
<span class="keyword">function</span> <span class="identifier2">onLoad</span>() {
stars = [s0, s1, s2, s3, s4];
<span class="keyword">for</span> (<span class="keyword">var</span> i=0; i<stars.><span class="identifier2">length</span>; i++) stars[i].setRank(i+1);
setParams(<span class="identifier">_root</span>.dvdid, <span class="identifier">_root</span>.dvdvotes, <span class="identifier">_root</span>.dvdaverage);
setState(ShowVoteStateClass);
}
<span class="keyword">public</span> <span class="keyword">function</span> submitVote(vote:<span class="identifier">Number</span>) {
currentVote = vote;
<span class="identifier2">message</span> = <span class='string'>"Sending vote..."</span>
setState(WaitStateClass);
<span class="keyword">var</span> voteCall = <span class="keyword">new</span> RubyCall(<span class="identifier">this</span>, voteResult);
<strong>voteCall.<span class="identifier2">execute</span>(<span class='string'>"/admin/vote_for_dvd/"</span>+dvdId+<span class='string'>"?rank="</span>+vote);</strong>
}
<span class="keyword">public</span> <span class="keyword">function</span> voteResult(<span class="identifier2">result</span>) {
<span class="keyword">if</span> (<span class="identifier2">result</span>.success) {
<span class="identifier2">message</span> = <span class="identifier">null</span>;
votes = <span class="identifier2">result</span>.<span class="identifier2">data</span>.votes;
average = <span class="identifier2">result</span>.<span class="identifier2">data</span>.average;
getUrl(<span class='string'>"javascript:hightlightVote('"</span>+dvdId+<span class='string'>"')"</span>);
} <span class="keyword">else</span> {
<span class="identifier2">message</span> = <span class='string'>"Send Error!"</span>;
}
setState(ShowVoteStateClass);
}
}
</pre>
</blockquote>
<p>To invoke the ActionController we simply use the standard Flash LoadVar class that issues a HttpRequest. We did wrap the LoadVar in the following class:</p>
<blockquote>
<pre><span class="keyword">import</span> <span class="identifier2">mx</span>.utils.Delegate;
<span class="keyword">class</span> RubyCall {
<span class="keyword">var</span> callback:<span class="identifier">Function</span>;
<span class="keyword">function</span> RubyCall(obj, func) {
callback = Delegate.create(obj, func);
}
<span class="keyword">function</span> <span class="identifier2">execute</span>(<span class="identifier">url</span>:<span class="identifier">String</span>) {
<span class="keyword">var</span> result_lv:<span class="identifier">LoadVars</span> = <span class="keyword">new</span> <span class="identifier">LoadVars</span>();
result_lv.delegate = <span class="identifier">this</span>;
result_lv.<span class="identifier2">onLoad</span> = <span class="keyword">function</span>(success:<span class="identifier">Boolean</span>) {
<span class="identifier">this</span>.delegate.<span class="identifier2">onResult</span>(success, <span class="identifier">this</span>);
};
<span class="keyword">var</span> send_lv:<span class="identifier">LoadVars</span> = <span class="keyword">new</span> <span class="identifier">LoadVars</span>();
send_lv.<span class="identifier">sendAndLoad</span>(<span class="identifier">url</span>, result_lv, <span class='string'>"POST"</span>);
}
<span class="keyword">function</span> <span class="identifier2">onResult</span>(success:<span class="identifier">Boolean</span>, lv:<span class="identifier">LoadVars</span>) {
callback({success:success, <span class="identifier2">data</span>:lv});
}
}
</pre>
</blockquote>
<p>The following call invokes the controller and pass the dvdId and rank. </p>
<blockquote>
<pre>voteCall.<span class="identifier2">execute</span>(<span class='string'>"/admin/vote_for_dvd/"</span>+dvdId+<span class='string'>"?rank="</span>+vote);
</pre>
</blockquote>
<p>From Ruby the <em>admin_controller.vote_for_dvd</em> method is invoked (@todo: change admin_controller to dvd_controller)</p>
<blockquote>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">def</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> vote_for_dvd</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> @dvd = Dvd.find(@params[:id], :</span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">include</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"> => :vote)</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> rank = @params[:rank].to_i</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> vote = @dvd.vote</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> vote.votes += </span><span style="font-family:Monaco;font-size:10.0pt;color:blue;">1</span><span style="font-family:Monaco;font-size:10.0pt;color:black;"></span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> vote.average += (rank/vote.votes) </span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> @dvd.save</span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> render(:layout => </span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">false</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">, :action => </span><span style="font-family:Monaco;font-size:10.0pt;color:#891315;">'submit_vote'</span><span style="font-family:Monaco;font-size:10.0pt;color:black;">) </span></p>
<p class="MsoNormal"><span style="font-family:Monaco;font-size:10.0pt;color:black;"> </span><span style="font-family:Monaco;font-size:10.0pt;color:#760F50;">end</span></p>
</blockquote>
<h2>Calling a javascript function from a Flash component.</h2>
<p>Finally we call javascript from the Flash component just to demonstrate that it can be done. </p>
<blockquote>
<pre>getUrl(<span class='string'>"javascript:hightlightVote('"</span>+dvdId+<span class='string'>"')"</span>);
</pre>
</blockquote>
<h2>Conclusion</h2>
<p>In this demo we just scratched the surface on how Flash and Ruby on Rails can be integrated. The same example we showed can easily be written in plain Javascript. However on many projects you could use these techniques to add richer components like charts and other graphical representations of data. </p>
<p>There are some nice opensource frameworks that allow to generate Flash component directly from a Ruby application, there is the AMF4R library that enable passing typed objects between Ruby and Flash, there is the Flash Player 8 comming out with a new External Interface that opens great new possiblities. So this is just the start!</p>
<p>Enjoy!<br/>Daniel and Lee.</p>
<p> </p>
Applications2005-10-09T00:00:00-07:00http://onrails.org/2005/10/09/<h1>The future projects we are going to present:</h1>
<ul>
<li>http://dvds.onrail.org – a small Rails application allowing to search dvd titles, rate and comment them. This project will demonstrate some Flash/Ajax and Rails integration.</li>
<li>http://flash.onrails.org – Amf interation with ActiveRecord, allowing to build data-driven Rich Internet Applications.</li>
<li>http://time.onrails.org – a nice time record service for every Rails Consultant or software developer that needs to keep track of his time.</li>
</ul>dvds.onrails.org - integrating Flash with Ruby on Rails2005-07-31T00:00:00-07:00http://onrails.org/2005/07/31/dvdreleases-integrating-flash-with-ruby-on-rails<p>The purpose of the DvdReleases demo application is to investigate some of the possibilities to integrate a Flash Component with a Ruby On Rails application. <br />
We will describe:</p>
<ul>
<li>Enabling flash and javascript integration</li>
<li>Embedding the FlashTag in the .rhtml file.</li>
<li>passing initial values to a Flash component from an ActiveView.</li>
<li>embedding multiple Flash components in a .rhtml file.</li>
<li>Invoking remotly an ActionController from a Flash component.</li>
<li>Calling a javascript function from a Flash component.</li>
</ul>
<p>“Keep Reading>>”:/pages/applications/dvds</p>
<p>“Click here to Try it!>>”:http://dvds.onrails.org/admin</p>RubyConf is on the radar.2005-06-09T00:00:00-07:00http://onrails.org/2005/06/09/rubyconf-is-on-the-radarLee, Tom, and I just booked for the RubyConf 2005 in San Diego that will take place October 14th-16th. So hope to meet you there...
No fluff just stuff2005-05-14T00:00:00-07:00http://onrails.org/2005/05/14/no-fluff-just-stuff<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
I
spent most of my week-end learning new stuff, and I
also attended the Wedding of Marla and Lee. It has been
pretty busy and pretty fun.
<br>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ; font-weight: bold;">
Day
1.
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
<br>
It all started on Friday the 13th. Good day to start a
seminar with four "Dave Thomas" sessions that where
pretty impressive, especially that I just read two of
his "pragmatic" series book, namely
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ; color: rgb(54, 84, 131);">
<u>
The Pragmatic Programmer
</u>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
and
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ; color: rgb(54, 84, 131);">
<u>
Programming Ruby (2nd. Ed.)
</u>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
.
The talks are 1. OpenSource Ecosystems 2. Ruby for Java
Programmers 3. Ruby on Rails 4. and the Keynote du
jour. His first talk "OpenSource Ecosystems" highlights
the principles behind successful open-source projects
and how it could be applied to your enterprise
projects. His keynote presentation on Friday draws
analogies between the art in engineering and software
development. Of course his two Ruby talks where as
entertaining as instructive. Ruby is really worth
taking a look at...
<br>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ; font-weight: bold;">
Day
2.
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
<br>
Herding Racehorses and Racing Sheep by Dave Thomas. He
did it again, an excellent non technical people
oriented presentation, investigating learning/teaching
and knowledge mechanism based on the level of people
(from beginner to expert) based on experiences
extracted from other professions. (That description
doesn't give justice to his presentation :-)
The next talk was NakedObjects by
Eitan Suez. Model driven UI's...just what I was
looking into for Flex. Foolowing was,
</span>
<span style="font-family: Trebuchet,Verdana,serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
<em>
AJAX
</em>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
by Justin Gehtland as a presentation going behind the
buzzword and showing many of the javascript techniques
used to make google-maps and other dynamic websites.
<br>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ; font-weight: bold;">
Day
3.
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
<br>
</span>
<span style="font-family: Trebuchet,Verdana,serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
<em>
Hibernate
and J2EE Transaction Integration
</em>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
by Mark Richards. Mark showed ways to make it work and
presented several gotcha's to be aware of. Better to
use Hibernate just with Spring if possible. I attended
three presentations by Bruce Tate,
</span>
<span style="font-family: Trebuchet,Verdana,serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
<em>
Beyond Java
and Ruby persistence
</em>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
,
</span>
<span style="font-family: Trebuchet,Verdana,serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
<em>
Introduction
to Spring
</em>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
,
and
</span>
<span style="font-family: Trebuchet,Verdana,serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
<em>
Beyond
Java
</em>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
.
The Spring and Java talks where really interesting and
informative, his last talk on Ruby persistence, as
Bruce warned us, was the first time he presented it and
still a little refinement is needed. Other than that
Bruce is an excellent speaker worthwhile listening
too...
<br>
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ; font-weight: bold;">
Reflecting
on The conference
</span>
<span style="font-family: 'Lucida Grande',LucidaGrande,Verdana,sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 11px; line-height: normal; font-size-adjust: none; font-stretch: ;">
<br>
First, you should attend one, it's just a great way to
learn some of the latest stuff and interact with some
off the leaders and experts in the field.
<br>
I get really energized when attending these
conferences, so much to try out, so many new thoughts,
so many new projects I now want to do, but mostly they
confirmed a reflection and phase I started a couple of
months ago. A "Back to basics" phase. My goals was to
stop trying out everything and not finishing really
anything. Energy and simplicity are not contradictory.
I will just spend more time doing less, and more energy
simplyfing what I do. I just read several of the
pragmatic series books (automated build, subversion)
and have a few more to read (JUnit). Although I use
these approaches during my day job, I didn't do it on
my midnight projects. Why? Well not 100% sure why, but
it would have saved me time and headaches. Most likely
I believe that outside of the constraint of work, I
used to like to get more creative and less organized,
but that is changing and I get a lot of satisfaction
trying to do less and more carefully.. So last month I
first purged many of my obsolete projects (the
WebObjets ones, the older java ones, the Cocoa ones)
and one by one decided what I wanted to keep based on
what I wanted to achieve...well I ended up with no old
projects...and just one new one. Yea, that felt good.
Then I moved the rest of my stuff into subversion.
After a little issues with French characters in some of
my documents I got everything working. Now I can trace
back everychange in my source even for my midnight
projects. On osx I use SnvX and the merge tool provided
by the osx dev tools. Pretty slick!!
<br>
So my only new midnight project is integrating Flex and
RubyOnRails. I will be working hard at ensuring that it
contains the minimal amount of code to achieve the
integration, that's it is fully unit tested, and
integrated with an automated build tool. During my day
job I use cruisecontrol, I am still debating if I will
use DamageControl (a Ruby one)...I am currently
inclined going the Ruby way.
<br>
Well as you see these conferences get me going...
</span>