Tag: RoR

Upgrading to Rails 4.0 from Rails 3.2 – Test case – Part I (preparations, configuration, gems)

In this articles series, I'll try to cover all the issues that I had, when I was upgrading one of my Rails app from Ruby on Rails 3.2 to Ruby on Rails 4.0.

Preparations - What should we do before upgrading to Rails 4?

  • Upgrade your Ruby version at least to 1.9.3 (I would recommend 2.0)
  • Upgrade bundler
  • Upgrade your application to the most recent Rails 3.2 version
  • Check gems compatibility (you may want to be on edge with few gems (or use Rails 4 branches))
  • Write more tests if you don't have a decent code coverage

The last point is the most important. If you don't have a good code coverage level and you lack tests, upgrading from Rails 3.2 to Rails 4 might be a big problem.

Attributes protected and some other Rails 3 features

Rails team moved a lot of stuff from Rails core to gems. In order to make an upgrade smooth, probably the best solution is to add all the gems into Gemfile and then upgrade given functionalities one by one after successful Rails 4 migration:

gem 'protected_attributes' # https://github.com/rails/protected_attributes
gem 'active_resource' # https://github.com/rails/activeresource
gem 'actionpack-action_caching' # https://github.com/rails/actionpack-action_caching
gem 'activerecord-session_store' # https://github.com/rails/activerecord-session_store
gem 'rails-observers' # https://github.com/rails/rails-observers
# Note that there might be more functionalities that were extracted

Be aware, that some of those gems might not be maintained longer than till Rails 4.1 release!

Upgrading to Rails 4 - Gemfile

First thing that needs to be done, when upgrading to Rails 4 is changing our Gemfile:

gem "rails", '~>4.0.0'
# Remember to require dalli if you're using memcached
gem 'dalli'
# Remember to update any gems that require something special in order to work with Rails 4
gem 'squeel', :git => "git://github.com/ernie/squeel.git"
gem "ransack", :git => "git://github.com/ernie/ransack.git", :branch => 'rails-4'
gem 'simple_form', :git => 'git://github.com/plataformatec/simple_form.git'

Also if you have an assets group, it needs to be removed. You can move the assets gems to a default group:

# group :assets <--- this needs to go away
gem 'coffee-rails'
gem 'sass-rails'
gem 'uglifier'
# end

After updating your Gemfile you can do a

bundle install

and hopefully you're ready for upgrade!

Configuration files - rake rails:update

There are some changes in configuration files (that I will cover), but I would strongly recommend running:

rake rails:update

allow it to overwrite your files and then just add the stuff that you've needed and is not there. IMHO it is way less complex approach, that trying to add all new config options manually.

Rails.root + /config/environments/*.rb

Things that are no longer available and need to be removed from those file:

  • config.whiny_nils = true
  • config.action_dispatch.best_standards_support = :builtin
  • config.active_record.mass_assignment_sanitizer = :strict
  • config.active_record.auto_explain_threshold_in_seconds = 0.5

Things that need to be added (with values appropriate for given environment):

  • config.eager_load = false
  • config.active_record.migration_error = :page_load

Things that need to be changed:

  • config.cache_store = :dalli_store => config.cache_store = :mem_cache_store

Remember to set eager_load in all environments. If not, you'll see following warning:

config.eager_load is set to nil. Please update your config/environments/*.rb files accordingly:

  * development - set it to false
  * test - set it to false (unless you use a tool that preloads your test environment)
  * production - set it to true

If you don't remove the auto_explain_threshold_in_second option, you'll see following warning:

DEPRECATION WARNING: The Active Record auto explain feature has been removed.

To disable this message remove the `active_record.auto_explain_threshold_in_seconds`
option from the `config/environments/*.rb` config file.

filter_parameters

In Rails 3 filter_parameters setting was set up in application.rb. In Rails 4 there will be created an initializer for that (config/initializers/filter_parameters.rb):

Rails.application.config.filter_parameters += [:password, :file_value]

So you may consider moving this setting our of your application.rb file.

Secret token (config/initializers/secret_token.rb)

There is a new value for that initializer:

Susanoo::Application.config.secret_token = 'your current token'
Susanoo::Application.config.secret_key_base = 'secret value' # this needs to be added

The secret_key_base is not required but if you don't add it, you'll have a deprecation warning:

DEPRECATION WARNING: You didn't set config.secret_key_base.

Cookies from Rails 3 will be transformed automatically into Rails 4 format but be aware, that this won't work the other way around, so if by any reason you'll want to get back to Rails 3, all the user cookies will be unreadable.

In order to generate a random secret_key value, you can use rake task:

rake secret

This will just generate secret, you need to copy it to this initializer manually!

Rails.root + /config/application.rb

If you had any interactions with routes loading process you need to change config/routes in such a way:

config.paths['config/routes.rb'] # add .rb

Example:

# Load all the routes from routes directory
Dir["#{Rails.root}/config/routes/**/*.rb"].each do |route_file|
  config.paths['config/routes.rb'] << route_file
