Here’s a quick and easy way to sort a Ruby hash by its keys. The ability to sort recursively and provide a custom sort block are also available features.

The Method

I took the approach of monkey patching a sort_by_key method into the Ruby Hash class itself. The method can be easily modified and placed into a utility class if you’d prefer to take more procedural approach.

class Hash
  def sort_by_key(recursive = false, &block)
    self.keys.sort(&block).reduce({}) do |seed, key|
      seed[key] = self[key]
      if recursive && seed[key].is_a?(Hash)
        seed[key] = seed[key].sort_by_key(true, &block)
      end
      seed
    end
  end
end

Basic Usage

Below is a very disorganized nested hash and an example of using the recursive sort option to get it back into line using Hash.sort_by_key(true).

h = {
  "b" => 2, "c" => 3, "a" => 1, "d" => {
    "b" => 2, "c" => 3, "a" => 1, "d" => {
      "b" => 2, "c" => 3, "a" => 1
    }
  }
}
h.sort_by_key(true) # =>
{
  "a" => 1, "b" => 2, "c" => 3, "d" => {
    "a" => 1, "b" => 2, "c" => 3, "d" => {
      "a" => 1, "b" => 2, "c" => 3
    }
  }
}

What About Mixed Type Hash Keys!?

If we continued the example from above by executing h[:a] = "one", and then calling h.sort_by_key, we would be slapped in the face with an exception of …

  • ArgumentError: comparison of String with :a failed

Looking at the backtrace it appears the call to self.keys.sort is the culprit.

So What’s The Solution?

There are a couple of solutions depending on your coding style and opinion on Ruby convention.

Option 1: Don’t do that!

Many coders in the Ruby community will argue that it’s not the job of Ruby to undo a user’s mistakes. While “Don’t do that!” that can sound like a copout, it’s also really good advice – keep things simple.

Generally, it’s not a good idea to mix the types of Hash keys. If you find that you’re getting this exception it’s probably an indication that “You’re doing it the wrong way.”

Option 2: Passing a custom sort block, and casting key values…

Coming from PHP I’ve grown accustomed to certain… luxuries, in that if you ask PHP to ksort() an array it will do its very best to get you something reasonable back. By passing a custom sort block to Hash.sort_by_keys we can mimic PHP’s robustness.

Let’s change how Hash.sort_by_keys is called by passing it a custom sort block that casts each key to a string before the comparison.

h.sort_by_key(true) {|x, y| x.to_s <=> y.to_s} # =>
{
  :a => "one", "a" => 1, "b" => 2, "c" => 3, "d" => {
    "a" => 1, "b" => 2, "c" => 3, "d" => {
      "a" => 1, "b" => 2, "c" => 3
    }
  }
}

It’s a very simplistic technique that should be capable of accommodating almost all of the off-the-beaten-path situations out there in the wild.

Summary

I ended up needing a variant of this solution to address a situation where http parameter ordering had to be alphabetical in order to create and validate signed requests to OAuth based APIs. So far things are working well and my code is a lot cleaner.

In my search for an existing sorting solution I also stumble upon this StackOverflow.com Question that shed some light on other hash key sorting techniques.

License

This code is released under the New-BSD License.

If you’ve found an issue, improvement, or bug with this technique please Contact Me, or comment below.

I’ve been loving the Twitter Bootstrap buttons so I came up with a quick technique that turns them into actual working form input elements.

HTML

Just like a normal Bootstrap Button Group, but with a few added attributes.

<div class="btn-group" data-toggle-name="is_private" data-toggle="buttons-radio">
  <button type="button" value="0" class="btn" data-toggle="button">Public</button>
  <button type="button" value="1" class="btn" data-toggle="button">Private</button>
</div>
<input type="hidden" name="is_private" value="0" />

Note: Yes, nested names like bookmark[is_private] work just fine.

JavaScript

On document load we apply the button logic and state based on the hidden input’s value.

jQuery(function($) {
  $('div.btn-group[data-toggle-name=*]').each(function() {
    var group   = $(this);
    var form    = group.parents('form').eq(0);
    var name    = group.attr('data-toggle-name');
    var hidden  = $('input[name="' + name + '"]', form);
    $('button', group).each(function(){
      var button = $(this);
      button.on('click', function(){
        hidden.val($(this).val());
      });
      if(button.val() == hidden.val()) {
        button.addClass('active');
      }
    });
  });
});

