Nicolas Alpi, Web developer

A blog about productivity, startups and me.

I’ll Become a Ruby on Rails Full Time Freelancer

This is the good news of the day. I’m leaving HP in one month now, for going full time Ruby On Rails / Jquery / Other stuffs full time freelancing.

I’ll start on projects for a company called Jiva in south Bristol for several months which is an ideal position!.

On these kind words, I’ll leave you and go on holidays for about 2 weeks. Preparing my RailsRumble app, my freelance CV and try to sleep a bit.

Holidays D-1, I’ll Do My Homeworks for the Railsrumble

Haa, holidays are coming. I’ll be ending in North of France, enjoying Belgium beer, Nathalie’s grand parents fresh vegetables and … will be a bit disconnected. This will be the occasion for me to put some order in remaining/waiting projects.

But, as last year, I’ll compete at the RailsRumble this year. My app? PlanetToaster.

rr09_badge_250

So I’ll do my homeworks, and try to be organized for the DDay.

What if learned so far from last year is :


  • 48 Hours is not so long!

  • You need to prepare your timing as much as your application itself. This year I’ll try to come with a detailed schedule for every 30 minutes/1 Hours.

  • Prepare your assets. Prepare your icons (CC) prepare your wireframes for EVERY pages, even the so forgotten 404 / FAQ.

  • Don’t overestimate your capacity. During these 48 Hours, you’ll under pressure, and your brain will not work as fast as you want.

  • Register everything. Domain name / Emails / Twitter /

  • Only use gem that you know. It’s not the time to have trouble with something you’ve never played with (like myself last year and the Timezone broken in Rails …)

  • Do your tests, but not to much. This will be time consuming (at least for me flying solo).

  • Prepare your ring. Prepare your desk and computer, clean everything and just keep what you need for the rumble.

  • If, as me, you have pretty rubbish design capacities, try do go as simple as possible. If your app worth it, you’ll still be able to improve it later.

  • Commit early, commit often. This will help to keep trace when your brain will start to burn.

  • Sleep well, the 2 days before.

  • Enjoy it as much as possible. Even if we are all behind our screen, this is a fantastic opportunity to (virtually) meet new people. And there is a great satisfaction after the 48 Hours to see your works live.

So in a nutshell, prepare carefully your application development process, prepare your time schedule, prepare everything you can before the competitions.

I’ll be back from my holidays the 14 of August. Have a nice week!

Passing Env Variable to Ruby With Apache

I had a problem last week, while developing tweetcetera. I need to use open-uri to open the twitter search url.

BUT, when I develop/test from from my office, I needed to pass through my corporate proxy. Obviously not when I’m at home, and not on my staging/development server.

For the first days I just manage to remove the proxy config variable in my application.rb and that was ok, but it’s certainly not an elegant solution.

First I wanted to create new environments like development_office and test_office, with specific config files … bullshit.

The solution is pretty easy.

open_uri look at environment variables.
Apache use a file call envvars, to setup these environment variables.

So just edit your envvars file (In your Apache folder), and add your env variable like

export http_proxy=http://mycorporate.proxy.com:8080

Restart apache and it’s ok.

Sweet.

10 Things I’ve Learned Developing in Rails

I’ve started learning Rails and Ruby 3 years ago now, and now all my side projects are made in RoR.
I’ll be ready soon to release my third rails application, but having launched earlier this year serialcooking.com I’ve learn a lot on good RoR good practice in terms of development, deployment and maintenance.
I just wanted to share some of my learning/mistakes over the time.

Manage your queries properly

Believe it or not, but before the beta launch of serialcooking.com, my index page was performing 95 queries! Outch. I wanted to write my code as fast as possible and completely forgot to do performance review.

Here were my mistakes:


  1. I wasn’t using :joins and :include properly (See FIND doc on apidock)

  2. I wasn’t using query_reviewer (Query reviewer on googlecode)

Query Reviewer is a fantastic tool, helping you to resolve query numbers and table indexes problem in development mode. Worth try it!
h2. Assets management

