Geocoding using Mapbox, Rails 5 and NuxtJS/VueJS

Geocoding using Mapbox, Rails 5 and NuxtJS/VueJS

<strong>Geocoding is the process of taking latitude and longitude to determine an address, or taking an address and producing latitude and longitude coordinates.</strong>

Geocoding is the process of taking latitude and longitude to determine an address, or taking an address and producing latitude and longitude coordinates.

There are numerous reasons an application needs to use a geocoder. For Now Serving, we use it during the sign up process, as well as making it easy to find nearby restaurants with a single click of ‘Find Me’.

Let’s get to coding!

Rails API

We’ll need to grab the mapbox-sdk and add it to the Gemfile.

_gem_ **'mapbox-sdk'**, **'~>2'**

Create a simple initializer to set the access token in your app (e.g config/initializers/mapbox.rb)

**_Mapbox_**.access_token = MAPBOX_ACCESS_TOKEN

Next, let’s add a couple routes:

_namespace_ **:address_search do** _get_ **'expand'**, **to**: **'expand'** _get_ **'parse'**, **to**: **'parse'

And an address_search_controller.rb:

class AddressSearchController < ApplicationController

Take an addresss and return lat/lng

def expand begin @addresses = Mapbox::Geocoder.geocode_forward(address_params[:a]) unless address_params[:a].nil? render template: 'address_search/result' rescue StandardError render json: { errors: ['Unable to perform forward geocoding'] } end end

Take lat/lng array and return a postal address

def parse begin @location = { latitude: address_params[:latitude].to_f, longitude: address_params[:longitude].to_f } @addresses = Mapbox::Geocoder.geocode_reverse(@location) render template: 'address_search/result' rescue StandardError render json: { errors: ['Unable to perform reverse geocoding'] } end end


def address_params params.permit(:a, :latitude, :longitude) end end

The expand method takes the a query params and asks the geocoder service to return a latitude/longitude array. For getting an address from lat/lng we are expecting a hash like { latitude: 0, longitude: 0 }.

You may not want to render a template here but in my case I wanted to always return an array, so the best way to ensure that happened was rendering it with jbuilder one-liner:

json.array! @addresses

And a request spec:

RSpec.describe 'Address Search' do

it 'parses an address and returns latitude and longitude' do get '/api/v1/address_search/expand', params: { a: '401 B St, San Diego CA' } expect(response).to be_successful end

it 'parses latitude and longitude and returns an address' do get '/api/v1/address_search/parse', params: { longitude: 127.0, latitude: -43.64} expect(response).to be_successful end end

Front End

We’re using the awesome NuxtJS framework for our UI. If you haven’t used it before, definitely give it a look. If you can’t use it, don’t worry; this code will work fine without Nuxt.

We use Vuex actions to call our back end, so we have a store for our Mapbox configuration.

export const actions = {
  locate({ commit }, { longitude, latitude }) {
    return this.$axios.get('/address_search/parse', { params: { longitude: longitude, latitude: latitude } })
  coordinate({ commit }, params) {
    return this.$axios.get('/address_search/expand', { params: { a: params } })

For presentation, we use vue-i18n, vue-notify, bootstrap-vue and vue-fontawesome.

    <font-awesome-icon v-if="state === 1" :icon="['far', 'spinner']" spin />
    <font-awesome-icon v-else :icon="['far', 'location-arrow']" />
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'

export default { components: { FontAwesomeIcon }, props: { locationLabel: { default: 'Find my current location', type: String } }, data() { return { state: 0 } }, computed: { btnVariant() { switch (this.state) { case 0: return 'outline-primary' case 1: return 'info' case 2: return 'success' default: return 'outline-primary' } } }, methods: { findMe() { const vm = this this.state = 1 if (!navigator.geolocation) { vm.$notify({ text: vm.$t('geolocation.not_supported'), group: 'alerts' }) return }

  function success(position) {
    const accuracy = position.coords.accuracy
    vm.$store.dispatch('mapbox/locate', {
      latitude: position.coords.latitude,
      longitude: position.coords.longitude,
      accuracy: accuracy
      .then((resp) =&gt; {
        vm.state = 2
        vm.$emit('result', { name:[0].features[0].place_name, center:[0].features[0].center })
      .catch(() =&gt; {
        vm.state = 0
        vm.$notify({ text: vm.$t('geolocation.not_found'), type: 'warning', group: 'alerts' })

  function error() {
    vm.$notify({ text: vm.$t('geolocation.not_found'), group: 'alerts', type: 'warning' })

  navigator.geolocation.getCurrentPosition(success, error)

} } </script>

There’s a lot going on here, so lets break it all down.

The location button has three states; default state, active state, and a success state. The computed property handles changing out the css classes for each state.

There is also a tooltip that displays on hover to explain that the browser will ask for permission to send location information to the back end.

The findMe method is called on click. In it we have two callbacks for success and error that the browser’s built in [getCurrentPosition]( to work correctly. When the browser provides the latitude and longitude to the success callback, we can send that to the back end using the Vuex action. Once the back end response comes, the component emits a result event containing the address name and coordinates. If permission is denied, we display an error notification. Also if the browser doesn’t support location services, we notify the user of that case.


Congrats you have a fully implemented API for forward and reverse geocoding solution!

Originally published by Todd Baur at

Learn more

☞ The Complete Ruby on Rails Developer Course

☞ Testing Ruby with RSpec: The Complete Guide

☞ How to build Instagram using Ruby on Rails

☞ Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

☞ Nuxt JS with Laravel - Build API driven SSR Vue JS Apps

vue-js nuxt-js ruby-on-rails

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

How to use Inertia.js to build a Vue.js frontend within a Ruby on Rails application

This is an example on how to use Inertia.js to build the frontend with Vue.js within a Ruby on Rails application Styles made with Tailwind CSS.There is already a demo application to show how Inertia.js works (see Ping CRM) - but for PHP/Laravel only. I've build this thing to try Inertia.js with Rails.

Hire Ruby on Rails Developer | Hire RoR Developer

#1 Ruby on Rails development company. Hire Ruby on rails developer or a team to build secure, scalable and complex web solutions with a quick turnaround time.

8 Popular Websites That Use The Vue.JS Framework

In this article, we are going to list out the most popular websites using Vue JS as their frontend framework. Vue JS is one of those elite progressive JavaScript frameworks that has huge demand in the web development industry. Many popular websites are developed using Vue in their frontend development because of its imperative features.

Serverless-side rendering with Vue.js, Nuxt.js and AWS Lambda

We want the best of both worlds. The SEO boost server-side rendering provides, and the speed of a Single Page Application. All this while hosted basically for free in a serverless environment on AWS Lambda. Here’s a quick overview of what we’ll be building for you to get up to speed. Feel free to jump to the step that interests you the most.

How to build a Ruby on Rails Application with Vue.js using JSX

This is a step-by-step tutorial on how to build a Ruby on Rails application with Vue.js using JSX.