2021年1月20日水曜日

ActiveRecord 超入門

概要

ActiveRecord を使うときは大体 Rails や Sinatra などの Web フレームワークが絡んできます
データベースの操作をするようなバッチを作る場合は ActiveRecord 単体で使いたいことが出てくると思います
そんなときのために ActiveRecord のみで使う方法を紹介します

環境

  • macOS 11.1
  • Ruby 3.0.0p0
  • ActiveRecord 6.1.1

インストール

  • bundle init
  • vim Gemfile
gem "activerecord"
gem "mysql2"
  • bundle install

今回は MySQL に接続してみます

MySQL 側準備

以下の構成の test.users テーブルにアクセスします

  • mysql -u root test -e "show create table users\G"
Create Table: CREATE TABLE `users` (
  `id` int NOT NULL AUTO_INCREMENT,
  `first_name` varchar(128) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci


データも適当に入れておきます


* mysql -u root test -e "select * from users\G"

*************************** 1. row ***************************
        id: 1
first_name: hawk
       age: 10
*************************** 2. row ***************************
        id: 2
first_name: snowlog
       age: 20
*************************** 3. row ***************************
        id: 3
first_name: hawksnowlog
       age: 30

モデルを作成する

establish_connection で接続先のデータベース情報を明記します
Rails などを使っている場合は config/database.yml に記載します

  • mkdir models
  • vim models/users.rb
require 'active_record'

class User < ActiveRecord::Base
  establish_connection(
    adapter:  "mysql2", 
    host:     "localhost",
    username: "root",
    password: "",
    database: "test",
  )
end

動作確認

作成したモデルを使用する動作確認用のスクリプトを作成します

  • vim app.rb
require './models/user.rb'

users = User.all
users.each do |user|
  puts user.id
  puts user.first_name
  puts user.age
end
  • bundle exec ruby app.rb

test.users テーブルの情報が表示されることを確認しましょう

Relation がある場合はどうなるか

外部キー制約が入ると一気に複雑になります
has_onebelongs_to など ActiveRecord::Base の基本的な使い方の知識が必要になります

テーブル修正

sports テーブルを作成し user はどれか一つのスポーツと紐付けます
sport.idusers.sport_id で外部キー制約を設けます


* create table sports (id int auto_increment, name varchar(255), primary key(id));
* alter table users add sport_id int;
* alter table users add foreign key (sport_id) references sports(id);
* insert into sports values (null, "baseball");
* insert into sports values (null, "soccer");
* insert into sports values (null, "basketball");
* update users set sport_id=1 where id=1;
* update users set sport_id=2 where id=2;
* update users set sport_id=3 where id=3;

  • select * from sports\G
*************************** 1. row ***************************
  id: 1
name: baseball
*************************** 2. row ***************************
  id: 2
name: soccer
*************************** 3. row ***************************
  id: 3
name: basketball
  • select * from users\G
*************************** 1. row ***************************
        id: 1
first_name: hawk
       age: 10
sport_id: 1
*************************** 2. row ***************************
        id: 2
first_name: snowlog
       age: 20
sport_id: 2
*************************** 3. row ***************************
        id: 3
first_name: hawksnowlog
       age: 30
sport_id: 3

スクリプト修正

新たに Sport クラスを追加します
establish_connect はもう少しうまく書けると思います
has_onebelongs_to でテーブル同士に関係性を持たせます

  • vim models/user.rb
require 'active_record'

class User < ActiveRecord::Base
  establish_connection(
    adapter:  "mysql2", 
    host:     "localhost",
    username: "root",
    password: "",
    database: "test",
  )
  belongs_to :sport
end

class Sport < ActiveRecord::Base
  establish_connection(
    adapter:  "mysql2", 
    host:     "localhost",
    username: "root",
    password: "",
    database: "test",
  )
  has_one :user
end
  • vim app.rb
require './models/user.rb'

users = User.joins(:sport).all
# users = User.includes(:sport).all
users.each do |user|
  puts user.id
  puts user.first_name
  puts user.age
  puts user.sport.name
end


外部キー先の情報も取得する場合は joins または includes を使います

  • bundle exec ruby app.rb

これで外部キーの参照先の情報も取得できるようになります

最後に

ActiveRecord を単体で使えるようになると理解も深まると思います
Rails などで使うときも幅が広がると思います

参考サイト

0 件のコメント:

コメントを投稿