The less you transfer, the fastest your page will load.

So instead of linking to my server Jquery file, I used the Google Ajax API, which is available for various JavaScript libraries.

Another interesting tool to package your assets in rails is the asset packager plugin. (Asset packager on github)

Basically, you declare in one config file all your assets to package, and on your staging/production server it will only transfer 1 packaged file per type (CSS/JavaScript …). The gain is just fantastic, and it’s so easier to maintain.
h2. I’ll never use HTML again

Forget about HTML and ugly coded view. Welcome to HAML!. (HAML/SASS website).

I must admit, I came to HAML late, doing resistance and loving my XHTML. But I give it a real try on a side project. And the fact is, it’s just wonderful!

Judge by yourself

<div id="profile">
<div class="left column">
<div id="date"><%= print_date %></div>
<div id="address"><%= current_user.address %></div>
</div>
<div class="right column">
<div id="email"><%= current_user.email %></div>
<div id="bio"><%= current_user.bio %></div>
</div>

</div>

Will become in HAML

#profile
.left.column
#date= print_date
#address= current_user.address
.right.column
#email= current_user.email
#bio= current_user.bio

The learning curve is really quick. My only regret is to not have tried it before!.
h2. Never, never render HTML in your Rails Helpers

This is something I did a bit in the beginning. I quickly went back. Rendering HTML in your helpers is a very bad idea, rendering a partial instead is a better one ;)
h2. Never use RJS again

For my first Rails project, I used RJS. (It was 2 years ago). At the time, it was fantastic, quick bla bla bla. Well, today, with current Javascript practices and Javascript libraries I don’t see the point of having ugly and obtrusive JavaScript in my code.

I prefer using Jquery like in this previous post. So easier to maintain.
h2. Maintain and deploy your code smarter

I use git and github to manage my projects code. I use Capistrano and Capistrano-ext combined with the github repository to deploy my code and I use Passenger on Apache2 to access my application.

I also ALWAYS use a staging environment, just to be sure that everything is ok before moving to production.
h2. Don’t believe in anyone, test!

I now test my code for 1 year. I first started with the embded Rails testing framework, and then, because all the cool kids were loving it, I migrate to Rspec during 3 months. I didn’t like it, but because everyone liked it I force myself to continue!

Finally I was writing bad quality tests, and didn’t enjoy my tests.

I then came over shoulda and now I enjoy again writing my tests.

The point here is, and it’s the same when you choose Rails over Django or Symphony, don’t trust anyone because he says “this is the better plugin/technology/language ever”.

Instead, try by yourself, see what the others can brings to you, and have a clear in mind choice.
h2. Monitor your application

Using a tool like Newrelic is a real benefit on monitoring what’s happening in your web app, in real time. Find the slowest part of it and fix it.
Just fantastic. Currently I just use the free version, but I’m considering on upgrading as it’s so useful.
h2. Never let an error blocking your users

I use Hoptoad to catch all the errors happening on my apps. As newrelic, you just install the plugin, and it works like a charm. You receive an email when an exception is raised in your app, so you can resolve it as fast as possible.
h2. The tail command

A very useful command that I just learned months ago.

$ tail -f log/development

And leave your terminal window open. It will refresh every second with new thing coming from your log. Really useful, I don’t remember how I was doing before that!.

What about you?

Do you see something that you learned and is not present here? Just add it in comment.

Nathalie Is Looking for a New Position.

Nathalie‘s (now my fiancee) temporary position has ended last week, and she is looking for a new position in or around Bristol.
Currently working in marketing/web marketing, it’s not the best season/time to search for a new position.
With an average of 1 new job per day, I don’t think she’ll find something quickly.

I’d say that it’s normally a bad news, but this time it might be better than we thought.

Since her graduation, Nathalie always wanted to work in the web industry, That why we created SerialCooking and she was pretty good at managing the blog and the community on this project, but it was missing something: Coding.

