Rails default scripts and jquery-rails

I recently had an issue in a (3.0.7) rails app where link_to some_path, :method => :post was calling the action associated with GET, this was caused by not having a link to jquery_ujs.js (I’m using jquery so don’t want rails.js) in my html output.

Googling turns up a number of suggestions to add jquery_ujs.js and the other jquery script files to the default javascripts by amending config/application.rb. This works ok but it’s not ideal as you probably want minified versions of the files in production and non minified in development.

Digging into the jquery-rails gem reveals railtie.rb:

This sets the default scripts before config/application.rb is run. Unfortunatley with application.rb as it is generated if you run rails new with the -J switch (you probably don’t want prototype if you plan to use jquery) these defaults are overridden. Commenting out

From config/application.rb allows the jquery-rails scripts to load but doesn’t allow you to add to the defaults. I did submit a pull request amending the railtie to run it’s code on before_initialize (after config/application.rb has been run). This allowed defaults to be set and the jquery defaults appended but as Indirect pointed out, this prevents you overriding the jquery defaults in application.rb.

The way to add your own scripts is to append them to the defaults using:

This works but there are 2 related issues; jquery_ujs.js should be the last script loaded as it needs to hook into any submission events for ajax elements and it can’t unless scripts for those events are loaded before it.

With the solution above we have application.js (added by Rails) and our scripts loaded after jquery_ujs.js. Our scripts can be placed first by changing application.rb to:

This still leaves application.js loaded after jquery_ujs.js but that should be fine as long as there aren’t any submission events scripted in it.

Using the railtie to set the default scripts then allowing you to append or override these defaults is a neat solution by the jquery-rails gem, unfortunately it doesn’t seem that many know about it as there seems to be a lot of advice to add the jquery script files directly in config/application.rb. It looks as these issues will go away in Rails 3.1 anyhow.

Rails Autoload and Ruby Require

Rails methods of locating and loading files is mostly based on convention but is built on top of Ruby’s methods.

Ruby

The basic way to tell a ruby to load a file is to require it, e.g. require some_file will load some_file.rb if the file has not already been loaded. load some_file.rb will load the file (and execute any code) regardless of if the file has been loaded already.

In 1.9.2 the path that Ruby looks for these files includes:

  • A number of directories in your Ruby install.
  • Directories of any gems loaded
  • Directories you have added to $LOAD_PATH, Rails adds a number of app directories to this variable. To see exactly what is added run puts $LOAD_PATH in both irb and a rails console.

To require a file relative to the file doing the requiring use require_relative some_directory/some_file.

Require and load both load the file when execution reaches the relevant require or load call, autoload some_file will not load the file until a module in the file is called.

Rails

In addition to adding  app directories to the $LOAD_PATH, Rails loads all *.rb files in /config/initializers/ when the application starts.

Rails also has an autoload_path, If Rails comes across an uninitialized constant it will check any paths in autoload_path for a file matching the name of the constant e.g. when execution hits an unrecognized constant MyConstant it will check for a file called my_constant.rb in any paths included in autoload_paths.

The autoload_path in 3.0.7 is empty, to add the lib directory to it, add config.autoload_paths += %W(#{config.root}/lib) to config/application.rb.

If the module name does not match the file name then the file will need to be required in the normal way.

Rails also allows you to require a file with require_dependency. Require_dependency works exactly like Ruby’s require except, in development mode, it reloads the file when a view is refreshed allowing you to make changes to the required file and see them by refreshing the browser.

Incude and Extend

There seems to be some confusion between require and include/extend but they are totally unrelated. Require and similar deal with loading files from the filesystem. Include and extend deal with including code from one module in another. A class the includes a module allows an instance of the class to access code from the included module. A class that extends allows the class to access code from the module called.

 

 

 

Launching irb from vim

You can run irb from vim with the command !irb.

Running !irb -r % should run the current file in irb then leave irb open. Unfortunately ruby 1.9.2 removed the current directory from the load path which causes this to fail. You could construct a path but it is easier to add the current directory back in, especially if you are using irbtools which does it for you.

Once irbtools are installed add:

map <F2> <ESC>:w<CR>:!irb -r %<CR>

to .vimrc.local which will write then load the current file into irb.

Edit: I was getting some weirdness with the irb prompt with irbtools so I have removed it and added

$: << ‘.’  if RUBY_VERSION >= ‘1.9.2’

to my .irbrc file to add the current directory to the load path.

 

Recovering from ‘the application finder can’t be opened’

Every now and again I get an error when opening finder:

‘the application finder can’t be opened’

Whilst I am sure a restart would fix it, I normally don’t want to restart as I am in the middle of something. The solution is to run the following in terminal:

/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder &

(don’t forget the &) If this continues to happen I should probably try and find the cause, more likely that I will just map the command to a bash alias though :).

