rails snippets

Capistrano 2 task for backing up your MySQL production database before each deployment

Tagged ruby, rails, mysql, backup, capistrano  Languages ruby

This Capistrano task connects to your production database and dumps the contents to a file. The file is compressed and put in a directory specified with set :backup_dir, "#{deploy_to}/backups". This is a slight modification of http://pastie.caboo.se/42574. All credit to court3nay.

task :backup, :roles => :db, :only => { :primary => true } do
  filename = "#{backup_dir}/#{application}.dump.#{Time.now.to_f}.sql.bz2"
  text = capture "cat #{deploy_to}/current/config/database.yml"
  yaml = YAML::load(text)

  on_rollback { run "rm #{filename}" }
  run "mysqldump -u #{yaml['production']['username']} -p #{yaml['production']['database']} | bzip2 -c > #{filename}" do |ch, stream, out|
    ch.send_data "#{yaml['production']['password']}\n" if out =~ /^Enter password:/
  end
end

To automatically backup your data before you deploy a new version add this to config/deploy.rb:

task :before_deploy do
    backup
  end

To restore the backup run the following command:

mysql database_name -uroot < filename.sql

Jump start a Rails project with Rails Edge, Capistrano, Mongrel and Mercurial

Tagged rails, capistrano, mongrel, mercurial  Languages bash
# Create a Rails project
rails project -d sqlite3
cd project
# Delete index file
rm public/index.html
# Use Rails edge. Use  rake rails:freeze:edge TAG=rel_1-2-3 to get a specific version.
rake rails:freeze:edge
# Add Capistrano configuration file
capify .
# Add Mongrel cluster configuration file
sudo mongrel_rails cluster::configure -e production \
    --user mongrel --group mongrel \
    -c /var/www/project-xxx/current \
    -a 127.0.0.1 \
    -p 8000  \
    -N 3
# Create a Mercurial repository
hg init
# Add project to repository
hg commit -A --message "Project started"
# Push changes to a remote repository
hg push ssh://user@ip:port//var/mercurial/xxx

Cloning is done with hg clone:

hg clone ssh://user@ip:port//var/mercurial/xxx

How to use Rails helpers from controllers, models, anywhere

Tagged ruby, rails, helpers, template, link_to, url_for  Languages ruby

How to use e.g. url_for where you need it, not where you’ve been told to use it:

Rails 4

ActionController::Base.helpers.escape_javascript(text)
ActionController::Base.helpers.image_path(path)

Rails 3

class URLHelper
  include Singleton
  include ActionDispatch::Routing::UrlFor
  include Rails.application.routes.url_helpers
end

Rails 1-2.x

Use this snippet if you need to use one of the many Rails helpers in controllers or elsewhere:

class Helpers
    include Singleton
    include ActionView::Helpers::TextHelper
    include ActionView::Helpers::UrlHelper
    include ActionView::Helpers::DateHelper
    include ActionView::Helpers::TagHelper
    include ActionView::Helpers::ActiveRecordHelper
end

Console

You can test named routes in the console through the app object:

app.get '/'
# Named route
app.image_path Image.first

Usage

For example, to obfuscate email use the mail_to helper and set the encoding to JavaScript:

Helpers.instance.mail_to "me@domain.com", "My email", :encode => "javascript"

In Rails controllers there's no need to do anything, simply use the template instance to call helpers:

def index
   @template.link_to x, x.title
end

Troubleshooting

If you get this error:

Missing host to link to! Please provide :host parameter or set default_url_options[:host]

Fix it by specifying the host:

URLHelper.default_url_options[:host] = 'xxx.com'

Fixing "warning: already initialized constant OPTIONS"

Tagged rails, edge, mongrel, mephisto  Languages bash

If you're using Edge Rails and mongrel you might have seen this error:

warning: already initialized constant OPTIONS

There's a bug report here that explains this problem in detail.

The solution for me was to rerun the freeze command:

rake rails:freeze:edge

You might also get "warning: already initialized constant OPTIONS" error if you haven't installed a gem your software relies on. In the following example openssl should be installed:

/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in gem_original_require’: no such file to load—openssl (MissingSourceFile)

ActiveResource might also be the problem:

gem install activeresource --source http://gems.rubyonrails.org

How to install the exception_logger Rails plugin and protect the logs with basic authentication

Tagged rails, ruby, exception_logger, install, routes, basic, authentication  Languages ruby

This snippet explains how to install and use the Rails exception_logger plugin. I'll also show you how to protect your logs by extending the plugin with basic authentication.

script/plugin source http://svn.techno-weenie.net/projects/plugins
script/plugin install exception_logger

I'm using Rails Edge on this project, so I had to install classic pagination also:

script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination

Next create and execute the migration file:

./script/generate exception_migration
rake db:migrate

Before starting the server we need to setup the routes:

map.exceptions '/logged_exceptions/:action/:id', :controller => 'logged_exceptions', :action => 'index', :id => nil

You also need to include the ExceptionLoggable in your ApplicationController:

class ApplicationController < ActionController::Base
  include ExceptionLoggable
...

