Ai ♥ Ruby on Rails

Let's build a powerful, dynamic website!

Hey there! Thanks for dropping by Theme Preview! Take a look around
and grab the RSS feed to stay updated. See you around!

I recently moved both of my Rails applications to Heroku.

I used to use Hostmonster (and this blog still runs on Hostmonster), but they are not specialized in Rails, so deployment and maintenance became just too complicated. They could not give the kind of support I wanted. Also, the apps were so slow there.

Heroku made my work so much easier. I admire the engineers who created it.

For those who want to learn Ruby on Rails and didn’t know about Heroku, I would say that this is the ONLY way I recommend for you to deploy your rails app.

It’s also free if you don’t need a gigantic space or special features.

I explained in this post how to automatically append locale as a parameter at end of every URL throughout the site. However, when you have a form like this, you have to pass a locale using a hidden field in the form.
<% form_tag ‘‘, :method => ‘get’ do %>
…..
some input text fields/text box
…..
<% if !params[:locale].nil? %>
<%= hidden_field_tag :locale, params[:locale] %>
<% end %>
<%= submit_tag (…..) %>
<% end %>
Now, if your locale is not nil (that is, not the default), locale will be appended to the next URL.

Specify the default locale by uncommenting the following two lines in config/environment.rb file:

Rails::Initializer.run do |config|

# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
config.i18n.default_locale = :jp

end

Now, you may be thinking, “Do I have to care about passing locale as a parameter every time I put a link?”

For example, like this:

link_to(“Contact”, :controller => “contacts”, :action => “index”, :locale => params[:locale])

This will definitely work, but you don’t wanna do this throughout your site.

Solution! You just put this piece of code in your app/controllers/application_controller.rb

def default_url_options(options={})
logger.debug “default_url_options is passed options: #{options.inspect}\n”
{ :locale => I18n.locale }
end

This will automatically append ‘?locale=locale’ at the end of every URL when you navigate through the site.

First, let’s find a file en.yml under config/locales . That’s where all of your YAML files will go.

The file should have something like this:

# Sample localization file for English. Add more files in this directory for other locales.
# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.

en:


hello: "Hello"

Now create a file jp.yml under config/locales and write this:

jp:

hello: “ハロー”

Be careful with the indentation (use a Tab key), because it matters.

Now, put the following code somewhere in your top page (view):

<%=t :hello %>

As you see, instead of typing I18n.t all the time, you can just type t (translate).

Then, try typing this on your address bar: http://localhost/?locale=jp

Not working? Now add the following to your app/controllers/application_controller.rb file

before_filter :set_locale

def set_locale

I18n.locale = params[:locale]

end

This should do it!

Reference(s):

I wanted to make my website bilingual (English and Japanese). There are mainly 3 approaches to internationalize your site.  The URLs below represent how your site’s top URL will look like for each approach (jp represents the Japanese version) :

  1. http://ainakatani.com/?locale=jp
  2. http://ainakatani.com/jp
  3. http://ainakatani.jp

The last approach requires you to obtain an additional domain, so you may not even consider. You can try the first or the second by using I18N (Internationalization Gem).

I tried the first option.

In the next post, I’ll explain how I did it.

RSS and 502 Bad Gateway Error

I made my portfolio here:  http://ainakatani.com

I’m displaying my recent twitter and blog posts on the top page using rss.

Problem:

About one out of 5 times, I get 502 Bad Gateway Error because my controller failed to get the information from my blog (or twitter)’s rss.

The error looked like this:

-------------------------------------

OpenURI::HTTPError in HomeController#index

502 Bad Gateway Error

/usr/lib64/ruby/1.8/open-uri.rb:277:in `open_http'
/usr/lib64/ruby/1.8/open-uri.rb:616:in `buffer_open'
/usr/lib64/ruby/1.8/open-uri.rb:164:in `open_loop'
/usr/lib64/ruby/1.8/open-uri.rb:162:in `catch'
/usr/lib64/ruby/1.8/open-uri.rb:162:in `open_loop'
/usr/lib64/ruby/1.8/open-uri.rb:132:in `open_uri'
/usr/lib64/ruby/1.8/open-uri.rb:518:in `open'
/usr/lib64/ruby/1.8/open-uri.rb:30:in `open'
/home2/myproject/rails/project1/app/controllers/home_controller.rb:13:in `index'
-------------------------------------

Solution:

I put the code in begin and rescue block (just like try and catch block in Java).

My controller looks like this:

require ‘rss’

def index

begin

rss = RSS::Parser.parse(open(“http://blog.ainakatani.com/?feed=rss2″).read, false)

@rss_blog = rss.items[0]

@blog_success = true

rescue

@blog_success = false

end

end

Now, in my view, I added a piece of code looks like this:

<% if @blog_success %>

<p><%= @rss_blog.title %></p>

<p><%= @rss_blog.description %></p>

<% end %>

Now the recent post will be displayed only if the controller could succeed to get the information.

Share

require ‘rss’
def index
begin
rss = RSS::Parser.parse(open(“http://blog.ainakatani.com/?feed=rss2″).read, false)
@rss_blog = rss.items[0]
@blog_success = true
rescue
@blog_success = false
end
end
Now, in my view, I added a piece of code looks like this:
<% if @blog_success %>
<p><%= @rss_blog.title %></p>
<p><%= @rss_blog.description %></p>
<% end %>

Meta tags on RoR

On my website Mixed Baby Name, I have a dedicated page for each baby name.  For example, the name Ai is on this page.

Because I use layout ‘application‘, by default, all of the pages’ title, keywords, and description were same as specified in layouts/application.html.erb

I wanted to show a baby name on the browser tab (title) so that when the multiple pages are open on tabs, the users will know which page is on which tab. Bookmarking would also be easier.

I found this article by SEO on Rails very useful: Getting your meta tags on track

Now each of the name pages has a unique title.  Also, when you click on a flag, the new page title also contains the region name.

Share

Sometimes when you ask a user an input, he/she may include white space before/after the actual input by mistake.
You may want to clean them up before saving the input into the database.
Same can be said when the user performs a search.  On my website Mixed Baby Name, if the user types
‘Ai    ’
or
‘    Ai’
or even worse,
‘    Ai     ‘
instead of  just ‘Ai’ to look for my name, I have to make sure that the user won’t get an empty result.
The method you are looking for is strip.
I find strip! (with the ! mark) very useful, because it does a strip in place.
For your models, you can write a piece of code like this in your model to ensure that your records won’t have any white space at the beginning and end.
class Babyname < ActiveRecord::Base
before_validation :delete_whitespace
def delete_whitespace
self.name.strip!
end
end
This will define and call the function delete_whitespace before any kind of validation happens  (such as presence of other attributes and uniqueness of the attribute, etc.)
You can also want to add a line of code like this  after the strip to ensure that only the first letter is capitalized.
self.name.capitalize!
For example, this will change the name entry “AI” or “ai” into “Ai” in place.

Share

Joining attributes into a string

If you have multiple objects and you want to show certain attributes as one string, with, for example, a comma in between, you write:

<%= objects.map(&:attribute).join(, ‘) %>

For example, if I want to output a string consisting some objects(say babynames)’ names, I write:

<%= babynames.map(&:name).join(‘, ‘) %>

The output will be something like:

Andrew, Chris, Oliver, Anna

This is nice because you don’t have to write a loop and check whether to add a comma (or period or whatever) after each name.

Share