Categories
Blog Coding Rails

Using local gems in your Rails application

The Bundler documentation is pretty brief when it comes to creating and using local gems.

In a nutshell, if you want to reference a local gem in your application you have to make sure a .bundle/config file is created in your application directory (local config) or your home directory (global config). Running the command below will create the .bundle/config file in your application’s directory, provided the current working directory your run the command from is your application’s directory:

bundle config local.GEM_NAME /path/to/local/git/repository

One problem you might run into is that this file gets disregarded when you run “bundle install”.
The solution is fairly simple:
You must specify the gem’s source and branch explicitly in your Gemfile, such that, if you were to include the udemy gem you would setup your Gemfile as follows:

gem 'udemy', git: 'git@github.com:jonaphin/udemy.git', branch: "master"

Running bundle install should yield the following message:
Using udemy (0.1.4) from git@github.com:jonaphin/udemy.git (at /local/path/to/udemy)

I hope this helps you as I wish it had helped me 🙂

Categories
Coding Geekery Linux

Generate a Self-Signed SSL Certificate in 2 Easy Steps

Ever wanted to generate your own domain’s SSL certificate?
Let me first put it out there: It’s a bad idea if you intend to make your domain publicly available.
Ahh, the air’s more breathable now that the elephant’s out of the room!

You’re still here? Good. Let’s proceed!

Let’s say you do need a self-signed SSL certificate for one of your domains, and you don’t feel like typing more than two commands. You’re in luck!
First and foremost, find a cosy (and preferably organized) place for your certificates to live. I personally like to stick them in /data/ssl/certs/[domain]/[subdomain]/, but to each their own.

Command #1:
openssl req -new -nodes -keyout domain.key -out domain.csr
This command generates both a domain server key and a certficate signing request, which you’ll need to generate your crt file in command #2.
It will ask you a bunch of questions. The important one is the “Common Name”, as it is the one that needs to match your domain.
For example, I setup a certificate for https://www.quotir.com, so I set the common name to “www.quotir.com” hmmkay?

Command #2:
openssl x509 -req -days 365 -in domain.csr -signkey domain.key -out domain.crt
There you have it, your domain certificate will be valid for a year!

As a bonus, here’s how I setup nginx to redirect all https traffic to http, using my shiny new self-signed SSL cert:

In nginx.conf

server {
listen *:443;
ssl on;
server_name quotir.com;
rewrite ^(.*) http://www.quotir.com$1 permanent;

ssl_certificate /data/ssl/certs/quotir/www/quotir.crt;
ssl_certificate_key /data/ssl/certs/quotir/www/quotir.key;
}

Happy Sysadmining friends and don’t be shy, say hello!

Categories
Blog Coding Rails

Import CSV Files 100x Faster in Rails 3

I recently tasked myself with helping a good friend import a relatively large (1 million+ records) CSV file into a database powering a Rails application.
The database and code were hosted on a 512MB Chunk at Chunkhost, which is also where I host once hosted Quotir (I now use DigitalOcean, they really rock!).
As any well-intentioned Railsist would, I embarked on the journey armed with my usual import toolbox, which consists of:

  • A Rake Task to handle the import
  • FasterCSV (which is the default CSV import tool in Rails 3)
  • ActiveRecord, because life is so much more beautiful when we don’t have to deal with the database directly

The initial code (pre-optimization) looked a bit like this:

namespace :foo do
  desc "Import bar data"
  task bar: :environment do
    require 'csv'

    headers = [
      "xxx",
      "yyy",
      "zzz"      
    ]

    CSV.foreach("#{path}/bar_data.csv", {headers: :first_row}) do |row|
      bar = Bar.new

      headers.each_with_index do |key, idx|
        bar.send("#{key}=", row[idx])
      end

      # ... do some cool stuff, update some records in other tables

      bar.save

      # ... do some more cool stuff, which happens to also create some new records in other tables
    end
  end
end

In my specific case, the CSV.foreach loop would iterate about once per second. Dear, was I not ready to accept waiting 12 days for this script to finish running!

You see, the beautiful thing about constraints is how they remind you of what is absolutely necessary, and what is well, extraneous.
One doesn’t have to look very far to realize that ActiveRecord is a commodity, a luxury one has to part with when the carriage becomes too heavy for the horse.

So we parted… Me and ActiveRecord bid each other safe travels, and promised we’d meet again.
Now friend, the reason you’re still reading this is because you too, at some point, might have to leave AR (That’s its nickname) by the curb to get to your destination faster.

How did I do it?
Without further ado, here’s what the code above looks like after optimization:

