Nice way to set data attributes when creating elements with Rails helpers

You can say this in helpers like link_to and content_tag:

= link_to 'Label', root_url, :data => { :foo => 'bar', :bam => 'baz' }

This will produce:

<a href="/" data-foo="bar" data-bam="baz">Label</a>

Only works in Rails 3. In Rails 2 you do

= link_to 'Label', root_url, 'data-foo' => 'bar', 'data-bam' => 'baz' }

Click on a piece of text in Cucumber / Capyabra

The step definition below lets you write:

When I click on "Foo"

This is useful in Selenium features where the element you click on is not necessarily a link or button, but could be any HTML element with a Javascript event binding.

The easiest way to get this step is to use Spreewald. If you would like to add it manually, here is the step definition:

When /^I click on "([^\"]+)"$/ do |text|
  matcher = ['*', { :text => text }]
  element = page.find(:css, *matcher)
  while be...

Rack dies when parsing large forms

  • Rack has a limit for how many form parameters it will parse.
  • This limit is 65536 by default.
  • There is a bug in Rack that will incorrectly count the number of input fields in nested forms. In my case a form with 1326 input fields was enough to break the default limit.
  • If Rack thinks your request is too large, the request will fail with a low-level Ruby message like Fix: "undefined method `bytesize' for #" or the standard Rails error box.
  • You ...

Do not use "find" on Capybara nodes from an array

In a nutshell: Capybara's find will not work properly on nodes from a list. Don't find on elements from a list.

Background

Consider this HTML:

<div class="message">
  <h2>Hello World</h2>
  Lorem ipsum...
</div>
<div class="message">
  <h2>Hello Universe</h2>
  Lorem ipsum...
</div>

Now let's say you obtain a list of all such message containers as an array:

messages = page.all('.message')

And then you look at their titles like this:

messages[0].find('h2').text
=> "Hello W...

Use Nokogiri to convert CSS to XPath

CSS is a lot easier to write and read than clumsy XPath expressions. So when you need to use XPath, you can have Nokogiri help you out on creating it.

Simply use Nokogiri's xpath_for:

Nokogiri::CSS.xpath_for('#foo')
# =>  ["//*[@id = 'foo']"]
Nokogiri::CSS.xpath_for('#foo .bar:nth-of-type(2)')
# => ["//*[@id = 'foo']//*[contains(concat(' ', @class, ' '), ' bar ') and position() = 2]"]

Since XPath is more powerful you may still need to do some hardcore XPath hacking eventually. But at least you don't need to for simple cases.

Rails 2's CookieStore produces invalid cookie data, causing tests to break

Note that this seems to affect only recent Rails 2 versions.

You will not encounter this until you are writing to the cookie more than once, but when doing so, integration tests (Cucumber) may break for you with this error:

You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[] (NoMethodError)

Background

The regular/short cucumber backtrace is not of any help but looking at the full trace reveals that ActionPack's `actio...

LibreOffice Impress: Distorted text letters in presentation mode

Upgade to LibreOffice 3.5.3+ or disable hardware accelleration in Tools → Options → LibreOffice → View → Graphic output.

Show hint in HTML 5 text fields

To have your text input field pre-filled in with some text that disappears as soon as the user selects it, use the attribute placeholder:

<input type="text" placeholder="User name here">

This will only work in recent browsers (IE >= 10, FF >= 4, Chrome >= 4, Safari >= 5, Opera >= 11.6).

Use "overflow: hidden" to avoid floating elements from wrapping a container's text

Consider this HTML:

<div id="container">
  <div id="actions">
    <a href="#">Click me!</a>
  </div>
  <div id="content">
    Hello Universe! Hello Universe! Hello Universe! Hello Universe! Hello Universe! Hello Universe!
  </div>
</div>

If you want the actions element to float on the left, you'd just say this in your CSS:

#actions { float: left; }

Unfortunately, any content of the content's text will wrap underneath it:

![paja9.png](https://makandracards.com/makandra/9245-use-overflow-hidden-to-a...

Fix: Capybara is very slow when filling out fields in large forms

In large forms (30+ controls) new Capybara version become [extremely slow] when filling out fields. It takes several seconds per input. The reason for this is that Capybara generates a huge slow XPath expression to find the field.

The attached code patches fill_in with a much faster implementation. It's a dirty fix and probably does a lot less than Capybara's own fill_in so don't use it unless you are having problems with test suites that are unusable because of this...

Updated: Helpers to render (money) amounts

  • The amount helper now retrieves the decimal separator from your I18n dictionary (number.format.separator) instead of hardcoding it to a comma.
  • money_amount helper tunnels options to amount
  • New money_amount option :zero_as_dash

Rails asset pipeline: Why relative paths can work in development, but break in production

The problem

When using the asset pipeline your assets (images, javascripts, stylesheets, fonts) live in folders inside app:

app/assets/fonts
app/assets/images
app/assets/javascripts
app/assets/stylesheets

With the asset pipeline, you can use the full power of Ruby to generate assets. E.g. you can have ERB tags in your Javascript. Or you can have an ERB template which generates Haml which generates HTML. You can chain as many preprocessors as you want.

When you deploy, Rails runs assets:precompile...

Plotting graphs in Ruby with Gruff

Geoffrey Grosenbach has created Gruff for easily plotting graphs. It is written in pure Ruby and integrates with Rails applications.

It provides features as automatic sizing of dots and lines (the more values, the thinner the graph's elements), custom or predefined themes, different styles (bar, line, dot and many more) and multiple graphs in one chart.

Installation

In your Gemfile:

gem 'rmagick', :require => false
gem 'gruff'

Then run bundle install (and don't forget to restart your development server.)

Usage

This i...

The Ruby Toolbox – a collection of good gems

If you need a gem for a certain purpose, be sure to check this site.


The rankings are determined by counting up the number of forks and watchers of various github projects, so I'd view it less as "this is what I should be using," and more as "these are some things I should check out." At the very least, they're all likely to be under active development and fairly up to date, and it's very useful to see groups of gems broken down by category.

Mysterious "margin" below an image

Consider the following HTML & CSS:

<div><img src='http://makandra.com/images/makandra-ruby-on-rails.png' /></div>

^
img {
background-color: red;
}
div {
border: 1px solid black;
}

This will leave a margin of about 5px between the lower edge of the image and the containing div, although there are no paddings or margins set, and there's no whitespace. The reason is, the image will vertically align baseline, and the space below the image is just kept for descenders (the part of letters below the basel...

Guide to localizing a Rails application

Localizing a non-trivial application can be a huge undertaking. This card will give you an overview over the many components that are affected.

When you are asked to give an estimate for the effort involved, go through the list below and check which points are covered by your requirements. Work with a developer who has done a full-app localization before and assign an hour estimate to each of these points.

Static text

  • Static strings and template text in app must be translated: Screens, mailer templates, PDF templates, helpe...

Removing white space after links in HAML

TL;DR

%p
  #{link_to "label", "url"}!

Haml is a great engine for writing shorter, readable HTML. However, there is one thing that troubles me regularly. Consider this Haml code:

%p
  Visit our homepage at
  = link_to "www.makandra.com", "http://www.makandra.com"
  !

Haml will insert a space around the generated link, the result is this (see the space before the exclamation mark!):

<p>
  Visit our website at <a href="http://www.makandra.com">www.makandra.com</a> !
</p>

They suggest to us...

How to use pessimistic row locks with ActiveRecord

When requests arrive at the application servers simultaneously, weird things can happen. Sometimes, this can also happen if a user double-clicks on a button, for example.

This often leads to problems, as two object instances are modified in parallel maybe by different code and one of the requests writes the results to the database.

In case you want to make sure that only one of the requests "wins", i.e. one of the requests is fully executed and completed while the other one at least has to wait for the first request to be completed, you ha...

Howto properly use vertical-align to align elements vertically

Say you want to vertically align a div box inside a div container. This is how you do it:

HTML

<div id="container">
  <div class="box">
    <span> Some text...<br />in two lines. </span>
  </div>
</div>

CSS

Set the line-height to the container's (implicit) height. The container MUST have a height >= its line-height, because the line-height actually spans the area inside which .box will align vertically.

#container {
  line-height: 50px;
}

Because the container's line-height is inherited by .box,...

Rails 3 routing: Be careful with matching routes *including their format*

Today, this line made me trouble. Can you spot the mistake?

match 'sitemap.xml' => 'feeds#sitemap', :constraints => { :format => 'xml' }, :as => 'sitemap'

The mistake is to match sitemap.xml. Rails will by default strip any dot-anything, remember it as desired format and forward the rest of the request to the routing engine. Since we're making .xml part of the match, it is not available for format determination and Rails will set the format to html.

Unfortunately, the constraint won't complain in this case and Rails even ren...

Three quick Rails console tips

How to call routes, make requests and try out helpers from the Rails console.

Open Helvetica alternatives

The closest is probably Nimbus Sans L, which is released under the GPL, AFPL, LPPL licenses. However, I couldn't find a way to convert Nimbus Sans L into a web font.

I finally settled with Liberation Sans, which is awesome for some reasons:

  • Although it's available for free, it's a high quality font because its creation was thankfully sponsored ...

Authorize allowed values with assignable_values

All our projects have enum-like requirements like this:

  • An attribute value must be included in a given set of values.
  • The list of allowed values must be retrievable in order to render <select> boxes.
  • Each value has a humanized label.
  • Sometimes there is a default value.

Most of the time, this requirement is also needed:

  • The list of assignable values depends on the user who is currently signed in.

In our past projects there are many different solutions for these related requirements, e.g. ChoiceTrait, methods like `available_...

Convert primitive Ruby structures into Javascript

Controller responses often include Javascript code that contains values from Ruby variables. E.g. you want to call a Javascript function foo(...) with the argument stored in the Ruby variable @foo. You can do this by using ERB tags (<%= ruby_expression %>) or, in Haml, interpolation syntax (#{ruby_expression}).

In any case you will take care of proper quoting and escaping of quotes, line feeds, etc. A convenient way to do this is to use Object#json, which is defined for Ruby strings, numb...