MacVim, NerdTree, Janus Annoyances

I’ve decided to use Vim for a few weeks at least and am enjoying it. There are plenty of posts on using Vim as a Ruby IDE and switching from your IDE of choice. Most of the TextMate to Vim posts seem to recommend Janus and for good reason.

Janus adds a number of plugins and settings to Macvim including NerdTree. NerdTree displays a project drawer in a window which is in a vertical split, normally alomgside your working buffer. The first problem is that if you close your working buffer with :bd or :bw, the NerdTree window will fill the MacVim tab, to cycle to the next or previous buffer then entails resizing splits which is not what I want.

Janus solves this with a function in .vimrc:

This function closes the MacVim tab (i.e. Cmd + W) if there is only one tab and it contains 2 windows, one of them with the NerdTree buffer. Unfortunately this doesn’t consider buffers that are not currently displayed. If I want to close MacVim or the MacVim current tab, I’ll use Cmd + Q or W, when I delete a buffer I want the window to display the next buffer.

To disable the Janus function add an override to .vimrc.local:

It’s better to make changes in .vimrc.local and .gvimrc.local as Janus can be updated to the latest version without losing your customisations.

Luckily there is a script on the vim wiki that keeps the window open when deleting a buffer. It can be amended to ignore the NerdTree buffer, if I want to close NerdTree I will use the key mapped to toggle it:

I would like to map :bd to :Kwbd but it seems it can’t be done (I’d be happy to be proved wrong here) so have mapped Ctrl + Shift + B in .vimrc.local:

HTML5 Creating the Header and Testing

This post is following on from a previous post on Creating the footer.

Creating the header was a lot simpler than I thought it would be. The original header in the Roots template is pretty sparse and I want to end up with this:Header final
(I’m still unsure about the tag line but it’s not something I will worry about for the moment.)

As with the footer, I want a full page width bar behind the header. I previously removed the Blueprint .container div that wrapped the whole page to allow this and this caused all elements to shift towards the left hand edge of the page. Wrapping the header element in it’s own .container div brings it back to the centre and allows me to include a div above it that can extend to the page edges.

The header bar is styled to be full width, 10 pixels high, and to have a shadow:

The rest of the header content is contained in 2 divs; one for the logo and the other for the navigation and the tagline.

The logo is positioned with padding and sits below  a div with a top margin of -10px for the green flash.

The navigation bar has rounded lower corners and sits between 2 canvas elements with the concave curves drawn on them with javascript. The js/scripts.js will override the scripts.js file in the parent theme and run the document.ready function after the document finishes

Using rounded corners, shadows, and canvas elements means the site will not look the same in older browsers. I used Adobe BrowserLab to test this after uploading the site to a temporary WordPress install (in the process I learned that the template name in child_theme/style.css needs to be lower case otherwise WordPress thinks that the child theme is broken.)

Chrome 9 and 10 for Windows were both fine as was Firefox 3.6 and 4 on Mac and Windows. Safari 5 was good, Safari 4 lost the drop shadows but rendered everything else ok. Internet Explorer 7 and 8 didn’t render the shadows, rounded corners, or canvases and, strangely IE 8 lost the footer bar, I checked IE 8 manually in a VM and the bar was there so presumably this is some BrowserLabs oddity. IE 9 was fine. I’m not concerned with Firefox 3.5 or IE 6.

The site is usable in IE 7 and 8 but doesn’t have curves, canvases, or shadows. I may try and address those issues later using modernizer, images and fixing the navigation font size for IE 7 and 8 but it is certainly not a priority at the moment.

Checking on an iphone reveals another problem; the divs for the header and the footer are supposed to have be 100% of the page width but they are only covering the left third of the screen (this happens on the ipad also). After trying various things it turns out that it is due to the viewport meta tag:

When this tag is removed and Safari is allowed to render the page as with it’s default settings, the footer and header extend to full width. In a more responsive layout that adapted itself to mobile screens the viewport tag is useful, but as this site is 960px wide and the default iphone viewport is 980px there is no reason to have the tag.

HTML5 Creating the Footer

This is the third post in what is turning out to be a series on my ‘adventures’ with WordPress and HTML5. Previously I set up a development environment and installed a barebones HTML5 theme.

Now I want to style the footer (start with the easiest part) to go from this:

Footer start

To this:

Footer finish

I want the dark grey bar of the footer to extend the whole width of the page but because I am using the Blueprint grid, everything inside the body element is wrapped in a div with a class of container. For any element to us the Blueprint grid layout it needs to be in a container but the container class styles the wrapper div to be 950 pixels wide and centred.

The way around this is to remove the top level wrapper div and wrap the header, content, and footer elements in their own separate container divs, these container divs can then be inside divs that extend the full width of the page.

From this

To this

Template files in the child theme will override the files in the parent theme. I need to customise header.php and footer.php so the easiest way to start is to copy the original files to the child theme.

