Rubyと筋肉とギターとわたし

筋トレが仕事です

【Vim】rails(ruby)でvim-lspを導入するとnokogiriで怒られる

f:id:rdwbocungelt5:20200320131618p:plain

どうもてぃ。

最近vimneocompleteneocomplcacheのサポートが終わってることを知り、ちょうどいい機会だったのでlspに移行しようとした際にハマったので備忘録として。

lspの導入

lspとは…という説明はいろんなところでなされてるためここでは割愛します。

極ありふれた表現で簡単に表現すれば補完できるすごいやつです。凄いやつは使いたくなりますよね、vimmerならば。

vimrc

ずっと整理したいtomlにできないまま、また一年が経過しそうになってますが、こんな感じです。

  " vim lsp
  call dein#add('prabirshrestha/async.vim')
  call dein#add('prabirshrestha/asyncomplete.vim')
  call dein#add('prabirshrestha/vim-lsp')
  call dein#add('mattn/vim-lsp-settings')
  call dein#add('prabirshrestha/asyncomplete-lsp.vim')
  if executable('solargraph')
      " gem install solargraph
      au User lsp_setup call lsp#register_server({
          \ 'name': 'solargraph',
          \ 'cmd': {server_info->[&shell, &shellcmdflag, 'solargraph stdio']},
          \ 'initialization_options': {"diagnostics": "true"},
          \ 'whitelist': ['ruby'],
          \ })
  endif

公式通りに必要なものをセットで入れてます。

まだ導入段階で解決できてないところ多いんですが、asyncomplete入れてるのに自動補完されないんですよね…それはまた今度調査します。

Rubyではlsp用のgem solargraphを使用するのでとりあえずローカルにぶち込みます。

$ gem install solargraph

とりあえず準備OK。

適当にRailsプロジェクトのファイルを開く

app/controllers/users_controller.rbを開いたとしましょう。

Please do :LspInstallServer to enable Language Server ~~~と出てくるので:LspInstallServerでlspの設定。対象のgem等がインストールされていくはずです。

が、安定のnokogiriさんに阻まれました。

/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/ext/nokogiri/tmp/x86_64-pc-linux-gnu/ports/libxml2/2.9.10/libxml2-2.9.10/libtool: File name too long
Makefile:1015: recipe for target 'install-libLTLIBRARIES' failed
make[3]: *** [install-libLTLIBRARIES] Error 126
make[3]: ディレクトリ '/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/ext/nokogiri/tmp/x86_64-pc-linux-gnu/ports/libxml2/2.9.10/libxml2-2.9.10' から出ます
Makefile:1792: recipe for target 'install-am' failed
make[2]: *** [install-am] Error 2
make[2]: ディレクトリ '/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/ext/nokogiri/tmp/x86_64-pc-linux-gnu/ports/libxml2/2.9.10/libxml2-2.9.10' から出ます
Makefile:1479: recipe for target 'install-recursive' failed
make[1]: *** [install-recursive] Error 1
make[1]: ディレクトリ '/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/ext/nokogiri/tmp/x86_64-pc-linux-gnu/ports/libxml2/2.9.10/libxml2-2.9.10' から出ます
Makefile:1786: recipe for target 'install' failed
make: *** [install] Error 2
========================================================================
*** 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.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=/home/motty/.asdf/installs/ruby/2.6.3/bin/$(RUBY_BASE_NAME)
        --help
        --clean
        --use-system-libraries
        --enable-static
        --disable-static
        --with-zlib-dir
        --without-zlib-dir
        --with-zlib-include
        --without-zlib-include=${zlib-dir}/include
        --with-zlib-lib
        --without-zlib-lib=${zlib-dir}/lib
        --enable-cross-build
        --disable-cross-build
