“Banners” = Bad in Ad Blocker World

Just ran into a rather aggravating issue…

In building a site meant to preview mobile ads, I used the term “banners” in the URL to point to image previews then spent 2+ hours tracking down why it worked in my development environment but not in production.

Luckily a colleague pointed out my ad blocker, which seems to have a broad match on the word “banner”…block all. Changing the name in the path fixed the problem.

Advertisements

Installing Nokogiri via Bundler on Mac (or why did this take two hours?)

If this post saves one person the headache of several hours of trying to build Nokogiri via Bundler on a Mac, maybe my time wasn’t wasted, but it was painful.

The setup…
Trying to install Nokogiri 1.6.1 as a dependency for other gems via Capistrano’s bundle:install task, I continually ran into “Failed to build gem native extension” error. Scrolling through the errors, the one item that stuck out was “You have to install development tools first.”

Although 100% certain my server had Xcode Command Line tools installed (it was recently updated at noted in the App Store), I reinstalled manually and tried to deploy again. Same error.

I then proceeded down the path of using Homebrew to install the various Nokogiri dependencies (e.g. libxml2, libxslt). Deploy…build…fail.

I ran “gem install nokogiri” locally on the server. Build…success. Tried to deploy again…build…fail.

Finally, I dug up the make log for Nokogiri (path below for reference) where I noted a message indicating that “gcc-4.2” was not installed. gcc is installed, but the build script seems specific. Not finding a switch to change the name of gcc, I went brute force:

sudo ln -s /usr/bin/gcc /usr/bin/gcc-4.2

Deploy…build…success! Annoying problem, solved.

Better suggestions welcome.

Make log: /shared/bundle/ruby/2.0.0/gems/nokogiri-1.6.1/ports/x86_64-apple-darwin13.1.0/ext/nokogiri/mkmf.log

Update
After all that, I noticed a warning: “Nokogiri was built against LibXML version 2.8.0, but has dynamically loaded 2.9.1”. After trying a few paths, I was able to rectify the warning via the steps in the comments of this :

  1. brew remove –force libxml2
  2. bundle config –delete build.nokogiri
  3. bundle exec gem uninstall nokogiri libxml-ruby
  4. bundle
  5. The commenter notes that Nokogiri 1.6+ now bundle the necessary libraries so there is no need to use the Homebrew versions.


Ransack: Search with Multiple Checkboxes (Rails)

I’ve been using the outstanding Ransack gem to enable search for a recent project. Ransack provides a tremendous amount of flexibility in a straightforward manner, but it took me a bit to understand how to search a single field across multiple values selected via checkboxes. My approach follows.

(Note that the field I was searching contained a serialized array of data, not to make life more difficult)

To start, a simplified model:

class Zoo < ActiveRecord::Base
  has_many :animals
end

class Animal < ActiveRecord::Base
  belongs_to :zoo # we'll assume an animal can only belong to one zoo
  validates_presence_of :name
end

Next, the controller, which is pretty much out-of-the-box from the Ransack documentation:

class ZoosController < ApplicationController
  def search # or index
    @search = Zoo.search(params[:q])
    @zoos = @search.result(distinct: true)
  end
end

And finally, the magic is really in the view:

<%= search_form_for @search, url: search_zoos_url do |f| %>
  <% Animal.all.uniq.each do |animal| %>
    # the check_box helper will not work as effectively here
    <%= check_box_tag('q[animals_name_cont_any][]', animal.name) %>
    <%= animal.name %>
  <% end %>
  <%= f.submit "Search" %>
<% end %>

The key is the name of the check box field. We are passing an array and also using Ransack’s cont_any predicate, which searches for any records whose name field contains one of the selected names.


Rails Asset Pipeline + Bootstrap 3 Fonts

I admit it, I find the Rails Asset Pipeline confusing at times (as do seemingly many others judging from Stackoverflow and elsewhere).  Successfully adding the Bootstrap 3 glyphicon fonts took some trial-and-error amongst the various solutions I found as many still resulted in not found errors.