The Result

Twitter Bootstrap Radio Button Form Inputs Result

Notes & Considerations

  • This solution requires JavaScript in order to work properly so use judgement when implementing it.
  • The type="button" is required to prevent the form getting submitted when the toggle buttons are clicked.
  • You may also need to do some styling to get the buttons to look right in some contexts. Thankfully I’ve found this to be a relatively painless experience.

Summary

Please comment or contact me if you find any issues. I’ve tested this technique and so far I’ve been very happy with it.

I had just finished the standard installation of ActiveAdmin when I noticed that authentication was implemented using the fantastic Devise Gem. I had already been planning on using Devise for authentication within my application so I initially thought integration would be a snap. However, as development progressed it became clear that all of the pieces were not quite fitting together.

Realization

After exploring the idea of using one login for ActiveAdmin and the application I ran into a rather large road block. By default ActiveAdmin uses an AdminUser Devise model to manage user authentication. Why is that such a big problem you ask?

Well, I really wanted to avoid having…

  • the application users login via the ActiveAdmin interface
  • a model named AdminUser representing an application user
  • two models that contained much of the same code and functionality
  • to maintain two separate user management systems (Admin vs Application)

In most cases ActiveAdmin would be used by… well, administrators. However, that was not my situation. I had a slew of qualified people that needed access to both ActiveAdmin and the Application; having two sets of credentials was just not the optimal solution.

The Optimal Solution

What I really wanted was for both the ActiveAdmin and Application users to be…

  • able to sign in/out via a single set of Devise controller/actions routes
  • managed by single, Devise configured, User model
  • distinguished by a boolean flag — such as user.superadmin?
  • restricted from accessing ActiveAdmin based on the above flag.

After chewing on the problem for a while, reading through ActiveAdmin documentation, and talking to a couple of colleagues I managed to come up with a way of implementing a solution that provided exactly what I was looking for.

Setting Up the ActiveAdmin/Application User Model

For the purposes of making this walkthrough more adaptable to other projects I’ve chosen to explain the entire process starting from scratch using a brand new Rails 3.1 project.

Step 0: Preparation

We start off by creating the classic Rails “blog” application…

$ rails new blog

Next, we open the project’s Gemfile and add the required ActiveAdmin and Devise gems…

# ==> File: /Gemfile

# Active Admin + Required Gems
gem 'activeadmin'
gem 'sass-rails'
gem "meta_search", '>= 1.1.0.pre'

# Devise
gem "devise", "~> 2.0.0"

We then install the gems with bundler and run the ActiveAdmin installation generator …

$ bundle install
  ... bundler output ...

$ rails generate active_admin:install
  invoke    active_record
  create      db/migrate/20120205064942_devise_create_admin_users.rb
  create      app/models/admin_user.rb
  invoke      test_unit
  create        test/unit/admin_user_test.rb
  create        test/fixtures/admin_users.yml
  insert      app/models/admin_user.rb
   route    devise_for :admin_users
    gsub    app/models/admin_user.rb
    gsub    config/routes.rb
  insert    db/migrate/20120205064942_devise_create_admin_users.rb
  create  config/initializers/active_admin.rb
  create  app/admin
  create  app/admin/dashboards.rb
   route  ActiveAdmin.routes(self)
generate  active_admin:assets
  create  app/assets/javascripts/active_admin.js
  create  app/assets/stylesheets/active_admin.css.scss
  create  db/migrate/20120205014944_create_admin_notes.rb
  create  db/migrate/20120205014945_move_admin_notes_to_comments.rb

Note: You may see some Devise specific errors at this point, ignore them for now.

At this point the ActiveAdmin gem has been installed and its files and routes have been generated using the steps outlined in the official installation instructions. This is where we leave those instructions behind…

Step 1: Creating a new Devise User model

First thing’s first, let’s run the Devise 2.0 installation generator.

Note: Enter “Y” (yes) if you are prompted to overwrite the devise initializer file.

$ rails generate devise:install
   conflict  config/initializers/devise.rb
Overwrite blog/config/initializers/devise.rb? (enter "h" for help) [Ynaqdh] Y
      force  config/initializers/devise.rb
  identical  config/locales/devise.en.yml

