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...
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')"
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...
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...
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...
3 tags
Bundler’s Best Kept Secret (bundle viz) →
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.
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...
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...
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
April 2011
2 posts
How to Name Gems →
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
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
Bundler Best Practices →
1 tag
Pairing tete-a-tete →
1 tag
Extreme Pairing →
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.
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...
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 # =>...
1 tag
Rails ERD – Entity-Relationship Diagrams for Rails →
Back in the day I had used railroad.
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.
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.
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.”
Undefined method `load_yaml' for Gem:Module in... →
Also relevant if you’ve upgraded to RubyGems 1.6 from 1.4 or earlier.
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...
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.
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...
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...
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 %>
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
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|
...
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,...
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.
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.
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 }
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 |...
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...
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…
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.
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...
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...
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...
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...
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...
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
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
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,...
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...
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...
1 tag
RSpec presentation by Kerry Buckley →