Using heredoc for prettier Ruby code
You can use heredoc to avoid endlessly long lines of code that nobody can read. Heredoc strings preserve linebreaks and can be used like this:
def long_message
puts(<<-EOT)
Here goes a very long message...
Sincerely,
foobear
EOT
end
<<-EOT
will be somewhat of a placeholder: anything you write in the line after you used it will be its value until you write EOT
in a single line.
You can use any string to flag your heredocs. To be more verbose you...
Rendering a custom 404 page in Rails 2
Simple: Tell the application controller how to handle exceptions, here a RecordNotFound
error.
Do this with the following line:
# application_controller.rb
rescue_from ActiveRecord::RecordNotFound, :with => :render_404
This will call the method render_404
whenever a RecordNotFound
error occurs (you could pass a lambda
instead of a symbol, too).
Now write this method:
def render_404
render 'errors/404', :status => '404'
end
Finally create a 404 document views/errors/errors.html.haml
.
%h1 Record...
Let a Rails 3 application make a request to itself
Ever wondered how Rails talks to itself in a Cucumber feature? In Rails 3 you can do it like this:
def rack_env(path)
{ "rack.input" => {},
"PATH_INFO"=>"#{path}",
"REQUEST_METHOD"=>"GET" }
end
request = rack_env('/users/new')
response = Rails.application.call(request)
status, headers, body = response
puts status # e.g. 200
puts headers.inspect # hash of headers
puts body.body # html of response body
Instead of Rails.application
you can also call any Rack application.
When Rails no longer renders changes in view templates or Sass stylesheets
Do you have page caching enabled for the development
environment and there are cached pages lying around in public/
?
Fix: "undefined method `bytesize' for #<Array>"
I believe that when WEBrick has trouble bringing up your Rails application, the WEBrick component that is supposed to print you a pretty error message has a bug and sometimes fails with this message:
"undefined method `bytesize' for #<Array>"
Starting the application in Passenger gave me a stacktrace in log/development.log
that pointed to the actual problem.
Possible causes discovered by looking at the logs
-----------------------------------------------------...
How to use Rails URL helpers in any Ruby class
If you have any class which requires access to some path methods generated by your routes. Even though you could technically include Rails.application.routes.url_helpers
, this may include way too many methods and even overwrite some class methods in the worst case.
Instead, most of the time the following is advised to only make the desired methods available:
class Project
delegate :url_helpers, to: 'Rails.application.routes'
def project_path
url_helpers.project_path(self)
end
end
Invoices: How to properly round and calculate totals
While it might seem trivial to implement an invoice that sums up items and shows net, gross and vat totals, it actually involves a lot of rules and caveats. It is very easy to create invoices where numbers don't add up and a few cents are missing. A missing cent is a big deal for an accountant, so it is important for your invoices to list correct numbers.
Note that this is not legal advice. Also note that while this note has a number of code examples in Ruby and MySQL, the concepts apply to all programming languages and data stores.
When ...
Always show all form errors during development
You've been there: A form cannot be submitted, but you don't see a validation error because the field at fault has no corresponding input field on the form. Because this is usually a bug, you insert debug information listing all errors into the form view. And once the bug is fixed, you forget to take out that debug information.
There is a better way. By copying one of the attached initializers into config/initializers
, your forms will always render a small box listing all form errors in the bottom right corner of the screen. This box is n...
Distance of time in what you like: days, months, years
Sometimes the Rails helper #distance_of_time_in_words
is using too much magic.
When you need a time difference in a specific unit, use this method:
^
def distance_of_time_in(unit, from, to)
diff = to - from
if 1.respond_to? unit
distance = diff / 1.send(unit)
distance.abs.round
else
raise ArgumentError, "#{unit.inspect} is not supported as unit"
end
end
distance_of_time_in(:days, Time.now, 1.year.ago)
=> 365
Remove the .abs
if you want the mathematical *differ...
How to make a single check box (or image, etc) align vertically
Consider this HTML:
<div style="line-height: 42px">
<input type="checkbox" />
</div>
Even though the surrounding container defines a line-height
, which vertically centers its inline elements, the check box will be top aligned if it is the only element inside the container.
It will be aligned correctly if the HTML looks like this:
<div style="line-height: 42px">
<input type="checkbox" /> foo
</div>
So the ac...
Ruby GetText will eval scripts containing ActiveRecord classes
When the Ruby parser module of Ruby-GetText comes across a file in one of its search directories (e.g. lib/scripts/
) and finds out that you are defining ActiveRecord classes inside it, it evaluates the whole file. Here is how to avoid that.
What's happening?
Let's say you have the following script which is only run once, manually, via script/runner
:
# lib/scripts/doomsday.rb
class User < ActiveRecord::Base; end
User.destroy_all
In that case we ...
Detect the current Rails environment from JavaScript or CSS
Detecting if a Javascript is running under Selenium WebDriver is super-painful. It's much easier to detect the current Rails environment instead.
You might be better of checking against the name of the current Rails environment. To do this, store the environment name in a data-environment
of your <html>
. E.g., in your application layout:
<html data-environment=<%= Rails.env %>>
Now you can say in a pi...
How to stub class constants in RSpec
Hint: There's another card with this helper for Cucumber features.
Sometimes you feel like you need to stub some CONSTANT you have defined in an other class. Since actually constants are called constants because they're constant, there's no way to easily stub a constant.
Here are three solutions for you.
Easiest solution
Rethink! Do you really need CONSTANT = %w[foo bar]
to be constant? In many cases, setting it as a...
Capybara - The missing API
The Capybara API is somewhat hard for parse for a list of methods you can call on a Capybara node. Below you can find such a list. It's all copied from the Capybara docs, so all credit goes to the Capybara committers.
When you talk to Capybara from a Cucumber step definition, you always have page
as the document root node, or whatever you scoped to by saying within(selector) { ... }
. You can select child notes by calling page.find(selector)
or page.all(selector)
. You can call the same ...
How to grep through the DOM using the Capybara API
When your Cucumber feature needs to browse the page HTML, and you are not sure how to express your query as a clever CSS or XPath expression, there is another way: You can use all
and find
to grep through the DOM and then perform your search in plain Ruby.
Here is an example for this technique:
Then /^I should see an image with the file...
How to diff two strings in Ruby
When you need to use diff
in either some Ruby code or your Rails app, use the differ gem.
puts Differ.diff "foo", "boo"
# => {"boo" >> "foo"}
Usage
There are several variants available, all using the base method diff(to, from, separator = "\n")
.
You have diff_by_line
, diff_by_word
, diff_by_char
and may of course use your own separator:
puts Differ.diff 'Hauptsatz, und mein Nebensatz.', 'Hauptsatz, und dein Nebensatz.', ','
# => Hauptsatz,{" und dein Nebensatz." >> " un...
JSONP - Wikipedia
Under the same origin policy, a web page served from server1.example.com cannot normally connect to or communicate with a server other than server1.example.com. An exception is the HTML <script> element. Taking advantage of the open policy for <script> elements, some pages use them to retrieve Javascript code that operates on dynamically-generated JSON-formatted data from other origins. This usage pattern is known as JSONP. Requests for JSONP retrieve not JSON, but arbitrary JavaScript code.
Use Capybara on any HTML fragment or page
I think this pattern is really useful not just for upgrading suites from Webrat, but really anywhere you have an HTML fragment or string that you’d like to use Capybara’s matchers on.
Hide your Selenium browser window with a VNC server
This is now part of geordi. Please don't follow the instructions below, if you use geordi.
Inspired by the recent headless Selenium note, I found yet another solution for the problem to hide your selenium tests away.
This has the advantages
^
- not to require a gem (so you do not force this on others)
- to allow you to take a look at the running webdriver if necessary
Simply make a script th...
simple_format helper for Javascript
The Javascript code below is a rough equivalent to the simple_format helper that ships with Rails:
function simpleFormat(str) {
str = str.replace(/\r\n?/, "\n");
str = $.trim(str);
if (str.length > 0) {
str = str.replace(/\n\n+/g, '</p><p>');
str = str.replace(/\n/g, '<br />');
str = '<p>' + str + '</p>';
}
return str;
}
Unlike the Rails helper, this does not preserve whitespace. You probably don't care.
A few hints when upgrading to Ruby 1.9
Note: If you are currently working with Ruby 1.8.7 or 1.9.3, we recommend to upgrade to Ruby 2.1 first. From our experience this upgrade is much smoother than the jump from 2.1 and 2.2, while still giving your the huge performance gains of Ruby 2. Also, if you're on Ruby 1.8.7, we recommend to skip a troublesome upgrade to 1.9.3 and go straight to 2.1.
When trying to make a Rails app run on Ruby 1.9, you're likely to encounter several issues. Here are a few solutions (obviously not exhaustive):
When running `bundle ...
Rails 3: Make "link_to :remote => true" replace HTML elements with jQuery
In Rails 2, you could use link_to_remote ... :update => 'id'
to automatically replace the content of $('#id')
.
To do the same in Rails 3, include usual rails-ujs JavaScript, and put this into your application.js
:
$(function() {
$('[data-remote][data-replace]')
.data('type', 'html')
.live('ajax:success', function(event, data) {
var $this = $(this);
$($this.data('replace')).html(data);
$this.trigger('ajax:replaced');...
Virtual attributes for date fields
Note that this card is very old. You might want to use ActiveType for your auto-coerced virtual attributes instead.
We sometimes give our models virtual attributes for values that don't need to be stored permanently.
When such a virtual attribute should contain Date
values you might get unexpected behavior with forms, because every param is a string and you don't get the magic type casting that ...
Shell script to generate a Git commit with Pivotal Tracker story ID and title
We usually generate our commit messages from Pivotal Tracker IDs and titles, like
[#15775609] Index view for conflicts
The geordi command commit
automates this. (See: Pretty Commit messages via geordi).
Just run geordi commit
and it will connect to PT and let you select from a list of all started and finishes stories. Then it runs git commit
with the generated message (i.e. all staged changes will be commited).
When running for the first time, Geordi will request your PT...