LoginSignup
1
0

More than 3 years have passed since last update.

simple_calendarを導入したRails6.0でのDB環境PostgreSQLの設定

Last updated at Posted at 2021-01-05

学習メモ用です。

解決したい問題

simple_calendarを導入したRails6.0で
開発環境DBがSQLite3、本番環境DBがPostgreSQL

本番環境において下記エラーが発生し、posts/index viewが表示されない事態に。
simple_calendarを使っているから?

ActionView::Template::Error (PG::UndefinedColumn: ERROR: column posts.user_id does not exist

なぜか、本番環境ではpostsテーブルにuser_id columnだけが存在しないからうまくいかない。

と、いうことで開発環境にもPostgreSQLを適用してみる!

開発環境

Ruby 2.7.1
Rails 6.0.3
OS macOS Catalina

pggemのインストール

rails6.0では

% rails db:system:change --to=postgesql

このコマンドで簡単に移行できるよう。

以下のようにsqlite3だったところがpgに置き換わる(Gemfileも同様に置き換わる)

config/database.yml

<!-- some long code -->

default: &default
    - adapter: sqlite3
    + adapter: postgresql

<!-- some long code -->

bundle installを実行すると

    [!] There was an error parsing `Gemfile`: You cannot specify the same gem twice with different version requirements.
    You specified: pg (~> 1.4) and pg (>= 0). Bundler cannot continue.

pggemのバージョン違いが同時にあるためbundleinstallできないとのこと
pg (~> 1.4)を残し、gem pgは削除して再度

    Fetching gem metadata from https://rubygems.org/.
    Could not find gem 'pg (~> 1.4)' in any of the
    gem sources listed in your Gemfile.

'pg (~> 1.4)'が見つからないとのことで、gem istall pgを実行すると

    Building native extensions. This could take a while...
    ERROR:  Error installing pg:
    ERROR: Failed to build gem native extension.

            <!-- some long code --> 

    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

            <!-- some long code --> 

No pg_configとCan't find the 'libpq-fe.h header が問題っぽい。

まずPostgreSQLインストールをできていないのでは?

% brew install postgresql

↑これだと最新安定版をインストール可
インストール成功!

% postgres --version postgres 
(PostgreSQL) 13.1

gem install pgを実行

    Building native extensions. This could take a while...
    Successfully installed pg-1.2.3
    Parsing documentation for pg-1.2.3
    Installing ri documentation for pg-1.2.3
    Done installing documentation for pg after 1 seconds
    1 gem installed

    gem 'pg (~> 1.4)' in any of the gem sources listed in your Gemfile

gem 'pg (~> 1.4)'はインストールできなかったので、指定やめた。

再度bundle install実行、無事成功!

rails sを起動してうまくいってるか確かめようとしたところ、
いつも通りyarn installをしろとのことで、

 % yarn install --check-files
    yarn install v1.22.10
    [1/4] 🔍  Resolving packages...
    [2/4] 🚚  Fetching packages...
    [3/4] 🔗  Linking dependencies...
    warning " > webpack-dev-server@3.11.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
    warning "webpack-dev-server > webpack-dev-middleware@3.7.2" has unmet peer dependency "webpack@^4.0.0".
    [4/4] 🔨  Building fresh packages...
    [1/3] ⠈ fsevents
    [-/3] ⠈ waiting...
    error /Users/shigeyuki_yunoki/ucms_app/node_modules/node-sass: Command failed.
    Exit code: 1

       <!-- some long code --> 

    No receipt for 'com.apple.pkg.CLTools_Executables' found at '/'.

    No receipt for 'com.apple.pkg.DeveloperToolsCLILeo' found at '/'.

    No receipt for 'com.apple.pkg.DeveloperToolsCLI' found at '/'.

    gyp: No Xcode or CLT version detected!
    gyp ERR! configure error 
    gyp ERR! stack Error: `gyp` failed with exit code: 1
    gyp ERR! stack     at ChildProcess.onCpExit (/Users/shigeyuki_yunoki/ucms_app/node_modules/node-gyp/lib/configure.js:345:16)
    gyp ERR! stack     at ChildProcess.emit (node:events:376:20)
    gyp ERR! stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:284:12)
    gyp ERR! System Darwin 19.6.0
    gyp ERR! command "/usr/local/Cellar/node/15.5.0/bin/node" "/Users/shigeyuki_yunoki/ucms_app/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
   gyp ERR! cwd /Users/shigeyuki_yunoki/ucms_app/node_modules/node-sass
   gyp ERR! node -v v15.5.0
    gyp ERR! node-gyp -v v3.8.0
   gyp ERR! not ok 
   Build failed with error code: 1

   <!-- some long code --> 