namespace :foo do
  desc "Import bar data"
  task bar: :environment do
    require 'csv'

    headers = [
      "xxx",
      "yyy",
      "zzz"      
    ]

    ActiveRecord::Base.establish_connection

    CSV.foreach("#{path}/bar_data.csv", {headers: :first_row}) do |row|
      sql_keys = []
      sql_vals = []

      created_at = Time.now.strftime("%Y-%m-%d %H:%M:%S")

      headers.each_with_index do |key, idx|
        val = row[idx]

        sql_keys << key
        sql_vals << ActiveRecord::Base.connection.quote(val)
      end

      sql = "
        INSERT INTO bars (#{sql_keys.join(', ')}, created_at, updated_at) 
        VALUES (#{sql_vals.join(', ')}, '#{created_at}', '#{created_at}')
      "

      res = ActiveRecord::Base.connection.execute(sql)
      bar_id = ActiveRecord::Base.connection.last_inserted_id(res)

      # do some cool stuff, like create records in other tables that reference bar_id
      # use ActiveRecord::Base.connection.execute(your_sql) in subsequent calls.
      # no need to close the connection, or reopen it before calling execute.      
    end
  end
end

 

It all starts with a call to
ActiveRecord::Base.establish_connection
The line above will establish a direct connection with the database set by your environment in the config/database.yml file.

Two important details to note in the code above:
ActiveRecord::Base.connection.quote(val)
This is one of the proper ways to escape your SQL. Use it. If you favor prepared statements, then by all means look at sanitize_sql_array
The second detail is the time stamps. If you’re working in Rails you will want to add the time stamps for created_at/updated_at manually, as they cannot be null.

And this is how my import script went from taking 12 days to run to taking 3 hours only!

See that? A tavern! This is where me and this post will rest for a while, right by the “Post Comment” button, so how about you stop by and share your thoughts on our journey and yours, fellow traveler?

Note: This code should work with Rails 2 with minimal changes.

EDIT: As mentioned by “Taladar” on the Reddit thread for this post, using LOAD DATA INFILE can drastically reduce import times. Depending on the case at hand (and specifically if it’s a simple record insert per CSV row), this might be the optimal solution.

Categories
Blog Coding

Speed up local HTTP requests on OS X Lion

Are you developing web applications on OS X Lion? Are you testing on a local server? Is it horribly slow?

You’re still here! Great, that means you, me, and a plethora of other devs have endured the same issue on OS X Lion, specifically.

While it may not be the only source of the slowdowns in your local stack the following trick might prove invaluable to you, as it was to us:

Open your /etc/hosts file, locate the 127.0.0.1 lines, and merge them into one line!

Go from:

To this:

Good Hack is Good

We all owe a big thanks to our friend Joey for the sweet hack! 🙂

Categories
Coding Plugins

Introducing PepperSpray, a jQuery Plugin

PepperSpray

Ever wanted to annoy the hell out of your users?

Look no further. Pepper Spray will drive 99% of your traffic away, thanks to its amazing features:

Disable Right-Click

That’s right! Right Mouse Clicks can be so dangerous we made it simple
to disable it with a single call to:
$.pepperspray("disableRightClick", true);

Disable Text Highlighting (and yes, Images too!)

Don’t allow other suckers to steal your content. You’ve worked so hard copying it from somewhere else!
Here, one shot of pepper spray and look at them poor villagers, with their menacing pitchforks, all up-in-arms! But who cares? No subject shall walk off with her majesty’s property!
$.pepperspray("disableHighlighting", true);

Disable the Back Button Functionality

The world is a prison. Let your users feel it. Oh, one squirt of this pepperspray wonder suffices to piss them off! Ain’t nobody goin’ nowhere!
$.pepperspray("disableBackButton", true);

To download, contribute, or read the documentation, click on the link below:
https://github.com/jonaphin/pepperspray

Categories
Blog Coding

Remove jQuery plugins at runtime

A good friend of mine asked me last week how she could remove jCarouselLite on the fly, after it had been instantiated. Allow me to share with you guys how to do this, and hopefully show you a trick or two along the way.

As you may know, a typical jCarouselLite plugin is instantiated as such:
$(function() { $(".anyClass").jCarouselLite({ btnNext: ".next", btnPrev: ".prev"}); });

where “.anyClass” is the name of your gallery container, “.prev” and “.next” are the gallery’s previous and next navigation links, respectively.


Removing the plugin at runtime is fairly simple once you understand what is involved:
$('.anyClass').jCarouselLite = null;
$('.prev').unbind('click');
$('.next').unbind('click');

These 3 lines allow you to re-initialize jCarouselLite later on within the same page. Pretty simple and neat, isn’t it?
Let’s decompose what just happened so you may get a better understanding.
$('.anyClass').jCarouselLite = null; removes the jCarouselLite instance from our gallery. In other words, you will have to reinitialize jCarouselLite if you want to reuse it on this page for this gallery.
This isn’t all, however. When jCarouselLite is initialized, it creates what we call event bindings.
Whenever you destroy the jCarouselLite instance the bindings are still lingering and problems will start occurring if you re-initialize jCarouselLite on the same page, for the same gallery, as the click events on the navigation links will have been bound twice.
To prevent this issue from occurring, we add the two following lines:
$('.prev').unbind('click');
$('.next').unbind('click');

Which brings me to one last pro-tip about dealing with groups and bindings.
There are two main ways to deal with group bindings in jQuery:
– The first one is fairly common. It consists of using a common class to all elements of a similar group.
$('.clickable').bind('click', function(){ alert("Hi, I'm clickable!"); });
$('.clickable').unbind('click');

In the code above, all elements of the class “clickable” will have the mouse click event bound (then unbound) to them.

There is however a second, more mystical way to do this in jQuery: Namespacing.
Let’s say you create an instant link preview feature that you want to disable and re-enable at will on your page. We will call our namespace “linkPreview”.
Here’s the event binding to our namespace:
$('a').bind('mouseover.linkPreview', myPreviewFunction);

And the event unbinding, just as easily:
$('a').unbind('mouseover.linkPreview');

This makes it easy to unbind only specific events from our elements. In this case, all other mouseover events would still be bound to our page links. Isn’t this amazing?