She is now learning XHTML/CSS and web standard  to have a better understanding of the whole process. And I must admit she is doing very well, and likes coding. Will she be looking for a Junior Web Developer position soon? Never know ;).

She has a good understanding of technologies, web technologies and social networking.

So if you know someone who know someone with a job opportunity (Every position considered!), please let her know. Thanks a lot.

Here Nathalie Derain, online marketing executive resume in pdf.

Starting With Backup-manager, or How to Never Loose Data Again!

Loosing data can be quite ... annoying.

The last thing you want is to have a disaster on your server and being unable to recover your data.
I run all my projects and different blogs on one server, hosted by OVH. So I have multiple databases, gems, websites and configurations that I want to backup.
Hopefully, OVH provide with every dedicated server an external FTP server dedicated to backups.
So I’ve installed backup-manager and make it runs twice a day.

Warning

Because backup-manager compress your files into archives, it will cost you some space on the disk, so be sure to change the default value of the target and do your backup on a proper partition.
If you don’t, backup-manager will do the backups in / by default, so when it’ll be full, your sever will not work properly.

Installation

sudo apt-get install backup-manager

Tweacking

Installation create a default config file. You’ll need to edit it to match you configuration.

sudo vim /etc/backup-manager.conf

Before I explain you my config file, here is how I’ve config my server:

  • I have 4 PHP Applications (Blogs/apps) and 3 Ruby on Rails apps running on it.
  • Each application has it own directory in /home/ .
  • REE is installed in /opt, and so are the gems.
  • I keep an automatic backup of my server configurations (DNS/Host/Users/Right…) in /home/config (Only accessible by root).
  • I’ve created an new partitions call “/backups”.

So basically, want I want is:

I save my /home/, /etc/, /opt/, all my databases to an external partition then an external FTP.

In backup-manager.conf, you’ll need to set:

Local Storage

  • BM_REPOSITORY_ROOT “/backups” Where to store local backups.
  • BM_ARCHIVE_TTL “3” Local archive time to live.
  • BM_ARCHIVE_METHOD “tarball” Which archive method do you want to use (You can mix and match different types).

Backup directories

  • BM_TARBALL_DIRECTORIES “/etc /home /opt” Directories to backup.
  • BM_TARBALL_BLACKLIST “/home/nobackup” Exclude some directories.

Backup transfer

  • BM_UPLOAD_METHOD “ftp” Backups transfer method.
  • BM_UPLOAD_FTP_USER “myftpusername” FTP login.
  • BM_UPLOAD_FTP_PASSWORD “myFtpPassw0rd” FTP Password.
  • BM_UPLOAD_FTP_HOSTS “ftp.backups.com” FTP Server.
  • BM_UPLOAD_FTP_PURGE “true” Clear the remote directory before to upload.
  • BM_UPLOAD_FTP_DESTINATION “/” Upload existing directory.

Incremental Archives (set BM_ARCHIVE_METHOD = tarball-incremental)

  • BM_TARBALLINC_MASTERDATETYPE “monthly” Complete archive creation frequency (daily or monthly)
  • BM_TARBALLINC_MASTERDATEVALUE “23” Creation day of the complete archive

Mysql databases

  • BM_MYSQL_DATABASES “mysql1 db2 db3”“ALL” mysql db names separate by space or ALL
  • BM_MYSQL_ADMINLOGIN “backupuser” Mysql user (DO NOT USE ROOT!, see below)
  • BM_MYSQL_ADMINPASS “backuppassword” Mysql user password
  • BM_MYSQL_HOST “localhost” Mysql Server
  • BM_MYSQL_PORT “3306” Mysql port
  • BM_MYSQL_FILETYPE “bzip2” Backup compression method

Others

  • BM_PRE_BACKUP_COMMAND "" Execute a command before the backup
  • BM_POST_BACKUP_COMMAND "" Execute a command after the backup

Pratical Backups

Databases

