もた日記

くだらないことを真面目にやる

Railsメモ(30) : DBをSQLite3からPostgreSQLに変更する

groupdateというgemを使おうとしたらSQLite3はサポートしていないとのこと。今後、似たような状況が発生すると思われるのでDBをSQLite3からPostgreSQLに変更してみる。

PostgreSQL 9.4のインストール


下記ページを参考にVagrant上のCentOS 6.6(64bit)にPostgreSQL 9.4をインストールしてみる。

まず、CentOS-Base.repoファイルの[base]と[updates]セクションにexclude=postgresql*を追加する。

$ sudo vi /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-$releasever - Base
 …
exclude=postgresql*

#released updates
[updates]
name=CentOS-$releasever - Updates
 …
exclude=postgresql*

下記コマンドでPGDG RPMファイルをインストールする。

$ sudo yum localinstall http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-centos94-9.4-1.noarch.rpm
読み込んだプラグイン:fastestmirror
ローカルパッケージ処理の設定をしています
 …
インストール:
  pgdg-centos94.noarch 0:9.4-1

完了しました!

そして、postgresql94-serverをインストールする。

$ sudo yum install postgresql94-server
読み込んだプラグイン:fastestmirror
インストール処理の設定をしています
 …
インストール:
  postgresql94-server.x86_64 0:9.4.4-1PGDG.rhel6

依存性関連をインストールしました:
  postgresql94.x86_64 0:9.4.4-1PGDG.rhel6                             postgresql94-libs.x86_64 0:9.4.4-1PGDG.rhel6

完了しました!

これでインストールは完了したので、データベースを初期化する。

$ sudo service postgresql-9.4 initdb
データベースを初期化中:                                    [  OK  ]

今後、OS起動時にPostgreSQLサービスが自動起動するように設定を有効にする。

$ sudo chkconfig postgresql-9.4 on

インストールした直後なので手動でサービスを起動する。

$ sudo service postgresql-9.4 start
postgresql-9.4 サービスを開始中:                           [  OK  ]

これで接続できるようになったのでバージョンを確認してみる。

$ psql --version
psql (PostgreSQL) 9.4.4

と、参考ページではこれでインストール設定は完了となっていたが、Railsで使用すると問題が出てくるのでpostgresql94-develを追加インストール。

$ sudo yum install postgresql94-devel
読み込んだプラグイン:fastestmirror
インストール処理の設定をしています
 …
インストール:
  postgresql94-devel.x86_64 0:9.4.4-1PGDG.rhel6

完了しました!

pg_configがインストールされるのでコマンドが実行できるようにパスを通しておく。

export PATH=/usr/pgsql-9.4/bin:$PATH
$ which pg_config
/usr/pgsql-9.4/bin/pg_config


PostgreSQLのユーザ作成とパスワード設定


デフォルトでpostgresユーザが作成されているのでパスワードを設定する。

$ sudo -u postgres psql
psql (9.4.4)
"help" でヘルプを表示します.

postgres=# \password postgres
新しいパスワード:
もう一度入力してください:

新しいユーザとしてCREATEDB権限を持つユーザを作成する。ユーザ名とパスワードはvagrantとした。

postgres=# CREATE USER vagrant WITH PASSWORD 'vagrant' CREATEDB;
CREATE ROLE
postgres=# \du
                                         ロール一覧
 ロール名 |                                 属性                                 | メンバー
----------+----------------------------------------------------------------------+----------
 postgres | スーパーユーザ, ロールを作成できる, DBを作成できる, レプリケーション | {}
 vagrant  | DBを作成できる                                                       | {}

パスワード認証で接続するようにpg_hba.confファイルを編集(METHODをmd5に変更)してPostgreSQLサービスを再起動する。

$ sudo cat /var/lib/pgsql/9.4/data/pg_hba.conf
 …
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
# local   all             all                                     peer
local   all             all                                     md5
# IPv4 local connections:
# host    all             all             127.0.0.1/32            ident
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
# host    all             all             ::1/128                 ident
host    all             all             ::1/128                 md5
$ sudo service postgresql-9.4 restart
postgresql-9.4 サービスを停止中:                           [  OK  ]
postgresql-9.4 サービスを開始中:                           [  OK  ]

これでパスワード認証で接続するようになった。

$ psql -U vagrant -d postgres -h localhost
ユーザ vagrant のパスワード:


Railsアプリの変更点


Railsアプリの変更点を確認するためにデフォルトDBをPostgreSQLとしてアプリを新規作成する。

$ rails new appname -d postgresql --skip-bundle

ファイルの差分を確認してみたところ、Gemfileconfig/database.ymlを修正すればよさそうだ。

Gemfileの編集

SQLite3からPostgreSQLを使用するように変更してbundle installする。

# Use sqlite3 as the database for Active Record
# gem 'sqlite3'
# Use postgresql as the database for Active Record
gem 'pg'

もし下記エラーが発生する場合は、postgresql94-develがインストールされているかの確認と、pg_configコマンドが使えるかの確認をする。

Installing pg 0.18.2 with native extensions

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    /home/vagrant/.rbenv/versions/2.2.2/bin/ruby -r ./siteconf20150823-19680-xh7x9r.rb extconf.rb
checking for pg_config... no
No pg_config... trying anyway. If building fails, please try again with
 --with-pg-config=/path/to/pg_config
checking for libpq-fe.h... no
Can't find the 'libpq-fe.h header
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.
 …
extconf failed, exit code 1

Gem files will remain installed in /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/pg-0.18.2 for inspection.
Results logged to /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/extensions/x86_64-linux/2.2.0-static/pg-0.18.2/gem_make.out
An error occurred while installing pg (0.18.2), and Bundler cannot continue.
Make sure that `gem install pg -v '0.18.2'` succeeds before bundling.


config/database.ymlの編集

config/database.ymlの変更点は多いので、rails new appname -d postgresqlで作成したファイルを持ってくる。
最初に、ファイルの中でappnameとなっている文字列を既存アプリ名に変更する。
次にPostgreSQLの接続情報を追加する(username以降が追加分)。

default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: 5
  username: vagrant
  password: vagrant
  host: localhost
  port: 5432


DB作成、マイグレーション、データ追加

以上で設定は完了したのでDB作成、マイグレーション、データ追加などをすれば今までどおりアプリが動作する。
デフォルトのdevelopment環境のDB名はアプリ名_developmentだが、設定ファイルで変更可能。

$ rake db:create
$ rake db:migrate
$ rake db:seed_fu

なお、下記エラーが発生する場合はpg_hba.confの設定がうまくいっていない。

$ rake db:create
FATAL:  ユーザ"vagrant"のIdent認証に失敗しました
 …

ちなみに、PostgreSQLに変更したのでgroupdateというgemのメソッドが使えるようになった。

[1] pry(main)> Song.group_by_day(:created_at).count
   (22.7ms)  SELECT COUNT(*) AS count_all, (DATE_TRUNC('day', (created_at::timestamptz - INTERVAL '0 hour') AT TIME ZONE 'Etc/UTC') + INTERVAL '0 hour') AT TIME ZONE 'Etc/UTC' AS day FROM "songs" WHERE (created_at IS NOT NULL) GROUP BY (DATE_TRUNC('day', (created_at::timestamptz - INTERVAL '0 hour') AT TIME ZONE 'Etc/UTC') + INTERVAL '0 hour') AT TIME ZONE 'Etc/UTC'
{
    Sun, 23 Aug 2015 00:00:00 UTC +00:00 => 2500
}

パーフェクト Ruby on Rails

パーフェクト Ruby on Rails