February 2012
2 posts
3 tags
Beware of chaining lambda scopes
Here’s a gotcha to watch out for! Let’s say you have these scopes in your Rails 3 project: scope :started, lambda { where("starting_at <= ?", Time.now) } scope :unfinished, lambda { where("ending_at > ?", Time.now) } When you call either of these scopes, because you have used lambda, the value of the lambda is re-evaluated each time so that Time.now is dynamic. That’s...
Feb 23rd
1 note
1 tag
Check SQL from Rails scopes
To see the sql generated by a scope method in Rails 3 use the to_sql method. For example: Post.current.to_sql => "SELECT `posts`.* FROM `posts` WHERE (created_at > '2012-02-22')"
Feb 22nd
January 2012
1 post
2 tags
bundler_wrapper
Long ago I installed and tried out rubygems-bundler. Unfortunately, I didn’t follow the instructions when I uninstalled it. So for months, I’ve been plagued with this error: env: bundler_wrapper: No such file or directory I’ve managed to get around it but never quite knew what was causing it or where to look to fix it. Google didn’t help me this time. This time, it...
Jan 2nd
6 notes
September 2011
5 posts
1 tag
The pack-unpack hack
Hacks should generally be avoided. Generally, if you need to use a hack, you’re probably going against the design/purpose of the framework/language. There is likely a better way of doing it. You just have to find it. Unfortunately, hacking the code seems the quicker and easier solution. In the long run, it’s not. Often, I’ll get a feeling that what I’m coding is...
Sep 29th
1 note
1 tag
Beware of shortcuts
Here’s a bit of code that caused a failure today: scenario.illustrations << illustration if illustration = Illustration.find_by_code(legacy_scenario_illustration.IllustNo) The if condition was added to ensure that only non-nil values are added to the scenario.illustrations collection. It uses the convenience of making the assignment of the local variable illustration inside the...
Sep 29th
1 note
3 tags
Bundler’s Best Kept Secret (bundle viz) →
Sep 29th
1 tag
Upgrading authlogic for Rails 3
If you are experiencing this error when trying to upgrade your Authlogic-powered app to Rails 3: undefined method `underscore' for nil:NilClass Then, try using this fork/commit instead. It fixes a bug where you have used a different name for the authentication model. In my case, we used Login instead of the standard convention of UserSession used by Authlogic.
Sep 19th
24 notes
2 tags
bypass_rescue in RSpec
If you are using rescue_from to handle an exception then the following spec won’t work: it "should raise an access denied error" do expect { get(:new) }.to raise_error(CanCan::AccessDenied) end Instead you need to use rspec-rails’s bypass_rescue: it "should raise an access denied error" do bypass_rescue expect { get(:new) }.to raise_error(CanCan::AccessDenied) end This...
Sep 5th
11 notes
June 2011
2 posts
1 tag
Git admin - cleaning up remote branches
When using git branches and pushing them to a remote you inevitably need to do some tidy up. Deleting a local branch: git branch -d branch_to_delete Deleting a local branch that is not in the current history: git branch -D branch_to_delete Deleting a branch in the remote (origin) repo: git push origin :branch_to_delete Deleting the local copy of a remote branch: git branch -d -r...
Jun 16th
2 notes
May 2011
0 posts
1 tag
Presence
I just came across this object method in Rails (when did this go in?): Instead of writing something like: state = params[:state] if params[:state].present? you can now do: state = params[:state].presence Object.presence is the equivalent of object.present? ? object : nil See the docs
May 31st
2 notes
April 2011
2 posts
How to Name Gems →
Apr 28th
3 tags
Sorting custom objects
To sort custom objects, in the class of the object include the Comparable module and then define the comparable operator: class Person include Comparable # name is a string attribute def <=> (other_person) self.name <=> other_person.name end end This then lets you do the following to sort person objects by each person’s name: people.sort
Apr 6th
57 notes
March 2011
18 posts
2 tags
Make forward delete work in irb (on a mac)
Here’s how to rid yourself of these annoying ~~~~ characters you keep typing into irb because forward delete doesn’t work: Open Terminal > Preferences > Settings > Keyboard Double click on “forward delete” Change the action string from \033[3~ to \004
Mar 31st
Bundler Best Practices →
Mar 30th
1 tag
Pairing tete-a-tete →
Mar 27th
1 note
1 tag
Extreme Pairing →
Mar 26th
2 tags
Creating a legacy rails app
Question: When you have the latest and greatest version of Rails installed, how do you create a new app using an older version of Rails? Answer: # rails 3: rails _3.0.11_ new myapp # rails 2: rails _2.0.11_ myapp Thanks to this stack overflow question.
Mar 25th
1 tag
Talkative migrations
Sometimes I’ll have a migration that needs to convert existing data. When run, it can look like the migration has stalled (especially if you didn’t write the migration and are simply migrating your database to the latest). I like to wrap these blocks with the say_with_time method to let the developer know what is happening. The say_with_time method outputs text along with how long it...
Mar 23rd
2 tags
Converting numbers and letters
When dealing with legacy data I often find annoying things like integers used to represent letters, integers stored as strings, or both. "1", "2", "3", "4", "5" => "A", "B", "C", "D", "E" In ruby 1.9, if you want to convert a number that is stored as a string to its corresponding capital letter: ("1".to_i + 64).chr # => "A" To go back the other way: ("A".ord - 64).to_s # =>...
Mar 22nd
1 tag
Rails ERD – Entity-Relationship Diagrams for Rails →
Back in the day I had used railroad.
Mar 21st
1 tag
Git commit stats
To get a quick overview of how many commits each developer has made: git shortlog -s -n Obviously, it shouldn’t be used as a metric of quality, just activity.
Mar 20th
1 note
1 tag
Creating and publishing your first ruby gem →
A really great and simple to follow tutorial on getting starting with creating and publishing your first gem.
Mar 19th
1 tag
Semantic Versioning →
Good rules that all gem developers should follow: “Consider a version format of X.Y.Z (Major.Minor.Patch). Bug fixes not affecting the API increment the patch version, backwards compatible API additions/changes increment the minor version, and backwards incompatible API changes increment the major version.”
Mar 18th
Undefined method `load_yaml' for Gem:Module in... →
Also relevant if you’ve upgraded to RubyGems 1.6 from 1.4 or earlier.
Mar 17th
1 tag
Git bisect
I linked to a good article about git bisect recently. I’ve now experimented with it on a project and here’s a few extra pieces I found out: git bisect log shows you the history of the bisect git bisect reset completes the bisect and returns you to HEAD (or whatever commit you specify) git bisect visualize shows the bisect status in gitk (I prefer gitx though) git bisect run...
Mar 16th
2 tags
Uninitialized constant...
So I pulled in some recent changes to a project, ran bundle install, rake db:migrate and then rake db:test:prepare. I was then greeted with the following error: uninitialized constant ActiveSupport::Dependencies::Mutex A quick search provided me with the answer on StackOverflow. Simply upgrade to Rails 2.3.11. The problem was caused by me upgrading to RubyGems 1.6.
Mar 15th
1 tag
Descriptions for capistrano tasks
To see the list of available capistrano tasks, use: cap -T This only shows tasks which have a description. To see the full list of all available capistrano tasks whether or not they have a description, use: cap -vT To get further information about a task, use: cap -e task_name To add a description for a task, use desc above your task block: desc 'Start god if it is not already...
Mar 10th
1 tag
Capistrano Variables
Eric Davis wrote down a handy list of capistrano variables: application - required repository - required scm - defaults to :subversion deploy_via - defaults to :checkout revision - defaults to the latest head version source - Capistrano::Deploy::SCM object real_revision strategy - Capistrano::Deploy::Strategy object defined by deploy_via release_name - timestamp in the form of...
Mar 9th
3 tags
Using namespaced routes with forms
If you have a namespaced route, like admin_post_path, you can’t use the resource-oriented style of form_for: <% form_for @post do |f| %> ... <% end %> You need to do a little bit more work: <% form_for([:admin, @post]) do |f| %> ... <% end %>
Mar 8th
5 notes
2 tags
ActiveResource with a different name
If you need to use a different name for an activeresource, just set the element_name value: class Candidate < ActiveResource::Base self.site = 'http://my_other_app.local' self.element_name = 'users' end
Mar 2nd
February 2011
10 posts
1 tag
Calling cucumber steps with tables
You can easily call other cucumber steps from within other steps. This makes it easy to reuse step definitions. Then /^no users should exist$/ do Then "0 users should exist" end To do this with a cucumber step that takes a table or a multiline string, just pass the table or string as the second argument for the step: Given /^the following users have been assigned to the group$/ do |table| ...
Feb 27th
Rails 3 Validation Shortcut
rubyquicktips: In Rails 2 the only way to add multiple validations to a field is through separate validate statements: validates_presence_of :title validates_length_of :title, :maximum => 30 Rails 3 simplifies this process by adding a method called validates which is a “shortcut to all default validators”. Using the validates method your code will look like this: validates(:title,...
Feb 23rd
12 notes
2 tags
Adjusting pagination size in cucumber tests
Check out my blog post about adjusting the default per_page size of pagination with your cucumber tests to make them faster. I just added a comment to it describing how to effectively turn off pagination for scenarios that require no pagination.
Feb 17th
12 notes
2 tags
Validates presence of booleans
A gotcha that often trips me up - you can’t use the validates_presence_of with a boolean attribute in your rails app. validates_presence_of :paid You need to use validates_inclusion_of. validates_inclusion_of :paid, :in => [true,false] According to the rails api docs, this is due to the way Object#blank? handles boolean values: false.blank? # => true.
Feb 16th
4 notes
1 tag
Clean rspec output
I like my rspec progress dots to remain undisturbed by output generated by the application eg puts, restarting/reindexing sphinx, prince. I use the silence_stream rails kernel method to keep things quiet: silence_stream(STDOUT) { Users.import }
Feb 14th
7 notes
4 tags
Add cucumber to rake stats
I added the following to the statsetup task in rspec.rake inside my rails app: ::STATS_DIRECTORIES << %w( Cucumber\ features features ) if File.exist?('features') ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features') Now when I run rake stats, I get: +----------------------+-------+-------+---------+---------+-----+-------+ | Name | Lines |...
Feb 13th
2 tags
Yielding multiple times
When you need to stub out the values you pass into a block you can use rspec’s and_yield method: sftp_mock.stub_chain(:dir, :foreach).and_yield(entry_1) When you need to pass in values several times you can chain the and_yield: sftp_mock.stub_chain(:dir, :foreach).and_yield(entry_1).and_yield(entry_2) These examples were for spec’ing the behaviour of downloading files from an...
Feb 4th
3 notes
3 tags
Ruby Quicktips: How to check if objects or... →
rubyquicktips: Here’s an interesting fact when checking if objects or relations exist in a collection. To check if there were any items present in a collection you can do something like this: Object.relation.present? This, however, is better: Object.relation.any? Turns out that - when you request…
Feb 3rd
37 notes
2 tags
Silence warnings
If you find that you need to reset the value of a constant in a spec, use the silence_warnings rails method to keep your output quiet: silence_warnings { MY_CONSTANT = "hello" } The times I find I need to modify a constant in a spec is when it is a constant that ought to be modified only for your tests eg a filepath or a pagination value.
Feb 3rd
1 note
January 2011
11 posts
2 tags
Cucumber vs Steak →
I blogged recently about focusing on the behaviour, not the UI when writing Cucumber features. This article I’ve linked too here by Iain Hecker discusses something similar and it explains the reason behind the nagging feeling I’ve had that I wasn’t quite writing cucumber features in the best way. Iain says you should describe what you want to achieve, not how you want to...
Jan 31st
3 tags
Skip automatic time zone conversion
Use the following in your ActiveRecord model when you want to avoid Rails automatically converting your times according to your timezone: def self.skip_time_zone_conversion_for_attributes [:approved_at, :published_at] end Or, for a single attribute: skip_time_zone_conversion_for_attributes << :exposed_at You can also turn off automatic time zone conversion for an entire model: def...
Jan 31st
4 notes
2 tags
Sort vs sort_by
I always forget the difference between Ruby’s sort and sort_by methods. In a nutshell: sort can be used with or without a block the block takes two arguments inside the block you need to use the <=> operator sort_by can only be used with a block the block takes only one argument Generally, you’ll want to use the sort_by method unless your list is a simple one. What I...
Jan 28th
2 tags
Beware of comparing times in Rails
I posed this rails question to my team today: date1 # => Sat, 12 Sep 2009 09:08:33 +0000 date2 # => Sat, 12 Sep 2009 09:08:33 +0000 date1 == date2 # => false So why can this comparison be false? The answer is that the two dates are in fact not identical times. See: date1.to_f # => 1252746513.25 date2.to_f # => 1252746513.75 They both have a decimal component which is...
Jan 27th
1 tag
Access file attributes through Net::SFTP
If you want to access the modification time of a file on a remote server via Net::SFTP, use the following: Net::SFTP.start('sftp.foo.com', 'user', :password => 'pass') do |sftp| sftp.dir.glob('/remote/path', '**/*.rb') do |file| puts file.attributes.mtime end end You can also get these attributes as well: permissions uid gid size atime (time of last access) mtime and atime...
Jan 26th
1 tag
Using a password with Net::SFTP
To ignore your private key when trying to make an sftp connection using a password with Net::SFTP, specify only the password authentication method like so: Net::SFTP.start('sftp.foo.com', 'user', :password => 'pass', :auth_methods => ["password"]) do |sftp| # do stuff end
Jan 24th
1 note
2 tags
Lock the screen on a Mac
For quite a while there wasn’t a simple keyboard shortcut for locking your Mac’s screen. Now all you need to do is: CTRL + SHIFT + EJECT
Jan 20th
2 notes
1 tag
Shallow clones with git
In setting up a continuous integration server I discovered this command: git clone --branch #{git_branch} --depth 1 #{git_repo} Using the —depth option and setting it to 1 creates a shallow clone of your git repo. It basically truncates your history to the specified number of revisions. For something like CI servers (and possibly production servers) you don’t need full history,...
Jan 19th
2 tags
PDF generation with princely under Ruby 1.9
Under Ruby 1.9, princely fails to generate a pdf with the following error: ArgumentError (invalid byte sequence in UTF-8) The solution seems to be forcing binary encoding of the data you pass into the send_data method used by princely: def make_and_send_pdf(pdf_name, options = {}) send_data( make_pdf(options).force_encoding('BINARY'), :filename => pdf_name + ".pdf", :type...
Jan 13th
4 tags
CSV and FasterCSV with Ruby 1.8 and 1.9
In upgrading a Rails 2.3 app from Ruby 1.8 to 1.9, I had to cope with FasterCSV becoming the new CSV library. It simply meant replacing all references I had to FasterCSV with just CSV. This works well but I wanted to maintain backwards compatibility with Ruby 1.8 (at least for the short term) so I also did the following: In my Gemfile, I instruct bundler to include the fastercsv gem only if the...
Jan 11th
1 tag
RSpec presentation by Kerry Buckley →
Jan 7th