Please be careful, as you’ll need to write in this file the login and password of a user to procede to dabases backups.
Don’t use root!, neither an existing user. You’re going to create a new user, with limited right on databases and tables, and you’ll protect the backup manager config file.

mysql -u root -p

GRANT SHOW DATABASES,SELECT,LOCK TABLES ON . TO ’backupuser’@’localhost’ IDENTIFIED BY ‘secretpassword’;
exit;
sudo chown root:root /etc/backup-manager.conf
sudo chmod 640 /etc/backup-manager.conf

Now you can set the 2 values in the backup-manager config file.

  • export BM_MYSQL_ADMINLOGIN=“backupuser”
  • export BM_MYSQL_ADMINPASS=“secretpassword”

BM_MYSQL_FILETYPE

Mysql database compression after dump.

  • export BM_MYSQL_FILETYPE="bzip2"*

Make sure that bzip2 is intalled

sudo apt-get install bzip2

BM_POST_BACKUP_COMMAND

Execute a command once bakcup done. You can,for example, use this to send an email after the backup.

Automated backups

You can use cron to schedule your backups. Before just create a little script

cat &lt;&lt; EOF &gt; /etc/backup-manager.sh &amp;&amp; chmod 700 /etc/backup-manager.sh

#!/bin/sh
test -x /usr/sbin/backup-manager || exit 0
/usr/sbin/backup-manager
EOF

And now you can add this script to your contab

crontab -e

And add

1 0 * * * /etc/backup-manager.sh

Here is ubuntu cron doc, easy to understand (https://help.ubuntu.com/community/CronHowto)

Do more

For example, you can call backup-manager with backup-manager -c /path/to/configfile and by this way, having 2 crons. One running every days, executing backups of files and db, and another one, in the middle of the day, only for the db ;).

You can do much more than these options (cd/dvd burning for example), please be sure you read the complete wiki at http://wiki.backup-manager.org/index.php/Main_Page#Documentation

My New Moo Card Set Arrived Today

My moo business cards set


This year I’m looking to more networking and freelancing in the Uk, so I’ve made these business cards and they’ve been printed by Moo.

As alway, Moo quality is just fantastic, and I’m happy with the result. But I’ll certainly do another with Web Strategy Developer or something like that (more generic than Ruby on Rails evangelist).

Anyway, what do you think?

business card

Let’s Go Cycling … And Taste a Car!

Accidented bike #6


6 months ago, I decided to change my commute habits, to become greener. My bike became my principal mode of transport. And it’s really pleasant. Even in winter, you fell alive, you arrive earlier to work and at home, your not stuck in traffic. Honestly I didn’t see any inconvenient. Well, I didn’t.


I’d already realized that, sometimes, car drivers doesn’t care about cyclists. They pass us very close, they use cycle lanes or cycle part at red lights. Anyway, not really a big deal, but sometimes it can be more dangerous.


Last Friday (29th of June), a car driver simply didn’t see me, and cut my road. I hit the car back, and fall down.


First, a teenager helps me to stand up, and took my bike to the pavement, the driver took nearly 2 or 3 minutes to came out of her car. When see came out, the first think she said was : “Do you have a mobile phone to call someone?”. Well, under the shock and the pain, I said yes, and took my phone to call my fiancée 3 times. She didn’t respond (hopefully). I tried to move my right shoulder, and completely felt down under the pain. So I asked the driver to call an ambulance or the police. After going to her car taking her phone, she just asked me to call again my fiancée. Nathalie wasn’t here, so she didn’t respond. So the driver just propose me to give me a lift to the hospital (Why bloody why didn’t she wants to call someone).


She wasn’t really in panic, but I don’t know were she had her license. On the way to the hospital, she passes 2 red lights!!!.


She stopped nearly 200 meters before the hospital entrance, and said “I’ll leave you here”. The emergency room is completely the opposite!. I took her phone number, after asking 2 or 3 times, and before she left, I took a reg number.


