Build a Rails App with TiDB and the ActiveRecord TiDB Adapter
Tags: rails, tidb, activerecord
Published: 2021-08-27 08:48:17

---
title: Build a Rails App with TiDB and the ActiveRecord TiDB Adapter
published: true
description: 
tags: rails, tidb, activerecord
//cover_image: https://direct_url_to_image.jpg
---

[TiDB](https://github.com/pingcap/tidb) is an open-source NewSQL database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads. It is MySQL compatible and features horizontal scalability, strong consistency, and high availability.

I assumed using TiDB as a backend storage layer of Ruby on Rails application perhaps is a great way to manage storages into one place.

This post describes how to get started and how to use TiDB as backend of Ruby on Rails applications for developers.

Example source codes are available at [rails-tidb](https://github.com/hooopo/rails-tidb) in GitHub.

## Setting up local TiDB server
Install tiup
```bash
$ curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
```
Starting TiDB playground
```bash
$ tiup playground  nightly
```

Then, we can connect to the TiDB instance just as connecting to MySQL.

```bash
mysql --host 127.0.0.1 --port 4000 -u root -p
```

## Initialize Ruby on Rails application

```bash
$ ruby -v
ruby 2.7.0

$ rails -v
Rails 6.1.4

$ rails new tidb-rails --database=mysql --api
```

Add [activerecord-tidb-adapter](https://github.com/pingcap/activerecord-tidb-adapter) to Gemfile

```bash
$ bundle add activerecord-tidb-adapter --version "~> 6.1.0"
```

After creating a new app, edit `config/database.yml` to configure connection settings to TiDB.

```yml
default: &default
  adapter: tidb
  encoding: utf8mb4
  collation: utf8mb4_general_ci
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: 127.0.0.1
  port: 4000
  variables:
    tidb_enable_noop_functions: ON
  username: root
  password:

development:
  <<: *default
  database: tidb_rails_development
```
No need to add additional database configurations to use TiDB. It’s ready to use TiDB as a database of the Rails app!

## Create a database

```bash
$ bundle exec rails db:create
Created database 'tidb_rails_development'
Created database 'tidb_rails_test'
```
## Manipulate TiDB data through Rails app

Defining Model using rails g command.

```bash
$ bundle exec rails g model user email:string name:string gender:integer
...
$ vim ./db/migrate/20210826174523_create_users.rb # edit
```

db/migrate/20210826174523_create_users.rb

```ruby
class CreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      t.string :email, index: {unique: true}
      t.string :name
      t.integer :gender

      t.timestamps
    end
  end
end
```

Then, apply database migration.

```
$ bundle exec rails db:migrate
== 20210826174523 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.1717s
== 20210826174523 CreateUsers: migrated (0.1717s) =============================
```

Launch Rails console to play with the app.

```bash
$ bundle exec rails c
Running via Spring preloader in process 13378
Loading development environment (Rails 6.1.4.1)
irb(main):001:0> 30.times.each { |i| User.create!(email: "user-#{i}@example.com", name: "user-#{i}", gender: i % 3) }
   (1.2ms)  select version()
  TRANSACTION (0.8ms)  BEGIN
  User Create (93.5ms)  INSERT INTO `users` (`email`, `name`, `gender`, `created_at`, `updated_at`) VALUES ('user-0@example.com', 'user-0', 0, '2021-08-26 17:50:40.661945', '2021-08-26 17:50:40.661945')
  TRANSACTION (14.9ms)  COMMIT
...
=> 30
irb(main):002:0> User.count
   (8.9ms)  SELECT COUNT(*) FROM `users`
=> 30
irb(main):003:0> User.first
  User Load (5.8ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User id: 1, email: "user-0@example.com", name: "user-0", gender: 0, created_at: "2021-08-26 17:50:40.661945000 +0000", updated_at: "2021-08-26 17:50:40.661945000 +0000">
```

## Summary

TiDB offers MySQL interfaces which can be used as backend database layers of Ruby on Rails applications. 

We can use ActiveRecord ORM directly, or use activerecord-tidb-adpater, a lightweight extension of ActiveRecord that supports several rails versions, including 5.2, 6.1, and 7.0. 

The [activerecord-tidb-adapter](https://github.com/pingcap/activerecord-tidb-adapter) provides compatible patches and some tidb-specific functions, such as [Sequence](https://docs.pingcap.com/tidb/stable/sql-statement-create-sequence).