Youtilize

Read all about technology, web development and creative entrepreneurship

Currently showing 4 posts in category Ruby on Rails

 

Jun 12, 2007
Ruby on Rails

Simply put, permalinks are great for SEO, but not only that, they make our URLs human readable for easier identification.

For blogs, just like tags and comment systems, they’re a must (or a standard I should say.)

Permalink generation

Case: Say your Post model has a ‘permalink’ field that will contain a string value of your automatically generated permalink.

When you submit a new post, simply do the usual new and save commands in your Controller. For example:

@post = Post.new(params[:post])
if @post.save
  flash[:notice] = "Post '#{@post.title}' saved successfully" 
    # and so on...
end

Now open up your Post model and add the following filter:

before_create :generate_slug

This will make sure that before a new post is saved, generate_slug function will execute automatically.

Below in your Post model, add the actual meat of this action:

protected
  def generate_slug
    self.permalink = title.gsub(/\W+/, ' ').strip.downcase.gsub(/\ +/, '-')      
  end

This simply takes the title attribute and passes it through a few RegEx replacements leaving you with a nice permalink.

For some reason, it took me a while to find this snipped online, so I wanted to make it available for other beginners. (Probably because everyone else just writes their own RegEx!)

Things to improve

» Make sure permalink isn’t already in use (thanks Joel)

» Make sure permalink isn’t too long (thanks Jason)

Other options

This could simply be done with JavaScript as another alternative.

 

Jun 01, 2007
Ruby on Rails

Having switched to Ruby on Rails (for now), I was looking for the same functionality as the popular time_since() function and after hours of searching, I found that Ruby has this exact function built in.

No need to download a 3rd party module and add it to your project, simply use:

time_ago_in_words()

time_ago_in_words() does exactly this. Simply pass it a Date or a Time object and it will spit out time since in words. API

distance_of_time_in_words()

This is another cool function I just added to the comment bit. Instead of simply saying how long has passed since comment was added to now, I wanted to say how long has passed after the post was created to when the comment was added. Ex: about 10 minutes after. API

Here’s my code in the post view:

<% for comment in @post.comments %>
  ... stuff here ...
  <%= distance_of_time_in_words(@post.added, comment.added) %>
  ... stuff here ...
<% end %>

Hope these help out. I spend ridiculous amount of time looking for functions like this so you won’t have to :)

 

May 31, 2007
Ruby on Rails

Update: Instructions have been updated for Capistrano 2.0. More info can be found here and here.

Capistrano is a small RubyGem that is designed to run a number of scripts on a remote server and is used primarily to deploy applications. Think of it as an automated way to grab the latest revision of your application from Subversion, upload it to your domain and then restart the server to take into account the changes.

Assumptions

First of all, I’m assuming that you’ve already been able to setup your Ruby on Rails application on TextDrive. In other words, you’ve already configured and ran Lighttpd as well as Ruby. We will need to edit those configuration files, primarily those located in your /etc/lighttpd directory later on. If not, follow these directions.

I’m also assuming that your app is installed on a secondary domain (not primary domain of shared account) and is located in the following directory: /users/home/USER/domains/DOMAIN.tld/web. You can easily adjust the following walkthrough for a primary domain setup by adjusting the paths.

On top of it all, you must already have Subversion repository setup on your server and have committed at least one time to it. I realize this is also a pretty complex thing to setup, especially for someone new, so expect a post in the near future on it. For now, use the following directions.

Installing Capistrano

On your local machine, open up Terminal (I’m on a Mac) and install Capistrano by executing the following line:

gem install capistrano

This is the easy part and you should now be able to use the cap command in console.

Still with me so far? At this point, you’ve installed Capistrano and should now be ready to set it up.

Deployment Recipe

Capistrano uses a file called ‘Recipe’ to deploy your application. It provides it with directions to your server, Subversion repository and your main account username. Main account has access to all the repositories, so it’s easier to use.

Rails creates a default recipe for you in a file called deploy.rb in the /config directory. Open it up in your favorite editor and replace everything with the following recipe:

set :user, "" # Your main account username
set :domain, "" # Your secondary domain name. For ex: myname.com
set :txd_server, "" # The TextDrive server you're currently located on. For ex: nicola.textdrive.com
set :subversion_repo_name, "" # Your Subversion repo name. For ex: repos
set :application, "" # The name of your application (ie. youtilize)

