Monday, June 28, 2010

Rspec with Rails 3

First of all, we will need to setup Rspec on Rails 3,
sudo gem install rspec
sudo gem install rspec-rails --pre

Then we include them in our gemfile,
gem 'rspec'
gem 'rspec-rails'

Then we will run the generator:install,
rails g rspec:install
which will provide us with all the files/directory that we need to use Rspec

For a more robust TDD/BDD, we could install autotest. This would assure that each time we edit the test file, the Rspec test will be conducted automatically without the need of us typing the command out.
gem install autotest
gem install autotest-fsevent
gem install autotest-growl (For some reason i still couldn't set it up to work with Growl for OSX)

Open the autotest file,
mate ~/.autotest

Add these 2 lines to the file
require "autotest/fsevent"
require "autotest/growl"

Kick it off with
autotest

If we are testing model, be sure to do
rake db:test:prepare
or Rspec will complain.

Friday, June 18, 2010

Upgrading a Rails 2 App to Rails 3

Most of us have Rails 2 Application in our stash and it would be nice to support the latest Rails 3 since some day the Rails 2 methods and architecture will be deprecated.

Some of the useful reads are Simon Carletti's Blog, Rails Dispatch, and omgbloglol.

So what you can do to upgrade an existing app is by running a (rails generate new app) on an existing Rails 2 application.

Say your previous Rails 2 app is in a folder titled "blogApp", then run
rails blogApp


It doesn't exactly forcefully overwrite the entire folder, but it prompts you if you wanna keep this particular file or if you wanna update it, and it also adds all the files that Rails 3 need like gemfile bundler, new rails.rb in the script folder, and so on.

Based on omgbloglol, it would probably be a save bet to overwrite these files:-
  • Rakefile
  • README
  • config/boot.rb
  • public/404.html (unless you’ve customized it)
  • public/500.html (unless you’ve customized it)
  • public/javascripts/* (if you don’t have a lot of version dependent custom JavaScript)
  • script/* (they probably wouldn’t work with the new Rails 3 stuff in their old form anyhow)
And depending on our needs, we might or might not wanna overwrite these :-
  • .gitignore (unless you don’t really care; the new standard one is pretty good)
  • app/helpers/application_helper.rb
  • config/routes.rb
  • config/environment.rb
  • config/environments/* (unless you haven’t touched these as many people don’t)
  • config/database.yml
  • doc/README_FOR_APP (you do write this, don’t you?)
  • test/test_helper.rb
By doing that, we pretty much have the boilerplate of a Rails 3 application and all we have to do is tweak the codes to conform to Rails 3.
  1. Moving gem to gemfile Bundler
  2. Moving the configurations from config/environment.rb to config/application.rb
  3. Routers new syntax
  4. etc..
And you can find the steps for the upgrade at omgbloglol, which to me is pretty comprehensive.

Let the Rails 3 Migration begin.

Wednesday, April 14, 2010

Recaptcha on Rails

I am going to show you a basic example on how to stick ReCaptcha in your Rails application.

First of all, we are gonna need the tools,
Go ahead and register an API key at Recaptcha. Then go ahead and install the plugin/gem at Ambethia's Recaptcha on GitHub.

Once we got those installed and done, first thing first is to setup the API keys.
/config/environment.rb
# Load the rails application
require File.expand_path('../application', __FILE__)

ENV['RECAPTCHA_PUBLIC_KEY'] = '6LetRwwAAAAAAHYInUoOSj2mN_2dafLelpON4VzV'
ENV['RECAPTCHA_PRIVATE_KEY'] = '6LetRwwAAAAAAHYInUoOSj2mN_2dafLelpON4VzV'

# Initialize the rails application
RecapApp::Application.initialize!



Then we are generally gonna use Recaptcha in a form submission. Let's stick it there.
/views/posts/_form.html.erb
#Add this somewhere, note the Raw as Rails 3 automatically escapes html
<%=raw recaptcha_tags %>



Then we will have to take care of the backbone in the controller. So we want Recaptcha to kick in when a user sends a POST request or submit a post.
/controllers/posts_controller.rb
def create

@post = Post.new(params[:post])
respond_to do |format|
if (verify_recaptcha(:model => @post, :message => "The captcha does not match!") &amp;&amp; @post.save)
format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
format.xml { render :xml => @post, :status => :created, :location => @post }
format.js
else
format.html { render :action => "new" }
format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
format.js
end
end
end


The :message option will deal with the error message in the form if the captcha doesn't match.

And there you have it!

Thursday, March 25, 2010

JQuery and Unobtrusive Javascript on Rails 3

In the earlier post, JQuery on Rails 3. You will need a few files to kick start in using JQuery.
  1. rails.js from http://github.com/rails/jquery-ujs
  2. jquery.js from http://code.jquery.com/jquery-1.4.2.js
  3. application.js having your custom javascript command
  4. Load them in the layout file
Lets try adding an ajax link somewhere on a page. Notice the difference, we are no longer using link_to_remote anymore. We will instead be using link_to, passing in the :remote key.
index.html.erb

<span id=\"ajax_button\"><%= link_to \'ajax!\', \'/\', :remote => true %></span>

<div id =\'ajax\'>
</div>

What Rails 3 gives us in doing this. If you take a look at the html source file, we get a clean ajax request link in line with html5.

Then we will throw in some trivial JQuery codes into a generic application.js file. We will specify the span id of ajax_button to change the html content of a div id of ajax to have "lol" when the link is clicked.
application.js
$(document).ready(function(){
$("#ajax_button").click(function(){
$("#ajax").html("lol");
});
});


When done right, we should see an update on div id ajax.

In the next example, we are going to do some ajax together with Rails controller request.

For this example, a controller file, posts_controller.rb. We will add a format.js under the respond_to so the method knows that it should format a javascript file.

def create
@post = Post.new(params[:post])
respond_to do |format|
if @post.save
format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
#format.xml { render :xml => @post, :status => :created, :location => @post }
format.js
else
format.html { render :action => "new" }
format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
end
end
end


Then the same is true for forms in Rails 3, when we wanna send an ajax request, the remote_form_for has been scrapped and we will use form_for(@post, :remote => true), again passing in the remote key.
new.html.erb

<% form_for(@post, :remote => true) do |f| %>
<%= f.error_messages %>

<div class=\"field\">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class=\"actions\">
<%= f.submit %>
</div>
<% end %>

Then we will create another file in the View folder, create.js.erb which holds the JQuery logic that we want it to run when the create method is fired.
create.js.erb
$("#ajaxified").html(""); // updates the div id ajaxified
alert("Ajax works!"); // prints an alert message
It should print a message and update the ajaxified id with the post title when the form is submitted!

Monday, March 22, 2010

Sending Email on Rails 3

Rails 3 makes sending E-mail easy and intuitive. Thanks to the tutorial at
http://railscasts.com/episodes/206-action-mailer-in-rails-3

We will create a setup_mail.rb file under the config/initializers with this code (sending email from a gmail smtyp)


ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "rails3mailer.com",
:user_name => "rails3mailer",
:password => "password",
:authentication => "plain",
:enable_starttls_auto => true
}


We will then generate a mailer


rails g mailer registration
create app/mailers/registration.rb
invoke erb
create app/views/registration
invoke test_unit
create test/functional/registration_test.rb


class Registration< ActionMailer::Base

def registration_confirmation(user)
@username = user.name
mail(:to => user.email, :subject => "Registered", :from => "rails3mailer@gmail.com")
end

end


As you can see, it works like a Controller now. The @username is the instance variable storing the user.name from the user object that we are going to pass in when the method is called.
Next line, would be the mailing method. We specify that we will want to send the email to user.email (just like accessing an object instance variable), specifying the subject and from who.

This would be the view aka. what will the user receive.
Putting in whatever text will be the mail that the user would receive. And since we have passed the user name through the instance variable. We can actually use that to put the user name here like,

app/views/registration.text.erb
Hey, @username
You are onboard!


To make sure the mail is delivered, we will have to do one more thing.
In Ryan Bates' example, this can reside in the User controller after the User is created.

Registration.registration_confirmation(@user).deliver

We basically call that method and then Deliver!

Tuesday, February 23, 2010

JQuery on Rails 3.0

Firstly, head over to http://github.com/rails/jquery-ujs and obtain the rails.js file and substitute with the one in our javascript folder.

We will then include the required javascript files,

<%= javascript_include_tag 'jquery','rails','application' %>

Get the jquery.js file from http://code.jquery.com/jquery-1.4.2.js

Now... let's do some trivial testing so that we know JQuery is actually working.


class EntriesController < ApplicationController
respond_to :html, :xml, :js

def index
@entries = Entry.all_entries
respond_with(@entries);
end

def new
@entry = Entry.new
end

def create
@entry = Entry.new(params[:entry])
if @entry.save
respond_with(@entry, :location => entries_path)
end

end

end


We will then create a create.js.erb file which contains the JQuery code that we want to run when then action is invoked.
Let's put something like,
alert("Thanks for visiting!");

The new syntax in Rails 3 is that we will not use remote_form_for no more, but instead

<% form_for @entry, :remote => true do |f| -%>
<%= f.error_messages %>
<%= f.label :title, "Title" %>
<%= f.text_field :title %>


Same is true if it's a link,

<%= link_to 'Ajaxified', :remote => true %>

If done right, the browser should fire an Alert box when the form is submitted.