Semantic markup standard for search engines
If you would like to enrich your website with semantic markup like contact data, places or events you should have a look at schema.org. "Search engines including Bing, Google and Yahoo! rely on this markup to improve the display of search results, making it easier for people to find the right web pages."
The following example from the schema.org documentation shows you how to describe a movie with semantic markup:
<div itemscope itemtype ="http://schema.org/Movie">
<h1 itemp...
Matching elements on complex web pages with Webrat
XPath matchers can be combined with CSS-selector matchers. This is really useful if not, for example, the content of an element should be matched but the element itself like in the following example. Here a form is used to display data as default value in its input elements. This can be the case in web applications in which data should be edited easily without additional clicks.
Execution of shell code in Ruby scripts
Deprecated ways to execute shell code in Ruby
This is just a reference for legacy code. For new code, always use capture3
.
%x{ } or backticks – quick and easy
Returns the standard output of running the given command in a subshell. This is an alias for `...`, and you can use string interpolation.
Example:
name = 'ls'
result = `which #{name}`
It does not escape anything you inject in the string, so be aware of possible security vulnerabilities...
Defining host aliases in your SSH config
You probably already manage servers you often connect to inside the ~/.ssh/config
file. What is nice: you may define alias names for hosts so that you can say something like ssh foobar-staging
.
This is especially helpful for servers whose hostnames are hard to remember or who don't have a DNS record at all (and must be accessed via their IP address).
To achieve the above, you can define something like this in your ~/.ssh/config
:
Host foobar-staging
Hostname staging.example.com
Note that SSH will only match this for `ssh f...
How to employ and run your tests with parallel_tests to speed up test execution
When your cucumber features grow massively over time, the test execution can take a lot of time.
One easy way to speed up your test execution is to use the parallel_tests gem.
It comes along with some useful rake tasks that let you setup your local test environment shortly to run your features, specs or unit-tests in parallel.
Follow these steps to get it to work.
-
Add the parallel_tests gem to your
Gemfile
test sections like that:# ./Gemfile group :development, :test do
...
ActiveSupport::StringInquirer
Wrapping a string in this class gives you a prettier way to test for equality.
Test that a number or money amount is shown with Cucumber
This is an awful way to test whether a number is shown on the screen:
Then I should see "5"
It is awful because the step above is green for 5, 5123 and -51.
This step definition below makes sure this doesn't happen. You can use it like this:
Then I should see the number 5
The step also works if you you'd like to test that the number is followed by a unit:
Then I should see the amount 5 €
The separator between the number and its unit is allowed to be either a space or a [nbsp](https://makandracards.com/makandra/838-generate...
Don't call #node on a Capybara element
Capybara allows you to select DOM elements, e.g. by using field
, find_field(...)
or field_labeled(...)
:
role_select = field_labeled('Role')
In the example above, role_select
is now a Capybara::Driver::Node
. You can call a number of methods on such a node, e. g. in order to click it or to make a selection on its descendants. These methods should be the same regardless of the driver Capybara is using (drivers are e.g. the headless Rack::Test or Selenium).
It i...
Cucumber steps to travel through time with Timecop
These steps are now part of Spreewald.
Here are some useful examples how to use the attached Cucumber Timecop steps:
When the date is 2011-05-06
When the time is 2011-05-06 17:30
There is also one really awesome step that lets you travel to the past or to the future:
When /^it is (\d+|a|some) (seconds?|minutes?|hours?|days?|months?|years?) (later|earlier)$/
As yo...
Don't define a controller action called #process
Remember that your controller actions share the same method space with private methods defined in ActionController::Base
. If your controller behaves in super-weird ways, check that you don't overwrite some internal method with a controller action.
Examples for internal methods:
#process
#process_action
#cookies
#params
#request
#response
Debugging
If you accidentally did overwrite some internal method, you may come across an ArgumentError
with the message `wrong number of arguments (given 1, expe...
Fix randomly failing PDF cucumber tests
Sometimes PDF cucumber tests fail at the first test run and succeed at the second run. You can fix this with this step:
When PDF generation is ready
And I follow "Save as PDF"
# Checks for PDF contents go here
Here is the step definition:
When /^PDF generation is ready$/ do
Then 'I should see ""'
end
Conditional comments for Internet Explorer with Haml
Internet Explorer 5+ is aware of conditional comments that let you target HTML for selected versions of IE. For example the HTML below would ask users of IE 6 and IE 7 to install Firefox:
<!--[if lt IE 8]>
<a href='http://www.mozilla.com/en-US/firefox/'>Get a real browser</a>
<![endif]-->
You might wonder how to express such a conditional comment in your favorite templating language, Haml. You might even have converted a template back to ERB just for this ...
Split an array into columns
You know that you can collect an array as groups using in_groups
or in_groups_of
.
Maybe you want to fetch those values in "columns" where the first value lives in the first column, the second one in the second, etc. until it wraps, so that for example the fourth value is in the first of three columns.
Put the attached file into config/initializers/
to be able to say in_columns
on any Array
:
>> [1, 2, 3, 4, 5, 6, 7].in_columns(3)
=> [[1, 4, 7], [2, 5], [...
Bash script to run specs and features
Run rspec-and-cucumber
from any project directory to run both RSpec and Cucumber. If available, rspec_spinner or cucumber_spinner are used.
Note that features are not run when specs fail.\
If you prefer to run them in parallel or run features regardless of the spec results, please adjust it for yourself accordingly.
This script is part of our geordi gem on github.
Using QEMU to quickly test an ISO or bootable USB drive
When you want to quickly boot from a drive or image in a virtual machine you do not need to setup up a VirtualBox machine. Often QEMU does the job well enough.
Install it:
sudo apt-get install qemu
To boot an ISO:
qemu-system-x86_64 -cdrom filename.iso
If you prepared a USB pen drive and want to test it, run it like this (/dev/sdx
being your device name; you may need to sudo
to access it):
qemu-system-x86_64 -hda /dev/sdx
Be aware that not everything runs smoothly in QEMU -- you might need to set up a _VirtualBox...
Validations on associated objects
Validations that need to access an associated object may lead to some trouble. Let's exemplify that using this example:
class Project < ActiveRecord::Base
has_one :note
end
class Note < ActiveRecord::Base
belongs_to :project
end
Now say we need a validation that ensures that a description is set (validates_presence_of :description) within Note
but only if the Project
has a flag called external
set to true. The following code will lead to some problems as the associated object is not present when creatin...
How DECIMAL columns deal with numbers exceeding their precision or scale
When storing floating-point numbers such as prices or totals in an SQL database, always use a DECIMAL
column. Never use FLOAT
or kittens will die.
DECIMAL
columns are parametrized with a precision and a scale. These parameters describe which numbers can be stored in that column. E.g. a decimal with a precision of 5 and a scale of 2 can store numbers from -999.99
to 999.99
, but not 1000
or 1.234
.
This card explains what various databases do when you try to store a number in a DECIMAL
field, and that number exceeds that colum...
Why preloading associations "randomly" uses joined tables or multiple queries
ActiveRecord gives you the :include
option to load records and their associations in a fixed number of queries. This is called preloading or eager loading associations. By preloading associations you can prevent the n+1 query problem that slows down a many index view.
You might have noticed that using :include
randomly seems to do one of the following:
- Execute one query per involved table with a condit...
Cast a string to the type of an ActiveRecord attribute
ActiveRecord models know how to cast a given string to the type of a given attribute (or column).
The following model will serve as our example:
create_table :notes do |t|
t.string :title
t.integer :user_id
t.boolean :deleted
end
You can make the Note
class cast strings into their respective types like this:
Note.columns_hash['user_id'].type_cast('123') # => 123
Note.columns_hash['deleted'].type_cast('1') # => true
Note.columns_hash['deleted'].type_cast('0') # => false
How to send HTTP requests using cURL
-
Reading a URL via GET:
curl http://example.com/
-
Defining any HTTP method (like POST or PUT):
curl http://example.com/users/1 -XPUT
-
Sending data with a request:
curl http://example.com/users -d"first_name=Bruce&last_name=Wayne"
If you use
-d
and do not set an HTTP request method it automatically defaults to POST. -
Performing basic authentication:
curl http://user:password@example.com/users/1
-
All together now:
curl http://user:password@example.com/users/1 -XPUT -d"screen_name=batman"
...
How to perform HTTP basic authentication in RSpec
The Basic Authentication header encodes username and password. Effectively, it's just Base64 plus a "Basic
" prefix.
You can use ActionController::HttpAuthentication::Basic.encode_credentials
for that, and put its result into the Authorization
request header.
Request specs
For request specs, use the :header
option.
it 'requires authentication' do
get '/'
expect(response.status).to eq(401)
end
it 'accepts valid credentials' do
encoded_credentials = ActionController::HttpAuthentication::Basic.encode_credentials(use...
Default views in Rails 3.0 with custom resolvers
It is common in Rails 3.0 applications that you want to provide default views for a group of controllers. Let’s say you have a bunch of controllers inside the Admin namespace and you would like each action to fallback to a default template. So if you are rendering the index action for Admin::PostsController and “app/views/admin/posts/index.html.*” is not available, it should then render “app/views/admin/defaults/index.html”.
Since Rails 3.0, we have a new abstraction called resolvers that holds the logic to find a template.
How to send a test e-mail from shell
If you want to manually check if e-mail delivery works on a machine by sending an e-mail you can run the following:
mail -s Test someone@example.com < /dev/null
This will send an empty e-mail with "Test" as its subject to someone@example.com
.
If you want it to contain a message body, call mail -s Test someone@example.com
only; the mail
application will then read your input from stdin. Finish your message by sending EOT with Ctrl-D -- if you are asked for anything else ...
Imperative vs Declarative Scenarios in User Stories
Bryan talked about the differences between imperative and declarative scenarios. In my opinion, both styles have benefits and should be used appropriately based on the situation. The majority of examples on rspec's story runner currently on the web, including mine, are of the imperative type. Since the declarative type has many advantages I thought it would be worth while to present some examples and contrast the differences between the two styles.