ハッキングバカ

プログラミングに関するメモ

不要な Gem を削除したときの警告メッセージが消えない

環境: macOS 10.14.6, ruby 2.6.3, rails 6.0.0

Rails で普通に gem をアップデートすると、古い gem は残ったままなので、使っていない gem は削除したい。

bundle install --clean

とすると、

Cleaning all the gems on your system is dangerous! If you're sure you want to remove every
system gem not in this bundle, run `bundle clean --force`.

と言われるので、

bundle clean --force

とすると、現在の rails プロジェクトで使用していない gem は削除される。
複数の rails プロジェクトがある場合は注意が必要だ。
ともかく、これで削除は出来るのだけれど、それ以降 bundle update や bundle install をする度に上の警告が表示される。
実害はないがうっとうしい。
設定ファイルを削除することで消すことが出来る。
.bundle/config と言うファイルが出来ているので

# .bundle/config
---
BUNDLE_CLEAN: "true"

これを削除する。

rm .bundle/config

無事警告は消えた。

参考: Sticky clean warning · Issue #6250 · bundler/bundler · GitHub

Amazonica で AWS S3 を使う [Clojure]

Rails における Carrierwave のようなものを Clojure で探していたところ Amazonica というのがあるらしい。
ドキュメントがちょっと分かりにくいので、手順のメモ。

前提として、S3 でバケットを作成しアクセス権限などを設定、アクセスキー、シークレットキーを取得したものとする。

まずはプロジェクトに追加。

; project.clj

[amazonica "0.3.139"]

今回は io ストリームから S3 にアップロードする。

(ns upload
  (:require [amazonica.aws.s3 :as s3])
  (:import [java.io File FileInputStream FileOutputStream]))

(def cred {:access-key "access-key"
           :secret-key "secret-key"
           :endpoint   "ap-northeast-1"})

(defn upload [tempfile size]
  (try
    (with-open [in (new FileInputStream tempfile)]
      (s3/put-object cred
                     :bucket-name "example"
                     :key "test/test.png"
                     :input-stream in
                     :metadata {:content-length size}
                     :return-values "ALL_OLD"))))

無事出来た。

参考:
GitHub - mcohen01/amazonica: A comprehensive Clojure client for the entire Amazon AWS api.
amazonicaとAWS Lambdaで定期的にEBSのスナップショットを作成する - Qiita

ユーザがフォローしているユーザを得るクエリ[Mariadb]

Clojure の Web フレームワークである Luminus では RailsActiveRecord のように SQL クエリが抽象化されているわけではなく、(デフォルトでは)自分で SQL 文を書く必要がある。
そんなわけで少しずつ SQL を学んでいるが、JOIN 周りなどはまだ理解が浅い。
良く有るであろうフォロワーを得るクエリが必要なときに少しはまった。

users: [id, name, email]
relationships: [id, followed_id, follower_id]

のようなテーブルがあって、あるユーザが中間テーブルを通してフォローしているユーザのリストが欲しいときにどうやるかが調べても見つからなかったので、以前作った Rails アプリがどういうクエリを発行しているのかをカンニングした。

SELECT users.name, users.email, FROM users
INNER JOIN relationships ON relationships.followed_id = users.id
WHERE relationships.follower_id = :user_id;

Luminus の本番環境でエラーが生じる[Clojure]

環境: macOS 10.14.3 Ubuntu 18.04

*追記有り

Luminus ではローカルで作成したものを

$ lein uberjar

で jar ファイルにして本番サーバに送って起動しているが、開発時に上手く動いていたものが突然本番サーバで起動できなくなった。

hackbaka@ip-111-111-111-111:~/deploy$ sudo java -jar exam.jar
clojure.lang.LispReader$ReaderException: java.lang.RuntimeException: Reader tag must be a symbol
	at clojure.lang.LispReader.read(LispReader.java:292)
	at clojure.lang.LispReader.read(LispReader.java:196)
	at clojure.lang.LispReader.read(LispReader.java:185)
	at clojure.core$read.invokeStatic(core.clj:3666)
	at clojure.core$load_data_reader_file.invokeStatic(core.clj:7485)
	at clojure.core$load_data_reader_file.invoke(core.clj:7480)
	at clojure.core.protocols$fn__6755.invokeStatic(protocols.clj:167)
	at clojure.core.protocols$fn__6755.invoke(protocols.clj:124)
	at clojure.core.protocols$fn__6710$G__6705__6719.invoke(protocols.clj:19)
	at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)
	at clojure.core.protocols$fn__6738.invokeStatic(protocols.clj:75)
	at clojure.core.protocols$fn__6738.invoke(protocols.clj:75)
	at clojure.core.protocols$fn__6684$G__6679__6697.invoke(protocols.clj:13)
	at clojure.core$reduce.invokeStatic(core.clj:6545)
	at clojure.core$load_data_readers$fn__7291.invoke(core.clj:7511)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.lang.Var.alterRoot(Var.java:303)
	at clojure.core$alter_var_root.invokeStatic(core.clj:5299)
	at clojure.core$alter_var_root.doInvoke(core.clj:5294)
	at clojure.lang.RestFn.invoke(RestFn.java:425)
	at clojure.core$load_data_readers.invokeStatic(core.clj:7510)
	at clojure.core$fn__7294.invokeStatic(core.clj:7515)
	at clojure.core$fn__7294.invoke(core.clj:7515)
	at clojure.core__init.load(Unknown Source)
	at clojure.core__init.<clinit>(Unknown Source)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:374)
	at clojure.lang.RT.classForName(RT.java:2168)
	at clojure.lang.RT.classForName(RT.java:2177)
	at clojure.lang.RT.loadClassForName(RT.java:2196)
	at clojure.lang.RT.load(RT.java:443)
	at clojure.lang.RT.load(RT.java:419)
	at clojure.lang.RT.doInit(RT.java:461)
	at clojure.lang.RT.<clinit>(RT.java:331)
	at clojure.lang.Namespace.<init>(Namespace.java:34)
	at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
	at clojure.lang.Var.internPrivate(Var.java:151)
	at exam.core.<clinit>(Unknown Source)