set :repository, "svn+ssh://#{user}@#{txd_server}/users/home/#{user}/domains/#{domain}/svn/#{subversion_repo_name}/trunk" # Edit this path if you're installing on primary domain or your SVN repo is located elsewhere
set :deploy_to, "/users/home/#{user}/domains/#{domain}/web" # This is where files will be uploaded to

role :app, "#{user}@#{txd_server}" 
role :web, "#{user}@#{txd_server}" 
role :db, "#{user}@#{txd_server}" 

namespace :deploy do
  desc "Restart Lighttpd and Ruby" 
  task :restart, :roles => :app do
    run "pkill lighttpd; pkill ruby" # Kill processes
    run "nohup /users/home/#{user}/etc/rc.d/lighttpd.sh start; nohup /users/home/#{user}/etc/rc.d/rails.sh" # Start processes
  end
end

Go ahead and follow directions in the file to fill in the blanks with all your information.

Capistrano 2.0 doesn’t automatically use the Rail’s recipe we just setup, so run the following to put finishing touches on the recipe setup:

capify .

At this point you’ve given Capistrano a recipe to follow when deploying your application.

Setting up your directories

Capistrano now needs to install default directories and chmod them accordingly to them give proper permissions. Aren’t you happy you don’t have to deal with permissions?

To do this, delete everything in your /web directory of your secondary domain.

cd /users/home/USER/domains/DOMAIN.tld/web/
rm -rf .

It’ll give you an error about not being able to delete .textdrive file. That’s fine, leave it be.

What you’ve done now is effectively wiped out your whole application! Don’t worry, in a couple of minutes, Capistrano will put it back for you. It first needs to install a couple of directories of its own, so execute the following:

cap deploy:setup

This installs two directories in your /web directory: /web/shared, and /web/releases. It also installs a system link in /web/current that will point to the latest release of your application. So, your actual application will now live in /web/current NOT /web where your server is currently pointing to. So we need to adjust that:

Reconfiguring your Lighttpd

Grab both lighttpd.conf from /users/home/USER/etc/lighttpd and your APPNAME.conf from /users/home/USER/etc/lighttpd/vhosts.d (Rememeber, APPNAME is whatever you named your .conf file before). You can do this step via FTP.

In ligghtpd.conf, change:

server.document-root = base + "/domains/DOMAIN.tld/web/public/"

to:

server.document-root = base + "/domains/DOMAIN.tld/web/current/public/"

Next, in APPNAME.conf, change:

server.document-root = base + "/domains/DOMAIN.tld/web/public/"

to:

server.document-root = base + "/domains/DOMAIN.tld/web/current/public/"

Don’t forget to change DOMAIN.tld to your domain name. Re-upload the files to their proper directories and guess what:

You’re all set to deploy!

Ready, Set, Deploy!

To deploy your application, on your local machine execute the following in you app directory:

cap deploy

You will be asked for your server password, so type that in (probably multiple times) and watch the process. At the end, Capistrano will restart the server for you and you should be able to load your site in the browser. In case the server doesn’t start, start it manually first time around.

Don’t forget to commit your recent changes to the Subversion repository before deploying:

svn commit -m="Bug fixes" 
cap deploy

Best of luck and hope this saved you many grueling hours.

 

May 29, 2007
Ruby on Rails

For those of you that aren’t ready to take the plunge and get a dedicated server, don’t worry, you are not alone. I pondered about this for a while, but it didn’t make sense financially for me to be spending $50+ on my own space monthly just to run a simple blog. I thought I was in great hands as I had MediaTemple Grid-Service hosting, meaning I had my own Ruby on Rails container that I could modify to my needs. I was wrong, read on.

Deploying Ruby on Rails application

RoR creates a lot buzz because of how it saves the developer time by taking care of most mundane tasks one would normally have to do manually if they were coding in say.. PHP. That is totally true and being a brand new convert (and an old PHP coder), I can see that. In the amount of time I was able to code this blog engine, I would still be figuring out database stuff in PHP.

Deploying those easily built apps is quite another story though. It often takes hours just to get the server setup the way you need it to be. Development setup on a local machine is usually quite different than what web hosting production servers have, especially shared hosting accounts.

I spent about 4-5 hours just trying to get everything working on (mt) hosting, only to realize how horrible their support is in such things. They guide you through setting it a test application and if it works, they won’t lift a finger helping you to setup your own app, which will require a much different setup than a default “hello world” Rails application.

