News flash: Absolute CSS positioning on opposite sides is not a problem

Back in the old days, we couldn't do something like that:

.foo {
  position: absolute;
  bottom: 0;
  /* This was bad: */
  left: 10px;
  right: 10px;
}

Why? Because IE5 and IE6 (which a majority of people used back then) failed horribly trying to render it.

I've now checked if this is still an issue with any browser that's not from the stone age. \
Turns out all is well -- except if you have to support IE6 and below, but then you're in some other kinds of trouble.

It works in all sane browsers, and Internet Explorer 7, 8...

How to clear cookies in Capybara tests (both Selenium and Rack::Test)

Capybara drivers will usually delete all cookies after each scenario. If you need to lose cookie data in the middle of a scenario, you can do this:

browser = Capybara.current_session.driver.browser
if browser.respond_to?(:clear_cookies)
  # Rack::MockSession
  browser.clear_cookies
elsif browser.respond_to?(:manage) and browser.manage.respond_to?(:delete_all_cookies)
  # Selenium::WebDriver
  browser.manage.delete_all_cookies
else
  raise "Don't know how to clear cookies. Weird driver?"
end

Duplicate a git repository with all branches and tags

In order to clone a git repository including all branches and tags you need to use two parameters when cloning the old and pushing to the new repository respectively:

git clone --bare http://example.com/old-repo.git
cd old-repo
git push --mirror http://example.com/new-repo.git

Of course, the URLs to your repository might look different depending on the protocol used, username required, etc.
For a user git using the git protocol, it could be git@example.com:repository-namespace/repository.git

How to find out which type of Spec you are

When you need to find out in which kind of spec you are during run-time, it's definitely possible. It's a lot easier in RSpec 2+.

For example, consider this global before block where you'd want to run some code for specific specs only:

config.before do
  # stuff
  that_fancy_method
  # more stuff
end

RSpec 2+

If you want to run such a block for a specific type of specs, you can use filters:

config.before do
  # stuff
  # more stuff
end

config.before :type =...

How to find out if you are in Cucumber or in RSpec

Sometimes you need a piece of code to do something different for specs than for features. If you don't have separate environments, you can't check your Rails.env.

I managed to distinguish between specs and features by asking Capybara.

Note that this only works when you do not use Capybara in specs.

if defined?(Capybara) and Capybara.respond_to?(:current_driver)
  # you're in a Cucumber scenario
else
  # you're probably in a spec
end

You could omit the defined?(Capybara) condition, if you are sure that Capybara...

Browsers will not send a referrer when linking from HTTPS to HTTP

  • When your site is on HTTPS and you are linking or redirecting to a HTTP site, the browser will not send a referrer.
  • This means the target site will see your traffic as "direct traffic", i.e. they cannot distinguish such hits from a user who directly typed in the URL.

Reasons for this behavior

It's probably because of this RFC:

Clients SHOULD NOT include a Referer header field in a (non-secure) HTTP request if the referring page was transferr...

Quick git contributors list

git shortlog -s -n [commit-range]

-n, --numbered
Sort output according to the number of commits per author

-s, --summary
Suppress commit descriptions, only provide commit count

[commit-range]
E.g. $tagname.. for "everything after that tag"

Example output for spreewald:

60  Tobias Kraze
12  Henning Koch
 7  Dominik Schöler
 6  Thomas Eisenbarth
 5  Martin Straub
 3  Minh Hemmer
 2  Alex McHale
 1  Manuel Kallenbach
 1  Andreas Robecke

#...

Good real world example for form models / presenters in Rails

We have often felt the pain where our models need to serve too many masters. E.g. we are adding a lot of logic and callbacks for a particular form screen, but then the model becomes a pain in tests, where all those callbacks just get in the way. Or we have different forms for the same model but they need to behave very differently (e.g. admin user form vs. public sign up form).

There are many approaches that promise help. They have many names: DCI, presenters, exhibits, form models, view models, etc.

Unfortunately most of these approaches ...

Pitfall: ActiveRecord callbacks: Method call with multiple conditions

In the following example the method update_offices_people_count won't be called when office_id changes, because it gets overwritten by the second line:

after_save :update_offices_people_count, :if => :office_id_changed? # is overwritten …
after_save :update_offices_people_count, :if => :trashed_changed? # … by this line

Instead write:

after_save :update_offices_people_count, :if => :office_people_count_needs_update?

private

def office_people_count_needs_update?
  office_id_changed? || trashed_changed?
end

Or...

OpenStack instance not configuring network (DHCP) correctly

We ran into trouble when adding additional compute units to our railscomplete Hosting environment lately.

VM-instances on the new compute units where booting and requesting private IP addresses via DHCP correctly (DHCPDiscover), but after the answer of the dnsmasq dhcp server (DHCPOffer) we did not see any further traffic on the host machine. FYI: The instance should request the IP via DHCPRequest which in turn should be acknowledged by a DHCPAcknowledgment packet.

We assumed this DHCP UDP traffic did not...

How to discard a surrounding Bundler environment

tl;dr: Ruby's Bundler environment is passed on to system calls, which may not be what you may want as it changes gem and binary lookup. Use Bundler.with_original_env to restore the environment's state before Bundler was launched. Do this whenever you want to execute shell commands inside other bundles.

Example outline

Consider this setup:

my_project/Gemfile     # says: gem 'rails', '~> 3.0.0'
my_project/foo/Gemfile # says: gem 'rails', '~> 3.2.0'

And, just to confirm this, these are the installed Rails versions for each ...

