1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?