Wednesday, December 16, 2009

JavaScript and CSS Compression for Production Rails Apps

When you build a big application you normally use more than one CSS and JS file. The problem start here, because sometimes you have to upload several megabytes of CSS and JS files to the browser just to open a login page or something like that. This process take a lot of time and it’s not recommended.

I start searching for a solution to this problem, and I found that there are a Rails plugin that automatically compresses the CSS and JS files in just one file to use in production mode which makes the upload much faster, because the server will only send one file, and that file will be smaller since it’s compressed. In development mode you can continue to use all the uncompressed files.

In order to use the AssetPackager you need to download it from http://github.com/sbecker/asset_packager and install it.

Note: I put all my plugins in the vendor/plugins folder of my rails project since it’s a common good practice in Rails Development.

Then you run rake asset:packager:create_yml to generate the /config/asset_packages.yml file the first time.

Edit this file in order to set all the dependencies in the correct order and then create the result files with rake asset:packager:build_all.

To use the compressed files:

<%= javascript_include_merged :base %>
<%= stylesheet_link_merged :base %>
 
And that’s it.  ;)
 
 
Sheers,
Hélder Loureiro

Wednesday, November 4, 2009

Cache in Rails (Intro)

Today i dedicate time to upgrade my rails application performance using cache techniques.

There a lot of solutions:
- Page caching
- Action Caching
- Fragment Caching
- Sweepers
- SQL Caching
- Advanced Caching

You can learn more here http://guides.rubyonrails.org/caching_with_rails.html.

If you have static pages that not change very often you can use Page caching.
Page caching is a Rails mechanism which allows the request for a generated page to be fulfilled by the webserver, without ever having to go through the Rails stack at all. Obviously, this is super-fast. Unfortunately, it can’t be applied to every situation (such as pages that need authentication) and since the webserver is literally just serving a file from the filesystem, cache expiration is an issue that needs to be dealt with.


Action caching works like page caching except for the fact that the incoming web request does go from the web server to the Rails stack and Action Pack so that before filters can be run on it before the cache is served. This allows you to use authentication and other restrictions while still serving the result of the output from a cached copy.

Fragment Caching allows a fragment of view logic to be wrapped in a cache block and served out of the cache store when the next request comes in.

Cache sweeping is a mechanism which allows you to get around having a ton of expire_{page,action,fragment} calls in your code. It does this by moving all the work required to expire cached content into na ActionController::Caching::Sweeper class. This class is an Observer that looks for changes to an object via callbacks, and when a change occurs it expires the caches associated with that object in an around or after filter.

Query caching is a Rails feature that caches the result set returned by each query. If Rails encounters the same query again during the current request, it will used the cached result set as opposed to running the query against the database.


Cache Money is a write-through and read-through caching library for ActiveRecord. Read-Through: Queries like User.find(:all, :conditions => ...) will first look in Memcached and then look in the database for the results of that query. If there is a cache miss, it will populate the cache. Write-Through: As objects are created, updated, and deleted, all of the caches are automatically kept up-to-date and coherent.



--More about the Cache Money -- Some of the Twitter solution --

Fist: Install and configure memcache.
http://www.danga.com/memcached/download.bml
tar zxvf memcache.tar.gz
./configure ( libevent is needed!)
make install
Lunch daemon /usr/local/bin/memcached -d -m 512 -l 127.0.0.1 -p 11211

Second: Install and configure cache-money gem
gem sources -a http://gems.github.com
sudo gem install nkallen-cache-money


Configure MemCached
More instructions in http://github.com/nkallen/cache-money.

Third: Use

Queries like User.find(1) will use the cache automatically. For more complex queries you must add indices on the attributes that you will query on. For example, a query like User.find(:all, :conditions => {:name => 'bob'}) will require an index like:

class User < ActiveRecord::Base
index :name
end

For queries on multiple attributes, combination indexes are necessary. For example, User.find(:all, :conditions => {:name => 'bob', :age => 26})