Caused by: java.lang.RuntimeException: Reader tag must be a symbol
	at clojure.lang.LispReader$CtorReader.invoke(LispReader.java:1221)
	at clojure.lang.LispReader$DispatchReader.invoke(LispReader.java:684)
	at clojure.lang.LispReader.read(LispReader.java:263)
	... 38 more
Exception in thread "main" java.lang.ExceptionInInitializerError
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:374)
	at clojure.lang.RT.classForName(RT.java:2168)
	at clojure.lang.RT.classForName(RT.java:2177)
	at clojure.lang.RT.loadClassForName(RT.java:2196)
	at clojure.lang.RT.load(RT.java:443)
	at clojure.lang.RT.load(RT.java:419)
	at clojure.lang.RT.doInit(RT.java:461)
	at clojure.lang.RT.<clinit>(RT.java:331)
	at clojure.lang.Namespace.<init>(Namespace.java:34)
	at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
	at clojure.lang.Var.internPrivate(Var.java:151)
	at exam.core.<clinit>(Unknown Source)
Caused by: clojure.lang.LispReader$ReaderException: java.lang.RuntimeException: Reader tag must be a symbol
	at clojure.lang.LispReader.read(LispReader.java:292)
	at clojure.lang.LispReader.read(LispReader.java:196)
	at clojure.lang.LispReader.read(LispReader.java:185)
	at clojure.core$read.invokeStatic(core.clj:3666)
	at clojure.core$load_data_reader_file.invokeStatic(core.clj:7485)
	at clojure.core$load_data_reader_file.invoke(core.clj:7480)
	at clojure.core.protocols$fn__6755.invokeStatic(protocols.clj:167)
	at clojure.core.protocols$fn__6755.invoke(protocols.clj:124)
	at clojure.core.protocols$fn__6710$G__6705__6719.invoke(protocols.clj:19)
	at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)
	at clojure.core.protocols$fn__6738.invokeStatic(protocols.clj:75)
	at clojure.core.protocols$fn__6738.invoke(protocols.clj:75)
	at clojure.core.protocols$fn__6684$G__6679__6697.invoke(protocols.clj:13)
	at clojure.core$reduce.invokeStatic(core.clj:6545)
	at clojure.core$load_data_readers$fn__7291.invoke(core.clj:7511)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.lang.Var.alterRoot(Var.java:303)
	at clojure.core$alter_var_root.invokeStatic(core.clj:5299)
	at clojure.core$alter_var_root.doInvoke(core.clj:5294)
	at clojure.lang.RestFn.invoke(RestFn.java:425)
	at clojure.core$load_data_readers.invokeStatic(core.clj:7510)
	at clojure.core$fn__7294.invokeStatic(core.clj:7515)
	at clojure.core$fn__7294.invoke(core.clj:7515)
	at clojure.core__init.load(Unknown Source)
	at clojure.core__init.<clinit>(Unknown Source)
	... 13 more
Caused by: java.lang.RuntimeException: Reader tag must be a symbol
	at clojure.lang.LispReader$CtorReader.invoke(LispReader.java:1221)
	at clojure.lang.LispReader$DispatchReader.invoke(LispReader.java:684)
	at clojure.lang.LispReader.read(LispReader.java:263)
	... 38 more

エラーに自前のコードが全く含まれていないので、どこがおかしいのか全く分からなかった。
しかしどうやら leiningen 2.9.0 で jar ファイルを作成するときにこのようなエラーが起こることがあるらしい。
何気なく brew upgrade を行ってしまったのが直接の原因だった。
参考: Leiningen creates non-backwards compatible data_readers.clj · Issue #2530 · technomancy/leiningen · GitHub
バージョンを leiningen 2.8.3 に戻して uberjar を行うと無事動いた。
macOS の手順は

$ cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula

コミットログを見て一つ前のバージョンを探す。

$ git log leiningen.rb
$ git checkout fd1c0ba8f162a3c41debef6143dca8ba19227f90 leiningen.rb

