Question

TL/DR: What's a good way to use an underscored naming convention serverside (RoR) with a camelCased naming convention clientside (JS)

Server-side programming environments like Ruby on Rails use underscored variables. Conventionally, JavaScript uses camelCased variables. This is problematic when sending data from the client to the server.

For example, consider sending user information to the client. There may be a property in the database called num_times_ordered, yet in JavaScript you'd traditionally want to refer to this as numTimesOrdered.

Has anyone come up with an elegant way of dealing with this? Here are some options, none particularly nice:

  1. Convert data to camelCase when fetched from server.
  2. Use camelCase when sending it from the server
  3. Use an underscored naming convention in your Javascript (although then you're inconsistent with any third party libraries, like jQuery)
  4. Use a camelCased naming convention on your backend (although then you're inconsistent with your backend's conventions)

I'm leaning towards #3, and using underscores in my JavaScript. It'll look weird when I use camelCased third party libraries, though.

Was it helpful?

Solution

I believe ember.js (via Ember Data) takes approach #1: converting underscored JSON to camelCase on the client-side when fetched; and doing the reverse before posting back to the server.

I've been working on a small library that performs these conversions: https://github.com/domchristie/humps, allowing you to do things like:

// GET
$.ajax({
  url: '/posts',
  dataType: 'json',
  success: function(data, status, xhr) {
    data = humps.camelizeKeys(data);
  }
});

// POST
$.ajax({
  type: 'POST',
  url: '/posts'
  dataType: 'json',
  data: humps.decamelizeKeys({
    title: "Foo",
    publishedAt: "2012-09-03T21:35:46.068Z"
  })
});
// Sends: { title: "Foo", published_at: "2012-09-03T21:35:46.068Z" }

I should add, it has not been heavily tested, but contributions welcome!

OTHER TIPS

Resurrecting this for a more modern approach.

This is a great use case for axios interceptors

Basically, define a client class and attach a before/after interceptor that converts the request/response data.

export default class Client {
    get(url, data, successCB, catchCB) {
        return this._perform('get', url, data, successCB, catchCB);
    }

    post(url, data, successCB, catchCB) {
        return this._perform('post', url, data, successCB, catchCB);
    }

    _perform(method, url, data, successCB, catchCB) {
        // https://github.com/axios/axios#interceptors
        // Add a response interceptor
        axios.interceptors.response.use((response) => {
            response.data = toCamelCase(response.data);
            return response;
        }, (error) => {
            error.data = toCamelCase(error.data);
            return Promise.reject(error);
        });

        // Add a request interceptor
        axios.interceptors.request.use((config) => {
            config.data = toSnakeCase(config.data);
            return config;
        }, (error) => {
            return Promise.reject(error);
        });

        return axios({
            method: method,
            url: API_URL + url,
            data: data,
            headers: {
                'Content-Type': 'application/json',
            },
        }).then(successCB).catch(catchCB)
    }
}

Here's a gist with a longer example using React/axios.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top