Start your server and access the exception log at /logged_exceptions.

Exceptions can contain email addresses, passwords, credit card numbers, so you'll want to protect /logged_exceptions from the public. This can be done by adding the following code to the end of environment.rb:

config.after_initialize do
  require 'application' unless Object.const_defined?(:ApplicationController)
  LoggedExceptionsController.class_eval do
    before_filter :authenticate

    protected

    def authenticate
      authenticate_or_request_with_http_basic do |username, password|
        username == "foo" && password == "bar"
      end
    end
  end
end

With this code we add a before filter that shows a login dialog to anyone trying to access /logged_exception/. Note that this requires Rails 2.0 basic authentication to work, so make sure you have the proper version installed.

Fixing "config.breakpoint_server has been deprecated and has no effect" when using Rails Edge

Tagged deprecated, rails, edge, debug  Languages ruby

You might get this error if you're using Rails Edge: config.breakpoint_server has been deprecated and has no effect:

To fix the error we need to remove the following from config/environments/development.rb:

config.breakpoint_server = true

Next install ruby-debug:

gem install ruby-debug

Then add this to the end of config/environments/development.rb:

require 'ruby-debug'

Next, start your server, and the error should be gone...

To debug your code just add a call to debugger:

class MySillySpace ...
  def create
    debugger # add this line
  end

Now when you access the URL with your browser you'll have access to the debugger from the console window.

To learn how to use ruby-debug, read this tutorial written by the ruby-debug author.

Valid RSS 2.0 Feed Template for Rails

Tagged atom, example, ruby, rails, rss2.0, feed, rss, template  Languages ruby

If you like Atom more than RSS use the atom_feed_helper.

Here's the template, modify it to fit your needs. I know there are plugins and other ways of doing this, but I hate code that gets too abstract:

<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <atom:link href="http://xxxxxxx" rel="self" type="application/rss+xml" />
    <title>Code Snippets - Aktagon</title>
    <link>http://snippets.aktagon.com/</link>
    <description>Share your code with the world. Allow others to review and comment.</description>
    <language>en-us</language>
    <pubDate><%= @snippets[0].created_at.rfc822 %></pubDate>
    <lastBuildDate><%= @snippets[0].created_at.rfc822 %></lastBuildDate>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>Aktagon Snippets</generator>
 <% for snippet in @snippets %>
    <item>
      <title><![CDATA[<%= snippet.title %>]]></title>
      <link><%= snippet_url(snippet) %></link>
      <description><![CDATA[<%= snippet.rendered_body %>]]></description>
      <pubDate><%= @snippets[0].created_at.rfc822 %></pubDate>
      <guid><%= snippet_url(snippet) %></guid>
      <% for tag in snippet.tags%>
        <category domain="http://snippets.aktagon.com/snippets"><![CDATA[<%= tag.name %>]]></category>
      <% end%>
    </item>
<% end %>
  </channel>
</rss>

Remember to serve the feed with the correct HTTP headers.

It also helps to have an auto-discovery tag inside the head tag:

<link rel="alternate" type="application/rss+xml" title="RSS feed" href="http://<%= request.host %>/rss/" />

How to install and use the restful_authentication Rails plugin

Tagged ruby, authentication, restful_authentication, rails  Languages ruby

This is an adaptation of the restful_authentication screencast by Ryan Bates, which has an issue with Rails 2.0.3 that throws the following error:

NameError (uninitialized constant SessionsController):
    /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:266:in load_missing_constant'
    /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:453:in const_missing'
    /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:465:in const_missing'
    /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/inflector.rb:257:in constantize'

Installing the restful_authentication plugin

script/plugin source http://svn.techno-weenie.net/projects/plugins/
script/plugin install restful_authentication

Generating the model and controller

script/generate authenticated user sessions

Now run the migration:

rake db:migrate

Configure routing

Open config/routes.rb and add the following routes:

map.resources :users
map.resource  :session

map.signup '/signup', :controller => 'users', :action => 'new'
map.login  '/login', :controller => 'sessions', :action => 'new'
map.logout '/logout', :controller => 'sessions', :action => 'destroy'

Include restful_authentication in ApplicationController

First remove these lines from the users and sessions controllers:

# Be sure to include AuthenticationSystem in Application Controller instead
  include AuthenticatedSystem

Now include restful_authentication in the application controller:

class ApplicationController < ActionController::Base
  include AuthenticatedSystem

Integrate restful_authentication with your views

First let's create a controller and view by executing the generate script:

script/generate controller home index

Modify index.html.erb as follows:

<h1>Welcome</h1>

<% if logged_in? %>
  <p><strong>You are logged in as <%=h current_user.login %></strong></p>
  <p><%= link_to 'Logout', logout_path %></p>
<% else %>
  <p><strong>You are currently not logged in.</strong></p>
  <p>
    <%= link_to 'Login', login_path %> or
    <%= link_to 'Sign Up', signup_path %>
  </p>
<% end %>

Start Rails and access your application. If needed, add the following to config/routes.rb to make the home controller the default:

map.root :controller => "home"

Login, sign up and logout should work.