Now, at this point one might ask: “Can’t I just simply rename the AdminUser model?” – Nope! Unfortunately there are no migrations, routes, or tests in place to support a model named User yet.

To fix that let’s go ahead and create them using the Devise model generator.

$ rails generate devise User
  invoke  active_record
  create    db/migrate/20120120053416_devise_create_users.rb
  create    app/models/user.rb
  invoke    test_unit
  create      test/unit/user_test.rb
  create      test/fixtures/users.yml
  insert    app/models/user.rb
  route  devise_for :users

Now that the User model has been created a superuser? boolean flag must be added. Additionally we need to insert an initial Superamin User record so that we may login and access ActiveAdmin later on. These two steps can be accomplished with a simple rails migration…

$ rails generate migration AddSuperadminToUser
invoke  active_record
create    db/migrate/20120122062203_add_superadmin_to_user.rb
# ==> File: /db/migrate/20120122062203_add_superadmin_to_user.rb

class AddSuperadminToUser < ActiveRecord::Migration
  def up
    add_column :users, :superadmin, :boolean, :null => false, :default => false

    User.create! do |r|
      r.email      = 'default@example.com'
      r.password   = 'password'
      r.superadmin = true
    end
  end

  def down
    remove_column :users, :superadmin
    User.find_by_email('default@example.com').try(:delete)
  end
end

Note: These temporary user credentials will be used later on in Step 4.

Finally, open up the User model and replace its content with the example code below – modify to taste.

# ==> File: /app/models/user.rb

class User < ActiveRecord::Base
  devise :database_authenticatable, :recoverable,
         :rememberable, :trackable, :validatable
  attr_accessible :email, :password, :password_confirmation,
                  :remember_me
end

Great, you’ve just configured what will be the unified User model!

Step 2: Reconfiguring ActiveAdmin

As it turns out ActiveAdmin has some nifty configuration settings that allow for its authentication behavior to be modified. Open up the ActiveAdmin initializer file and update it to reflect the configuration settings below…

# ==> File: config/initializers/active_admin.rb

config.authentication_method = :authenticate_active_admin_user!
config.current_user_method   = :current_user
config.logout_link_path      = :destroy_user_session_path
config.logout_link_method    = :delete

There is a lot here so let’s quickly go over whats happening.

  • The ActiveAdmin current_user_method and authentication_method configuration settings specify which methods to call when retrieving and authenticating a user, respectively.
  • When someone attempts to access any of the ActiveAdmin actions a call is made to both methods which are scoped to the Rails ApplicationController instance.

We’ve instructed ActiveAdmin to use a new custom authentication method: authenticate_active_admin_user! It doesn’t exist yet so we must define it in the ApplicationController

class ApplicationController < ActionController::Base
  protect_from_forgery

  def authenticate_active_admin_user!
    authenticate_user!
    unless current_user.superadmin?
      flash[:alert] = "Unauthorized Access!"
      redirect_to root_path
    end
  end
end

Perfect, ActiveAdmin is now properly configured to take advantage of the superadmin? user flag.

Step 3: Cleaning up the code left behind by ActiveAdmin

Now that the new Devise User model is setup we can start to cleanup the code and files leftover from the ActiveAdmin install generator. We start by deleting the AdminUser model and its associated migration file…

$ cd /path/to/your/rails/project

$ rails destroy model AdminUser
  invoke  active_record
  remove    migration.rb
  remove    app/models/admin_user.rb
  invoke    test_unit
  remove      test/unit/admin_user_test.rb
  remove      test/fixtures/admin_users.yml

