ruby-buildでRubyをインストールしようとしたらoptparseが無いって言われる
なにごと?
ruby-build
で rbenv install 3.0.2
したら optparse
が無いって言われてエラーになるんですよ。
$ rbenv install 3.0.2 Downloading ruby-3.0.2.tar.gz... -> https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.2.tar.gz Installing ruby-3.0.2... BUILD FAILED (Ubuntu 20.04 using ruby-build 20210526-11-gebdcf0c) # (略) ./tool/file2lastrev.rb:6:in `require': cannot load such file -- optparse (LoadError) from ./tool/file2lastrev.rb:6:in `<main>'
環境
なんとかする
今までも ruby-build
は普通に使ってたし、これまでのバージョンは入ってるのだけど。
$ rbenv versions 2.7.2 * 3.0.0 (set by /home/*****/.rbenv/version)
ってよく見ると system
のRubyが無いなって思っておもむろにインストール& rbenv
で使うように切り替え。
$ sudo apt-get install ruby $ rbenv global system $ rbenv rehash
この状態で ruby install
するとちゃんとインストールできた。
$ rbenv install 3.0.2 Downloading ruby-3.0.2.tar.gz... -> https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.2.tar.gz Installing ruby-3.0.2... Installed ruby-3.0.2 to /home/*****/.rbenv/versions/3.0.2
KarateでのAPIテストと同時にAssertJ-DBでデータの確認もやりたい
はじめに
Karateを使うとWeb APIのリクエスト&レスポンスのテストがとてもいい感じにできるが、そうすると今度は「POSTされたデータがちゃんとDBに入っているかどうか」とかも確認したくなってきてしまうもの。 そこでKarateでのテストシナリオ実行の際、AssertJ-DBでのデータのアサーションが行われるようにしてみる*1。
環境
- Spring Boot 2.5.0
- Karate (karate-junit5) 1.0.1
- AssertJ-DB 2.0.2
ポイント
Karateのfeatureファイルでは、Java.type('パッケージ+クラス名')
でJavaのクラスを参照できる。
これを利用し、あらかじめDBのテスト用メソッドをAssertJ-DBで書いておいて、それをfeatureファイルから呼び出すようにする。
サンプルコード全体は下記のとおり。
やり方
JavaでDBのアサーションを行うメソッドを定義する
テストランナーのクラスにDBのアサーションを行うメソッドを定義しておく。下記サンプルの public static void assertTable(String expectedMessage)
がそれ。
package demo; // ... @SpringBootTest(classes = DemoApplication.class) public class DemoTestRunner { private static DataSource dataSource; @Autowired private void setDataSource(DataSource dataSource) { DemoTestRunner.dataSource = dataSource; } @Karate.Test Karate testAll() { return Karate.run().relativeTo(getClass()); } public static void assertTable(String expectedMessage) { var table = new Table(dataSource, "messages"); assertThat(table).hasNumberOfRows(1) .row(0) .column("message").value().isEqualTo(expectedMessage); } }
Java.type()
で使いたいのでメソッドは public static
にする必要があり、それに合わせて DataSource
をstaticフィールドにしている。
staticなDataSourceをインジェクションできるようにするため、 setDataSource()
はだいぶ無理やり感がある…。
DBのアサーション自体は普通にAssertJ-DBで書けばよい。
featureファイルのシナリオでJavaのメソッドを呼び出す
こんな感じ。
Feature: Demo Background: * url baseUrl * def DemoTestRunner = Java.type('demo.DemoTestRunner') Scenario: Add a message Given path '/' And request { "message": "Hello" } When method post Then status 200 And DemoTestRunner.assertTable('Hello') Scenario: Find messages # ...
Background
で def DemoTestRunner = Java.type('demo.DemoTestRunner')
することで、引数で指定されたJavaのクラス(今回は DemoTestRunner
)が使えるようにしておく。
シナリオでは DemoTestRunner.assertTable('Hello')
のようにしてメソッドを呼び出す。
実行してみる
いつもどおりテストランナーのクラス(今回は DemoTestRunner
)を実行すればよい。
IntelliJ IDEAだとテスト結果は普通にこんな感じで出てくる。
HTMLレポートも出てくる。
試しにこんな感じでテストをわざと失敗させてみると…
Scenario: Add a message Given path '/' And request { "message": "INVALID" } When method post Then status 200 And DemoTestRunner.assertTable('Hello')
失敗時の情報もちゃんと出てくる。よさそう。
Spring Bootでプロファイルごとに実装を切り替える
TL; DR
@Profile
や @ConditionalOnExpression
を使う。ちょっとつらいけどがんばる。
サンプルコードは下記のとおり。
やりたいこと
システム日時を取得するユーティリティがあるが、テストのときに日時が毎回変わると困るので、特定の場合は固定値を返すようにしたい*1。
TERASOLUNAの下記機能とほぼ同じ。ただしSpring Bootなので、XMLを使わずアノテーションでなんとかしたい。
環境
- Spring Boot 2.5.0
解決方法
@Profile
アノテーションを使用し、指定されたプロファイルに応じてインジェクションされる実装を切り替える。
例えば、インタフェース DateTimeUtils
に対して本物のシステム日時を返す実装クラス SystemDateTimeUtils
と、固定日時を返す実装クラス FixedDateTimeUtils
を作るとする。
下記のような動作にしたい。
- プロファイル
with-fixeddatetime
が指定されている場合はFixedDateTimeUtils
を使う - そうでない場合は
SystemDateTimeUtils
を使う
固定日時を返す実装クラス FixedDateTimeUtils
では、@Profile("with-fixeddatetime")
を付与する。
@Component @Profile("with-fixeddatetime") public class FixedDateTimeUtils implements DateTimeUtils { // ...
本物のシステム日時を返す実装クラス SystemDateTimeUtils
では、@Profile("!with-fixeddatetime")
を付与する。
@Profile
でのプロファイル指定はSpring 式言語 (SpEL)が使える。!with-fixeddatetime
で「with-fixeddatetime
以外」となる。
@Component @Profile("!with-fixeddatetime") public class SystemDateTimeUtils implements DateTimeUtils { // ...
プロファイルの指定には、下記のような方法がある。
application.properties
で指定
spring.profiles.active=with-fixeddatetime
@SpringBootTest @ActiveProfiles("with-fixeddatetime") class DemoApplicationWithFixedDateTimeTests { // ...
その他、実行時の引数や環境変数での指定なども可能。
参考:2.6. アクティブ Spring プロファイルを設定する | Spring Boot 「使い方」ガイド - リファレンスドキュメント
@Profile("!with-fixeddatetime")
って書かないといけないのはつらい
つらいけどしょうがない。
本当は @Profile("!with-fixeddatetime")
って書かなくても with-fixeddatetime
じゃなければデフォルトで @Profile
無しのものを使ってほしいところ。
しかし @Profile
を付与しない場合は「どのプロファイルでも常に使われる」という動作になるらしい。今回の例で SystemDateTimeUtils
から @Profile
を外すと、with-fixeddatetime
プロファイルを指定した場合に下記エラーとなる。
*************************** APPLICATION FAILED TO START *************************** Description: Field dateTimeUtils in com.example.demo.service.impl.DemoServiceImpl required a single bean, but 2 were found: - fixedDateTimeUtils: defined in file [/path/to/springboot-profile-switch-demo/target/classes/com/example/demo/util/impl/FixedDateTimeUtils.class] - systemDateTimeUtils: defined in file [/path/to/springboot-profile-switch-demo/target/classes/com/example/demo/util/impl/SystemDateTimeUtils.class] Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
@Profile("default")
だと、default
プロファイルでない場合に使われないので、これもNG。
@ComponentScan
でコンポーネントスキャンの対象を変更することでの対応もできそうだが、ちょっと大掛かりではある。
実装クラスが3つ以上あるんですけど???
下記のような動作にする。
- プロファイルが
with-fixeddatetime
の場合はFixedDateTimeUtils
を使う - プロファイルが
with-adjusteddatetime
の場合はAdjustedDateTimeUtils
を使う - それ以外の場合は
SystemDateTimeUtils
を使う
AdjustedDateTimeUtils
には @Profile("with-adjusteddatetime")
を付与するとして…
@Component @Profile("with-adjusteddatetime") public class AdjustedDateTimeUtils implements DateTimeUtils { // ...
SystemDateTimeUtils
の @Profile
は with-fixeddatetime
と with-adjusteddatetime
の両方を除外するために、@Profile("!with-fixeddatetime && !with-adjusteddatetime")
みたいになる。つらい。
@Component @Profile("!with-fixeddatetime && !with-adjusteddatetime") public class SystemDateTimeUtils implements DateTimeUtils { // ...
SpELは正規表現もサポートされているので、@ConditionalOnExpression
を使用して「with-〜
にマッチしない」という指定もできる。プロファイル名をルール化できる場合は、この方法がよいかもしれない。
@Component @ConditionalOnExpression("#{ not ('${spring.profiles.active}' matches '^with-.+') }") public class SystemDateTimeUtils implements DateTimeUtils { // ...
この場合、JUnitテストクラスでは @TestPropertySource
でプロファイルを指定する必要がある。あまりちゃんと調べられていないけど、@ActiveProfiles("プロファイル名")
だと spring.profiles.active
に値が設定されず、@ConditionalOnExpression
が意図通りに動かない(Environment#getProperty("spring.profiles.active")
が null
になる)。
@SpringBootTest @TestPropertySource(properties = "spring.profiles.active=with-fixeddatetime") class DemoApplicationWithFixedDateTimeTests { // ...
SpELについては、下記のドキュメントを見るとよい。
4. Spring 式言語 (SpEL) | Spring Framework コアテクノロジー - リファレンス
演算子については下記の部分を参照。
4.3.7. 演算子 | Spring Framework コアテクノロジー - リファレンス
参考
*1:テストだけであればMockitoを使ったほうが真っ当ではあるが、そうもいかないことが稀によくある。また、テスト以外でも状況に応じて挙動を切り替えたいこともたまにある。実行環境が異なる場合とか、バッチを特定の日付で実行したい場合とか…。
IntelliJ IDEAを使い始めたときに見るとよい情報まとめ
はじめに
最近ようやくIntelliJ IDEAを使い始めたので、役に立った情報をまとめておきます。
想定環境
とりあえずはじめに読むもの
Javaプログラムの作成〜実行
デバッグ
便利な機能・ショートカットなど
個人的によく使うのは下記のもの*1。よく使う順。
超使う
- 複数ファイル内検索 (Find in Files)
- 実装に移動
- 前に戻る(「実装に移動」でジャンプした後、元の場所に戻るときなど)
- どこでも検索 (Search Everywhere)
Shift
Shift
かなり使う
- プロジェクトの使用箇所を検索する (Find Usage):変数やメソッドが使われている場所を検索する
- 右クリックでコンテキストメニューを開き、
Find Usages
- 右クリックでコンテキストメニューを開き、
- ブックマーク:ソースコードの行にブックマークを設定し、ちょっとしたメモやジャンプができる
- 行番号付近を右クリックしてコンテキストメニューを開き、
Add Bookmarks
- 保存したブックマークは画面左下あたりの
Favorites
メニューで表示できる。ショートカットは macOS:Command
+F3
, Ubuntu:Alt
+2
- 行番号付近を右クリックしてコンテキストメニューを開き、
- ソースファイルの構造 (Structure):エディタで開いているクラスのフィールドやメソッドの一覧表示、移動ができる
- なんでも実行 (Run Anything)
その他
他にもいろいろある。下記記事などが参考になる。
公式のショートカット一覧は壁に貼って毎日眺めるとよい。
パンくずリスト
現在見ているクラス名やメソッド名がひと目でわかる。クソデカクラス/メソッドを読んでると、自分が今どこにいるのかわからなくなるので、そういうときに便利。 環境によってはデフォルトで表示されているかもしれないが、表示されていなかったら下記記事を参考に設定する。
いじってたらぶっこわれてまともに動かなくなったときに設定ファイルを消す
下記記事を参考に、ディレクトリごと削除すればよい。
*1:ショートカットは環境によって異なるかもしれないが、リンク先の公式サイトでは上部メニューの「Shortcuts」からOS等が選択できるので、自分の環境に合ったものを確認するとよい。
クリップボード操作コマンドを活用してテキストを手軽に一括編集する
はじめに
macOSの pbcopy
, pbpaste
やLinuxの xsel
を使うと、クリップボードにコピーした値を sed
などのコマンドで編集後、別のエディタやスプレッドシートにペースト、といった操作が簡単にできて便利という話です。
スクリプトを書くほどでもないけど手で編集するのは面倒だからシェル芸したい!という場合におすすめ。
環境
どちらの環境ともシェルは zsh です。
よくある使用例
macOSの場合
例えばソースコードに記載されたエラーコードを抜き出してスプレッドシートに貼り付けたいとき。
当該部分を Command-C
でコピーして…
pbpaste
で出力した結果から grep
や sed
で目的の部分を取り出す。
$ pbpaste | grep 'ErrorCode' | sed -E 's/[^"]+"([0-9A-Z]+)",?/\1/g' E0001 E0002 E9999
そのままパイプで pbcopy
につなげれば、目的の値がクリップボードにコピーされる。
$ pbpaste | grep 'ErrorCode' | sed -E 's/[^"]+"([0-9A-Z]+)",?/\1/g' | pbcopy
あとはスプレッドシートにそのまま Command-V
とかで貼り付ければOK。
Linuxの場合
macOSの例で使用した pbcopy
, pbpaste
をそれぞれ xsel -bi
, xsel -bo
に置き換えるだけ。
$ xsel -bo | grep 'ErrorCode' | sed -E 's/[^"]+"([0-9A-Z]+)",?/\1/g' | xsel -bi
ただし xsel
は標準では入っていないので、事前にインストールが必要。こんな感じ。
$ sudo apt-get install xsel
コマンド説明
macOSの場合
pbcopy
: 標準入力の内容をクリップボードにコピーする
下記の例では HOGE
がクリップボードに登録される。普通にコピーしたときと同じく、Command-V
で結果を貼り付け可能。
$ echo HOGE | pbcopy
pbpaste
: クリップボードの内容を標準出力に書き出す
前述の例でクリップボードに登録された HOGE
が標準出力に表示される。
$ pbpaste HOGE
Linuxの場合
xsel
: 選択範囲を操作する
xsel
はX Window System上で選択された部分を操作するコマンド。オプション -b
または --clipboard
をつけることで、クリップボードの操作ができる。
入力と出力の切り替えはオプション -i
-o
で行う。
xsel -bi
: 標準入力の内容をクリップボードにコピーする
入力は -i
オプションで行う。クリップボードのオプションとまとめて -bi
で指定。
下記の例ではMacでの例と同じく、標準入力から受け取った HOGE
がクリップボードに登録される。こちらも Ctrl-V
で結果を貼り付け可能。
$ echo HOGE | xsel -bi
-i
オプションは省略してもOK。
$ echo HOGE | xsel -b
xsel -bo
: クリップボードの内容を標準出力に書き出す
出力は -o
オプション。
前述の例でクリップボードに登録された HOGE
が標準出力に表示される。
$ xsel -bo
HOGE
ちなみにLinuxには xclip
というコマンドもある
xsel
と同じく、デフォルトでの操作対象は選択部分。-selection c
でクリップボードの操作になる。
$ echo HOGE | xclip -selection c $ xclip -selection c -o HOGE
xclip
は画像などのバイナリデータを扱えたり、パイプを経由せず直接ファイルから入力ができたりと、 xsel
より便利な機能もある。
$ xclip -selection c -t image/jpeg foo.jpg # 画像ファイルをクリップボードにコピー $ xclip -selection c -o > bar.jpg # クリップボード内の画像データをファイルに出力
ただ、クリップボードを指定するためのオプションが -selection c
と少し長いので、普段はやっぱり xsel
を使ってしまう…。
参考
Pleiades (Eclipse)でのSpringアプリ開発時にjarファイルが削除/変更できなくなったので対処した
環境
現象
Springアプリの開発に独自のjarライブラリを使用していたのですが、jarを上書きしたり、jar更新後にGitのブランチ切り替えをしたときにこんなエラーが出ることがありました。
リソースの削除中に問題が発生しました。 'D:\local\pleiades\workspace\***\WebContent\WEB-INF\lib\***.jar' を削除できませんでした。 ファイルの削除中に問題が発生しました。 D:\local\pleiades\workspace\***\WebContent\WEB-INF\lib\***.jar を削除できませんでした。 D:\local\pleiades\workspace\***\WebContent\WEB-INF\lib\***.jar: プロセスはファイルにアクセスできません。別のプロセスが使用中です。
Could not rename file D:\local\pleiades\workspace\***\WebContent\WEB-INF\lib\._***.jar9000261316551232106.tmp to D:\local\pleiades\workspace\***\WebContent\WEB-INF\lib\***.jar
ProcessExplorerで調べてみると、EclipseのSpringプラグインらしきものがjarファイルを掴んでいる様子。
対処方法
Springの言語サーバが原因っぽいので、OFFにしてしまいます。おそらく補完などに影響が出るけど、そこは諦める方針。
メニューから「ウィンドウ」→「設定」 をクリック。
「言語サーバ」をクリックし、言語サーバのチェックを外して「適用して閉じる」*1。
*1:勢いで全部OFFにしたけど、Springのやつだけでよかった気がする
2018年に行ったライブ、フェス
今年はいろいろ行きました。
No. | 日付 | 名称 | 会場 | 一言 |
---|---|---|---|---|
1 | 2/14 | P.T.A.発足10周年!! と5周年!! “Perfumeとあなた”ホールトゥワー | 幕張イベントホール | 最高。初めての生edge。最高。 |
2 | 3/21 | Perfume x TECHNOLOGY presents Reframe | NHKホール | 1曲目のDISPLAYの没入感がやばくて、最初ぜんぶCGかと思った。テクノロジーさん最高。 |
3 | 6/2 | Amuse Fes in MAKUHARI 2018 -雨男晴女- | 幕張メッセ国際展示場 9〜11ホール | カタカナTとかサコッシュとか、グッズがPerfumeっぽいと思ったら本当にPerfumeの仕業だった。最高。 |
4 | 8/17-8/18 | SONICMANIA 2018 | 幕張メッセ | 中田ヤスタカ→MARSHMELLO→FLYING LOTUS(ちょっとだけ)→電気グルーヴ。中田ヤスタカ目当てで行ったらMARSHMELLOにハマった。あとTシャツ買うのに2時間かかってCORNELIUS見逃した。 |
5 | 8/19 | SUMMER SONIC 2018 | 幕張メッセ | レキシ→JORJA SMITH(ちょっとだけ)→m-flo→新しい学校のリーダーズ→THUNDERCAT→GEORGE CLINTON & PARLIAMENT FUNKADELIC。レキシでイルカのバルーンをポンポンしたりm-floで爆踊りしたりGEORGE CLINTONと愉快な仲間たちでいえーいってなったりいろいろあったんだけど、最後にやってたオカマのお姉さんたちに全部持ってかれた。 |
6 | 10/13 | Yasutaka Nakata presents OTONOKO 2018 | 石川県産業展示館 4号館 | やっぱりCAPSULEは最高。そしてまさかの米良美一。 |
7 | 10/23-10/24 | BABYMETAL WORLD TOUR 2018 in JAPAN | 幕張メッセイベントホール | ゆいちゃんが…。でもライブ自体はすごくよかった。IN THE NAME OFは7人いるからこそできるパフォーマンスだと思う。あとゲストのGalactic Empireも何気に好き。 |
8 | 12/11 | Perfume 7th Tour 2018 「FUTURE POP」 | 横浜アリーナ | ふゅーーーちゃーーーーーぽーーーーーーーっぷ!!!! |
9 | 12/29 | COUNTDOWN JAPAN 18/19 | 幕張メッセ国際展示場1~11ホール, イベントホール | きゃりーぱみゅぱみゅ→シシド・カフカ→ZAZEN BOYS→打首獄門同好会→CAPSULE/中田ヤスタカ→DJピエール中野。みんながだいすきな向井秀徳さんがいました。CAPSULE/中田ヤスタカは30分で最初短いなーと思ったけど、盛り上がるやつ全部入りみたいなセトリで終始爆踊りだったので超満足。 |
10 | 12/31 | Perfume 7th Tour 2018 「FUTURE POP」ファンクラブ限定・カウントダウン公演 | 横浜アリーナ | これから行く。ふゅーーーーーちゃーーーーーーーぽーーーーーーーーーっぷ!!!!!! |
来年もいろいろ行きたい。
それでは良いお年を。