How to write complex migrations in Rails

Rails gives you migrations to change your database schema with simple commands like add_column or update.
Unfortunately these commands are simply not expressive enough to handle complex cases.

This card outlines three different techniques you can use to describe nontrivial migrations in Rails / ActiveRecord.

Note that the techniques below should serve you well for tables with many thousand rows. Once your database tables grows to millions of rows, migration performance becomes an iss...

ActiveRecord: Passing an empty array into NOT IN will return no records

Caution when using .where to exclude records from a scope like this:

# Fragile - avoid
User.where("id NOT IN (?)", excluded_ids)

When the exclusion list is empty, you would expect this to return all records. However, this is not what happens:

# Broken example
User.where("id NOT IN (?)", []).to_sql
=>  SELECT `users`.* FROM `users` WHERE (id NOT IN (NULL))

Passing an empty exclusion list returns no records at all! See below for better implementations.

Rails 4+

Use the .not method to let Rails do the logic

`...

How to access your Rails session ID

This only works when you actually have a session ID (not the case for Rails' CookieStore, for example):

request.session_options[:id]
# => "142b17ab075e71f2a2e2543c6ae34b94"

Note that it's a bad idea to expose your session ID, so be careful what you use this for.

Controller specs do not persist the Rails session across requests of the same spec

In specs, the session never persists but is always a new object for each request. Data put into the session in a previous request is lost. Here is how to circumvent that.

What's going on?

You are making ActionController::TestRequests in your specs, and their #initialize method does this:

self.session = TestSession.new

This means that each time you say something like "get :index", the session in your controller will just be a new one, and you won't see ...

Rails: Overwriting default accessors

All columns of a model's database table are automagically available through accessors on the Active Record object.

When you need to specialize this behavior, you may override the default accessors (using the same name as the attribute) and simply call the original implementation with a modified value. Example:

class Poet < ApplicationRecord

  def name=(value)
    super(value.strip)
  end

end

Note that you can also avoid the original setter and directly read/write from/to the instance's attribute storage. However this is dis...

parallel_tests: Disable parallel run for tagged scenarios

Note: This technique is confusing and slows down your test suite.


Copy the attached code to features/support. This gets you a new Cucumber tag @no_parallel which ensures that the tagged scenario does not run in parallel with other scenarios that are tagged with @no_parallel. Other scenarios not tagged will @no_parallel can still run in parallel with the tagged test. Please read the previous sentence again.

This can help when multiple test processes that access a single resource that is hard to shar...

How to rotate log files explicitly

Usually, the logrotate service takes care of renaming log files each night or so to avoid logs becoming huge. That will rename your.log to your.log.1, the next time to your.log.2.gz, etc. Here is how to make that happen out of band (you should rarely need to do that).

Logrotate won't touch all your logs automagically. There is a config file for each service which you can tell logrotate to use.

So if you need logs to be rotated right now, do this (as root):

logrotate --force PATH_TO_CONFIG_FILE

For example, to rotate all y...

ApacheBench may return "Failed requests" for successful requests

When you use ab to do some performance benchmarking, you might run into output like this:

Complete requests:      200
Failed requests:        5
   (Connect: 0, Receive: 0, Length: 5, Exceptions: 0)

Note that in our example these "Failed requests" actually never failed.\
For some requests, the application just returned a response with a different content length than the first response. This is indicated by the "Length: 5" bit in the example above.

If you see requests that failed with other kinds of errors, they probably fail...

How to horizontally center absolute positioned container with CSS

Find out in this short guide, how to horizontally center a absolute positioned container with CSS.

Note: We have a card with all CSS centering options. You probably want to head over there and get an overview over what techniques are available for your use case and browser requirements.


Horizontally centering a static element in CSS is normally handled by setting the left and right margins to auto, for example:

// SA...

Rails: How to use a n:m association as 1:n association

Sometimes you might want to limit the number of associated records in a has_many association, but cannot add a foreign key to the other model (using belongs_to).

There are many takes on limiting the number of associated records in has_many associations, but none feels smooth.

However, when your...

How to set the user agent in tests

The User-Agent HTTP header identifies the client and is sent by "regular" browsers, search engine crawlers, or other web client software.

Cucumber

In Rack::Test, you can set your user agent like this on Capybara:

Given /^my user agent is "(.+)"$/ do |agent|
  page.driver.browser.header('User-Agent', agent)
  # Or, for older Capybaras:
  # page.driver.header('User-Agent', agent)
end

For Selenium tests with Firefox, it seems you can set the general.useragent.override profile setting to your preferred value. [See StackOver...

Spreewald: When using `patiently do`, don't reuse existing variable names

Spreewald's patiently repeats the given block again and again until it either passes or times out.

Be careful to give patiently a block that can actually be repeated. E.g. the following block can not be repeated:

Given /^the field "(.*?)" is empty$/ do |field|
  patiently do
    field = find_field(field)
    field.text.should be_blank
  end
end

The reason the above code will fa...

How to make Rational#to_s return strings without denominator 1 again

The way Rational#to_s works on Ruby has changed from Ruby 1.9 on. Here is how to get the old behavior back.

You may want this for things where Rationals are being used, like when subtracting Date objects from one another.

What's happening?

Converting a Rational to a String usually does something like this:

1.8.7 > Rational(2, 3).to_s
=> "2/3"
1.9.3 > Rational(2, 3).to_s
=> "2/3"
2.0.0 > Rational(2, 3).to_s
=> "2/3"

However, when you have a Rational that simplifies to an integer, you will only get a St...