So if you have an app that requires a WiFi network connection in order to reliably synchronize some large-ish data set, you need to notify your user if the connection is not available.

Apple provides the Reachability example app that demonstrates how to do this, and you can use the Reachablility class in that app in your own app.

1. Add the Reachability.h and Reachability.m files to your project.
2. Include Reachablility.h in the header of the file you’re going to do the check
3. Add the following line:

[[Reachability reachabilityForLocalWiFi] currentReachabilityStatus] == ReachableViaWiFi

Just a quick tip, this one!

If you have a model that is polymorphic, say a comment model:

class Comment
  belongs_to :user
  belongs_to :commentable, :polymorphic => true
end

and you want to link to the item the comment relates to in the admin system, you can do this:

<%= link_to comment.commentable.title, [:admin, comment.commentable] %>

Note this assumes all of your commentable models have a title attribute or method, and that you have used normal RESTful routes. The :admin symbol will namespace the link to /admin

If you don’t already know, Bort has now been updated to Rails 2.2. For more information on exactly what has changed, please see Jim’s post.

I have also updated my email-as-login fork of bort to include this release.

Please give us your feedback over on our Uservoice page.

When testing Controller actions for access restriction, I was building a set of tests for each controller that were in a similar format to this:

describe "access control" do
  it "should prevent access by non-logged-in users"
  it "should prevent access by normal users"
  it "should prevent access by editor users"
  it "should prevent access by admin users"
  it "should allow access by super admin users"
end

Unforunately, this was neither dry, complete, nor very readable, so I have come up with the following helper that allows you to specify the access restrictions for a number of methods:

In your spec_helper.rb file, add the following function:

def access_control (code, options={})
  options = {:allow => [], :disallow => []}.merge(options)

  options[:allow].each do |user|
    it "#{code} should allow #{user.to_s}" do
      login_as(user)
      eval code
      response.should_not redirect_to(login_path)
    end
  end

  options[:disallow].each do |user|
    it "#{code} should disallow #{user.to_s}" do
      login_as(user)
      eval code
      response.should redirect_to(login_path)
    end
  end
end

Then in the specs for your controller, call the function as follows:

access_control("get :index", {:allow => [:super_admin], :disallow => [:quentin, :admin]})

This allows you to very quickly build a set of specs that fully describe how access control to your methods should restrict your users:

[ "get :show, :id => 0",
      "get :new",
      "post :create, :setting_value => {:value => 'A new setting', :group => 0}",
      "get :edit",
      "put :update, :id => SettingValue.first.id, :setting_value => {:value => 'changed'}",
      "delete :destroy, :id => SettingValue.first.id"
    ].each do |action|
      access_control(action, {:allow => [:super_admin], :disallow => [:quentin, :admin]})

In order to DRY-up our process of creating new rails projects over at Fudge, we recently created Bort – a base rails application that contains all of the bits that we push together when starting out.

Jim has more about the base system, but there is also a fork that contains all of the bort goodness, with the notable difference that instead of using usernames to authenticate, the users email address is used instead.

Enjoy.

A recent release of Bouldr threw a bit of a spanner in the works when the excellent Asset Packager began choking when attempting to create our concatenated and compressed javascript file.

It turns out that as I am developing in Windows (gah!), I need to run dos2unix in order to ensure that the js files are in the appropriate file format (our server is running CentOS). In order to automate this process, I added the following to our deploy script:

# Need to ensure files are in UNIX format for the asset packager to run correctly
run "cd #{release_path}/public/javascripts && find . -name '*.js' -exec dos2unix '{}' \\;"

# Run the asset packager to create the production javascript and css files
run "cd #{release_path} && rake asset:packager:build_all RAILS_ENV=production"

I recently came across a small problem in RSH whereby on loading a page with a state in the url (e.g. localhost.com/test_page#test) would not trigger the history listener function on it’s initial load. To fix this, I needed to modify my window onload function to include a call to my history listener, as follows:

history_listener: function (newLocation, historyData) {
...
},

// Window.onload calls this
initialize_history: function () {
       	dhtmlHistory.initialize();
       	dhtmlHistory.addListener(this.history_listener.bindAsEventListener(this));

       	// Added this line to force a call to my history listener
       	this.history_listener(dhtmlHistory.getCurrentLocation());
}

This ensures that when the page is freshly loaded, the history listener is called with the contents of our initial location.

This one had me for a while: When attempting to install the MySQL gem on my shiny new Slicehost slice, I was getting the folowing error:

Building native extensions.  This could take a while...
ERROR:  Error installing mysql:
   ERROR: Failed to build gem native extension.

/usr/local/bin/ruby extconf.rb install mysql -- --with-mysql-include=/usr/include/mysql --with-mysql-lib=/usr/lib/mysql
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... yes
checking for mysql_query() in -lmysqlclient... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
   --with-opt-dir
   --without-opt-dir
   --with-opt-include
   --without-opt-include=${opt-dir}/include
   --with-opt-lib
   --without-opt-lib=${opt-dir}/lib
   --with-make-prog
   --without-make-prog
   --srcdir=.
   --curdir
   --ruby=/usr/local/bin/ruby
   --with-mysql-config
   --without-mysql-config
   --with-mysql-dir
   --without-mysql-dir
   --with-mysql-include=${mysql-dir}/include
   --with-mysql-lib=${mysql-dir}/lib
   --with-mysqlclientlib
   --without-mysqlclientlib
   --with-mlib
   --without-mlib
   --with-mysqlclientlib
   --without-mysqlclientlib
   --with-zlib
   --without-zlib
   --with-mysqlclientlib
   --without-mysqlclientlib
   --with-socketlib
   --without-socketlib
   --with-mysqlclientlib
   --without-mysqlclientlib
   --with-nsllib
   --without-nsllib
   --with-mysqlclientlib
   --without-mysqlclientlib

Gem files will remain installed in /usr/local/lib/ruby/gems/1.8/gems/mysql-2.7 for inspection.
Results logged to /usr/local/lib/ruby/gems/1.8/gems/mysql-2.7/gem_make.out

It turns out, all I needed was to run the following:

gem install mysql -- --with-mysql-config=/usr/bin/mysql_config

Hope this saves someone the hour or so I spent scratching my head!

OK, so say you have a form as follows:

<% form_tag '/', :method => :get do -%>
<p><%= text_field_tag 'q', params[:q] ||= '' %> <%= submit_tag 'Search' %></p>
<% end %>

That form will send the contents of the text box to the page at ‘/’. Unfortunately, it will also send through the value of the submit button, which is ‘Search’ in this case. The url generated will be:

/?q=something&commit=Search

In this case, we would want only the ‘q’ parameter passing through, and in order to do this, all we need do is nullify the name parameter:

<% form_tag '/', :method => :get do -%>
<p><%= text_field_tag 'q', params[:q] ||= '' %> <%= submit_tag 'Search', :name => nil %></p>
<% end %>

This will create the following url on submission:

/?q=something

Just a quick tip I recently came across:

If you want to see the docs for any of the gems installed on your dev machine, type the following in the command line…

gem_server

…and then browse over to http://localhost:8808/!