At the BRI (Bristol Royal Infirmary), I had a very nice doctor, she took care of me, did everything. The results, right collar bone broken, tendons stretched, I’ll not be able to use my arm for 4 weeks as minimum, and really pissed off about the driver attitude.


Since we are in Bristol, it’s my second accident. Last tme we were waiting to cross a road, and hit by a drunk driver in St Augustine Parade.


I think, next time, I’ll probably remove my French flag above my head ;).


So last we I didn’t code at all, I’ll try to do small things this week, but it’s really hard with one hand :(.


Anyway, please, if one day you have an accident, please, take time with the victim, and be human !.


Beginning Ruby on Rails, Where to Start and Find Help?

So that’s it, you want to start development with Ruby on Rails, but you don’t know where to start.
The good thing is Ruby on Rails has a very clever and smart community, and you can find lots of documentation on the web.
Here is quick summary on where to start.

Books

If you really want to learn Ruby on Rails, the best first thing to do is certainly to invest in a good paper/electronic book.
There are lots of books available outside but I would only recommend two of them.

Agile web development with Rails
Probably the most popular book outside. The third version include Rails 2.x support and was co-written by Sam Ruby, Dave Thomas, David Heinemeier Hansson, et al.
A must have.

The Rails Way
Obie Fernandez came here with one of the best book for rails developer. From the beginning to Rspec, you’ll learn how to start coding and testing your new Rails App. Btw, Obie Fernandez is the guy behind Thoughtbot.

Wiki

New ruby on rails wiki
While your waiting your book to be delivered, you might have a look to the  new ruby on rails wiki started by the Rails Activist Team. Let say, in a nutshell, that this wiki is a big FAQ for Rails, and beginners should find here responses to their questions.

On line Documentation

Rails Guides
You know what they say, RTFM before asking a dummy question! So be sure to checkout the awesome Rails Guides before asking any question, you’ll certainly find your answer.

Official Ruby on Rails doc
Well, not the best looking, but at least it does the job.

Rails Brain
Rails brain ajaxified the official ruby doc, for a smoother search experience. The good thing is you can access on line, old Rails versions doc. Note there is also RubyBrain

Rails *S*ea*rch*able API Doc
A very nice Ajax interface to parse the Rails (and some other gems) api. You can download it, and copy the directory in your web server root directory to have an off line access to it.

ApiDock
Probably Certainly the best documentation search tool ever!. It combines documentation and community in the same project. Very smart. (Note there are Firefox and Textmate extensions).

Community

Rails forum
A friendly and smart community, alway here to help. Feel free to ask your question if you didn’t find the answer above.

Ruby on Rails Google group
I’m not a big fan of malling lists/Google groups, but it’s a nice one, with again a huge community.

Screencast/Podcasts

Definitively one of the best way to learn how to develop is to listen/watch  some else coding.

Railscast
I don’t remember how was my Monday morning before the Railscast. Ryan Bates will offer you every week  a new free screencast, full of good coding practice and advice. A must to watch, with a warm cup of tea.

Peepcode
One of the best quality screencast for Rails/Merb/Development in general. If you are new to rails, I just recommend you the REST for Rails2 screencast and the Rails2 PDF.

Rails Envy Podcast
Still need to present them? Presented by Greg Pollack and Jason Siffier Saffer Seifer (he never knows how to pronounce names either!) . These guys are just crazy, and yes it’s a compliment. Every week, during 20 minutes, you’ll learn all the hot new stuff happening in the Ruby/Rails/Merb community, with fun. Check it out.

What else?

Sure you can extend this list with blog talking about Rails, Twitters of trendy rails developers to follow, github account to watch … sure, but I think with this list above you’ll have a good entry point to the community.
Now have fun and happy coding ;) (go write your tests!).

Beginners Guide to Jquery + Ruby on Rails

First time I wanted to use Jquery with Ruby on Rails I had some difficulties understanding how it can works.

Sure, you can easily use Jrails, that’ll brings you RJS helpers with Jquery, but I quite like the unobstrusive way, so Jrails is not (for me) the best solutions.