最新バージョンはあるとやっかいなのでアンインストール。

$ brew uninstall leiningen
$ brew install leiningen

確認。

$ lein --version
Leiningen 2.8.3 on Java 1.8.0_112 Java HotSpot(TM) 64-Bit Server VM

アップデートは気をつけるべきだという教訓。
Clojure のエラーメッセージはもっと分かりやすくならないだろうか。

参考: [2018/10]homebrewで過去バージョンのパッケージをインストールする - Qiita


---------------追記---------------

このエラーは Clojure のバージョンが 1.8.0 以下だと生じるようで、1.9.0 以上にアップデートすると起こらなくなる。
dependencies を書き換えバージョンアップする。

; project.clj

[org.clojure/clojure "1.10.0"]

これで leiningen 2.9.0 でも動くようになった。
参考:

Rails で Font-awesome 5 系を使う

RailsFont-awesome を使う場合 font-awesome-rails が一般的だったけれど、(今のところ) 5系に対応していない。
使いたい icon が5 系であることが多かったため、それらが使える font-awesome-sassに乗り換えることにした。
まずは gem に追加。font-awesome-rails があったらそちらは消しておく。

# Gemfile
gem 'font-awesome-sass', '5.3.1'

反映。

$ bundle update

アセットからインポートする。

/* app/assets/stylesheets/application.scss */
@import "font-awesome-sprockets";
@import "font-awesome";

これで view 中で

<%= icon("fas", "link") %>

のような形で使えるようになる。
font-awesome-rails からの移行も楽だろう。

公式: GitHub - FortAwesome/font-awesome-sass: Font-Awesome Sass gem for use in Ruby/Rails projects, Icons | Font Awesome
taka-no-MacBook-Air:~

Mariadb の文字コードを utf8mb4 に変更する[macOS]

環境: macOS 10.13.6 Mariadb 10.3.10

MariadbRails から絵文字を流し込むとエラーになった。
文字コードを確認。

MariaDB [(none)]>  show variables like 'char%';
+--------------------------+--------------------------------------------------------+
| Variable_name            | Value                                                  |
+--------------------------+--------------------------------------------------------+
| character_set_client     | utf8                                                   |
| character_set_connection | utf8                                                   |
| character_set_database   | utf8mb4                                                |
| character_set_filesystem | binary                                                 |
| character_set_results    | utf8                                                   |
| character_set_server     | utf8mb4                                                |
| character_set_system     | utf8                                                   |
| character_sets_dir       | /usr/local/Cellar/mariadb/10.3.9/share/mysql/charsets/ |
+--------------------------+--------------------------------------------------------+
8 rows in set (0.012 sec)

絵文字を扱うには utf8mb4 にする必要がある。
設定ファイルの include を有効化。

# /usr/local/etc/my.cnf
!includedir /usr/local/etc/my.cnf.d

my.cnf.d 下に設定ファイルを作成。

# /usr/local/etc/my.cnf.d/utf8mb4.cnf
[client-mariadb]
default-character-set = utf8mb4
[mariadb]
character-set-server = utf8mb4

mariadb を再起動して、確認。

MariaDB [(none)]> show variables like "chara%";
+--------------------------+---------------------------------------------------------+
| Variable_name            | Value                                                   |
+--------------------------+---------------------------------------------------------+
| character_set_client     | utf8mb4                                                 |
| character_set_connection | utf8mb4                                                 |
| character_set_database   | utf8mb4                                                 |
| character_set_filesystem | binary                                                  |
| character_set_results    | utf8mb4                                                 |
| character_set_server     | utf8mb4                                                 |
| character_set_system     | utf8                                                    |
| character_sets_dir       | /usr/local/Cellar/mariadb/10.3.10/share/mysql/charsets/ |
+--------------------------+---------------------------------------------------------+
8 rows in set (0.001 sec)

これでよし。
system だけちょっと気分が悪いがこれは変えられないらしい。
無事絵文字を使えるようになった。
ただしすでに作ったデータベースは utf8 のままなので再作成か変換が必要。

参考: Migrating UTF8 to UTF8-MB4 on MariaDB, MariaDB で 4バイトの utf を扱う設定 | Balun Software (Info)

Ruby インストール時の rdoc エラー[Ubuntu]

環境: ubuntu 16.04

新しく建てた ubuntu サーバに ruby を rbenv を用いてインストールしようとしたらエラーが発生した。

$ rbenv install 2.5.1
...
Generating RI format into /tmp/ruby-build.20180913055306.29926/ruby-2.5.1/.ext/rdoc...
Killed
uncommon.mk:491: recipe for target 'rdoc' failed
make: *** [rdoc] Error 137

インストール時のオプションを設定する。

$ RUBY_CONFIGURE_OPTS=--disable-install-doc rbenv install 2.5.1
...
Installed ruby-2.5.1 to /home/name/.rbenv/versions/2.5.1

参考: ruby 2.2.2 installation fails on Ubuntu 15.04 · Issue #223 · postmodern/ruby-install · GitHub