/home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:402:in `block in execute': Failed to complete install task (RuntimeError)
        from /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:373:in `chdir'
        from /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:373:in `execute'
        from /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:120:in `install'
        from /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/mini_portile2-2.4.0/lib/mini_portile2/mini_portile.rb:155:in `cook'
        from extconf.rb:365:in `block (2 levels) in process_recipe'
        from extconf.rb:257:in `block in chdir_for_build'
        from extconf.rb:256:in `chdir'
        from extconf.rb:256:in `chdir_for_build'
        from extconf.rb:364:in `block in process_recipe'
        from extconf.rb:262:in `tap'
        from extconf.rb:262:in `process_recipe'
        from extconf.rb:557:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/extensions/x86_64-linux/2.6.0/nokogiri-1.10.10/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10 for inspection.
Results logged to /home/motty/.local/share/vim-lsp-settings/servers/solargraph/vendor/bundle/ruby/2.6.0/extensions/x86_64-linux/2.6.0/nokogiri-1.10.10/gem_make.out

An error occurred while installing nokogiri (1.10.10), and Bundler cannot continue.
Make sure that `gem install nokogiri -v '1.10.10' --source 'https://rubygems.org/'` succeeds before bundling.

In Gemfile:
  solargraph was resolved to 0.40.0, which depends on
    reverse_markdown was resolved to 2.0.0, which depends on
      nokogiri

親の顔ほどみたエラー。つらい。

動いてるスクリプトに設定を追加

自分が使っているパッケージマネージャーはdein.vimです。

dein配下にあるsolargraphのスクリプトを確認してみます。パスは$HOME/.cache/dein/.cache/.vimrc/.dein/installer/install-solargraph.shでした(人によって違うと思うのでファイル名で検索するのもありかも)

#!/usr/bin/env bash

set -e

git clone --depth=1 https://github.com/castwide/solargraph .
bundle install --without development --path vendor/bundle

cat <<EOF >solargraph
#!/usr/bin/env bash

DIR=\$(cd \$(dirname \$0); pwd)
BUNDLE_GEMFILE=\$DIR/Gemfile bundle exec ruby \$DIR/bin/solargraph \$*
EOF

chmod +x solargraph

とりあえず、よく解決する設定をこのファイルにぶち込みます。

#!/usr/bin/env bash

set -e

git clone --depth=1 https://github.com/castwide/solargraph .
bundle config build.nokogiri --use-system-libraries # これ
bundle install --without development --path vendor/bundle

cat <<EOF >solargraph
#!/usr/bin/env bash

DIR=\$(cd \$(dirname \$0); pwd)
BUNDLE_GEMFILE=\$DIR/Gemfile bundle exec ruby \$DIR/bin/solargraph \$*
EOF

chmod +x solargraph

gem追加

もう一点。エラーメッセージにあった、mini_portile関連でエラーになってるっぽかったのでローカルに追加します。

$ gem install mini_portile

とりあえずこれで設定はおk。

LspInstallServer再実行

はい、うまくいったー。

調べても全く出てこなかったので、自力で頑張ってみました。

vim-lspでgem関連エラーが出る場合は実行スクリプト内でgemの操作をやってみるといいかもしれませんね。

それでは、おつでした。

【Ruby on Rails】rails consoleでActionDispatch::Http::Uploadedfileを作成・保存する

どうもてぃ。

久しぶりのRailsで少々ハマったのでメモをば。

やりたいこと

ローカルのファイルを読み込んで、carrierwaveに割り当てているカラムに保存したい。

ただそれだけ。

Let's go

まずはファイルの読み込み。

今回はtmp/uploads/配下にファイルを作っているものとします。

path = Dir.glob(Rails.root.join('tmp', 'uploads', 'test.pdf'))

filename = File.basename(path)
tempfile = File.open(path)

とりあえずこれで準備はおk

ActionDispatch::Http::Uploadedfileで読み込む

上記を使って読み込みます。

uploaded_file = ActionDispatch::Http::Uploadedfile.new(
  filename: filename,
  type: 'application/pdf',
  tempfile: tempfile
)

User.first.update(file: uploaded_file)

UserモデルにUserFileUploaderをマウントしたfileカラムがあるものとして保存してます。

class User < ApplicationRecord
・
・
・
  # ↓こういうやつ
  mount_uploaders :file, UserFileUploader 
・
・
・
end

終わり

ファイルタイプによってtypeをimage/jpegとかに変えれば画像もちゃんと保存できます。

