Monday, March 26, 2012

Converting CSS background images to use asset pipeline

In order to use the asset pipeline in Rails 3.1, not only do you have to move your assets (images, css, javascript, fonts) to the appropriate folders in the assets folder, but you also have to modify the css files so that background images point to the new location.

To make this easier, I used a couple of regex replaces to swap out the old formats for the new format.

For example, I had the following css class in one of my css files.
.standard_form form fieldset input.submit_button {
    background-image: url('../images/common/donate_now_new.png');
    width: 202px;
    height: 50px;
    border: none;
    color: white;
    font-size: 19px;
    text-shadow: 2px 2px 2px #666666;
    font-weight: bold;
    cursor: pointer;
}
I needed to convert the backround-image line to:

image-url('common/donate_now_new.png')

I used the following regex search and replace strings to do so:

Search: (url)\('(\.\.\/images\/)(.*)'\)
Replace: image-url('$3')


I also had background-image statements with the following format: url(../../images/common/input_bg2.png)

I used the following regex to make the replacement for these

Search: (url)\((\.\.\/\.\.\/images\/)(.*)\)
Replace: image-url('$3')

Once I had completed all of the replacements, I changed the file name, adding scss to the end to ensure it would be compiled and the image-url method would substitute the appropriate address for me. 

Wednesday, March 7, 2012

Adventures in moving from Rails 2.3.14 to 3.0: Controller Spec changes

I use integrate_views (or now render_views) when testing controllers and then, for the most part, don't do separate view tests.

A good portion of my tests check whether a particular element appears on the page. I use have_tag to do this. The rspec-html-matchers gem is a great replacement for the have_tag functionality that was removed from Rspec 2. I wish I had found it before changing many of my have_tag statement to have_selector.

In any case, there are some formatting differences between the new and the old have_tag matcher.

Using css matching
Using the CSS matching with have_tag did not previously require quotes around the value portion of an identifier. For example you could write  have_tag("div[id=my_id]") and it would work. Now, you have to place quotes around the my_id portion, or have_tag("div[id='my_id']"). 

To make this easier, I wrote a regular expression to search for quoteless have_tag matchers and insert the quotes. 

Regex: \[(id|class|href|type)=([^\[^'.]*)\]
Replace: [$1='$2']
Using Textmates find and replace, with the regular expressions checkbox checked, made it relatively pain free to do the replacements. 

Content within a tag
Have_tag used to except a string as a second parameter. The string represents content to search for within the tag. For example have_tag("a[href='people/4']", "John Doe") would search for a link to the 'people/4' path containing the text 'John Doe'.

Though this may still work in some instances, I found that a more consistent way of representing this is to use a :text qualifier: have_tag("a[href='people/4']",  :text => "John Doe"). Use regular expressions I was able to make the following replacement:

Regex: have_tag\((.*),(?: *)(?:"|'|/)(.*)(?:"|'|/)\)
Replace: have_tag($1, :text => /$2/)

This also then used regular expression for the match, instead of straight text.

Matching against response.body, not response
It used to be that you could match the have_tag against the response. But now that causes the following error:
  

     Failure/Error: response.should have_tag("div#group_list") do
     NoMethodError:
       undefined method `current_scope' for #

The have_tag matcher must be applied to the response.body, as in:

response.body.should have_tag("div#group_list")

Issues encountered when upgrading from rails 3.0.11 to 3.1.7

Here are a few things I encountered when making the upgrade.

Once I had changed the entry in gemfile to gem rails '3.1.7' and performed a 'bundle update rails', I ran a single cucumber feature, and got the following error:

/Users/user/.rvm/gems/ruby-1.9.2-p290@givecorps_rails_3_1/gems/activerecord-3.1.4/lib/active_record/attribute_methods/read.rb:91: syntax error, unexpected keyword_end
  /Users/user/.rvm/gems/ruby-1.9.2-p290@givecorps_rails_3_1/gems/activerecord-3.1.4/lib/active_record/attribute_methods/read.rb:93: syntax error, unexpected $end, expecting keyword_end (SyntaxError)
  ./features/step_definitions/model_steps.rb:9:in `block in build_models_from_table'
  ./features/step_definitions/model_steps.rb:8:in `each'
  ./features/step_definitions/model_steps.rb:8:in `build_models_from_table'
  ./features/step_definitions/model_steps.rb:17:in `/^the following ([^"]*):$/'
  features/admin_assigns_categories_to_causes.feature:8:in `Given the following cause:'

It turns out, this was caused by incompatibilities between rails 3.1 and the mysql2 gem. So I modified the gemfile with gem mysql2 '~> 0.3', and ran bundle update mysql2.

Running the feature again, I got:

Please install the mysql2 adapter: `gem install activerecord-mysql2-adapter` (can't activate mysql2 (~> 0.3.10), already activated mysql2-0.3.7. Make sure all dependencies are added to Gemfile.) (RuntimeError)

It turns out, when I had first run bundler to update mysql2, version 0.3.7 was installed. Rerunning bundler install got version 0.3.11, and the mysql2 adapter issue went away, and the feature ran.

I then started the server, and got the following error:

undefined method `debug_rjs=' for ActionView::Base:Class (NoMethodError)

I had to remove from development.rb the following:

config.action_view.debug_rjs             = true

I was then able to start the server.

Hitting the first page, however, I got the following error:

NoMethodError (undefined method `each' for nil:NilClass):
  

 Rendered /Users/user/.rvm/gems/ruby-1.9.2-p290@givecorps_rails_3_1/gems/actionpack-3.1.4/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.0ms)
 Rendered /Users/user/.rvm/gems/ruby-1.9.2-p290@givecorps_rails_3_1/gems/actionpack-3.1.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (18.0ms)
 Rendered /Users/user/.rvm/gems/ruby-1.9.2-p290@givecorps_rails_3_1/gems/actionpack-3.1.4/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (22.0ms)

This led to a discussion on rails and rack about ill-formed cookies that as of today, does not seem to be resolved.

So I cleared my browsers cookies, and was able to view the site. Hopefully, this won't be an issue on the production server.

Browsing the site, I got the following error:
undefined method `paginate' for #

I had updated to the rails 3 version of will_paginate. This required me to modify the syntax used in calling paginate, and to include the 'paginate/array' module since some of what I paginate are returned arrays (mostly to ensure uniqueness)