OscarGodson/jKey - GitHub

jQuery plugin to register callback functions to keyboard shortkuts. Keyboard events in vanilla Javascripts are super-painful to work with, so hopefully this library can help.

The Difference Between jQuery’s .bind(), .live(), and .delegate()

The difference between .bind(), .live(), and .delegate() is not always apparent. Having a clear understanding of all the differences, though, will help us write more concise code and prevent bugs from popping up in our interactive applications.

Calling selected methods of a module from another module

Given those modules:

module A
  def foo; end
  def bar; end
end

module B
end

When you want to call methods from A inside B you would normally just include A into B:

module B
  include A
end

Including exposes all of A's methods into B. If you do not want this to happen, use Ruby's module_function: it makes a module's method accessible from the outside. You could put the module_function calls into A but it would remain unclear to peop...

Split an array into groups

Given group size

If you would like to split a Ruby array into pairs of two, you can use the Rails ActiveSupport method in_groups_of:

>> [1, 2, 3, 4].in_groups_of(2)
=> [[1, 2], [3, 4]]

>> [1, 2, 3, 4, 5].in_groups_of(2)
=> [[1, 2], [3, 4], [5, nil]]

>> [1, 2, 3, 4, 5].in_groups_of(2, 'abc')
=> [[1, 2], [3, 4], [5, 'abc']]

>> [1, 2, 3, 4, 5].in_groups_of(2, false)
=> [[1, 2], [3, 4], [5]]

Given group cou...

Freeze (vendor, unpack) a single Ruby gem with and without Bundler

When you need to patch an existing gem, one way is to "vendor" the gem by copying it into the vendor/gems directory of your Rails project. You can then make any changes you require and Rails will use the vendored version of the gem after a server restart. Unfortunately you need to perform some additional steps to marry Rails and the copied gem. This notes describes what to do.

With Bundler

This is super-painful. If you just copy the gem to vendor/gems, Rails will complain:

Unpacked gem foolib in vendor/gems has no s...

MySQL: "LOAD DATA INFILE" says "file not found"

This might be due to AppArmor denying the MySQL server access to most of the filesystem. You can instead use
LOAD DATA LOCAL INFILE ...
to pipe data through the MySQL client, which can read everything the executing user can.

Properly sanitizing column names for MySQL

There are times when you need to send SQL to the database, like this:

def self.some_count(field)
  field = connection.quote_column_name(field)
  scoped(:select => "COUNT(DISTINCT #{field}) AS count")
end

Although the given variable is sanitized here, the MySQLAdapter's (and probably other adapters as well) method for this is insufficient as it only wraps backticks around it, not helping against injection:

Klass.some_count("id`); DELETE FROM users; -- ")
# Will result in this SQL which is valid but definitely undesi...

Test the status code of a response in Cucumber

Webrat

Then /^I should get a response with status (\d+)$/ do |status|
  response.status.should include(status)
end

Capybara

Then /^I should get a response with status (\d+)$/ do |status|
  page.status_code.should include(status.to_i)
end

Perform HTTP basic authentication in Cucumber (with or without Selenium)

This card describes a Cucumber step that lets you say:

When I perform basic authentication as "username/password" and I visit the admin area

The path component ("... the admin area") is parsed through your path_to helper in features/support/paths.rb.

Capybara

The step definition is part of Spreewald. The step has been tested with multiple versions of Capybara, Rack::Test and Selenium.

Webrat (legacy)

This is a simpler version of the step above:

When /...

Access the documentation of all locally installed gems

In case https://www.rubydoc.info/ is to slow or offline, you can also read a gem documentation offline.

Start a server with gem server and go to http://0.0.0.0:8808/. Here you will find a list of all installed gems and it is possible to navigate to the documentation if installed e.g. http://0.0.0.0:8808/doc_root/rubocop-0.77.0/


In case you set the configured RubyGems to not install documentation by default, you need to add generate the documentation for the specific gem.

gem install rubocop --document
`...

ETags with memcached

I love ETags, but there’s something that annoys me: most implementations revolve around pulling a record out of a data store and only “rendering” the response if it hasn’t been modified. 

The problem with this approach is that request has already gone through most of your application stack–parsing params, authentication, authorization, a few database lookups–so ETags are only saving you render time and some bandwidth.

While working on a Sinatra-based JSON web service that gets very heavy traffic, I wanted to find a way to short-circuit...

Always show the page if there is an error in Cucumber

Are you adding a "Then show me the page" and re-run Cucumber whenever there is a failing scenario? Don't be that guy!

Save time with the shiny new version of our cucumber_spinner gem. It comes with a Cucumber formatter that not only displays an awesome progress bar, and shows failing scenarios immediately, it will also open the current page in your browser whenever a scenario step fails.

After you installed the gem, use the formatter like this:

cucumber --format CucumberSpinner::Curiou...

In-depth HTTP traffic analysis using tcpdump & Wireshark

From time to time we're convinced that an error must be very close to the network card, OS IP stack or compiler. In reality this is quite rare, so before continuing, triple-check that the issue is not located between chair and keyboard...

If you're still convinced that a in-depth analysis of network traffic might help you, go on:

  • Find out the IP address the client causing trouble will come from.

  • Replace 147.0.0.123 with the client address, log into your web server and run:

    `remote$ sudo tcpdump host 147.0.0.123 and port 80 -s 0 -w...

Allow a user to run a single command with root privileges

It's that simple to allow one of your Linux users to run a single command as UID 0:

  1. sudo visudo
  2. Add the line below to allow user 'deploy' to run /usr/bin/bundle with root privileges
deploy  ALL=NOPASSWD: /usr/bin/bundle

How to fix "extconf.rb:8:in `require': no such file to load -- mkmf (LoadError)"

If you're on Ubuntu:

sudo apt-get install ruby-dev

On other platforms: Look for a package containing ruby header files. On Red Hat that's "ruby-devel" likely.

Setting up Tomcat to use an existing OpenSSL certificate

This is for those who already own an SSL certificate (e.g. using it in the Apache HTTP Server) and need to feed it to a Tomcat application. The main issue is that you need to convert your OpenSSL certificate for Java to use it in its keystore.

Create a keystore

This is the place where the application usually gets its keys from. The keytool is able to read certificate files but does not understand private key files which you need to use y...

Restrict Apache access to your local computer

When you are using Apache for development, it still accepts connections from everyone in the same network as you.

In order to only allow requests to your Apache coming from your local computer, edit your /etc/apache2/ports.conf so all Listen directives point to 127.0.0.1:

Listen 127.0.0.1:80
<IfModule mod_ssl.c>
    Listen 127.0.0.1:443
</IfModule>

After the change stop and start your Apache and check with netstat that Apache no longer listens to 0.0.0.0:

sudo /etc/init.d/apache2 stop
sudo /etc/init.d/ap...

Styling and scaling for mobile devices

If you want your application to display properly on iPad, iPhone or Android there are two things to do:

Define a stylesheet for mobile devices

Using the media attribute on stylesheet HTML tags allows you to have a CSS for mobile browsers:

<!--[if !IE]><!-->
  <%= stylesheet_link_tag 'mobile', :media => 'only screen and (max-device-width: 1024px)' %>
<!--<![endif]-->

Here I chose 1024 pixels as the maximum device width to include the iPad. If you want to target only mobile phones, pick 960 to include high-end Android d...

Shell script to clean up a project directory

Call geordi clean from a project root to remove unused and unnecessary files inside it.


This script is part of our geordi gem on github. In Geordi > 1.2 you can call geordi clean.

Speed up RSpec by deferring garbage collection

Update: This trick probably isn't very useful anymore in Ruby 2.x. The Ruby GC has improved a lot over the years.


Joe Van Dyk discovered that running the Ruby garbage collector only every X seconds can speed up your tests. I found that deferring garbage collection would speed up my RSpec examples by about 15%, but it probably depends on the nature of your tests. I also tried applying it to Cucumber f...

Computational cost of SSL connections

In January this year (2010), Gmail switched to using HTTPS for everything by default. Previously it had been introduced as an option, but now all of our users use HTTPS to secure their email between their browsers and Google, all the time. In order to do this we had to deploy no additional machines and no special hardware. On our production frontend machines, SSL/TLS accounts for less than 1% of the CPU load, less than 10KB of memory per connection and less than 2% of network overhead. Many people believe that SSL takes a lot of CPU time and...

Silencing Deprecation Warnings in Rspec

If you’re testing the behavior of deprecated code in your Ruby project, the warning messages littered throughout your spec output is incredibly noisy.

You could silence all warnings with ::ActiveSupport::Deprecation.silenced = true, but you might miss out on an important warning in one of your dependencies. It’s tempting to remove the tests altogether (the code will be burned soon too, right?), but I figured out something a little nicer a little while back in Formtastic’s test suite.

Iterate over every n-th element of a Range in Ruby

If you want to iterate over a Range, but only look at every n-th element, use the step method:

(0..10).step(5).each do |i|
  puts i
end

# Prints three lines:
# 0
# 5
# 10

This is useful e.g. to iterate over every Monday in a range of Dates.

If you are using Rails or ActiveSupport, calling step without a block will return an array of matching elements:

(0..10).step(5) 
# => [0, 5, 10]