定期的にRailsに触っておかないと忘れちゃいますね。

【Golang】sql-migrate upがCannot parse dateと出てうまくいかないとき

f:id:rdwbocungelt5:20200720165613p:plain

どうもてぃ。

今日もGolangやっていきます。

マイグレーションを実行してみた

% docker-compose exec golang sql-migrate up -config=config/dbconfig.yml
Migration failed: Cannot parse dates.

Make sure that the parseTime option is supplied to your database connection.
Check https://github.com/go-sql-driver/mysql#parsetime for more info.

上記のようにエラーになってしまいます。

sql-migrate newはうまくいってますが、upがうまくいかない。コード上でparseTimeとかつかっているところなんてない。

ただ、エラーメッセージを見てみると、

Make sure that the parseTime option is supplied to your database connection.

これですよ。

parseTimeオプションを追加しろと。

github.com

parseTimeはbool型のようなので、dbconfig.ymlの接続設定にparseTime=trueを追加しました。

development:
  dialect: mysql
  dir: pkg/db/migrations
  datasource: root:password@tcp(db:3306)/database_name?parseTime=true

これでマイグレーションが通るようになりましたとさ。

【Rails】enumからi18nを適応したhashを取得したいとき

どうもてぃです。

enumについてあんまり理解してなかったのでメモとして残します。

gemのenum_helpを入れている状態です。

環境

% lsb_release -a
No LSB modules are available.
Distributor ID: LinuxMint
Description:    Linux Mint 19.3 Tricia
Release:    19.3
Codename:   tricia

TL; DR

User model

class User < ApplicationRecord
  enum role: { admin: 0, manage: 1, guest: 2 }


・
・
・
end

locales/js.yml

ja:
  enums:
    user:
      role:
        admin: 管理者
        manage: マネージャー
        guest: 一般
・
・
・

コンソール

pry(main)> User.roles
=> {"admin" => 0, "manage" => 1, "guest" => 2}

pry(main)> User.roles_i18n
=> {"admin" => "管理者", "manage" => "マネージャー", "guest" => "一般"}

終わり

Userのインスタンスから取得することもできますが、今回はインスタンスを生成せずにenumを使いたかったので、i18nを試してみたらいけました。

User.roles_i18n.invertとすればselect_boxとかに使えそうですね。

【Golang】超絶簡素なwebサーバーを作る その3

f:id:rdwbocungelt5:20200720165613p:plain

どうもてぃ。

前回の記事がこちら。

smot93516.hatenablog.jp

template.htmlを読み込んでstructを渡す形のコードを前回作成しました。

まずはそのコードから見ていきます。

tempalteにstructを渡す

type Article struct {
    Title string
    Body  template.HTML
}

var tpl *template.Template

func init() {
    tpl = template.Must(template.ParseFiles("template.html"))
}

func escapeHTML(html string) (tpl template.HTML) {
    tpl = template.HTML(html)

    return
}

func helloHandler(rw http.ResponseWriter, req *http.Request) {
    article := Article{
        Title: "golang practice",
        Body:  escapeHTML("<h1>hello golang</h1>"),
    }

    if err := tpl.ExecuteTemplate(rw, "template.html", article); err != nil {
        log.Fatalln(err.Error())
    }
}

該当箇所だけ取り上げました。

Articleのstructを定義し、helloHandlerで初期化してます。

func helloHandler(rw http.ResponseWriter, req *http.Request) {
    // ここね
    article := Article{
        Title: "golang practice",
        Body:  escapeHTML("<h1>hello golang</h1>"),
    }、

    if err := tpl.ExecuteTemplate(rw, "template.html", article); err != nil {
        log.Fatalln(err.Error())
    }
}

そして、単にBodyを文字列としてtemplateにわたした際、htmlタグをエスケープしてくれないのでescapeHTML関数を作成し、template.HTMLに変換する処理を入れてます(わざわざ別関数にしなくても良い気がしてきた…)

article := Article{
    Title: "golang practice",
    Body: template.HTML("<h1>hello golang</h1>"),
}

これでいいかも。

だた、この方法はXSSの対象となるやりかたなので、使用する際は十分注意するようにしてください。