class User < ActiveRecord::Base
index [:name, :age]
end

Friday, October 30, 2009

Starting Rails

If you are starting developing web applications using the Ruby on Rails framework, you will need to basically read some nice for dummies books. The Ruby on Rails for Dummies, of Barry Burd it’s the best. After read this book you will be able to:

-Understand the need for agile software development;
-Discover Ruby’s role in agile development;
-Find out how Rails fits in;
-Explore Ruby fundamentals;
-Create basic Ruby on Rails applications.



Continuing you adventure, you will find the need to search for more plugins, gems and to know more about ActiveRecord and others libraries. So in the future you can consult others books, like The Rails Way, from Obie Fernandez.



sheers,
Hélder Loureiro

Wednesday, October 28, 2009

Paperclip

This is probably one of the most important plugin in Rails. Eve you ever thought about add some attachments to some model? Add photos, videos, mp3, pdf etc. Of course yes!
Paperclip makes your life much simpler, and adds to the ActiveRecord support to upload files.
There is also a well know plugin called Attachement_fu that does the exact same thing, but I sincerely prefer paperclip because it allows me to upload files directly to the file system and not to a database (I try Attachement_fu first but I couldn´t get it work on my application).
Like you maybe have heard yet, a file system it’s faster than a database, regarding file upload and download. Although using a file system raises the common security problem. And no, I not thinking about keep my files on the public folder. I use one protocol called sendfile that allow my apache server to send files that are in private folders (Try XSendFile plugin).

You can found much more information about this plugin here:
http://www.thoughtbot.com/projects/paperclip

This is a piece of my photo model:
has_attached_file :source,
:styles => { :medium => "560x480>",
:thumb => "60x60>" ,
:tiny => "30x30>" ,
},:url => "/photos/:id/", :path => ":rails_root/assets/photos/:id/:style/:basename.:extension"

validates_attachment_presence :source
validates_attachment_content_type :source,
:content_type => ["image/jpeg", "image/png", "image/gif" ,"image/pjpeg","image/x-png"],
:message => "Oops! Make sure you are uploading an image file."
validates_attachment_size :source,
:less_than => 10.megabyte,
:message => "max size is 10M"


As you can see with Paperclip I can verify the size and type of my uploaded file. Also with Paperclip I can create photos with different sizes.

Note: Do not forget to install ImageMagick in your server machine. Also, if you are using video upload, do not forget about ffmpeg to convert the file and maybe get some nice video picture preview to use in your application.

Continuing with the examples, this is a piece of my video.rb model.
def convert_command
flv = File.join(File.dirname(source.path), "#{id}.flv")
File.open(flv, 'w')
command = <<-end_command
ffmpeg -y -i #{ source.path } -f flv #{ flv }
end_command
command.gsub!(/\s+/, " ")
end


This is a convert method. It creates a new flv file.

def thumb_command
command2 = <<-end_command
ffmpeg -itsoffset -5 -i #{ self.source.path } -y -vcodec mjpeg -vframes 1 -an -f rawvideo -s 60x60 assets/videos/#{ self.id }/original/thumb.jpg
end_command
command2.gsub!(/\s+/, " ")
end


This is a thumb creator. It creates a picture of the movie in second five with 60x60 pixels (5 seconds it’s nice, but remembers, some videos may appear black in second 5, I still not have the solution for that).