end

Conclusion

If you have a decent code coverage level and you know what you're doing, upgrade should not be a big problem. At this point, if you're not using any fancy route settings, you should be able to at least start your application:

./script/rails s -u

I'll cover more deprecation warnings and other issues soon.

Apache (Passenger) Maintenance mode for Ruby on Rails application with Capistrano

Same of Nginx and Puma: Nginx (and Puma behind) maintenance mode for Rack/Rails applications with Capistrano

There is a time, when we need to switch our apps into maintenance mode. Maybe it is because of some data processing stuff, maybe because of backups, Capistrano or whatever good reason you might have. To be honest it doesn't matter why. What does matter, is how we should handle working users of our apps. Of course all the downtimes should take place when there is the smallest amount of users online. In most cases it might be a good idea to switch application off in the middle of the night (or on Sunday, etc.), but this won't solve our primary problem: what should we show users that are already online?

The worst scenario ever would be showing them nothing (for example by shutting down whole application server). Users probably will think, that something bad happened. Much better idea is to show users a maintenance page with some sort of information like "Temporary down for maintenance". It would be even better, it such a page would automatically show when needed.

To do so, we can use Apache Mod Rewrite module and a static 503.html page.

Mod Rewrite for Maintenance mode detection

How to determine if we are in maintenance mode? Let's check if maintenance.txt file exists in tmp/ dir of our app:

RewriteCond %{DOCUMENT_ROOT}/../tmp/maintenance.txt !-f

When it exists, we need to redirect user to our 503.html static page:

RewriteRule ^(.*)$ /503.html [NC,R,L]

Of course the whole .htaccess should include also enabling RewriteEngine, ignoring redirects of CSS files and redirecting from 503.html to root, when the maintenance is off:

RewriteEngine On
# Set error 503 static page
ErrorDocument 503 /503.html

# Don't redirect when someone requests assets used in 503.html
RewriteCond %{REQUEST_URI} !^/assets/layouts/portal/favicon.ico$
RewriteCond %{REQUEST_URI} !^/assets/libraries/bootstrap/bootstrap.min.css$
RewriteCond %{REQUEST_URI} !^/assets/layouts/portal/application.css$
RewriteCond %{REQUEST_URI} !^/503.html$
RewriteCond %{DOCUMENT_ROOT}/../tmp/maintenance.txt -f
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
# Set 503 status for all requests
RewriteRule ^(.*)$ /503.html [NC,R=503,L]

# When it is not maintenance mode redirect to root_path from 503.html
RewriteCond %{DOCUMENT_ROOT}/../tmp/maintenance.txt !-f
RewriteCond %{REQUEST_URI} ^/503.html
RewriteRule ^503.html http://www.project.domain/ [R=302,L]

Of course, you need to remember to create your own 503.html file, put it in public/ dir of your project and customize all the htaccess rules based on your needs.

Capistrano hookup

To automate enabling and disabling my projects, I use a set of simple Capistrano tasks, enclosed in an Apache namespace:

namespace :apache do

  desc 'Restarts the current Passenger project'
  task :restart do
    run "touch #{current_path}/tmp/restart.txt"
  end

  desc 'Sets project server in dev mode - so the 503 page is served'
  task :lock do
    run "touch #{current_path}/tmp/maintenance.txt"
  end

  desc 'Sets project to a standard mode'
  task :unlock do
    run "rm -f #{current_path}/tmp/maintenance.txt"
  end

end

Usage example:

before 'deploy:update' do
  apache.lock
end

after 'deploy:update' do
  apache.restart
  apache.unlock
end

That's all. Good luck and as few maintenance downtime as possible! P.S. With a bit of modifications, this code might be used also for PHP/Python Passenger based projects.

Copyright © 2025 Closer to Code

Theme by Anders NorenUp ↑