Enable CSRF protection in Javascript tests

You might not know that Rails disables CSRF protection in tests. This means that if you accidentally forget to send the CSRF token for non-GET requests, your tests will be green even though your application is completely broken (a failed CSRF check usually logs out the user). Rails probably does this because CSRF protection sort of requires Javascript.

You want to enable CSRF protection in Cucumber scenarios that can speak Javascript. To do so, copy the a...

RailsPanel chrome extension

Chrome extension that shows all info from your rails log (like parameters, response times, view rendering times, DB requests) inside a chrome panel.

Rails 3/4: How to add routes for specs only

If you want to have routes that are only available in tests (e.g. for testing obscure redirects), you can use the with_routing helper -- but that one destroys existing routes which may break a specs that require them to work.

To keep both "regular" and test routes, do this:

class MyApplicationController < ActionController::Base
  def show
    render text: 'Welcome to my application'
  end
end

test_routes = Proc.new do
  get '/my_application' => 'my_application#show'
end
Rails.application.routes.ev...

"cannot load such file -- nokogiri/nokogiri" (or any other Gem with native extensions on rvm and Ruby >= 2)

After running bundler / gem install I could not load nokogiri lately. It died with cannot load such file -- nokogiri/nokogiri.
This is not a problem of the gem but is due to a broken native extensions installation routine.

When installing nokogiri manually and with verbose output by using gem install -V nokogiri -v 1.5.6, you can see the problem scrolling by when the native extension is built:

/usr/bin//install -c -m 0755 nokogiri.so /home/thomas/.rvm/gems/ruby-2.0.0-p247/gems/nokogiri-1.5.6/lib/home/thomas/.rvm/rubies/ruby-2.0.0-p...

Capybara: Trigger requests with custom request method

