Automatically run bundle exec if required
There will probably be better solutions as we become more experienced with using Bundler, and more command line tools become Bundler-aware.
b
will use bundle exec
if there is a Gemfile
in the working directory, and run the call without Bundler otherwise.
b spec spec
This script is part of our geordi gem on github.
Airbrake notification in Rake tasks
Put
def task_with_hoptoad_notification(options)
task(options) do
begin
yield
rescue Exception => e
Airbrake.notify(e)
raise e
end
end
end
at the top of the Rakefile, and replace all relevant
task :my_task => :environment do
do_something
end
with
task_with_hoptoad_notification :my_task => :environment do
do_something
end
This will use the usual notification rules, i.e. you won't get anything in the development or test environments.
...
Bundler for Rails 2.3.x
Update RubyGems and Passenger
Bundler requires Rubygems >= 1.3.6. Run gem update --system
if you have an older version.
It also is not compatible with older versions of passenger, so bring that up to date as well (2.2.15 works).
If you installed RubyGems through apt (which you should never do!), you may see a message giving you a hint to use apt to update.
Some people advise to install the 'rubygems-update-1.3.7' gem on Ubuntu systems if you used apt to install RubyGems.
I did that - and lost all...
Rails: Preloading associations in loaded records
Sometimes you want to fetch associations for an ActiveRecord that you already loaded, e.g. when it has deeply nested associations.
Edge Rider gives your models a static method preload_associations
. The method can be used to preload associations for loaded objects like this:
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
@user.preload_associations(threads: { posts: :author }, messages: :sender)
end
end
The attached initializers re...
Defining custom RSpec matchers
There are three ways to define your own RSpec matchers, with increasing complexibility and options:
1) Use RSpec::Matchers.define
RSpec::Matchers.define :be_a_multiple_of do |expected|
match do |actual|
actual % expected == 0
end
# optional
failure_message do |actual|
"expected that #{actual} would be a multiple of #{expected}"
end
# optional
failure_message_when_negated do |actual|
"expected that #{actual} would not be a multiple of #{expected}"
end
end
- This is automatically available i...
Efficiently add an event listener to many elements
When you need to add a event listener to hundreds of elements, this might slow down the browser.
An alternative is to register an event listener at the root of the DOM tree (document
). Then wait for events to bubble up and check whether the triggering element (event.target
) matches the selector before you run your callback.
This technique is called event delegation.
Performance considerations
Because you only register a single listener, registering is ...
InfoQ: How to Design a Good API & Why it Matters
A well-written API can be a great asset to the organization that wrote it and to all that use it. Given the importance of good API design, surprisingly little has been written on the subject. In this talk (recorded at Javapolis), Java library designer Joshua Bloch teaches how to design good APIs, with many examples of what good and bad APIs look like.
Spec correct routing of custom URLs
When you roll custom URLs with hacks like routing-filter, you can put a spec like this into spec/routing/routing_spec.rb
:
Test e-mail dispatch in Cucumber
Spreewald has steps that let you test that e-mails have been sent, using arbitrary conditions in any combination.
The attached file is for legacy purposes only.
Testing validates_format_of with Shoulda matchers
Don't use should validate_format_of(...)
because that matcher works in weird ways. Use the allow_value
matcher instead:
describe Email, '#sender' do
# > Rspec 3 should syntax
it { should allow_value("email@addresse.foo").for(:sender) }
it { should_not allow_value("foo").for(:sender) }
# Rspec 3 expect syntax
it { is_expected.to allow_value("email@addresse.foo").for(:sender) }
it { is_expected.not_to allow_value("foo").for(:sender) }
end
Errors that may occur if you do use should validate_format_of(...)
:
...
Regular Expressions - Cheat Sheet
You can write regular expressions some different ways, e.g. /regex/
and %r{regex}
. For examples, look here.
Remember that it is always a good idea to match a regex visually first.
Characters
Literal Characters
[ ] \ ^ $ . | ? * + ( )
Character Classes
[ae] matches a and e, e.g. gr[ae]y => grey or gray => but NOT graay or graey
[0-9] ...
Multi-line step arguments in Cucumber
The following example is from the Cucumber wiki:
Given a blog post named "Random" with Markdown body
"""
Some Title, Eh?
==============
Here is the first paragraph of my blog post. Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
"""
That multi-line string will be given as the last block argument in your step definitions:
Given /^a blog post named "([^\"]*)" with Markdown body$/ do |title, markdown|
Post.create!(:title =...
rspec_candy is now a gem
Our awesome collection of rspec helpers (formerly known as "spec_candy.rb") is now available as a gem. It works, it is tested and there will be updates.
Usage
Add rspec_candy
to your Gemfile.
Add require 'rspec_candy/helpers'
to your spec_helper.rb, after the rspec requires.
List of features
Faking and testing the network with WebMock
An alternative to this technique is using VCR. VCR allows you to record and replay real HTTP responses, saving you the effort to stub out request/response cycles in close details. If your tests do require close inspection of requests and responses, Webmock is still the way.
WebMock is an alternative to FakeWeb when testing code that uses the network. You sh...
Forward HTTP through an intermediary server (Local Port Forwarding)
This will tunnel HTTP requests to one given domain and port through an intermediary SSH server:
ssh -L 8080:targethost:80 tunnelhost
http://localhost:8080 will now connect you to http://targethost:80, tunnelling all data through tunnelhost
via SSH.
Note that the connection between tunnelhost and targethost will still be unencrypted in this example.
Submit a form with Prototype
For example, to send a form and populate a preview div with the response.
$('content_form').request({
parameters: { 'preview': "1" }, // overrides parameters
onComplete: function(transport){
$('previewContent').update(transport.responseText);
}
});
Fixing Webrat after following an external link
When a Cucumber feature leaves your page through an external Link, Webrat has problems like "Could not find field: "E-mail" (Webrat::NotFoundError)
" using your page afterwards. It will also have trouble following redirects.
Fix it with this step:
Given /^I am back on my page$/ do
webrat_session.header("Host", "www.example.com")
end
MySQL replication how-to
This may be awkward to set up, but will work once you're done.
Fun facts:
- In case of a connection loss the slave will try to reconnect to the master server and resume replication for the next 24 hours
- If you want to use your slave as a "real" MySQL server, you basically need to switch off replication (
STOP SLAVE; RESET SLAVE;
and reset your my.cnf) and restart the MySQL daemon.
Master server configuration
-
- Create replication user
- In the MySQL shell:
CREATE USER 'replicator'@'%' IDENTI...
Cucumber Webrat steps
Most of these will not work in newer projects because these use the Capybara/Rack::Test combo in lieu of Webrat.
Find input fields
Then /^there should be a "([^"]+)" field$/ do |name|
lambda { webrat.current_scope.send(:locate_field, name) }.should_not raise_error(Webrat::NotFoundError)
end
Then /^there should be no "([^"]+)" field$/ do |name|
lambda { webrat.current_scope.send(:locate_field, name) }.should raise_error(Webrat::NotFoundError)
end
Find html content
Then /^I should see "([^\"]*)...
Aggregated RSpec/Cucumber test coverage with RCov
With defaults, RCov doesn't work the way you how you would like it to. To create a nice test coverage report, copy the attached file to lib/tasks/rcov.rake
. After that rake rcov:all
will run all RSpec examples and Cucumber features. The report will be written RAILS_ROOT/coverage/index.html
.
Here is what the task does in detail:
- Generates aggregated coverage of both RSpec and Cucumber
- Works with Rails 2 and Rails 3
- Reports for
app/**/*.rb
and nothing else - If called with an environment variable
IGNORE_SHARED_TRAITS=true
it ...
Better output for Cucumber
We built cucumber_spinner to have a progress bar for Cucumber features, which also outputs failing scenarios as soon as they fail.
Installation
gem install cucumber_spinner
Usage
cucumber --format CucumberSpinner::ProgressBarFormatter
If you use CucumberSpinner::CuriousProgressBarFormatter
and a feature fails, the according page will show up in your browser.
Note that if you run your Cucumber tests using the [cuc
](https://makandracards.com/makandra/1277-a-nicer-way-to-...
Test concurrent Ruby code
To test concurrent code, you will need to run multiple threads. Unfortunately, when you use blocking system calls (e.g. locks on the database), Ruby 1.8 threads won't work because system calls will block the whole interpreter.
Luckily you can use processes instead. fork
spins off a new process, IO.pipe
sends messages between processes, Process.exit!
kills the current process. You will need to take care of ActiveRecord database connections.
Here is a full-fledged example:
describe Lock, '.acquire' do
before :each do
...
Better Output for RSpec
rspec_spinner is a progress bar for RSpec which outputs failing examples as they happen (instead of all at the end).
Installation
gem install rspec_spinner
Usage
script/spec -r rspec_spinner -f RspecSpinner::Bar -c
To make a shortcut in your .bashrc
alias ss='script/spec -r rspec_spinner -f RspecSpinner::Bar -c'
There's also an alternate runner RSpecSpinner::Spinner
which shows a spinner and the name of the current spec instead of a progress bar.