yarnにおけるXcodeとCLTをインストール

gyp: No Xcode or CLT version detected!

これが問題らしい

% pkgutil --packages | grep CL

CLToolsを確認するが何も出力されず、

Xcodeのバージョンの問題だと思われるため、再インストール

% sudo rm -rf $(xcode-select -print-path)
Password:

macのパスワードを入力したものの反応なし

% sudo rm -rf /Library/Developer/CommandLineTools

Xcode Command Line Toolsのあるディレクトリを削除することでアンインストールする。
こちらは実行していないが、最終的にうまくいったので、Xcodeはインストールしていなかったものと思われ。

% xcode-select --install

コマンド上でXcode Command Line Toolsをインストール。

xcode-select: error: command line tools are already installed, use "Software Update" to install updates

インストール済みだと上記になる

Xcodeをインストールしてから実行すると以下が出力された。

% pkgutil --packages | grep CL
    com.apple.pkg.CLTools_Executables
    com.apple.pkg.CLTools_SDK_macOS110
    com.apple.pkg.CLTools_SDK_macOS1015
    com.apple.pkg.CLTools_macOS_SDK

% pkgutil --pkg-info com.apple.pkg.CLTools_Executables
    package-id: com.apple.pkg.CLTools_Executables
    version: 12.3.0.0.1.1607026830
    volume: /
    location: /
    install-time: 1609036372
    groups: com.apple.FindSystemFiles.pkg-group

No Xcode or CLT versionは解決した!

% yarn install --check-files
   yarn install v1.22.10
    [1/4] 🔍  Resolving packages...
    [2/4] 🚚  Fetching packages...
    [3/4] 🔗  Linking dependencies...
    warning " > webpack-dev-server@3.11.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
    warning "webpack-dev-server > webpack-dev-middleware@3.7.2" has unmet peer dependency "webpack@^4.0.0".
    [4/4] 🔨  Building fresh packages...
    ✨  Done in 184.82s.

yarn install成功!

PGSQLサーバーの起動

rails sを起動してみる

  PG::ConnectionBad (could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
    ):

PGSQLサーバーが動いていないということらしい

% brew service start postgresql
Error: Unknown command: service
% brew tap homebrew/services

このコマンドでservicesのような外部コマンドを取り込めるとのこと

    % brew services start postgresql
    ==> Successfully started `postgresql` 

PGSQLサーバーが動いた!

PGSQLでのDBの作成と権限付与

rails s起動すると

ActiveRecord::NoDatabaseError
FATAL: database "ucms_app_development" does not exist

DBが存在していない

このページで最初にあげたconfig/database.ymlの詳しい中身はこちら。

config/database.yml

        default: &default
        - adapter: sqlite3 
        + adapter: postgresql 
        username: ucms_app 追記
        password: 追記
        host: localhost 追記
        encoding: utf8
        pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
        timeout: 5000

        development:
        <<: *default
        - database: db/development.sqlite3
        + database: ucms_app_development

        test:
        <<: *default
        - database: db/test.sqlite3
        + database: ucms_app_test

        production:
        <<: *default
        - database: db/production.sqlite3
        # database: ucms_app_production  Herokuへのデプロイを考慮して削除
        # username: ucms_app default内に追記したので削除
        password: <%= ENV['UCMS_APP_DATABASE_PASSWORD'] %>

