Custom Wizard URLs in Rails with Wicked
14 Nov 2012I wrote this wizard controller library that people seem to really dig called Wicked. It works well to build after signup wizards and to incrementally build objects for the database but there is one thing it didn’t do very well until now: allow you to change the text in your wizard url’s quickly and easily.
If you’re new to Internationalization (I18n) it’s a process of making your website look native in more that one language. With the newly released Wicked you can translate your wizard urls or simply use it to change your custom urls in one language with no code changes. Check it out:
Internationalization of URLS (I18n)
If your site works in multiple languages, or if you just want more control over how your URL’s look you can now use I18n with wicked. To do so you need to replace this:
include Wicked::Wizard
With this:
include Wicked::Wizard::Translated
This will allow you to specify translation keys instead of literal step names. Let’s say you’ve got steps that look like this:
steps :first, :second
So the urls would be /after_signup/first
and /after_signup/second
. But you want them to show up differently for different locales. For example someone coming form a Spanish speaking locale should see /after_signup/uno
and after_signup/dos
.
To internationalize first you need to create your locales files under config/locales
such as config/locales/es.yml
for Spanish. You then need to add a first
and second
key under a wicked
key like this:
es:
hello: "hola mundo"
wicked:
first: "uno"
second: "dos"
It would also be a good idea to create a english version under config/locales/en.yml
or your english speaking friends will get errors. If your app already uses I18n you don’t need to do anything else, if not you will need to make sure that you set the I18n.locale
on each request you could do this somewhere like a before filter in your application_controller.rb
before_filter :set_locale
private
def set_locale
I18n.locale = params[:locale] if params[:locale].present?
end
def default_url_options(options = {})
{locale: I18n.locale}
end
For a screencast on setting up and using I18n check out Railscasts. You can also read the free I18n Rails Guide.
Now when you visit your controller with the proper locale set your url’s should be more readable like /after_signup/uno
and after_signup/dos
.
Wicked expects your files to be named the same as your keys, so when a user visits after_signup/dos
with the es
locale it will render the second.html.erb
file.
Important: When you do this the value of step
as well as
next_step
and previous_step
and all the values within steps
will
be translated to what locale you are using. To translate them to the
“canonical” values that you’ve have in your controller you’ll need so
use wizard_value
method.
For example, if you had this in your controller, and you converted it to a use Wicked translations, so this will not work:
steps :confirm_password, :confirm_profile, :find_friends
def show
case step
when :find_friends
@friends = current_user.find_friends
end
render_wizard
end
Instead you need to use wizard_value
to get the “reverse translation” in your controller code like this:
steps :confirm_password, :confirm_profile, :find_friends
def show
case wizard_value(step)
when :find_friends
@friends = current_user.find_friends
end
render_wizard
end
The important thing to remember is that step
and the values in steps
are
always going to be in the same language if you’re using the Wicked translations.
If you need any values to match the values set directly in your controller,
or the names of your files (i.e. views/../confirm_password.html.erb
, then you need
to use wizard_value
method.
Custom URL’s
Very similar to using I18n from above but instead of making new files for different languages, you can stick with one language. Make sure you are using the right module:
include Wicked::Wizard::Translated
Then you’ll need to specify translations in your language file. For me, the language I’m using is english so I can add translations to config/locales/en.yml
en:
hello: "hello world"
wicked:
first: "verify_email"
second: "if_you_are_popular_add_friends"
Now you can change the values in the URL’s to whatever you want without changing your controller or your files, just modify your en.yml
. If you’re not using English you can set your default_locale to something other than en
in your config/application.rb
file.
config.i18n.default_locale = :de
Important: Don’t forget to use wizard_value()
method to make
sure you are using the right cannonical values of step
,
previous_step
, next_step
, etc. If you are comparing them to non
wicked generate values.
Custom crafted wizard urls: just another way Wicked makes your app a little more saintly.
Richard @schneems (pronounced sorta like Schnapps), loves writing gems and works for Heroku. If you enjoy the wicked gem consider watching the repo or telling your friends.