While there may be a better way, I found this approach most effective:

    1. Copy the contents of the Bootstrap “dist/fonts” directory to the “vendor/assets/fonts” directory (you will need to create a “fonts” directory.  Bootstrap’s minified JavaScript and CSS files can be copied to the appropriate directly in “vendor/assets” as well.
    2. Add the following to “config/application.rb” within the application config block:
      config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts')
      config.assets.precompile += %w(.svg .eot .woff .ttf)
    3. Utilizing SASS (or LESS) here is useful in order to leverage built-in asset pipeline helper methods.  In a common file used across your site, include the following:
      @font-face {
        font-family: 'Glyphicons Halflings';
        src: font-url('glyphicons-halflings-regular.eot');
        src: font-url('glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),
        font-url('glyphicons-halflings-regular.woff') format('woff'),
        font-url('glyphicons-halflings-regular.ttf') format('truetype'),
        font-url('glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
      }

Thus far, Not Found errors seem to have been eliminated.  If there is a better way, please comment.


Very Useful

Rails Better Errors

Cleans-up Rails error messages, making them easier to understand and interactive. How have I missed this until now?


Rails: Page Specific JavaScript with Asset Pipeline

After being away from Rails for several years, coming back to Rails 3/4 and its asset pipeline was a challenge at times.  While the performance gains and automation are quite valuable, the asset pipeline isn’t without its occasional challenges.  One of those challenges was the growing amount of JavaScript being executed on every page of our site.  While this mostly amounted to at worst errors in the console, it just felt icky (that’s a technical term).

Upon exploring Stack Overflow and various blog posts, I finally found a solution that felt somewhat better: Page-Specific Javascript using Coffeescript.  The overall solution was fairly clean, didn’t cause an explosion in the number of JS files, and also did not require an update to the config each time a new JS file was added.  For larger, more modular needs, other solutions (e.g. this one) may be more applicable, but this approach works fine for our medium size app.

I will not review the entire approach verbatim here, but I did make several changes to the aforementioned article.  It’s important to note that this solution utilizes the object-oriented nature of CoffeeScript to simplify life.

First, we will create a base class that houses the common code executed on every page.  I named this class base.js.coffee (in app/assets/javascripts).

window.MyApp ||= {}  # namespace for your app, replace as you desire
class MyApp.Base
  constructor:() ->
    # common code we want to run on every page
    console.log('I print on every page!')
    # be sure to return this
    this

Next, we can begin to build controller-specific classes on top of the base class.  Like Rails, we will use the convention of the naming the class the same as the accompanying controller.  For example, our CommentsController will be accompanied by a CoffeeScript class called MyApp.Comments in the file comments.js.coffee.

window.MyApp ||= {}
class MyApp.Comments extends MyApp.Base
  constructor:() ->
    super  # call Base class for core functionality
    this   # and be sure to return this

  # now, we enumerate the actions for which we want page-specific behavior
  index:() ->
    console.log('I only print on the comments#index page')
  show:() ->
    console.log('I only print on the comments#show page')
  edit:() ->
    # something special for the comments#edit page

Continue to build a CoffeeScript class for each of your controllers that require JavaScript beyond whatever your Base class takes responsibility for.  Be sure to include a method for each action/page on which unique functionality is required.

Finally, we need to bring everything together and ensure our code is called wherever necessary.  One approach would be to include the following in your application’s layout view, though it could also be included anywhere sure to be called.

<%= javascript_tag do %>
$(document).ready(function() {
  window.$M = new (MyApp.<%= params[:controller].capitalize %> || MyApp.Base)();
  if (typeof $M.<%= params[:action] %> === 'function') {
    return $M.<%= params[:action] %>.call();
  }
});
<% end %>

The above first instantiates a new instance of our controller’s accompanying class and then attempts to call the action method, if it exists.  The approach used in our app is slightly different, but this works as well.

Note that I did run into an issue using Turbolinks in conjunction with the above approach that we are yet to solve.  In short, despite using jquery.turbolinks and other known approaches, the action methods were being called multiples times per page.  I have seen mention of this behavior when Turbolinks is used in conjunction with anonymous functions (e.g. those created by CoffeeScript), but have not found a fix.  Please comment if you can help.


Quick Link: Rails HTTP Status Code to Symbol Mapping

Very useful:

http://www.codyfauser.com/2008/7/4/rails-http-status-code-to-symbol-mapping