Virtually every single site that I had made have a form that asks for the user’s city and state. It’s a simple thing, omnipresent in almost any website, but oddly there’s no library to deal with that. Maybe its a regional need, specific to my country, IDK, I just know that is very usual to my clients require this information. So, in my day-to-day programmer’s life I have to copy-and-paste snippets with the full list of states and cities. In my projects I have to make something like that:

PS: of course I use a list of states from my country.

And I do the same thing with cities (actually I use a YAML file for the cities), which isn’t a very neat solution – hard coding your data is never a neat solution. Actually is even worse, because new cities are created every month in my country (so, the city list can be easily oudated), and also I limit the options for my single country.

Looking for better solutions, I found this Carmen gem, which provides a list of states from virtually every country in the world, but unfortunately doesn’t provides a list of cities. Also, it haves a big and frightening notice warning that the gem is outdated.

To solve this problem, I created a gem called city-state. This gem provides an easy way to get a list of states from a country, and also a list of cities from a state. It also have an update mechanism within the gem which avoids that I have to update the gem from time to time with new databases. This gem uses the MaxMind database, a very popular database used in many websites – mainly with the purpose of discover the localization of an IP – and it’s updated weekly.

To install the gem, put it in your Gemfile:

To use its easy like that:

To update the database from, use the CS.update command the internet:


How to build a state list in a form?

Let’s say that you have a form and want that your user picks a state and a city. Usually, you have a form like this:

With CityState gem you’ll change your code to this:


How to build a city list after user chooses a state?

To do that you’ll need to make something using JS. Below is an example on how to do this with Ajax.

  • Thompson Edolo

    Bless! This save me hours.

    • Dinkar Thakur

      I’m getting error

      CS.states(:us)
      NoMethodError: undefined method `present?’ for :US:Symbol

      • Luminus Olumide Alabi

        You need to run CS.update first to get the data from MaxMind.

        I ran into the same issue too.

    • Dinkar Thakur

      How to use CS in model

      • Juan Trejo

        you only need put something like this:
        class Model < ActiveRecord::Base
        ##your attributes and associations

        ## your methods
        ## …………..

        def self.get_countries
        CS.get
        end

        def self.get_states(country_code)
        CS.get country_code.to_sym
        end

        def self.get_cities(state_code)
        CS.get :us state_code.to_sym
        end
        end

  • jeffersonchoi

    Thanks for the gem! Just wondering are there anyways that I can make a city default in my selection?

    • Daniel Loureiro

      Thank you Jefferson. About the “default” behavior, I did the CS gem with a minimalist approach in mind. Instead of making a Rails library, a Sinatra library, a library to be used in raw ruby scripts, and so on, I’ve decided to make something that could be used in any of these softwares. So, there’s no specific Rails code on it. But I think it’s a great idea to make specific helpers to Rails, maybe create another gem, using CS as a building block, and adding helpers to extend Rails form helpers (and “simple_form_for” and “form_for”). I don’t have much time for now, but I think it’s a great idea. Thank you for your suggestion :)

  • Hello Daniel! thanks for gem and the tutorial!

    I found a error in _form.html.erb file!

    missing a *do* after the *each*!

    :D

    • Daniel Loureiro

      thanks Luiz! I wrote this code off the top of my head, directly on the wordpress editor without any actual testing (ugh!). It’s a miracle that this was the only error :P

      If you find another error, please let me know.

  • zainal mustofa

    Hi Daniel,

    if this gem can search for the city, without having to go through the state?

    e.g
    CS.cities(:US) => result all city from United States

  • malam jabba

    @danielloureiro:disqus
    code written above is a bit wrong. please update the code to this:

    Select Your State

    <option value="”>

    Select Your City

    $(‘#states-of-country’).change(function () {
    var input_state = $(this);
    var cities_of_state = $(“#cities-of-state”);

    if($(this).val() == “”) {
    cities_of_state.html(“”);

    } else {
    $.getJSON(‘/cities/’ + $(this).val(), function (data) {
    // cities_of_state.empty();
    var opt = ‘Select Your City’;
    console.log(data);
    if(data.length == 0){

    } else {
    data.forEach(function(i) {
    opt += ” + i + ”;
    cities_of_state.html(opt);
    });
    }
    });
    }
    });

    • malam jabba

      I’d also recommend to change $json by $ajax for drastic performance improvements because $json may slow down the browser while on the other hand $ajax would run async.

  • Divya Kunnath

    The .each method mentioned runs the method on the index. You should probably change that to

    $.each(data, function (i, ele) {

    var opt = ” + ele + ”;

    input_state.append(opt);

    });

    Thanks a lot for sharing this :)

  • Guayo Mena

    This is great! I’ve been looking for something like this
    Can I use it to create also a list of districts nested under province?

  • Sai Bharath kumar

    Hey Daniel,

    is it possible to get the actual name of the country/state from it’s KEY,

    suppose i want INDIA from IN key.