Let’s code together

What do we want?

We are going to simulate a blog post comment system. We need to be able to list the comments/create a new comment/rate a comment/delete a comment.

All this need to work with and without JavaScript enabled.

I deliberately didn’t use any user/role filtering, the goal of the code is to show of to work with Rails and Jquery

Step1: Prepare the app

We want to work with Jquery, so we don’t need the Prototype files anymore. Just remove everything from your public/javascript/ appart application.js.

In your master layout add this bunch of lines

&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js&quot;&gt;&lt;/script&gt;
<% if protect_against_forgery? %>
<script type=‘text/javascript’>
//<![CDATA[
window.auth_token_name = "#{request_forgery_protectiontoken}";
window.auth_token = "#{form_authenticitytoken}";
//]]>
</script>
<% end %>
<%= javascript_include_tag ‘application’ %>

We are linking Jquery to the google hosted version, and calling the application.js and setting the forgery protection.

Then in your application.js copy and past the content of my default application.js (Also available as a gist)

jQuery.ajaxSetup({ 'beforeSend': function(xhr) {xhr.setRequestHeader(&quot;Accept&quot;, &quot;text/javascript&quot;)} })

function _ajax_request(url, data, callback, type, method) {
if (jQuery.isFunction(data)) {
callback = data;
data = {};
}
return jQuery.ajax({
type: method,
url: url,
data: data,
success: callback,
dataType: type
});
}

jQuery.extend({
put: function(url, data, callback, type) {
return ajax_request(url, data, callback, type, ‘PUT’);
},
delete
: function(url, data, callback, type) {
return _ajax_request(url, data, callback, type, ‘DELETE’);
}
});

jQuery.fn.submitWithAjax = function() {
this.unbind(‘submit’, false);
this.submit(function() {
$.post(this.action, $(this).serialize(), null, "script");
return false;
})

return this;

};

//Send data via get if JS enabled
jQuery.fn.getWithAjax = function() {
this.unbind(‘click’, false);
this.click(function() {
$.get($(this).attr("href"), $(this).serialize(), null, "script");
return false;
})
return this;
};

//Send data via Post if JS enabled
jQuery.fn.postWithAjax = function() {
this.unbind(‘click’, false);
this.click(function() {
$.post($(this).attr("href"), $(this).serialize(), null, "script");
return false;
})
return this;
};

jQuery.fn.putWithAjax = function() {
this.unbind(‘click’, false);
this.click(function() {
$.put($(this).attr("href"), $(this).serialize(), null, "script");
return false;
})
return this;
};

jQuery.fn.deleteWithAjax = function() {
this.removeAttr(‘onclick’);
this.unbind(‘click’, false);
this.click(function() {
$.delete_($(this).attr("href"), $(this).serialize(), null, "script");
return false;
})
return this;
};

//This will "ajaxify" the links
function ajaxLinks(){
$(‘.ajaxForm’).submitWithAjax();
$(‘a.get’).getWithAjax();
$(‘a.post’).postWithAjax();
$(‘a.put’).putWithAjax();
$(‘a.delete’).deleteWithAjax();
}

$(document).ready(function() {

// All non-GET requests will add the authenticity token
// if not already present in the data packet
$(document).ajaxSend(function(event, request, settings) {
if (typeof(window.AUTH_TOKEN) == "undefined") return;
// IE6 fix for http://dev.jquery.com/ticket/3155
if (settings.type == ‘GET’ || settings.type == ‘get’) return;

settings.data = settings.data || ""; settings.data += (settings.data ? "&" : "") + "authenticity_token=" + encodeURIComponent(window.AUTH_TOKEN); }); ajaxLinks();

});

This is my default application.js when I want to work with Jquery.

Basically what brings you these functions are :

Any link for a class get/post/put/delete will be called via ajax only if JavaScript enabled. Same for form with ajaxForm class.

The code

You can find the original code on my github at

http://github.com/spyou/railsjquery/tree/master

