A simpler default controller implementation

Rails has always included a scaffold script that generates a default controller implementation for you. Unfortunately that generated controller is unnecessarily verbose.

When we take over Rails projects from other teams, we often find that controllers are the unloved child, where annoying glue code has been paved over and over again, negotiating between request and model using implicit and convoluted protocols.

We prefer a different approach. We believe that among all the classes in a Rails project, controllers are some of the hardest to...

VCR: Alternative way of mocking remote APIs

If you need to test interaction with a remote API, check out the VCR gem as an alternative to Webmock or stubbing hell.

The idea behind VCR is that is performs real HTTP requests and logs the interaction in a .yml file. When you run the test again, requests and responses are stubbed from the log and the test can run offline.

It's a great way to mock network requests to an external service without going through the pain of log...

Implementing social media "like" buttons: Everything you never wanted to know

So you client has asked you to implement a row of buttons to like the URL on Facebook, Twitter and Google+. Here are some things you should know about this.

0. Security considerations

Each "like" button is implemented by including a Javascript on your site. This means you are running fucking remote code on your page. You are giving Facebook, Twitter and Google+ full permission to e. g. copy user cookies. Check with your client if she is cool with that. Also note that if you're site is suggesting security by operating under HTTPS ...

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