Fully Headless JSSpec

Posted 20 days back at Relevance - Relevance Weblog

I have been frustrated at the state of testing for JavaScript. There are a bevy of great (and not-so-great) choices for testing your JavaScript, but nothing that is current, effective, and automated. We used Crosscheck for a while, but the project went stagnant and was awfully heavy-weight besides. On top of which, it didn’t offer a BDD-flavored spec syntax.

I’ve been a fan of JSSpec for a while, but its “runs tests only in the browser” style means that automated server-side, continuous testing was nigh upon impossible.

Then, along came John Resig and his marathon weekend of hacking to mock out the DOM API in a relatively simple JavaScript file and voila! Headless JSSpec testing for Rails apps could become a reality.

If you are interested in trying it out, first download and install Rhino 1.7R1. Make sure you put the js.jar file on a globally accessible path somewhere. Then, get a copy of my javascript_testing repo at Github (http://github.com/relevance/javascript_testing/tree/master). It is a minimal repo, with just enough to get you started. The files in the repo are:

  • env.js—a clone of John Resig’s browser environment file, with a couple of minor tweaks for Script.aculo.us support
  • test_jsspec.rake—a couple of rake tasks for running the tests, and for integrating them with CruiseControl (will add support for other CI solutions as I can)
  • jsspec/jsspec.js—an unmodified copy of the jsspec trunk, here for your convenience
  • jsspec/config.js—a series of, essentially, global includes for your specs. Edit to suit your own environment
  • jsspec/consoleReportForRake.js—an extension to JSSpec that adds an afterAll hook for reporting errors that blow up your Rake task appropriately (for continuous integration purposes)
  • jsspec/prototypeForJsspec.js—a minor tweak to Prototype to get it working with the env.js file

To get rolling, copy everything but the rake task into RAILS_ROOT/test/javascripts. Put the rake task in RAILS_ROOT/lib. Edit jsspec/config.js to load any standard JavaScript files your project uses. Then, start writing specs. Here’s an example, RAILS_ROOT/test/javascripts/spec_string.js:

load("jsspec/config.js"); 
with(Spec) {  
   describe("Prototype's String.stripTags", function() { with(this) {  

     it("should remove open and close tags", function() {  
        ("<h1>text</h1>".stripTags()).should(equal("text"));
     });

     it("should remove self-closing tags", function() {
        ("text<br/>".stripTags()).should(equal("text"));

     });
   }});
};

Specs.report = "ConsoleReport";  
Specs.run();

To run this, use the targeted version of the rake task:

:trunk:-> rake test:jsspec TEST=spec_string.js
(in /Users/jgehtland/RELEVANCE/project/trunk)
.
.

2 passed. 

Run 2 examples in 0.001seconds.

:trunk:-> 

(Simply running rake test:jsspec will run any file in your test/javascripts folder whose name begins with “spec” and report the results.)

We don’t actually encourage you to write specs and tests for standard libraries like Prototype, JQuery, etc. It just makes for an easy demo.

If you want to test something that requires some HTML to bind against, I generally create a folder called test/javascripts/fixtures, and load HTML exemplars in there. For example, to test Prototype’s $$ selector, you might create a fixture called fixtures/selector.html that contains the following:

<html>
<body>
  <div class="select_me"/>
  <span class="select_me"/>
  <div class="dont_select_me"/>
</body>
</html>

Your test, spec_selector.js, would now contain:

load("jsspec/config.js"); 
window.location = "fixtures/selector.html";
load("jsspec/jsspec.js");

with(Spec) {  
   describe("Prototype's $$ selector", function() { with(this) {  

     it("should find only elements with the provided class selector", function() {  
        ($$('.select_me').length).should(equal(2));
     });

     it("should find only elements with the provided tag", function() {
       ($$('div').length).should(equal(2));
     });

   }});
};

Specs.report = "ConsoleReport";  
Specs.run();

If you want these tests to be part of your regular CI process, just uncomment the second task in test_jsspec.rake and you can now have CI for your JS, ASAP.

Fully Headless JSSpec

Posted 20 days back at Relevance - Relevance Weblog

I have been frustrated at the state of testing for JavaScript. There are a bevy of great (and not-so-great) choices for testing your JavaScript, but nothing that is current, effective, and automated. We used Crosscheck for a while, but the project went stagnant and was awfully heavy-weight besides. On top of which, it didn’t offer a BDD-flavored spec syntax.

I’ve been a fan of JSSpec for a while, but its “runs tests only in the browser” style means that automated server-side, continuous testing was nigh upon impossible.

Then, along came John Resig and his marathon weekend of hacking to mock out the DOM API in a relatively simple JavaScript file and voila! Headless JSSpec testing for Rails apps could become a reality.

If you are interested in trying it out, first download and install Rhino 1.7R1. Make sure you put the js.jar file on a globally accessible path somewhere. Then, get a copy of my javascript_testing repo at Github (http://github.com/relevance/javascript_testing/tree/master). It is a minimal repo, with just enough to get you started. The files in the repo are:

  • env.js—a clone of John Resig’s browser environment file, with a couple of minor tweaks for Script.aculo.us support
  • test_jsspec.rake—a couple of rake tasks for running the tests, and for integrating them with CruiseControl (will add support for other CI solutions as I can)
  • jsspec/jsspec.js—an unmodified copy of the jsspec trunk, here for your convenience
  • jsspec/config.js—a series of, essentially, global includes for your specs. Edit to suit your own environment
  • jsspec/consoleReportForRake.js—an extension to JSSpec that adds an afterAll hook for reporting errors that blow up your Rake task appropriately (for continuous integration purposes)
  • jsspec/prototypeForJsspec.js—a minor tweak to Prototype to get it working with the env.js file

To get rolling, copy everything but the rake task into RAILS_ROOT/test/javascripts. Put the rake task in RAILS_ROOT/lib. Edit jsspec/config.js to load any standard JavaScript files your project uses. Then, start writing specs. Here’s an example, RAILS_ROOT/test/javascripts/spec_string.js:

load("jsspec/config.js"); 
with(Spec) {  
   describe("Prototype's String.stripTags", function() { with(this) {  

     it("should remove open and close tags", function() {  
        ("<h1>text</h1>".stripTags()).should(equal("text"));
     });

     it("should remove self-closing tags", function() {
        ("text<br/>".stripTags()).should(equal("text"));

     });
   }});
};

Specs.report = "ConsoleReport";  
Specs.run();

To run this, use the targeted version of the rake task:

:trunk:-> rake test:jsspec TEST=spec_string.js
(in /Users/jgehtland/RELEVANCE/project/trunk)
.
.

2 passed. 

Run 2 examples in 0.001seconds.

:trunk:-> 

(Simply running rake test:jsspec will run any file in your test/javascripts folder whose name begins with “spec” and report the results.)

We don’t actually encourage you to write specs and tests for standard libraries like Prototype, JQuery, etc. It just makes for an easy demo.

If you want to test something that requires some HTML to bind against, I generally create a folder called test/javascripts/fixtures, and load HTML exemplars in there. For example, to test Prototype’s $$ selector, you might create a fixture called fixtures/selector.html that contains the following:

<html>
<body>
  <div class="select_me"/>
  <span class="select_me"/>
  <div class="dont_select_me"/>
</body>
</html>

Your test, spec_selector.js, would now contain:

load("jsspec/config.js"); 
window.location = "fixtures/selector.html";
load("jsspec/jsspec.js");

with(Spec) {  
   describe("Prototype's $$ selector", function() { with(this) {  

     it("should find only elements with the provided class selector", function() {  
        ($$('.select_me').length).should(equal(2));
     });

     it("should find only elements with the provided tag", function() {
       ($$('div').length).should(equal(2));
     });

   }});
};

Specs.report = "ConsoleReport";  
Specs.run();

If you want these tests to be part of your regular CI process, just uncomment the second task in test_jsspec.rake and you can now have CI for your JS, ASAP.

Jester 1.6: Modern REST

Posted 3 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

I’m sticking this version number flag into the ground to bring attention to some crucial Jester updates. Namely, full compatibility with IE7, Safari, and Prototype 1.6. If you’ve been following Jester over on Github, or its SVN trunk, then you’ve already gotten these, some from as far back ago as January. There’s not a whole lot past those compatibility fixes, but you can see what there is over at the commit list for Jester at Github, which naturally includes the commit history prior to Jester’s migration from SVN.

Download a tarball of 1.6 (via Github), or check out the trunk in Git with:
git clone git://github.com/thoughtbot/jester.git.

Jester, if you don’t remember, is a little JavaScript library we developed here to act as a REST client. We modeled it after ActiveResource and its syntax, released it a little over a year ago this time, and it got a modest amount of attention. People seem to widely appreciate its syntax, and a less wide but consistent core of people have found some use out of it, and continue to contribute patches and bug reports to the project. We made a landing site, and a little walkthrough of its syntax and uses there.

The next major development step would be to detach Jester from Prototype and bridge it to JQuery and Mootools, if there’s community interest. Also, once Firefox 3 comes out and has genuine cross site XMLHttpRequests, that would be interesting to support. Let me know any other features you think Jester would benefit from, and might make it more useful to the JavaScript world at large.

Mailing List
Bug Tracker
Landing Site

Jester 1.6: Modern REST

Posted 3 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

I’m sticking this version number flag into the ground to bring attention to some crucial Jester updates. Namely, full compatibility with IE7, Safari, and Prototype 1.6. If you’ve been following Jester over on Github, or its SVN trunk, then you’ve already gotten these, some from as far back ago as January. There’s not a whole lot past those compatibility fixes, but you can see what there is over at the commit list for Jester at Github, which naturally includes the commit history prior to Jester’s migration from SVN.

Download a tarball of 1.6 (via Github), or check out the trunk in Git with:
git clone git://github.com/thoughtbot/jester.git.

Jester, if you don’t remember, is a little JavaScript library we developed here to act as a REST client. We modeled it after ActiveResource and its syntax, released it a little over a year ago this time, and it got a modest amount of attention. People seem to widely appreciate its syntax, and a less wide but consistent core of people have found some use out of it, and continue to contribute patches and bug reports to the project. We made a landing site, and a little walkthrough of its syntax and uses there.

The next major development step would be to detach Jester from Prototype and bridge it to JQuery and Mootools, if there’s community interest. Also, once Firefox 3 comes out and has genuine cross site XMLHttpRequests, that would be interesting to support. Let me know any other features you think Jester would benefit from, and might make it more useful to the JavaScript world at large.

Mailing List
Bug Tracker
Landing Site

Mephisto: Change from SVN to Git

Posted 4 months back at poocs.net - Home

The fine folks over at ENTP/ActiveReload have released version 0.8 of Mephisto, the Rails application that powers this site. With this new release, they, as everyone these days, have actively shifted the remaining bits and pieces of Mephisto’s development from Subversion to Git. (And its main repository is hosted at Github, where else.)

I hardly remember ever installing Mephisto from a tarball. I always used to track its Subversion trunk for the 3 blogs I run, which made upgrading as easy as svn up && rake db:migrate RAILS_ENV=production most of the time. Well, that was then and this is now. Looking at this recent shift to Git, I wanted to convert my blogs to the new Git repository without excessively messing with whatever I did to my local installation (quickly approaching my 30s, I might not even recall most of what I did). I was pretty certain, however, that I did not have massive local modifications. If I had, this approach might’ve been a little simplistic.

Here’s what I did.

Initializing

Starting out, you need to create a local Git repository within your local blog installation, which is as simple as:

$ cd /your/blog
$ git init
Initialized empty Git repository in .git/

The next step is to setup technoweenie’s master repository on Github as a remote to your local repository and fetch what’s currently in there.

$ git remote add technoweenie git://github.com/technoweenie/mephisto.git
$ git fetch technoweenie
remote: Generating pack...
...

This will fetch both the master branch and all branches technoweenie might’ve created. (This includes, for example, a branch that holds the current 0.8 release, if you don’t dare to ride the edge of Mephisto’s development.)

Merging

At this point we need to merge one of the branches we just fetched into your local (totally empty, for what it’s worth) repository. (I’ve decided to stay on the master branch. If you prefer a release branch, substitute it as appropriate.)

$ git merge technoweenie/master

Since Subversion scatters its .svn folders all over the place, we need to get rid of those. You can either do that manually or with a little find-fu.

$ find . -type d -name '.svn' -exec rm -rf {} \;

Excellent, that’s much better. Now it should be safe to check out the current state of affairs:

$ git status

Running this command will show you the currently untracked files. Those would be all files that existed locally before you started to create your own Git repository and which are non-existent in technoweenie’s repository.

Tracking local modifications

As I mentioned above, I didn’t have a boatload of local modifications. My changes were limited to bit of configuration, a few third party plugins (and the accompanying CSS/Javascript) and my local Mint installation. The additional files and directories that may show up are the cached HTML files that Mephisto sticks in public/.

To actually add your local modifications to your Git repository, simple add and commit them.

$ git add config/mongrel_cluster.yml
$ git commit -m 'Mongrel configuration'

If you’d prefer to rather ignore whatever else sits in your blog directory, add it to .gitignore

$ echo "public/*.html" >> .gitignore
$ echo "public/200*" >> .gitignore
$ echo "public/mint" >> .gitignore
$ git commit -m 'Ignore cache and mint' .gitignore

Cleaning up

I had a few files sitting in my directory that weren’t local modifications but seemed to have been removed from the official repository, too. Those weren’t caught by our merging of the Git branch since we started with zero history. To get rid of those, let’s take a look at git-clean.

$ git clean -n -d
Would remove app/views/admin/article_comments/
Would remove app/views/admin/articles/approve.rjs
Would remove app/views/admin/articles/comments.rhtml
Would remove app/views/admin/articles/destroy_comment.rjs
...

The -n argument prevents git clean from actually doing anything. If you’re confident it wouldn’t do anything harmful, go ahread and remove it. (You do have backups, right? Do you?)

At this point we’re down to regular upgrading business, so you might want to run the migrations and restart your Mongrel cluster. (Or whatever floats your deployment boat.)

$ rake db:migrate RAILS_ENV=production
$ mongrel_rails cluster::restart

Into the future

Now, whenever Mr. Weenie adds an exciting new feature to Mephisto you can grab that via:

$ git fetch technoweenie
$ git merge technoweenie/master

Or if you’d rather prefer to pick a specific commit:

$ git cherry-pick <SHA1>

Further reading

Since this is not a Git guide per-se, I’ll end the article at this point. There is plenty of other content available online to bring you up to speed with Git.

Rails or Merb, what's best for you?

Posted 4 months back at Rails on the Run - Home

If you follow my blog, you already know what Merb is.

I love Rails and I truly believe it has changed web development. At least it has changed the way I do web development.

But Merb looks slick, apparently is way faster than Rails, and has less "fluff" and less magic.

Now that we are getting really close to a Merb 1.0 (scheduled for Rails Conf '08) it's time to evaluate if Merb is the good choice for some of my clients' projects.

However, according to Merb's author, Ezra, at MountainWest RubyConf 2008, Rails will get you there faster. In a client's case, they don't need to build a huge app but need a lot of speed and the ability to easily handle a heavy load right away without using caching. Also most of the traffic will go through an API so we won't have to manage too many views.

Let's see how fast Merb really is.

To test Merb's speed, I built the very same prototype using Merb 0.9.2 and Rails Edge (pre 2.1). Both apps use ActiveRecord and are connected to a UTF8 MySQL database, both apps have exactly the same views. (Note that Merb would run way faster using DataMapper, but I don't feel that DM 0.9x is production ready yet, also, using a rack handler would certainly be way faster but my goal was really to compare ActionPack vs Merb.)

Both apps use the same ActiveRecord class, their controllers are a bit different but basically do the same thing.

Here is what was tested:

  • The Merb/Rails app should receive a GET request with a JSON object in the query.

  • The Merb/Rails app should route the request to a controller and pass the JSON object to an AR class.

  • The AR class should parse the JSON object (which contains an array of objects), extract each object, and try to find them in the database using one of the attributes. If the object isn't found, it should be created, otherwise it should return the AR object. The amount of hits should be incremented by 1 and the object should be saved back to the database.

  • A simple HTML view should be rendered

Quick Merb benchmark

merb

I setup Merb to run locally on my MacBook 2.16Ghz Core Duo 2, 2Gb Ram. To test the raw performance, Merb is started in production mode.

I then used httperf to make 10000 connections to the server at a rate of 500 (--rate=500 --send-buffer=4096 --recv-buffer=16384 --num-conns=10000 --num-calls=1)

Here are the results:

Maximum connect burst length: 29
Total: connections 4377 requests 4221 replies 2932 test-duration 41.629 s
Connection rate: 105.1 conn/s (9.5 ms/conn, <=1022 concurrent connections)
Connection time [ms]: min 41.0 avg 1920.4 max 35390.8 median 898.5 stddev 4887.3
Connection time [ms]: connect 2118.1
Connection length [replies/conn]: 1.000

Request rate: 101.4 req/s (9.9 ms/req)
Request size [B]: 321.0

*Reply rate [replies/s]: min 0.0 avg 73.3 max 143.0 stddev 65.8 (8 samples)*
Reply time [ms]: response 809.0 transfer 18.1
Reply size [B]: header 121.0 content 557.0 footer 0.0 (total 678.0)
*Reply status: 1xx=0 2xx=2932 3xx=0 4xx=0 5xx=0*

CPU time [s]: user 0.35 system 36.54 (user 0.8% system 87.8% total 88.6%)
Net I/O: 78.4 KB/s (0.6*10^6 bps)

Errors: total 7068 client-timo 0 socket-timo 0 connrefused 0 connreset 1445
Errors: fd-unavail 5623 addrunavail 0 ftab-full 0 other 0

What we care about is the reply rate/s. We have an average of 73.3 requests per second with a standard deviation of 65.8 using 8 samples.

We also make sure that all the replies were successful. (status == 2xx)

I also checked the database, made sure my AR object was created and that the hits were increased. AR object hits: 2932, which matches the amount of replies reported by httperf.

We don't care so much about the rest of the httperf. Let's move on to the Rails benchmark.


Quick Rails benchmark

rails

Rails is set the same way, running locally in production mode, same httperf settings.

Here are the results:

Maximum connect burst length: 44

Total: connections 2923 requests 2825 replies 1672 test-duration 37.418 s

Connection rate: 78.1 conn/s (12.8 ms/conn, <=1022 concurrent connections)
Connection time [ms]: min 382.7 avg 5635.4 max 36384.5 median 1887.5 stddev 10103.1
Connection time [ms]: connect 3631.2
Connection length [replies/conn]: 1.000

Request rate: 75.5 req/s (13.2 ms/req)
Request size [B]: 319.0

*Reply rate [replies/s]: min 0.0 avg 43.4 max 75.2 stddev 30.8 (7 samples)*
Reply time [ms]: response 1568.1 transfer 36.7
Reply size [B]: header 471.0 content 581.0 footer 0.0 (total 1052.0)
*Reply status: 1xx=0 2xx=1672 3xx=0 4xx=0 5xx=0*

CPU time [s]: user 0.25 system 31.31 (user 0.7% system 83.7% total 84.4%)
Net I/O: 69.4 KB/s (0.6*10^6 bps)

DB hits: 1672

First thing, the database object was created properly and the hits incremented to 1672 which matches the amount of replies reported by httperf.

Then, we notice that on this test, we only got 7 samples, that's more than enough though. The standard deviation is 30.8 which is better than Merb's 65.8. That means that in our benchmarks, the reply speed difference in Merb's requests was bigger than Rails'. Not a big deal, this is not a scientific test but it's good to acknowledge it.

What we really care about is the average reply rate: 43.4

Let's also note that all the replies had a 2xx status, so everything went well.

Results

Based on this really basic benchmark, my Merb app had an average reply rate of 73.3 requests per second against Rails' 43.4 requests per second.

That means that in this very specific case,

Merb is 69% faster than Rails! Sexy!

In other words, my Merb prototype could handle 69% more requests than the Rails prototype in the same amount of time.

I heard people reporting than Merb was 3 to 5 times faster than Rails. Honestly, it really depends on what you do. By using ActiveRecord on both prototypes, I limited the speed difference since AR is not multithread and therefore Merb can't run as fast as it would using Sequel or DataMapper. By actually hitting the database on every single request, I also made sure to really compare ActionPack vs Merb.

Conclusion

The conclusion is simple, I recommended that my client go with Merb. Merb 1.0 is almost ready, the public API has been frozen. My client needs speed and simplicity. Using Merb I get exactly what I need and nothing more. Actually, we'll probably increase the performance by writing a rack handler and bypassing the entire framework for API calls (that should be wicked fast!). Also, as soon as DataMapper becomes production ready, we'll switch to DM and should get way better performance!

Am I suggesting to give up Rails and switch to Merb? Absolutely not! First off, Merb is a "lower level" framework. It requires a deeper understanding of Web Development in general and being more than just 'acquainted' with the Ruby language. So, unless you are an advanced developer or have time to learn, I would suggest to keep on using Rails (start using Merb on personal projects, it's a perfect way of learning). If you have a lot of views and/or use loads of AJAX, RJS, built-in helpers, you probably want to stick to Rails and start looking at how you can do all of that from scratch. By default Rails uses nasty helpers that create inline javascript, and is something you really want to avoid. RJS is fun, but it goes against Merb's philosophy, so you need to make sure you can live without it (note that you can reproduce the same behavior in Merb rendering JS, it just requries more work). If you rely a lot of Rails plugins, you might want to delay your switch, Merb is pretty new and doesn't have a mass-load of plugins yet.

Finally, Merb doesn't have a lot of documentation and changed a lot when 0.9 got released. To understand how Merb works, you will need to go through the source code, specs, Google, and ask on the Merb IRC channel.

It turns out that in our case we have experienced developers, a great need for speed, not too many views and are following Merb's development really closely . I honestly think it's the best choice for my client and I'm excited they accepted to use Merb.

Merb is addressing different issues than Rails and doing it well. I think there is a bright future for Merb. And don't even think that Rails is going away, that won't happen anytime soon!

Recently, Sony Playstation even posted a job post looking for a Rails/Merb developer. This is very promising for the Merb community!

Ajax will_paginate, jq-style

Posted 5 months back at ones zeros majors and minors

Matt Aimonetti has a Prototype-based Ajax Pagination in less than 5 minutes article showing how to unobtrusively Ajaxify will_paginate. Cool, but I don’t use RJS or Prototype anymore. I use jQuery.

Using jQuery, we too can easily rock some gracefully degrading Ajax pagination.

First step: ensure you’ve made your app jQuery Rails friendly. This’ll get our respond_to.js hooked up.

Next step: add a respond_to line in your controller:

 def index @photos = Photo.paginate(:all, :conditions => { :user_id => current_user.id }, :page => params[:page] ) respond_to do |format| format.html # index.html.erb format.js { render :template => 'photos.html.erb' } end end 

We’re not using RJS, but we do want to respond to JS requests with some special sauce. In this case, we’re just rendering the layout-less bulk of our photos page.

With that done, it’s onto the javascript. We’re gonna use the LiveQuery plugin, which will re-apply behaviors to fresh HTML inserted into the DOM. In other words, the Ajax behavior we add to our will_paginate links will stick around between Ajax GET requests.

Grab it from Subversion:

 $ wget http://jqueryjs.googlecode.com/svn/trunk/plugins/livequery/jquery.livequery.js 

Be sure to include it in your layout:

 <%= javascript_include_tag 'jquery', 'jquery.livequery.js,' 'application' %> 

Finally, add this to your application.js:

 jQuery(document).ready(function($) { $('div.pagination a').livequery('click', function() { $('#main').load(this.href) return false }) }) 

Sub the #main with whichever element you want replaced by our fresh photos.html.erb. And that’s it.

-- Delivered by Feed43 service

Living on the edge (of Rails) #10

Posted 5 months back at redemption in a blog

Another awfully sleepy week on Rails edge. Though by the time I had sent over the notes to Gregg Pollack and Jason Seifer of the awesome Rails Envy podcast, there has been some nice changes (that I’ll be mentioning next week, but there’s absolutely nothing stopping you from checking those out yourself).

In other interesting news, Pratik Naik (lifofifo), a long-time Rails contributor has been given commit rights to Rails. Congrats Pratik, well-deserved and it has been long overdue in my opinion! Pratik keeps an interesting blog at http://m.onkey.org/ (where he’s not afraid to say “fuck” in his posts and his code) and hangs out an awful lot on #rubyonrails and #rails-contrib on IRC.

As a sidenote, Capistrano 2.2.0 was released by Jamis last week.

This week’s report covers changes from 25 Feb 2008 to 2 Mar 2008 (the day the corresponding Rails Envy podcast was recorded).

Time#end_of_XXX methods

A bunch of Time core extension methods have been added. These are: Time#end_of_day, Time#end_of_week, Time#end_of_year, and Time#end_of_quarter, which all return exactly what you expect them to return:

Time.now.end_of_week # => Sun Mar 09 00:00:00 0800 2008

Credit goes to Juanjo Bazán (a former Rails Hackfest winner) and Tarmo Tänav for contributing this patch.

Related changeset: http://dev.rubyonrails.org/changeset/8934

Date helpers now accept HTML options

ActionView’s date helpers (such as date_select, time_select, select_datetime) did not support any HTML options, unlike the other helpers (like f.text_field(:name, :class => 'my_css_class', :size => 20)). This inconsistency has been fixed and you can now finally do:

<%= date_select 'user', 'birthday', :order => [:day], :class => 'my_css_class' %>

Murray Steele (h-lame on the Rails Trac) and Jakob Skjerning contributed this patch.

Related changeset: http://dev.rubyonrails.org/changeset/8968

No need for explicit respond_to for RJS templates

ActionController has been changed so that JS requests will automatically render action.js.rjs files without the need to specify an explicit respond_to block. This means that your .rjs files work the same way as your .html.erb files - just put them in the right place and Rails will use it.

Related changeset: http://dev.rubyonrails.org/changeset/8956

Bugfixes

  • http://dev.rubyonrails.org/changeset/8937 - Prevent Rails from crashing when trying to deserialize an XML representation of a model named “Type” (using Hash#from_xml). Contributed by Juanjo Bazán and Isaac Feliu.
  • http://dev.rubyonrails.org/changeset/8942 - Fix eager loading so that it doesn’t pull in duplicate records in some cases. Contributed by Catfish.

As usual, let me know of any inaccuracies or any suggestions you may have in the comments!

Rails 2.0 TextMate bundle - Tasty Tidbit - respond_to and view navigation

Posted 5 months back at Dr Nic

The new release of the Rails TextMate bundle is coming soon. Its guaranteed to be shiny, sparkly and will fit in with any home or office decor. More importantly, it will be upgraded for Rails 2.0.

Today is the first Tasty Tidbit - a demonstration of one of the snazzy new features coming to your Macintosh soon.

In this Tasty Tidbit, we look at respond_to and the ability to create and navigate to view templates based on the selected format block, such as wants.js -> .js.rjs.

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="437" height="370" id="viddler"> <param name="movie" value="http://www.viddler.com/player/52b07473/"/> <param name="allowScriptAccess" value="always"/> <param name="allowFullScreen" value="true"/><embed src="http://www.viddler.com/player/52b07473/" width="437" height="370" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" name="viddler"></embed></object>

Cannot see the embedded video? Want the Hi-Def version? Download the video (5 Mb).

Zero Sign On - 1 better or Infinitely better than Single Sign On?

Posted 6 months back at Dr Nic

This article has no code in it. There are no TODO steps. Nothing to install. Its a picture of the future.

There is no reason to bookmark this article and read it another day. Its nearly all pictures. You can read it now.

This “picture of the future” was actually added to our browsers in the 90s. Netscape and MSIE3.0 both had it.

“It” is Client Certificates, and to me to means “never logging on with username/password NOR OpenID ever again”. Zero Sign On. It must be better than the much-targetted Single Sign On.

Client Certificates

Firefox 2.0:

no-certificates

Or on Safari/KeyChain:

Keychain Access - no certificates

Small problem: no website I’ve ever used has ever offered them, so I never knew they existed. I didn’t know what they did, nor as a web developer that I could create them for users who’d never need to login again.

Clifford Heath showed me the light. On #roro irc channel, we were exploring how “Zero Sign On” might be implemented using ssh-keygen, and browser plugins etc. Clifford mentioned client certificates and then someone else mentioned that MyOpenID already supported them.

I already had an myopenid account, so raced over to explore the new world of certificates.

Under “Authentication Settings”:

myopenid-create-certificate

After submit:

myopenid-creating-certificate-dialog

And then:

myopenid-certificate-creation-finished

Then feedback:

SSL Client Certificates

So I thought to test out if “Zero Sign On” actually worked. Normally, after logging out you’d need to submit username/password or if a site supported OpenID (yes myopenid.com is an OpenID provider which is a bit circular but bear with me) you login by entering your OpenID url and pressing Enter. Either way, you’ve got work to do.

Instead, I clicked “Login” link on the home page, and was redirected immediately to:

myopenid-login-uses-alternate-url

myopenid-signin-with-certificate-form

So it was still using cookies so that it could log me in immediately next time without clicking “login”, but either way, there is no username/password nor any other “type something here” login form. Just a “Remember Me” checkbox.

Finally, myopenid.com shows a log of your sign-in attempts:

activity.jpg

Your sites and the future

As a web developer, you can do one of two things to get some leverage of Client Certificates.

  1. Support OpenID as a login mechanism. Users with myopenid.com accounts (or other openid providers that support client certificates) will benefit from automatic login to their openid page and instant redirection to your site. You’ll also be able to help new users import their profile data to get them started quickly.
  2. Implement Client Certificates yourself. I would have liked to have had a crack at this before posting about Client Certificates and all their sweet loveliness, but I didn’t. My bad. Instead, I found a nice step-by-step (plus comments with updates) on implementing Client Certificates

If you have/do implement Client Certificates in Ruby/Rails world, you’ll get a 1000 Happy Points from me if you open source it/blog about it. Happy Points are redeemable for Happiness in all countries.


1 2 3 ... 6