Call Montréal, Canada 524-949-6869

Blog

Saturday, January 29, 2011

TextExpander stopped working

I can't live without TextExpander. But apparentely Firefox and Chrome are not playing nicely with it. TextExpander suddenly stopped working for. I don't use these browsers very often, most for browser testing. Anyway, here is an explanation from TextExpander support:

Most likely, you're being affected by the bug in Firefox and Chrome where they enable secure input but don't disable it. This bug is particularly infuriating because it doesn't seem clear to the end user what causes it. However, it does have a cause, a workaround, and it does seem to be getting some traction from the Mozilla folks. Switching product probably won't help, as the other text expansion applications observe input in the same way as TextExpander and thus are subject to deprivation by secure event input being left enabled. When these browsers display a password field, they turn on secure event input so that no one, including TextExpander, can peek at your passwords. Problem is, if you use the Return key to submit a form from within its secure field, they won't turn secure event input off. This appears to be a bug they've inherited from some Firefox code they use. The workaround is to use the submit button rather than using Return in the password field. 1Password is similarly affected by this bug. The workaround there is to turn off auto-submit and just use auto-fill then press the button to submit.

This is referenced on Mozilla's bug tracker.

Good quote on the misunderstandings of software development

Much of present-day software acquisition procedure rests upon the assumption that one can specify a satisfactory system in advance, get bids for its construction, have it built, and install it. I think this assumption is fundamentally wrong, and that many software acquisition problems spring from that fallacy. (Brooks 1987 cited Larman and Basili 2003, p.52).

Source: http://www.sebastiangreger.net/writings/concept-design-in-agile-environment/

Reminder: Restful controllers do not need to map one-to-one to models (in Rails)

The central concept of REST is the resource, which is a datastructure representing one or more business objects.

Source: http://nicksda.apotomo.de/2010/10/rails-misapprehensions-crud-is-not-rest/

A reminder for why to use ems for font-size, line-height and space in CSS

The advantage to using ems for font size, line height, and spacing between elements is that as text size is adjusted, those measurements will adjust proportionately.

Source: http://www.slideshare.net/LRyder/best-practices-and-css

Monday, January 24, 2011

Upgrading Git via MacPorts (1.6.6 to 1.7.3.5)

I upgrade Git this morning to the latest version available via MacPorts. I ran into a few issues, but mostly painless. Here is the run down:

sudo port selfupdate
sudo port upgrade git-core

First upgrade attempt resulted in the following error:

--->  Dependencies to be installed: readline
Portfile changed since last build; discarding previous state.
--->  Activating readline @6.1.002_0
Error: Target org.macports.activate returned: Image error: /opt/local/lib/libreadline.5.2.dylib already exists and does not belong to a registered port.  Unable to activate port readline. Use 'port -f activate readline' to force the activation.
Error: Failed to install readline
Log for readline is at: /opt/local/var/macports/logs/_opt_local_var_macports_sources_rsync.macports.org_release_ports_devel_readline/main.log
Error: The following dependencies were not installed: readline
Error: Problem while installing sqlite3

Executing the following command resolved this issue:

sudo port -f activate readline

Try upgrading again:

sudo port upgrade git-core

Resulted in the following error:

Configuring db46¬ 23 Error: db46 requires the Java for Mac OS X development headers.¬ 24 Error: Download the Java Developer Package from: ¬ 25 Error: Target org.macports.configure returned: missing Java headers¬ 26 Log for db46 is at: /opt/local/var/macports/logs/_opt_local_var_macports_sources_rsync.macports.org_release_ports_databases_db46/m    ain.log¬
 27 Error: Problem while installing db46¬
 28 To report a bug, see 

I downloaded and installed the Java Developer Package.

Another attempt:

sudo port upgrade git-core

Success!

git --version
git version 1.7.3.5

Sunday, January 16, 2011

Minitest raising error for Cucumber generate command in Rails 3/Ruby 1.9.2

I mistaken included the "shoulda" gem in the "development" group. When generating cucumber with the following options I receive the following error:

rails g cucumber:install --capybara --rspec --spork
/Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:566:in `block in process_args': invalid option: --capybara (OptionParser::InvalidOption)
 from /Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:545:in `new'
 from /Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:545:in `process_args'
 from /Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:576:in `run'
 from /Volumes/Data/Users/nicholas/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/minitest/unit.rb:492:in `block in autorun'

Excluding "shoulda" from the "development" group (i.e. just in test) resolved the error.

References

Google Groups

Friday, January 14, 2011

Stub called with unexpected arguments fixed in RSpec2 Mocks

In RSpec 1.3 the following would pass:

describe Person do
 describe "#greeting" do
   context "using #stub with correct parameters" do
     before(:each) do
       subject.stub(:greeting).with("Nicholas")
     end

     specify { lambda{ subject.greeting("Nicholas") }.should_not
raise_error(NoMethodError) }
   end

   context "using #stub with incorrect parameters" do
     before(:each) do
       subject.stub(:greeting).with("incorrect parameter")
     end
     specify { lambda{ subject.greeting("Nicholas") }.should
raise_error(NoMethodError) }
   end
 end
end

From the example above you can see that calling a stuff with a different parameter would raise a NoMethodError. A bit confusing.

Fortunately in RSpec 2 it fixed. The following error is raised:

1) Person#greeting using #stub with incorrect parameters 
     Failure/Error: specify { lambda{ subject.greeting("Nicholas") }.should raise_error(NoMethodError) }
       expected NoMethodError, got ##<RSpec::Mocks::MockExpectationError: #<Person:0x0000010216fb68#> received :greeting with unexpected arguments
         expected: ("incorrect parameter")
              got: ("Nicholas")>

Related links:

  • My post to RSpec mailing list
  • http://github.com/rspec/rspec-mocks/issues/20
  • http://groups.google.com/group/rspec/browse_thread/thread/ab3519f98597815c

RSpec double, mock, and stub

RSpec uses double to create a test double. However, there are two aliases for this method mock and stub. When do we use which alias? It depends on what role the test double is fulfilling.

If the test double is the focus of the test, then you will be setting a message expectation on the double, which takes the "mock" role.

If the test double is not the focus, and you are simply stubbing out methods on an object, then this takes the "stub" role. You can often eliminate the number of method stubs by ignoring method calls using #as_null_object.

Radiant, Cucumber and Globalize2 Extension

After installing the Globalize2 extension and creating Cucumber features for a dependent extension, I needed to remove the dataset class method to get features running since the models no longer matched the dataset factories:

# /Library/Ruby/Gems/1.8/gems/radiant-0.9.1/features/support/dataset.rb
require 'dataset'

Cucumber::Rails::World.class_eval do
  include Dataset
  datasets_directory "#{RADIANT_ROOT}/spec/datasets"
  self.datasets_database_dump_path = "#{Rails.root}/tmp/dataset"
 #dataset :users, :config, :pages, :layouts, :pages_with_layouts, :snippets, :users_and_pages, :file_not_found, :markup_pages
end

Concept of collapsing margins

CSS is a strange beast, and typically the behaviour of margins can be a little strange to beginners. Over seven years old, this article from Andy Budd, No Margin for Error, is still a good read for the CSS newbie:

At it's core, margin collapsing is very easy to understand. Basically when two vertical margins meet up, instead of adding together, the largest margin takes precedent and the other one "collapses" to nothing.

Never use rescue blindly

On a recent project I was horrified to see various inline rescues. Here are three examples:

# Example 1
def friend_recommended_picture
  friend.recommended_picture rescue ""
end

# Example 2
params[:search][:skip_conversion] = true rescue nil

# Example 3
item_image = Product.find_by_id(product_id).images.find(:first, :conditions => 'attachment_file_name like "%example.jpg"').attachment.url(:mini) rescue ''

In all of these examples I the author is protecting themselves from a NoMethodError with a NilClass.

My preference is to always use the try method (provided in Rails 2.x and standard in Ruby 1.9):

# Example 1
def friend_recommended_picture
  friend.try(:recommended_picture) # returns nil if friend is nil
end

In Rails, this can be cleaned up using the delegate class method:

delegate :recommended_picture, :to => :friend, :allow_nil => true, :prefix => true

For the second example I would prefer this, although there is a little more code involved (clarity over cleverness):

# Example 2
params[:search][:skip_conversion] = true if params[:search]

And for the final example, well this is a bit of a mess. Let's clean up the call:

item_image = item_image(Product.find(product_id))

And encapsulate the various scopings within the correct classes.

# products_helper.b
def item_image(product)
 product.example_image.try(:attachment) {|attachment| attachment.url(:mini) }
end

# models/post.rb
def example_image
  images.examples.first
end

# models/images.rb
named_scope :examples, :conditions => 'attachment_file_name like "%example.jpg"'

This last example illustrates well that the careless use of rescue nil is a symptom of other issues such as poor encapsulation.

There are plenty of examples of using rescue such as on Ruby Inside:

h = { :age => 10 }
h[:name].downcase                         # ERROR
h[:name].downcase rescue "No name"        # => "No name"

This still makes me feel dirty inside. Yes it is working on a Hash, but what if h becomes a more complex object, then that rescue could be obscuring other exceptions. My preference would be:

h[:name].try(:downcase) || "No name"

Jay Fields also has an interesting use for inline rescue. One of the commenters mentions "its important to use them judiciously." I suspect the inline rescue is a victim of cargo culting and 99% of the time there is a better solution.

Thursday, January 13, 2011

Interfacing with Web Services? Checkout Tammer Saleh's "Coding for Failure"

Last year when interfacing with several Web services for a project I found Tammer Saleh's "Coding for Failure" indispensable. Although it was presented two years ago, it's far from out of date.

You can check it out on the Confreaks website and download the slides from here (the link on Tammer's website is broken).

Specifically I found Tammer's summary of different exceptions helpful which I have included here:


See slides for handling in controllers and rake tasks and notification using HopToad.

Capture HAML to yield in a layout

Rails has the content_for method which allows you to yield content into a layout later in the rendering phase of a view. Often I need the same functionality when using StaticMatic. Since I'm using Haml this is easier to do.

Tuesday, January 4, 2011

Applying OO principles to CSS

 

One of the frustrating aspects of coding CSS is the ad-hoc approach in crafting styles. It felt all my software development practices went out the window. Compass, a stylesheet authoring framework, along with Sass, a stylesheet language, has alleviated most of my pain. However, implementation still varies from developer to developer.

I have refined my approach to focus on styling content elements first (e.g. H1, ul, p tags), the grid, and finally the chrome (e.g. backgrounds). While this approach has worked quite well, I'm still not completely satisfied on the reusability of the "chromed" elements. This is where Nicole Sullivan comes in, developer of the OO CSS framework. While a Compass implementation is in the works, I'm quite happy adapting the philosophy of the framework to may current workflow. Specifically the 10 Best practices she outlines in her presentation Object Oriented CSS:

  1. Create a component library
  2. Use consistent semantic styles
  3. Design modules to be transparent on the inside
  4. Be flexible
  5. Learn to love the grid
  6. Minimize selectors
  7. Separate structure and skin
  8. Separate container and content
  9. Extend objects by applying multiple classes
  10. Use reset and fonts from YUI

Practices 7 and 8 need more explanation. Below are comments from Nicole's blog post announcing the framework hosted on Github.

Separate structure and skin

Abstract the structure of the block from the skin which is being applied.

Separate structure from skin isn’t about HTML and CSS. Within the CSS, have one class that takes care of all of the little presentational elements, browser differences, basically all the complicated bits. Then build on that class with multiple skin classes, which then only need to contain simple things like border colors, background images, etc. The skins become super predictable.

 

Separate container and content

Break the dependency between the container module and the content objects it contains.

A glance at the CSS of most sites will tell you no one is doing this properly. At best we manage to separate by module, or sandbox individual components. Unfortunately, each of the modules has container and content completely tied together. This makes the CSS grow over time and the site not scale or perform well.

Her nine pitfalls are also worth noting:

  1. Location dependent styles
  2. Avoid specifying what tag a class applies
  3. Avoid IDS to style inside the main content areas
  4. Avoid drop shadows and rounded corners over irregular backgrounds
  5. Don't sprite every image together (unless your site has very few pages)
  6. Avoid height alignment
  7. Text as text, not as images
  8. Redundancy
  9. Avoid premature optimization

Nicole's presentation is well worth watching if you intend to adopt such a framework, or simply wish to improve you CSS authoring skills. I have included the video of the presentation below along with the slides. Here are some helpful links if you wish to research further:

Object Oriented CSS

Slides

Developing Ruby on Rails applications and custom Content Management Systems in Montréal. Contact Firsthand.