下記コマンドにより、PGSQLのDB設定にpgが導入され、sqliteが削除された。
更に設定を追記したのが上記。

% rails db:system:change --to=postgesql

これでDBが作られたわけではない。

% psql -l                                   

PGSQLのDB表示する

List of databases

Name Owner Encoding Collate Ctype Access privileges
postgres (macユーザー)     UTF8 C C
template0 (macユーザー)    UTF8 C C =c/(macユーザー)
template1 (macユーザー)    UTF8 C C =c/(macユーザー)

(3 rows)

"(macユーザー)"はユーザー毎に異なる。

DBを作成する

% createdb ucms_app_development
% createdb ucms_app_test 

% createdb ucms_app_productionはherokuで本番環境を扱うため不要

% psql -l

List of databases

Name Owner Encoding Collate Ctype Access privileges
postgres (macユーザー) UTF8 C C
template0 (macユーザー) UTF8 C C =c/(macユーザー)
template1 (macユーザー) UTF8 C C =c/(macユーザー)
ucms_app_development (macユーザー) UTF8 C C
ucms_app_test (macユーザー) UTF8 C C

(5 rows)

% psql -c 'select * from pg_user' postgres
usename usesysid usecreatedb usesuper userepl usebypassrls passwd valuntil useconfig
(macユーザー) 10 t t t t ********

(1 row)

ユーザーを作成する

% createuser ucms_app

'(macユーザー)'でpsqlを操作する

% psql -U (macユーザー) ucms_app_development

 ucms_app_development=# \du #ユーザー一覧を表示

List of roles

Role name Attributes Member of
(macユーザー) Superuser, Create role, Create DB, Replication, Bypass RLS {}
ucms_app {}
 ucms_app_development=# ALTER ROLE "ucms_app" WITH Superuser; 
 ALTER ROLE #⬆️(macユーザー)がucms_appに権限を付与。
 ucms_app_development=# \du

List of roles

Role name Attributes Member of
(macユーザー) Superuser, Create role, Create DB, Replication, Bypass RLS {}
ucms_app Superuser {}

config/database.ymlusername:と一致させる必要がある。

% psql -c 'select * from pg_user' postgres     
usename usesysid usecreatedb usesuper userepl usebypassrls passwd valuntil useconfig
(macユーザー) 10 t t t t ********
ucms_app 16384 f t f f ********

(2 rows)

% psql -l

List of databases

Name Owner Encoding Collate Ctype Access privileges
postgres (macユーザー) UTF8 C C
template0 (macユーザー) UTF8 C C =c/(macユーザー) +
(macユーザー)=CTc/(macユーザー)
template1 (macユーザー) UTF8 C C =c/(macユーザー) +
(macユーザー)=CTc/(macユーザー)
ucms_app_development ucms_app UTF8 C C
ucms_app_test ucms_app UTF8 C C
ucms_app_test-0 ucms_app UTF8 C C
ucms_app_test-1 ucms_app UTF8 C C

(7 rows)

% createdb ucms_app_development
% createdb ucms_app_test 

本当は上記のコマンドは

% createdb ucms_app_development -0 ucms_app
% createdb ucms_app_test -0 ucms_app

として、オーナーをusername:と同様のucms_appでDB作成すれば良かったが、
どこかの段階でオーナーが切り替えられたのでよしとする。

 ucms_app_development=# ALTER ROLE "ucms_app" WITH Superuser;
 ALTER ROLE

多分ここ。

rails sすると下記になるのでmigrateを実行する

    ActiveRecord::PendingMigrationError (

    Migrations are pending. To resolve this issue, run:

            rails db:migrate RAILS_ENV=development

    ):

これでPostgreSQLのDB環境設定は完了!

gem 'yaml_db'でsqlite3のデータをpgに移行

gem 'yaml_db'
bundle exec rails db:data:dump