I finally was able to get everything working only to find out how horrific loading speeds were (think 30-40 seconds per page). Also, after 5 minutes of starting the Rails application, I would randomly get proxy errors no matter what.

Goodbye MediaTemple. Hello TextDrive

Following Richard’s suggestion, I checked out TextDrive shared hosting accounts and got sucked in right away primarily by their huge support system that includes extensive help topics, manuals and most importantly, user forums that cover pretty much everything. With such a support system behind me, I knew I’d have no problem setting everything up on TextDrive.

So, $40 later and few more hours of work, Youtilize.com was finally up and running with exceptional speeds, much greater than those you can ever get on (mt)’s Grid-Service (unless you upgrade you Ruby on Rails container: $25 and MySQL container: $20 at which point just get a dedicated!).

Gems on Shared hosting

Ruby uses cool little things called Gems, which is a standard format for distributing Ruby libraries (think plugins). Source

That is all good and well, except that one cannot install those manually on shared accounts. Some hosting companies will install some gems for you as per request and all come with a wide array of pre-installed Gems for your use, but even then, if versions differ from those Gems that you have installed locally, things may (and in my case did) break.

Another solution: extract Gems into your application. Yes! Since a Gem is more or less a system-wide plugin, you can make a local install of this plugin just for your app (/vendor/ directory).

Because Rails itself is a Gem and TextDrive’s Rails versions is 1.1.6 (my app is made with 1.2.3), I simply couldn’t run my application on their server until I found out you can embed the framework you’re running your app on, inside your app. Weird? Yes, but so damn useful. On your local machine, simply run:

rake rails:freeze:gems

This will ‘freeze’ or extract your current Rails version right into your application. After further research, I found out that this a recommended step with any application in production. Since hosts usually like to keep things up-to-date, they may upgrade Gems at their own will and that MAY break your application. Source

Then simply upload directory called /rails/ in your /vendor/ directory to the server and restart Ruby.

Freezing other Gems

Now that you’ve learned how to extract Rails itself from its Gem into your own application, you may want to extract other custom Gems that your app uses and your host doesn’t have.

There are two ways to do so, a RubyGem way (try first) or the custom way by NubyOnRails.

1: RubyGem way: gem unpack

This is the easiest of the two ways and should be tried first.

On your local machine, first go into the /vendor/ directory of your app by running cd vendor and then execute the following to unpack the gem directly into your application:

gem unpack GEM-NAME

Don’t forget to replace GEM-NAME with the Gem you’ll be needing (for example: RedCloth)

This will simply unpack the Gem into your /vendor/ directory and from now on, your application will only use the unpacked Gem unless you delete the folder. Rails is setup to check there first, server second for Gems.

2: Second way

To freeze/unpack the Gem this way, you will need to download a small file called gems.rake (extract this first) and place it into your /lib/tasks/ directory. Source with more info

Then, open the file up in your favorite text editor and edit the following line with those Gems that you need extracted:

libraries = %w(gruff sparklines pdf-writer)

In other words, replace example Gems gruff spakrlines pdf-writer with for example: acts_as_taggable acts_as_ferret if you want those two extracted.

Finally, in console, execute:

rake freeze_other_gems

And it will grab all the specified Gems and throw them into your /lib/ directory. Simply upload the new files and folders and voila, you’re all set.

A note on unpacking/freezing gems

While most Gems can be unpacked directly into your application, not all are. Specifically, those Gems that require native extensions (such as the useful Ferret Gem) cannot be frozen.

Other randoms

If you want to test something out in the Ruby console on the server, don’t forget to run it under production mode!

ruby script/console production

Easy way to setup your database is to first create a schema of your development database on local machine. By executing the following, a file called schema.rb will be created in your /db/ directory:

rake db:schema:dump

Now, upload this file to the same location on your remote production server and execute (this time, on remote server):

rake db:schema:load RAILS_ENV=production

RAILS_ENV=production is super important as that tells the program to use Production database credentials, not Development.

Same goes to migrating database changes on the server. Once you’ve created new Models and thus new database changes, upload new contents of /db/migrate/ folder and run:

rake db:migrate RAILS_ENV=production

You’re all set

Go out there and conquer the world! If you make something cool, please do share.

Next up: Learn how to deploy your new application with Capistrano.