$ rm ./db/migrate/*_devise_create_admin_users.rb

Next, we need to make the comments within ActiveAdmin work properly again. Open up the following migration files, do a simple Find & Replace for :admin_user to :user, then save.

  • 20120212124753_create_admin_notes.rb
  • 20120212124754_move_admin_notes_to_comments.rb

Note: The timestamps of your migration filenames will be different.

The Devise routes that AdminAdmin generated for the AdminUser model still exist and must be removed. Open up the Rails routes.rb file and delete the following line of code…

devise_for :admin_users, ActiveAdmin::Devise.config

Great, the project has been clean of any left over files and all the features within ActiveAdmin will now work properly.

Step 4: Managing the Devise User model with ActiveAdmin

The User model is much more complex than your average ActiveRecord::Base class. It’s configured with Devise authentication options and now has a superadmin? flag that is responsible for controlling access to ActiveAdmin. As a result of this complexity we need to add some custom configuration.

The first thing we need to do is make ActiveAdmin aware of the User model by creating a corresponding registration file, like so…

$ cd /path/to/your/rails/project
$ touch ./app/admin/user.rb

Open the /app/admin/user.rb file with an editor of your choice and copy/paste the ActiveAdmin model registration code below.

Note: This is the absolute bare minimum configuration that is required to manage users from within ActiveAdmin. Feel free to modify this registration file to suit your needs. Keep in mind that as the User model gains more complexity, the ActiveAdimin registration file will need to grow along with it.
# ==> File: app/admin/user.rb

ActiveAdmin.register User do

  form do |f|
    f.inputs "User Details" do
      f.input :email
      f.input :password
      f.input :password_confirmation
      f.input :superadmin, :label => "Super Administrator"
    end
    f.buttons
  end

  create_or_edit = Proc.new {
    @user            = User.find_or_create_by_id(params[:id])
    @user.superadmin = params[:user][:superadmin]
    @user.attributes = params[:user].delete_if do |k, v|
      (k == "superadmin") ||
      (["password", "password_confirmation"].include?(k) && v.empty? && !@user.new_record?)
    end
    if @user.save
      redirect_to :action => :show, :id => @user.id
    else
      render active_admin_template((@user.new_record? ? 'new' : 'edit') + '.html.erb')
    end
  }
  member_action :create, :method => :post, &create_or_edit
  member_action :update, :method => :put, &create_or_edit

end

Step 5: Wrapping It All Up

Now that everything has been created and configured we can finally pull the trigger on the migration files. So let’s go ahead and run them like so…

$ cd /path/to/your/rails/project
$ rake db:migrate

It’s a good idea to setup some real user credentials so let’s start up the local rails server, by executing $ rails server and opening the browser to http://localhost:3000/users/sign_in.

Note:  If page layout looks completely broken don’t worry! It just means that you need to style or replace the Devise sign in page.

Sign in using the temporary email and password that was added via the migration created back in Step 1.

After you’ve logged in navigate to http://localhost:3000/admin, click on the Users tab, create a new super administrator user using the credentials of your choice and click save.

Lastly, sign out of ActiveAdmin, then sign in again with your new credentials and delete the temporary user.

That’s it, you’re done!

But! But! What About…

Some may be wondering why I did not use the optional user model parameter in ActiveAdmin install generator script.

Well, I didn’t use it in this post for a few of reasons. Mainly I wanted to make sure this walkthrough was applicable to the widest set of projects and situations. Thus, I wrote this post so that it could be followed by someone who was either starting a new Rails project or just needed to cherry pick some of the steps for their existing application.

I also found that running the ActiveAdmin installation generator over top of a pre-existing User model will cause code to be injected into that User model class file and migrations will be built that change the users table structure.

Lastly, the generator solution alone does not cover all of my other requirements that I listed above. ActiveAdmin would still use it’s own views for the authentication routes, and the superadmin? flag, configuration setting, and authentication method would still need be modified/created by hand.

Thus, I would recommend using it only if you’re aware of the pitfalls in doing so.

Environment

This walk through was tested and implemented using the following technologies…

  • Rails 3.1
  • Ruby 1.9.3
  • ActiveAdmin 0.4.0
  • Devise 2.0

Summary

This solution was made possible thanks to the work that Greg Bell and the ActiveAdmin Contributors put into making sure the flexibility of ActiveAdmin stayed a top priority. ActiveAdmin is a truly fantastic (and beautiful looking) gem that spares developers from spending extensive hours and resources building back-end administrative tools – I highly recommend using it.

If you have any suggestion on how to make this process better in anyway please contact me and I’ll make the appropriate updates.

I was in the middle of a code review a simple question came up: “What’s the fastest way to output a segmented string in PHP?”

echo '<div>';
echo '<span>';
echo 'This is a random number: ' . mt_rand(1,100);
echo '</span>';
echo '</div>';

– OR –

$html  = '<div>';
$html .= '<span>';
$html .= 'This is a random number: ' . mt_rand(1,100);
$html .= '</span>';
$html .= '</div>';
echo $html;

My initial guess was that calling echo as little as possible during a request would end up performing better as there would be no need to interact with an output buffer or perform other logic tied to STDOUT.

I ended up asking a few friends and colleges what they thought about the question and most responded with “hu?” After telling them that I was in fact serious the majority of their opinions fell on echo being the winner. Still, others thought of ways to get a segmented string out faster, like pushing them onto an array and executing echo implode('', $array);

This difference of opinion got me thinking about what was truly the most efficient way to output a collection of strings? Curiosity got the best of me and I quickly setup some profiling tests using my Bench Class to find out the answer.

Profiling Setup

I used the following code in order to get enough data points for a solid performance comparison.

$samples = 40;
$sets    = array(10,20,50,100,500,1000,1500,2000,2500,3000);
$results = array();
foreach($sets as $iterations) {
  $results[$iterations] = array();
  for($i=0; $i<$samples; $i++) {
    Bench::start();
    for($j=0;$j<$iterations;$j++) {
      // ... Output Test ...
    }
    $results[$iterations][] = Bench::stop();
    Bench::reset();
  }
}

Output Tests

I tested the performance using four different methods of outputting data…

Echo

for($j=0;$j<$iterations;$j++) {
  echo 'abcdefghijklmnopqrstuvwxyz0123456789';
}

Print

for($j=0;$j<$iterations;$j++) {
  print 'abcdefghijklmnopqrstuvwxyz0123456789';
}

Concatenation

$x = '';
for($j=0;$j<$iterations;$j++) {
  $x .= 'abcdefghijklmnopqrstuvwxyz0123456789';
}
echo $x;

Array + Implode

$x = array();
for($j=0;$j<$iterations;$j++) {
  $x[] = 'abcdefghijklmnopqrstuvwxyz0123456789';
}
echo implode('', $x);

Environment

I ended up testing with the php-cli in order to avoid the extra overhead of a browser and web server. When I attempted to test the performance in a browser it yielded vastly different datasets from one test to another.

Results

So this is what I ended up with…

Raw Numbers

  10 20 50 100 500 1000 1500 2000 2500 3000
Concat 3.80E-05 6.04E-05 0.0001506 0.0003327 0.0018855 0.0044077 0.0063608 0.0079579 0.0099115 0.0118193
Implode 4.00E-05 6.05E-05 0.0001454 0.0003285 0.0017583 0.0040021 0.0059396 0.0081685 0.0106799 0.0131378
Echo 2.43E-05 4.36E-05 0.0001046 0.0004600 0.0021742 0.0050115 0.006305 0.0086550 0.0105163 0.0133090
Print 5.76E-05 0.000119 0.0002459 0.0006077 0.0026465 0.0048339 0.0065905 0.0086254 0.0109871 0.0130858

Graphs

10-100 Results

500-3000 Results

Conclusions

As one can see there is very little difference in speed, and performance seems to scale up linearly. After playing around with various tested sizes I felt that going past the 3000 iterations mark would have been futile as it’s already quite a stretch that anyone would call echo that much within a single request.

While this post may be trivial it at least shows that there is no real performance benefits to using any of the four methods over one another. However, that’s not to say that all methods are equal when one is aiming towards maintainability – but that it another topic for a different day.

Summary

If you feel I’ve somehow misrepresented the data then by all means download the testing script, modify it, and educate me.

You can find the testing script and results here: PHP Output Profiling Testing Script.

A couple weeks ago I was looking for a simple way to make AJAX requests on admin or public WordPress pages from a theme or plug-in. After a bit of searching I could not find the solution I was looking for - so I built my own, AHAX.

AHAX is a drop-in solution that allows theme or plug-in developers to take advantage of a very simple and streamlined way of making AJAX requests.

Under The Hood

To create the example above I had to do two simple things. First, create the PHP function that handles the AJAX request in my theme’s function.php file and associate it with a specific AHAX action using ahax::bind(...). Second, create an instance of the AHAX JavaScript class and use its post method to make a request to the previously mentioned PHP function.

Back-End

PHP

ahax::bind( 'get_random_number', 'generate_number');
function generate_number($output) {
  $max    = abs((int)$_POST['max']);
  $output = mt_rand(0 ,($max <= 1000 ? $max : 1000));
  return $output;
}

Front-End

JavaScript

var ahax = new AHAX();
ahax.post('get_random_number', {max:1000}, function(response) {
  jQuery('#ahax_number').html(response);
});

Breaking It Down

With this plugin I’ve attempted to make the process of creating an AJAX request as simple as possible by centering everything around an action.

The Action

In the code example above get_random_number is the action of the AHAX request. The static method ahax::bind(...) is used to create a WordPress filter that corresponds to the JavaScript ahax.post(...) method’s first argument.

A valid action is only allowed to consist of a-z, A-Z, and underscore ( _ ) characters.

The Flow of Execution

  • The “Generate Number” button is clicked.
  • An AJAX request is initiated by the ahax.post("get_random_number", ...) method to the AHAX plugin’s request.php file.
  • The AHAX request.php file loads the WordPress bootstrap and executes the handler function(s) associated with the get_random_number action.
  • The handler function generate_number($output) is executed and returns a modified $output variable (string).
  • The AHAX request.php file calls echo on the modified $output variable.
  • The JavaScript ahax.post("get_random_number", ...) method’s callback function is called.
    • The callback function parameters are dependent on the JS framework used by AHAX, which is jQuery by default.
  • The responseText – which is a random number in this case – is then placed into innerHTML of the #ahax_number HTML element.

A More In-Depth Look

There are a few things you can do with AHAX that don’t fit in well with the very simplistic example above.

WordPress Framework Access

From within the handler function (generate_number() in the example) one can do anything needed, all with full access to the WordPress Framework. That means WordPress functions (get_bloginfo(), get_comments(), is_user_logged_in(), etc…), global objects ($wpdb), and user defined functions – that were created in a plugin or theme – are all available and functional from within the handler function.

AHAX JavaScript Class Config Options

There are currently only two configurable options of the AHAX class.

url - Optional - The URL of the AHAX request.php file.

var ahax = new AHAX("http://...");
// -- or --
var ahax = new AHAX({url:"http://..."});

framework - Optional - The JavaScript Framework used by AHAX.

var ahax = new AHAX({framework:"jQuery"});

Console Logging

The AHAX JavaScript Class will do its best to report any issues so keep an eye on the FireBug console while developing.

Binding Actions

Binding an action to a function is easy and can be accomplished in two ways …

ahax::bind('get_random_number', 'generate_number'); // Shorthand
# -- OR --
add_filter(ahax::tag('get_random_number'), 'generate_number'); // Longhand

Being Mindful of AHAX’s Limitations

There a few thing to be mindful of when developing a theme feature or a plugin around the functionality AHAX provides.

Supported JavaScript Frameworks

At this time the only framework supported by the AHAX JavaScript Class is jQuery. I’ve developed the AHAX class in such a ways as to allow easy implementation of other frameworks like Prototype, Ext.js/Sencha, etc…

If you feel like implementing another javascript framework feel free to fork this project on GitHub. When you’ve completed it send a pull request and your name/handle will be added to the “Contributors” section (on code review and approval).

You can also send requests to the AHAX plugin’s request.php file as you would in any other AJAX request. The only requirements are that the request be made using POST and an “action” variable be set that corresponds to a filter setup using ajax::bind(...) (see example above).

WordPress Framework Bootstrap

As previously mentioned in this post, each request made by AHAX has to load the entire WordPress bootstrap (including all active plugins and the theme) before executing the handler function. This adds a decent amount of time on to all AJAX requests made using the AHAX plugin.

For a large majority of users this extra time / server load will not be be a problem at all. However, if performance issues are becoming a noticeable problem some changes will need to be made by either optimizing your WordPress install / server side environment, or by just not using AHAX to make your AJAX requests.

Summary

AHAX was born out of a need to easily make and handle AJAX request from anywhere within the WordPress environment. I’ve since developed it into a “dependency” plugin that gives plugin and theme developers a quick and easy way to add AJAX functionality into their work.

The name AHAX was arrived at by combining “AJAX” and “HACK” together (it’s also a nice, small, and unique namespace).

License

This project / plugin and its code is released under the New-BSD License.

Requirements

  • PHP >= 5.0
  • WordPress >= 2.8.0

Download

The source code is available to anyone at https://github.com/veloper/AHAX.

It can also be installed via the wordpress.org plugin repository at http://wordpress.org/extend/plugins/ahax.