下記ファイルが作られる。

db/data.yml
       ーーー ar_internal_metadata:
            columns:
            - key
            - value
            - created_at
            - updated_at
            records: 
            - - environment
                - development
                - '2020-11-13 12:22:09.119176'
                - '2020-11-13 12:22:09.119176'

            ---
            posts:
            columns:
            - id
            - title
            - content
            - start_time
            - user_id
            - created_at
            - updated_at
            records: 

            <!-- some long code -->

            - - 75
                - ddd
                - ddd
                - '2020-12-18 00:00:00'
                - 1
                - '2020-12-18 12:29:39.573445'
                - '2020-12-18 12:29:39.573445'

            <!-- some long code -->


            ---
            users:
            columns:
            - id
            - name
            - email
            - seriousness
            - created_at
            - updated_at
            - password_digest
            records: 
            - - 1
                - sssss
                - s@gmail.com
                - 中等症
                - '2020-11-13 12:23:49.247847'
                - '2020-11-29 01:57:03.602324'
                - "$2a$12$/r0ip..."

            <!-- some long code -->

% bundle exec rails db:data:load

PostgreSQLにこれで移行できる。

ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column "user_id" of relation "posts" does not exist
    LINE 1: ...INTO "posts" ("id","title","content","start_time","user_id",...
                                                                ^
    bin/rails:4:in `<main>'

    Caused by:
    PG::UndefinedColumn: ERROR:  column "user_id" of relation "posts" does not exist
    LINE 1: ...INTO "posts" ("id","title","content","start_time","user_id",...

なぜか、postsのuser_idがなくなっている。。。
schema.rbが書き変わってる。。。なぜだ。。。

PostgreSQL導入前

ActiveRecord::Schema.define(version: 2020_11_15_015429) do

    create_table "posts", force: :cascade do |t|
        t.string "title"
        t.text "content"
        t.datetime "start_time"
        t.integer "user_id"
        t.datetime "created_at", precision: 6, null: false
        t.datetime "updated_at", precision: 6, null: false
        t.index ["user_id", "created_at"], name: "index_posts_on_user_id_and_created_at"
        t.index ["user_id"], name: "index_posts_on_user_id"
    end

PostgreSQL導入後

    ActiveRecord::Schema.define(version: 2020_11_15_015429) do

    # These are extensions that must be enabled in order to support this database
    enable_extension "plpgsql"

    create_table "posts", force: :cascade do |t|
        t.string "title"
        t.text "content"
        t.datetime "start_time"
        t.datetime "created_at", precision: 6, null: false
        t.datetime "updated_at", precision: 6, null: false
    end

直接、PostgreSQLに:user_id columnを作る!

    ucms_app_development=# ALTER TABLE posts ADD COLUMN user_id integer;  

    ALTER TABLE


    ucms_app_development=# \d posts

                 Table "public.posts"
    Column   |              Type              | Collation | Nullable |              Default              
    ------------+--------------------------------+-----------+----------+-----------------------------------
    id         | bigint                         |           | not null | nextval('posts_id_seq'::regclass)
    title      | character varying              |           |          | 
    content    | text                           |           |          | 
    start_time | timestamp without time zone    |           |          | 
    created_at | timestamp(6) without time zone |           | not null | 
    updated_at | timestamp(6) without time zone |           | not null | 
    user_id    | integer                        |           |          | 
    Indexes:
        "posts_pkey" PRIMARY KEY, btree (id)

    (END)

これでpostsテーブルにuser_id追加完了!

    % rails db:migrate              
    == 20201115015429 AddUserIdToPosts: migrating =================================
    == 20201115015429 AddUserIdToPosts: migrated (0.0000s) ========================

再度、% bundle exec rails db:data:loadでdb/data.ymlファイルをpgのDBに!

本番環境herokuにDB適応させる!

 % heroku pg:psql           
    --> Connecting to postgresql...
    psql (13.1, server 12.5 (Ubuntu 12.5-1.pgdg16.04+1))
    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
    Type "help" for help.


    ucmsapp...::DATABASE=> \d posts
                                            Table "public.posts"
    Column   |              Type              | Collation | Nullable |              Default              
    ------------+--------------------------------+-----------+----------+-----------------------------------
    id         | bigint                         |           | not null | nextval('posts_id_seq'::regclass)
    title      | character varying              |           |          | 
    content    | text                           |           |          | 
    start_time | timestamp without time zone    |           |          | 
    created_at | timestamp(6) without time zone |           | not null | 
    updated_at | timestamp(6) without time zone |           | not null | 
    Indexes:
        "posts_pkey" PRIMARY KEY, btree (id)

    ucmsapp...::DATABASE=> ALTER TABLE posts ADD COLUMN user_id integer;
    ALTER TABLE

開発環境と同様にuser_idを作成

% heroku run bundle exec rails db:data:load

もしかすると
% heroku run rails db:migrate
すれば良かっただけかも。

ページ下部に追記あり。

herokuに開発環境のDBをコピーするには?

    heroku pg:push ucms_app_development ucmsapp...             
    ▸    Unknown database: ucmsapp... Valid options are:
    ▸    DATABASE_URL
config/database.yml

    #You can use this database configuration with:
    #
    #   production:
    #     url: <%= ENV['DATABASE_URL'] %>

productionのurlは'DATABASE_URL'とのこと。

    heroku pg:push ucms_app_development DATABASE_URL
    heroku-cli: Pushing ucms_app_development ---> postgresql...
    ▸    Remote database is not empty. Please create a new database or use
    ▸    heroku pg:reset

    heroku pg:reset                    
    ▸    WARNING: Destructive action
    ▸    postgresql... will lose all of its data
    ▸    
    ▸    To proceed, type ucmsapp... or re-run
    ▸    this command with --confirm ucmsapp...

    > ucmsapp...
    Resetting postgresql... done
    heroku pg:push ucms_app_development DATABASE_URL               
    heroku-cli: Pushing ucms_app_development ---> postgresql...
    pg_dump: last built-in OID is 16383
    pg_dump: reading extensions
    pg_dump: identifying extension members

        <!-- some long code -->

    pg_restore: creating CONSTRAINT "public.posts posts_pkey"
    pg_restore: creating CONSTRAINT "public.schema_migrations schema_migrations_pkey"
    pg_restore: creating CONSTRAINT "public.users users_pkey"
    heroku-cli: Pushing complete.

まとめ

本番環境DBがPostgreSQLで、DBを移行することができた!
何故、postsテーブルにuser_id columnだけが存在しなくなるのかはわからなかったので、
その疑問もいつか解決できれば!

追記 2021.01.31

ポートフォリオ作成を進める中で、開発環境でDBをいじり、本番環境herokuで下記を実行した。

% heroku run rails db:migrate

AddRememberDigestToUsers (20210125071004)
== 20210125071004 AddRememberDigestToUsers: migrating =========================
-- add_column(:users, :remember_digest, :string)
D, [2021-01-31T01:12:39.614474 #4] DEBUG -- :    (0.7ms)  BEGIN
D, [2021-01-31T01:12:39.622072 #4] DEBUG -- :    (7.4ms)  ALTER TABLE "users" 
ADD "remember_digest" character varying
-> 0.0089s
== 20210125071004 AddRememberDigestToUsers: migrated (0.0090s) ================

DBの変更はできている。が、

本番環境ではDBの変更を伴う機能が動作しなかったため、DB上のデータ自体は反映されないことがわかった!

そこで上記と同様に、

heroku pg:push ucms_app_development DATABASE_URL 
<!-- some long code -->
heroku pg:reset 
<!-- some long code -->
heroku pg:push ucms_app_development DATABASE_URL 

で、本番環境herokuに開発環境のデータを反映でき、上手く機能を実行できた!

結論として、pgでは、DBの変更とデータの反映は別々に行なう!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0