Deleting the container class from the wrapping div in header.php then just pushes everything to the left hand edge of the screen. Wrapping the footer element in a .container div then pushes the footer back to the centre, I’ll re-centre the header and content when I get to them later.

Now it is easy enough to create a div surrounding the .container div and giving it an id of footer-bar. Writing the first style presents a problem though. Roots relies on a function get_roots_stylesheets() in functions.php to write the stylesheets into the head element, I want to add my own stylesheet but don’t want to change the parent functions.php. The solution is to write my own get_stylesheets() function in my own functions.php and add both the roots stylesheets and my own stylesheet in the function. WordPress loads the functions.php in the child theme in addition to the functions.php in the parent theme. I can then change the header.php to call my function rather than the roots one.

One thing to watch when editing funtions.php; make sure there are no blank lines outside the containing <?php … ?> tags. I had one blank line after the ?> and that caused me to completely lose the WordPress admin pages, they just showed as blank.

After styling the footer-bar div, stickyfooter.css can be used to stick the footer to the bottom of the page. I want the current page to be highlighted in the navigation links and the link to the current page to be disabled. WordPress adds the class current-page-item to the <li> containing the link so the following css does the trick.

The rest is fairly simple css.

Creating an HTML5 Boilerplate WordPress Theme

 

I’ve just had a logo and design done for Furld. I am pleased with the design but it was supplied in HTML and CSS rather than HTML5 and CSS3 so I want to convert it at the same time as I turn it into a WordPress theme.

Furld home page design

I like HTML5 Boilerplate by Paul Irish and luckily there is a WordPress theme called Roots, which is designed as a jumping off point for your own HTML5 theme.

I have installed WordPress locally to use as a development environment so I just have to copy the roots theme to mysite/wp-content/themes/roots and I can activate it.

After activating the theme I can visit the home page and see this.

New html5 home screen

Not very pretty but it is HTML5 and now I can start customising it. Rather than customising the theme itself I am going to create a child theme:

  • Create a directory mysite/wp-content/themes/roots-child/
  • Create a style.css in the directory.

When the Roots Child theme is activated the site should look exactly the same but changes I make in the child theme will override the parent theme. This means the parent theme can be updated by the original author and I will not lose any customisations I make to the child theme.

 

Installing WordPress on your Mac for Development

The Stack

To run WordPress locally you will need Apache, MySQL, and PHP installed. Although OS X comes with some of these it is more convenient to use MAMP. MAMP comes in a free version and a Pro version, for my purposes the free version should be fine.

Installation is just copying a folder from the disc image to your applications folder and removal is just a case of deleting the folder. Once the folder has been copied just start MAMP which will start the servers and open the home page on port 8888.MAMP

From the preferences > Apache pane set the document root to wherever you want to put your sites. I set mine to ~/dev/sites/.

The Database

Click on open start page on the MAMP dialogue then click on phpMyAdmin, enter a database name for your WordPress database then click on create. Click on privileges and create a new user with full privileges for the database.

WordPress

Create a subdirectory for your new web site in your sites directory, download WordPress from wordpress.org and unzip the contents of the download into the subdirectory.

Rename the file wp-config-sample.php to wp-config.php then edit it to fill in the database details and change the salts and keys.

Navigate to http://localhost:8888/ and you should see the subdirectory, click the link and you should get taken to the WordPress install page (if you get error connecting to database it is likely that either your database server is not running of there is an error in your wp_config.php). Fill in the blog title, username, password, and email, hit submit and you are done.

Rails, Compass, HTML5 Boilerplate and Heroku

Overview

HTML5 provides some great functionality but also, potentially, some headaches. HTML5 Boilerplate is a template which aims to solve the various cross-browser differences.

There is a gem to use HTML5 Boilerplate in a rails app which uses Compass to build the CSS. Using Compass on Heroku requires a small workaround as Heroku limits where an app can write to.

Setup

For a new Rails App: Follow the process in prior post on setting up a new project.

After the rspec and cucumber installs run

When asked, select yes for change of SASS location but no to change of CSS location

Carry on through prior post (but don’t install jquery as that is part of the HTML5 Boilerplate)

Create a home controller script

Delete the /public/index.html and the app/views/layouts/application.html.erb files

Set the root in the config/routes.rb

Fix the annoying Rails 3.0.5 bug by amending the javascript expansions line in config/application.rb to

The app should now run locally using hml5-boilerplate, compass, and haml.

Heroku

But not on Heroku, to run on Heroku the css files need to be written to a tmp directory as that is the only folder the app can write to.

In config/compass.rb change the css_dir line to

Change config/initializers/compass.rb to

This should allow the app to run locally and hosted on Heroku.

To push to Heroku follow these instructions.

In summary, once you have your SSH keys set up: