Bash Cheat Sheet (standard Emacs mode)
-
Ctrl + R Search commands you entered previously. Press Ctrl + R again to search further back, Ctrl + Shift + R searches forward again.
-
Ctrl + W Deletes from the cursor position to the left.
-
Ctrl + _ Undo. Yes, this also works with a German keyboard layout.
-
Ctrl + L Clear screen.
-
Ctrl + D _Close shell. (EOT, just like in many other shells.) Note: if you dove into another shell (e.g. with
sudo su username
) you will close it and return to ...
Standalone Cucumber Test Suite
Sometimes you inherit a non Rails or non Rack based web app such as PHP, Perl, Java / JEE, etc. I like using cucumber for functional testing so I put together this project structure to use as a starting point for testing non Ruby web based applications.
Request a non-HTML format in controller specs
If a controller action responds to other formats than HTML (XML, PDF, Excel, JSON, ...), you can reach that code in a controller spec like this:
describe UsersController do
describe '#index' do
it 'should be able to send an excel file' do
# stubs and expectations go here
get :index, :format => 'xls'
end
end
end
Remember that both the :format
parameter and the HTTP_ACCEPT
header can m...
Migrating to RSpec 2 from RSpec 1
You will need to upgrade to RSpec >= 2 and rspec-rails >= 2 for Rails 3. Here are some hints to get started:
- In RSpec 2 the executable is
rspec
, notspec
. - RSpec and rspec-rails have been completely refactored internally. All RSpec classes have been renamed from
Spec::Something
toRSpec::Something
. This also means that everyrequire 'spec/something'
must now berequire 'rspec/something'
. - In
spec_helper.rb
,Spec::Runner.configure
becomesRSpec.configure
- It has become really hard to extend specific example groups ...
Getting your e-mails back after upgrading Thunderbird to version 3
If you previously used version 2.x of Thunderbird and upgraded to 3.x (for example through an Ubuntu release upgrade) you might notice that Thunderbird will not show any of your old e-mails or settings.
This results from a different directory being used for storing profiles and configuration.
You can replace the blank profile with your old one like this:
cd ~
mv .thunderbird .thunderbird-invalid
cp -R .mozilla-thunderbird .thunderbird
Upon its next start, Thunderbird brings up the migration wizard introducing you to a few vers...
Force RubyMine to notice file system changes
If you did file operations inside a shell or for example using Nautilus, it can take quite a while until RubyMine takes note of them and updates things like your project tree or its internal file list.
Flushing file system buffers helps you out (run it from a terminal):
sync
This is also possibly via the RubyMine menus: File → Synchronize.
Setting nil values in Machinist blueprints
Take care when trying to set attributes to nil
in a blueprint.
Given the following master blueprint:
Story.blueprint do
title
author { User.make }
editor { User.make }
end
This approach will not overwrite/remove the editor
defined in the master blueprint:
Story.blueprint(:draft) do
editor nil
end
...whereas this one will (note the lambda):
Story.blueprint(:draft) do
editor { nil }
end
Match strings in a given order with Cucumber and Capybara
Sometimes the order in which strings appear on a page matters to you.
Spreewald gives you steps like these:
Then I should see in this order:
| Alpha Group |
| Augsburg |
| Berlin |
| Beta Group |
Or, if you prefer multiline strings:
Then I should see in this order:
"""
Alpha Group
Augsburg
Berlin
Beta Group
"""
The step ignores all HTML tags and only tests on plain text.
Machinist: Refer to another named blueprint inside a blueprint
Note: We are talking about Machinist 1 here, Machinist 2 may have solved this or might require a different approach.
Machinist allows named blueprints (e.g. User.blueprint(:admin)
) that inherit from the master blueprint (User.blueprint
).
If you also want to inherit from another blueprint (e.g. if "vip" should load "premium" and the master blueprint) you can do this:
User.blueprint(:vip) do
# Fields for the vip blueprint go her...
MySQL: Disable query cache for database profiling
If you want to see how long your database queries actually take, you need to disable MySQL's query cache. This can be done globally by logging into a database console, run
SET GLOBAL query_cache_type=OFF;
and restart your rails server.
You can also disable the cache on a per query basis by saying
SELECT SQL_NO_CACHE * FROM ...
You also probably want to disable Rails internal (per-request) cache. For this, wrap your code with a call to ActiveRecord::Base.uncached
. For example, as an around_filter
:
d...
Even with bundler your gem order can be significant
Even when you're using bundler, it might be significant in which order your gems are listed in your Gemfile
. This can happen when gems are running around calling require
or require_dependency
on other gems or application classes when loaded (don't do that!).
A known culprit of this is the (otherwise wonderful) resource_controller gem, which requires ApplicationController
when loaded. When your ApplicationController
requires later-loaded gems when loaded, Rails will not boot.
He...
Taking advantage of RSpec's "let" in before blocks
Inside before
:each
blocks you can refer to variables that you introduce via let
later on.
They do not need to be defined ahead of your before block and can be different for individual sections.
It works just like that:
describe User do
describe '#locked?' do
before :each do
subject.should_receive(:current_plan).and_return plan
end
context 'when expiring today' do
let(:plan) { stub(:expiry => Date.today) }
it 'should be false' do
subject....
Kill a dead SSH shell
If a SSH shell dies (from timeout for example), you cannot kill it with the usual CTRL-C
or CTRL-Z
. Instead, press
[ENTER]~.
(That is ENTER TILDE PERIOD
).
Cucumber step to match table rows with Capybara
These steps are now part of Spreewald.
This note describes a Cucumber step that lets you write this:
Then I should see a table with the following rows:
| Bruce Wayne | Employee | 1972 |
| Harleen Quinzel | HR | 1982 |
| Alfred Pennyworth | Engineering | 1943 |
If there are additional columns or rows in the table that are not explicitely expected, the step won't complain. It does however expect the rows to be ordered as stat...
Be careful with Array(...)
A popular ruby idiom I keep stumbling upon is
def do_some_thing_for(values)
values = Array(values)
values.each { ... }
end
The intent is to allow the user to pass in arrays as well as scalar values, since
Array("foo") == ["foo"]
Array(["foo", "bar"]) == ["foo", "bar"]
But Array()
actually calls to_a
on its arguments, which may not always do what you expect. For example
Array("foo \n bar") == ["foo \n", "bar"]
Reload the page in your Cucumber features
Both these approaches will keep your GET
parameters -- and will only work for GET
requests.
-
Capybara:
When /^I reload the page$/ do visit [ current_path, page.driver.request.env['QUERY_STRING'] ].reject(&:blank?).join('?') end
-
Webrat:
When /^I reload the page$/ do visit url_for(request.params) end
For a step that distinguishes between drivers (Selenium, Rack::Test, Culerity), check [n4k3d.com](http://n4k3d.com/blog/2011/02/02/reloading-the-page-in-cucumber-with-capybara-and-seleniu...
RSpec's context method is broken
RSpec's context
(which is basically an alias for describe
) takes over your whole application. No object may have its own context
method, or you will always receive errors like
"No description supplied for example group declared on ~/project/app/..."
The easiest workarounds:
- do not name any method
context
- use
describe
instead ofcontext
in your specs, and put this into yourspec_helper.rb
:\
Spec::DSL::Main.class_eval do
if method_defined? :context
undef :context
end
end
Save ActiveRecord models without callbacks or validations (in Rails 2 and Rails 3)
Rails 2
You can use
record.send(:update_without_callbacks)
or
record.send(:create_without_callbacks)
This can be used as a lightweight alternative to machinist's make
or FactoryGirl's create
, when you just need objects in the database but don't care about any callbacks or validations. Note that create_without_callbacks
does not return the object, so you might want to do
record = Record.new.tap(&:create_without_callbacks)
Rails 3
Rails 3 no longer comes with update_without_callbacks
or `crea...
Fix permissions of temporary RTeX files (which are group and world-readable)
We use RTeX for PDF exports.
While converting LaTeX to PDF, RTeX opens a temporary file which has problematic permissions: Both group and world can read those files.
Although the temp files should go away they sometimes live longer than one would expect.
We patched RTeX to fix this (and have more secure permissions). Place the code below into config/initializers/rtex.rb
Recent RSpec features you might not know about
With its
you can switch the subject of an example to a method value of the current subject:
describe Array do
its(:length) { should == 0 }
end
stub_chain
is the tie to go along with should_receive_chain's tux:
object.stub_chain(:first, :second, :third).and_return(:this)
You can restore the original implementation of stubbed methods with unstub
:
object.stub(:foo => 'bar')
# ...
object.unstub(:foo)
In recent RSpecs ...
Security issues with hash conditions in Rails 2 and Rails 3
Find conditions for scopes can be given either as an array (:conditions => ['state = ?', 'draft']
) or a hash (:conditions => { 'state' => 'draft' }
). The later is nicer to read, but has horrible security implications in some versions of Ruby on Rails.
Affected versions
Version | Affected? | Remedy |
---|---|---|
2.3.18 | yes | Use chain_safely workaround |
3.0.20 | no | ... |
Run a rake task in all environments
Use like this:
power-rake db:migrate VERSION=20100913132321
By default the environments development
, test
, cucumber
and performance
are considered. The script will not run rake on a production
or staging
environment.
This script is part of our geordi gem on github.
Run a single example group in RSpec
To only run a single describe
/context
block in a long spec, you can say
spec spec/models/note_spec.rb:545
... where the describe
block starts at line 545.
Note: This will only run examples that are direct children of this block, not descendants further down (when nesting describe
/context
blocks).
You may also pass the line of an it
block to run this exact one.
Ruby: How to collect a Hash from an Array
There are many different methods that allow mapping an Array to a Hash in Ruby.
Array#to_h
with a block (Ruby 2.6+)
You can call an array with a block that is called with each element. The block must return a [key, value]
tuple.
This is useful if both the hash key and value can be derived from each array element:
users = User.all
user_names_by_id = users.to_h { |user| [user.id, user.name] }
{
1 => "Alice",
2 => "Bob"
}
Array#to_h
on an array of key/value tuples (Ruby 2.1+)
Converts an Array ...