エスケープせずうまく出力する方法は以下。

type Article struct {
    Title string
    Body  string
}

var tpl *template.Template

func safeHTMLTemplate(text string) template.HTML {
    return template.HTML(text)
}

func init() {
    funcMap := template.FuncMap{ "safehtml": safeHTMLTemplate }
    tpl = template.Must(template.New("").Funcs(funcMap).ParseFiles("template.html"))
}

func helloHandler(rw http.ResponseWriter, req *http.Request) {
    article := Article{
        Title: "golang practice",
        Body:  "<h1>hello golang</h1>",
    }

    if err := tpl.ExecuteTemplate(rw, "template.html", article); err != nil {
        log.Fatalln(err.Error())
    }
}

Bodyをstringにしてます。 templateのエスケープしない処理部分をinit()に逃がしました。

template側は

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>{{.Title}}</title>
</head>
<body>
  {{.Body|safehtml}}
</body>
</html>

.Body|safehtmlとすることでhtmlタグのエスケープを気にせず、うまいこと表示を実現してます。

この方法は以下の記事を参考にしました。感謝。

qiita.com

特にセキュリティ意識しなければどちらでも問題ないとは思います。

最初の方がイメージしやすいので、慣れたらtemplate.FuncMap等使ってみると良いかもです。

jsonを返してみる

バックエンドはGo、フロントエンドはReactやVueを使いたい、そんなときGoはjsonを返すのがメインになると思います。

まずは超かんたんにhandlerを作成してみます。

