Skip to content

64kramsystem/json_on_rails

Repository files navigation

Build Status Coverage Status

JSON on Rails

This gem adds native support for MySQL [5.7+] JSON data type to Rails 4.2.

Introduction

Rails 5 introduced native support for the [MySQL] JSON data type; however, due to the Rails feature policy, version 4 won't receive this functionality.

This gem adds a Rails JSON data type, allowing the user to work with JSON attributes transparently, as a Array/Hash/etc.

The inner working is simple, and uses the standard Rails (internal) APIs; this is explained in a blog post of mine.

Installation

Add the gem to the Gemfile of your rails project:

gem "json_on_rails", "~> 0.2.0"

and update the environment:

$ bundle install

Change the mysql connection adapter to mysql2_json, in config/database.yml:

default: &default
  adapter: mysql2_json

that's all!

Usage/example

Create a table:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table "migration_models" do |t|
      t.string "login", null: false, limit: 24
      t.json "extras"
    end
  end
end

or add the column to an existing one:

class CreateUsers < ActiveRecord::Migration
  def change
    add_column "users", "extras", :json
  end
end

define the model (rails will automatically pick up the data type):

class User < ActiveRecord::Base; end

then (ab)use the new attribute!:

User.create!(login: "saverio", extras: {"uses" => ["mysql", "json"]})
# ...
User.last.extras.fetch("uses") # => ["mysql", "json"]

The schema can be dumped as usual; json columns will be transparently included:

$ rake db:schema:dump
$ cat db/schema.rb
ActiveRecord::Schema.define(version: 0) do

  create_table "users", force: :cascade do |t|
    t.json   "extras"
  end

end

Caveats/further documentation

MySQL SELECT DISTINCT JSON bug (IMPORTANT!)

MySQL versions up to at least 5.7.12 have a serious JSON bug.

In some cases, queries using DISTINCT on VARCHAR and JSON columns will not perform the deduplication, resulting in duplicate rows being returned, if there are any.

This has been fixed between 5.7.13 and 5.7.18 (I couldn't find the related enty in the release notes), therefore, MySQL 5.7 users are urged to upgrade to a recent version if they use JSON columns.

Documentation

Users are encouraged to have a look at the test suite (especially here and here) for an exhaustive view of the functionality.

JSON Symbols

Don't forget that JSON doesn't support symbols, therefore, they can be set, but are accessed/loaded as strings.

MySQL decimal normalization

MySQL (up to 8.0.3, included) will normalize decimal numbers with zero fractional (e.g. 5.0) to integers, therefore, changing the data type on save.

See relevant bug.