Preface: Normally, you would not need this in integrations tests (probably that's why it is so hard to achieve), because it is no actual "integration testing". If you use this step, know what you are doing.


Destroying a record with Capybara is not as easy as calling visit user_path(user, method: :delete), because RackTest's visit can only perform GET requests.

With this step you can destroy a records using either Selenium or RackTest. Ex...

Consul 0.10.0 allows multiple power mappings for nested resources

Consul 0.10.0 now allows multiple power mappings for nested resources.


When using nested resources you probably want two power
checks and method mappings: One for the parent resource, another for the child resource.

Say you have the following routes:

resources :clients do
  resources :notes
end

And the following power definitions:

class Power
  ...

  power :clients do
    Client.active if si...

Nested controller routes (Rails 2 and 3)

In order to keep the controllers directory tidy, we recently started to namespace controllers. With the :controller option you can tell Rails which controller to use for a path or resource. For nested resources, Rails will determine the view path from this option, too.

That means the following code in routes.rb

resources :users do
  resource :profile, controller: 'users/profiles' #[1]
end

… makes Rails expect the following directory structure:

app/
  controllers/
    users/
      profiles_controller.rb
    users_control...

RSpec: Where to put shared example groups

Shared example groups are a useful RSpec feature. Unfortunately the default directory structure generated by rspec-rails has no obvious place to put them.

I recommend storing them like this:

spec/models/shared_examples/foo.rb
spec/models/shared_examples/bar.rb
spec/models/shared_examples/baz.rb
spec/controllers/shared_examples/foo.rb
spec/controllers/shared_examples/bar.rb
spec/controllers/shared_examples/baz.rb

To ma...

Render a view from a model in Rails

In Rails 5 you can say:

ApplicationController.render(
  :template => 'users/index',
  :layout => 'my_layout',
  :assigns => { users: @users }
)

If a Request Environment is needed you can set attributes default attributes or initialize a new renderer in an explicit way (e.g. if you want to use users_url in the template):

ApplicationController.renderer.defaults # =>
{
  http_host: 'example.org',
  https:      false,
  ...
}
...

exception_notification 4.0.0+ makes it easier to ignore errors, crawlers

The new exception_notification has awesome options like :ignore_crawlers => true and :ignore_if => lambda { ... }. These options should be helpful in ensuring every notifications means something actionable (instead of a long log of failures that just scrolls by).

Note that you should not ignore crawlers by default. Ideally, cool URLs never change and always respond with a helpful redirect or similar.

Ignore Errors like this:

# config/initializers/exception_notification.rb

Ex...

MySQL: Careful when using database locks in transactions

We tend to use database transactions as a magic bullet to get rid of all our concurrency problems. When things get really bad, we might even throw in some locking mechanism, but then are usually done with it.

Unfortunately, transactions semantics in databases are actually very complicated, and chances are, your making some incorrect assumptions.

The MySQL innodb engine actually has [four different modes](ht...

Cryptic Ruby Global Variables and Their Meanings

The linked page lists and explains global Ruby "dollar" variables, such as:

  • $: (load path)
  • $* (ARGV)
  • $? (Last exit status)
  • $$ (PID)
  • $~ (MatchData from last successful match)
  • ...and many more you'll need when reading weird code.

Regex

  • $~ (last MatchData)
  • $1 $2 $3 $4 (match groups from the last pattern match)
  • $& (last matched string)
  • $+ (last match group)
  • `$`` (the string before the last match)
  • $' (the string after the last match

See [this extensive list of variables](http://www.tu...

Sprites with Compass

Using CSS sprites for background images is a technique for optimizing page load time by combining smaller images into a larger image sprite.

There are ongoing arguments on how useful this still is, as modern browsers become more comfortable to load images in parallel. However, many major websites still use them, for example amazon, [facebook](...

How I Explained REST to my Wife

A great and enjoyable introduction into the concept of the web and about what HTTP was designed for. The original post has been removed for some stupid gender discussion.

Common mistakes when storing file uploads with Rails

1. Saving files to a directory that is not shared between deploys or servers

If you save your uploads to a made up directory like "RAILS_ROOT/uploads", this directory goes away after every deploy (since every release gets a new). Also this directory is not shared between multiple application servers, so your uploads are randomly saved to one local filesystem or another. Fixing this afterwards is a lot of fun.

Only two folders are, by default, shared between our application servers and deployments: "RAILS_ROOT/storage" and `"RAILS...

Upgrading Rails 2 from 2.3.8 through 2.3.18 to Rails LTS

This card shows how to upgrade a Rails 2 application from Rails 2.3.8 through every single patch level up to 2.3.18, and then, hopefully, Rails LTS.

2.3.8 to 2.3.9

This release has many minor changes and fixes to prepare your application for Rails 3.

Step-by-step upgrade instructions:

  1. Upgrade rails gem
  2. Change your environment.rb so it says RAILS_GEM_VERSION = '2.3.9'
  3. Change your ...

Rails: Send links in emails with the right protocol

ActionMailer per default uses http as protocol, which enables SSL-stripping. When a logged-in user follows an http link to your application, it sends the cookies along with it. Although the application redirects the user to https and from that point has a secure connection to the user, an attacker may overhear that first unsafe request and hijack your session.

Teach ActionMailer to use the right protocol

If your application is behind SSL, turn on using https application-wide. In your environment file (either global or per environ...

Before you make a merge request: Checklist for common mistakes

Merge requests are often rejected for similar reasons.

To avoid this, before you send a merge request, please confirm that your code ...

Subscribe to Rails security mailing list without Google account

The Ruby on Rails security list archive can be found here: http://groups.google.com/group/rubyonrails-security

You can subscribe to this mailing list without a Google account by pasting this URL into your browser (after replacing the email address obviously).

http://groups.google.com/group/rubyonrails-security/boxsubscribe?email=your.name@example.com
                                                                       ^^^^^^^^^^^^^^^^^^^^^ <- Change this

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 =...

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...