func jsonResponseHandler(rw http.ResponseWriter, req *http.Request) {
    data := map[string]interface{}{
        "message": "hello golang",
        "status":  http.StatusOK,
    }

    // map to json
    bytes, err := json.Marshal(data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Fprint(rw, string(bytes))
}

func main() {
    // http.Handle("/hello", http.HandlerFunc(helloHandler))
    http.HandleFunc("/hello", helloHandler)
    http.HandleFunc("/dog", dogHandler)
    http.HandleFunc("/json", jsonResponseHandler)

    http.ListenAndServe(":3000", nil)
}

該当箇所をピックアップしてます。requestは特に気にせず、決まったjsonを返す形です。

手順としては…

  • map作成(valueはinterface型が望ましい)
  • mapをjsonに変換
  • 取得したbytesを文字列に変換して表示

です。json.Marshal()が今回の味噌。

func Marshal(v interface{}) ([]byte, error) {
    e := newEncodeState()

    err := e.marshal(v, encOpts{escapeHTML: true})
    if err != nil {
        return nil, err
    }
    buf := append([]byte(nil), e.Bytes()...)

    encodeStatePool.Put(e)

    return buf, nil
}

godocを見てみると、Marshalに渡すものは何でもokと(interface型はtypescriptで言うanyみたいなもん)。

深く見る必要はないので、返り値を確認するとbyteとerrorが返ってきてます。

何が返ってくるかはgodocを確認するか、エディタの拡張機能で定義元を確認するようにしてください。自分はvim-goを使ってます。

json.Marshal()を使うだけでjsonをbyte型に変換したものが得られるので、文字列に変換してやると見事にjsonを返すエンドポイントの完成ですb

structを使ったjsonを返してみる

次はmapではなくstructを使って返してみます。

DBからデータを抽出してstructにキャッシュし、それをjsonに変換してレスポンスを返す…みたいなことを想定してます。

type Product struct {
    Name     string `json:"name"`
    Price    int    `json:"price"`
    Quantity int    `json:"quantity"`
}

func productResponseHandler(rw http.ResponseWriter, req *http.Request) {
    // product := Product{"商品A", 100, 10}
    product := Product{
        Name:     "商品A",
        Price:    100,
        Quantity: 10,
    }

    // struct to json byte
    // bytes, err := json.Marshal(product)でもおk
    bytes, err := json.Marshal(&product)
    if err != nil {
        http.Error(rw, err.Error(), http.StatusInternalServerError)
        return
    }

    rw.Header().Set("Content-Type", "application/json")
    fmt.Fprint(rw, string(bytes))
}

また、追加部分だけ抜き出してます。

こう見ると、ほとんどmapのときと同じです。json.Marshal()をしてやるだけ。structの場合ポインタを渡すことが多いので、&productでわたしてます。

他にheader情報を付与したりhttp.Error()で明示的にエラーが出るようにしてますが、mapのときと同じ構成でも問題なく動きます。

ポイントはstructの定義の際に、json指定をしてあげること。

type Product struct {
    Name     string `json:"name"`
    Price    int    `json:"price"`
    Quantity int    `json:"quantity"`
}

これを指定しないと何が返ってくるかというと

f:id:rdwbocungelt5:20200915173004p:plain

ちゃんとjsonになってくれません。

structでレスポンスを返す場合は必ずjson指定をしましょう。

おわり

全体を通したコードがこちら

package main

import (
    "encoding/json"
    "fmt"
    "html/template"
    "log"
    "net/http"
)

type Article struct {
    Title string
    Body  string
}

type Product struct {
    Name     string `json:"name"`
    Price    int    `json:"price"`
    Quantity int    `json:"quantity"`
}

var tpl *template.Template

func safeHTMLTemplate(text string) template.HTML {
    return template.HTML(text)
}

func init() {
    funcMap := template.FuncMap{
        "safehtml": safeHTMLTemplate,
    }
    tpl = template.Must(template.New("").Funcs(funcMap).ParseFiles("template.html"))
}

func helloHandler(rw http.ResponseWriter, req *http.Request) {
    article := Article{
        Title: "golang practice",
        Body:  "<h1>hello golang</h1>",
    }

    if err := tpl.ExecuteTemplate(rw, "template.html", article); err != nil {
        log.Fatalln(err.Error())
    }
}

func dogHandler(rw http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(rw, "<h1>dogs</h1><h2>dog dog dog</h2>")
}

func jsonResponseHandler(rw http.ResponseWriter, req *http.Request) {
    data := map[string]interface{}{
        "message": "hello golang",
        "status":  http.StatusOK,
    }

    // map to json
    bytes, err := json.Marshal(data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Fprint(rw, string(bytes))
}

func productResponseHandler(rw http.ResponseWriter, req *http.Request) {
    // product := Product{"商品A", 100, 10}
    product := Product{
        Name:     "商品A",
        Price:    100,
        Quantity: 10,
    }

    // struct to json byte
    bytes, err := json.Marshal(product)
    if err != nil {
        http.Error(rw, err.Error(), http.StatusInternalServerError)
        return
    }

    rw.Header().Set("Content-Type", "application/json")
    fmt.Fprint(rw, string(bytes))
}

func main() {
    // http.Handle("/hello", http.HandlerFunc返す(helloHandler))
    http.HandleFunc("/hello", helloHandler)
    http.HandleFunc("/dog", dogHandler)
    http.HandleFunc("/json", jsonResponseHandler)
    http.HandleFunc("/product", productResponseHandler)

    http.ListenAndServe(":3000", nil)
}

次はもう少しhttp.Requestに関してまとめて、フレームワークを使った場合どうなるか、というのもまとめていければと思います。

ではでは。

【Docker】ローカルにredisをインストールしたくないときの対処法

どうもてぃです。

railsの完全ローカル環境を構築しないといけなくなったんですが、いかんせんインストールするものが多い。

題名の通りredisをインストールするのは良いんですが、他のプロジェクトでdockerを使っててdocker-compose upした際にポートがぶつかるのが面倒くさい。

そういった面倒臭さやインストールする煩わしさ、インストール後の設定の憂鬱さを解決する方法を伝授します。

環境

% lsb_release -a
No LSB modules are available.
Distributor ID: LinuxMint
Description:    Linux Mint 19.3 Tricia
Release:    19.3
Codename:   tricia
  • Docker version 19.03.6, build 369ce74a3c

TL; DR

$ docker pull redis

# requirepassはrails側で設定しているもの
$ docker run --name redis-container -d -p 6379:6379 redis redis-server --appendonly yes --requirepass password

データを永続化させたいとき

今回はただの開発環境でrailssidekiqのために必要であったため、特に永続化は気にしてません。

ですが、永続化させたくてどうしようもない方のために…

リファレンスを乗せときます\(^o^)/

docs.docker.jp

dockerのリファレンスは神なのでぜひ見ましょうね…





冗談です。

以下のコマンドでたぶんいけます。

$ docker run --name redis-container -d -p 6379:6379 -v redis-data:/data redis redis-server --appendonly yes --requirepass password

おわりに

docker run オプションについては自分の過去記事を漁ってもらうか、安心と信頼のとても見やすいリファレンスを確認するとよいです。

redis以外にも入れたくないものがあればdockerで同じように対応してみるとdockerに慣れていけるんじゃないでしょうかね。

最後にdockerリファレンスのリンク貼っときますね。

docs.docker.jp

【PostgreSQL】rails db:create時にrole <name> does not existsが出たときの備忘録

f:id:rdwbocungelt5:20181010100712p:plain

どうもてぃ。

久々にローカルDB環境を作ってて10分ほどハマったので、二度とないように備忘録書いときます。

環境

% cat /etc/lsb-release 
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=19.3
DISTRIB_CODENAME=tricia
DISTRIB_DESCRIPTION="Linux Mint 19.3 Tricia"

database.ymlの設定

config/database.ymlはこんな感じ。

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: <%= ENV['POSTGRES_DB'] %>

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: <%= ENV['POSTGRES_DB_TEST'] %>

usernameやpasswordは面倒くさかったので設定してません。

Let's rails db:create

% bundle exec rails db:create
% bundle exec rails db:create
FATAL:  role "motty" does not exist
Couldn't create 'project_dev' database. Please check your configuration.
rails aborted!
ActiveRecord::NoDatabaseError: FATAL:  role "motty" does not exist
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/postgresql_adapter.rb:696:in `rescue in connect'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/postgresql_adapter.rb:691:in `connect'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/postgresql_adapter.rb:223:in `initialize'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/postgresql_adapter.rb:48:in `new'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/postgresql_adapter.rb:48:in `postgresql_connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:830:in `new_connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:874:in `checkout_new_connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:853:in `try_to_checkout_new_connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:814:in `acquire_connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:538:in `checkout'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:382:in `connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_adapters/abstract/connection_pool.rb:1033:in `retrieve_connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_handling.rb:118:in `retrieve_connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/connection_handling.rb:90:in `connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/tasks/postgresql_database_tasks.rb:12:in `connection'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/tasks/postgresql_database_tasks.rb:21:in `create'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/tasks/database_tasks.rb:119:in `create'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/tasks/database_tasks.rb:139:in `block in create_current'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/tasks/database_tasks.rb:316:in `block in each_current_configuration'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/tasks/database_tasks.rb:313:in `each'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/tasks/database_tasks.rb:313:in `each_current_configuration'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/tasks/database_tasks.rb:138:in `create_current'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/railties/databases.rake:29:in `block (2 levels) in <main>'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.3/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.3/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.3/lib/rails/command.rb:48:in `invoke'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.3/lib/rails/commands.rb:18:in `<main>'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `block in require'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:257:in `load_dependency'
/home/motty/github.com/project/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `require'
bin/rails:4:in `<main>'

postgresqlをインストールした後なにもしてなかったので、ロールがないって怒られちゃいました。

roleを作成する

まずはポスグレの中に入ります

% sudo -u postgres psql
psql (10.14 (Ubuntu 10.14-0ubuntu0.18.04.1))
Type "help" for help.

postgres=# 

ロールの確認をすると

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

mottyっていうロールないですね(そりゃそうだわ)

てなわけで作りま。

postgres=# create role motty login createdb createrole password 'password';
CREATE ROLE

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 motty     | Create role, Create DB                                     | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

完璧にロールmottyが作成できました。

\qで戻れます。

おわり

rails db:createも無事に通りました。

普段自分が作ったdocker templateを使用してるので、まさかこんなところでハマるとは思ってませんでした。

もう二度とローカル環境構築とかいう無駄なことはやりたくないなぁ、と思う今日この頃でした。

おしまい。