In order to upload videos and music the model that represent’s the content must act as a state machine. That means the file will pass for different stats until gets converted (See Act as State Machine on http://agilewebdevelopment.com/plugins/acts_as_state_machine)

So in my video model for instance I can do:
acts_as_state_machine :initial => :pending
state :pending
state :converting
state :converted, :enter => :set_new_filename
state :error
event :convert do
transitions :from => :pending, :to => :converting
end
event :converted do
transitions :from => :converting, :to => :converted
end
event :failed do
transitions :from => :converting, :to => :error
end


This code says pretty much everything. The video file passes throw different stages (pending, converting, converted or error).

Cheers,
Hélder Loureiro

Act as Taggable

If you want some semantic in your web application the first thing that maybe you remember is to add some tags to your contents. This can be done automatically, or with some user help.
Act as Taggable easily integrates a tag system in your Rails application. It allows users to create tags in the model or models that you want. Imagine that you have a user and a photo model. Now you want to allow users to tag the photos, acts as taggable do all that for you.
The On Steroids version of Act as Taggble has also some methods to create Tag Clouds. Tag Clouds is nowadays a better and common way to represent terms and their importance, making the most important/searchable terms bigger and consequently most visible.

So, to install the Acts As Rateable plugin run the following command:
ruby script/plugin install http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids

Examples:
post.tag_list.add(“nice”, “interesting”) – Adds the tag nice and interesting to the post;

post.tag_list.remove(“funny”) – Removes the tag funny from the post;

Post.find_tagged_with(“nice”) – Returns all the post that have the tag nice;

Note: Do not forget to add acts_as_taggable to the model you want to make taggable.
I have to add some others fields to the taggable migration, because I want to identify the autor of the tag. So I added the field user_id.

For more information about this plugin you can search on:
http://agilewebdevelopment.com/plugins/acts_as_taggable_on_steroids

Greetings,
Hélder Loureiro

Act as Rateable

This plugin easily integrates a rating system in your Rails application. It allows users to create classifications in the model or models that you want. Imagine that you have a user and a photo model. Now you want to allow users to rate the photos, acts as rateable do all that for you. You will only need to personalize your views to reflect the changes and maybe use some AJAX to make it more user friendly.

So, to install the Acts As Rateable plugin run the following command:
script/plugin install http://juixe.com/svn/acts_as_rateable

You can found the rest of the instructions on http://www.juixe.com/techknow/index.php/2006/07/05/acts-as-rateable-plugin/

I have also added a new field in my rating migration to identify the content that has receive the classification.
To use this plugin, for instance if you want to create a classification you can do this:
post = Post.find(params[:id])
rating = Rating.new(:rating ==> 2, :submitted ==> Time.new)
@post.ratings << rating

This will rate the selected post with value 2.

If you want to know how much ratings does the post has:
post.ratings.size

To know the average classification of the post:
average_rating = post.rating

Note: Do not forget to add acts_as_rateable to the model you want to make rateable.
To have a much nicer experience you will need to have some JavaScript interaction with your rating system. There are a lot of free libraries that you can use which allows users to just click in a star and automatically recalculate the new rating average.

Cheers,
Hélder Loureiro

Wednesday, October 21, 2009

Import contacts from hotmail, gmail and others

There are some gems and plugin that can import contacts from different mail and social networks accounts. I was looking for a silver bullet. A plugin that can do it on gmail and also on hotmail accounts. The idea was to create a feature on my rails application where users could import their contacts to join my application.

I found blackbook, in order to install it correctly i have to install some gem dependencies:
- gem install mechanize (also need to install 'yum install libxslt-devel')
- gem install fastercsv
- gem install blackbook

Then hopefully everything works fine and i just need to use this line of code:
contacts = Blackbook.get :username => 'me@gmail.com', :password => 'whatever', :as => :xml

But unfortunately it not work :(

Then i search a little more and i found gem contacts from cardmagic. This gem has a importer to Gmail, Hotmail and also Yahoon account (who uses yahoo mail anyway).

The only thing i have to do is:
gem install contacts

Then in my code i can do:
Contacts.new(:hotmail, :email,:password).contacts
Contacts.new(:gmail, :email,:password).contacts
Contacts.new(:yahoo, :email,:password).contacts


This is very simple, but the gmail importer does not work. I discover that google has changed their API recently and now they use Auth authentication (We no longer need the password). So some guy found a fix to this problem and gem contacts now is working perfectly for gmail account (although still using email and password).

I found the fix in http://github.com/glennfu/contacts/tree/4e72b02b8c67b7b36083c8721a1d08c580068c0a

Sheers,
Hélder Loureiro