I’ve created a comment resource. The comments table has a body and a score field.

Here is the comments_controller.rb

class CommentsController &lt; ApplicationController
#This is a virtual comment manager. There is no user detection, no session
before_filter :load_post
#This is our entry point, I’m just going to display a factice post to comment
def index
@comments = Comment.all
respond_to do |format|
format.html #we only respond to the html request
end
end
def new
@comment = Comment.new
if !request.xhr?
@comments = Comment.all
end
respond_to do |format|
format.html
format.js {render :layout => false}
end
end
def create
@comment = Comment.create(params[:comment])
respond_to do |format|
format.html { redirect_to comments_path() }
format.js {render :layout => false}
end
end
#This is not a "normal" update, I’ll use this one to add points to the comment
def update
@comment = Comment.find(params[:id])
@comment.score = @comment.score + 1
@comment.save
respond_to do |format|
format.html { redirect_to comments_path }
format.js {render :layout => false}
end
end
def destroy
@comment = Comment.find(params[:id])
@comment.destroy
respond_to do |format|
format.html { redirect_to comments_path }
format.js {render :layout => false}
end
end
protected
def load_post
@post = "This is a factice post, I hope you like it. Just comment on the bottom!"
end

end

As you can see on it, we handle 2 different types of responses

respond_to do |format|
format.html
format.js {render :layout => false}
end

Format.html will load your [actionName].html.erb, but the format.js will load a page called [actionName].js.erb were you can put all the callback javascript you need.

For example here is my index.html.erb

&lt;%=
#Use a helper to display the current comments of the post
comments_display(@comments)
%>

<div class="newComment">
<%= link_to ‘Create a new comment’, new_comment_path(),:class => "get"%>
</div>

and the _comment.html.erb

&lt;div id=&quot;comment&lt;%= comment.id %&gt;&quot;&gt;

<%=
content_tag(:p,
comment.body)
>
<!— We are accessing the update function so we use put as class —>
<span class="score"><
= comment.score ></span><span> – <= link_to ‘Add one point!’,comment_path(comment),:class => "put" ></span>
<p> – <
= link_to ‘*Delete this comment’,comment_path(comment),:method => :delete,:class => "delete" ></p>
<p><
= comment.created_at %></p>
<hr />
</div>

You can see the use of get/put/delete class.

Here is now the new.js.erb (Where I call a _form.html.erb to render the new comment form)

$(&quot;.newComment&quot;).html(&quot;&lt;%= escape_javascript(render :partial =&gt; 'form') %&gt;&quot;);

ajaxLinks();

And here is the update.js.erb (Where I’m suppose to update the score of the comment without refresh)

//Update the score

$(‘#comment<%= @comment.id %> span.score’).html("<%= @comment.score %>");

The tests

Well, the problem with the test is, you can test the rendering of you page (in plain text) but you can’t be sure of the javascript execution.

I’m made some simple tests (testing the plain text) that you can find in the test/functional folder.

(Example with the new comment method)

#Testing the comment creation
context "handle :create" do
context "by html" do
setup do
post :create, :comment => { :body => "My comment" }
end
should_change "Comment.count", :by => 1
should_redirect_to("the index"){comments_path()}
end
context "by xhr" do
setup do
xhr :post, :create, :comment => { :body => "My xhr comment" }
end
should_change "Comment.count", :by => 1
should "Display the new comment link" do
assert_match(/new comment/,@response.body)
end
should "display the created new created message" do
assert_match(%(My xhr comment),@response.body)
end
end
end

This is just the beginning, I’m now looking to some Javascript testing solution for Rails, will be part of another tutorial.

In a nutshell

So in a nutshell, what’d learn here is :

  • Rails + Jquery is easy
  • format.js + file.js.erb and you’r done
  • A good application.js can save your ass

Just checkout the complete source code

git clone git@github.com:spyou/railsjquery.git

rake gems:install
rake db:create

jquery-rails-tutorial_1242648062355

I hope it was useful.