gradle initをDockerを使って実行する

タイトル通り。macOS Mojave 10.14.6、Docker 19.03.5で動作確認しました。

以下のコマンドを実行します。

docker run -it --rm -v `pwd`:/home/gradle  gradle:5.6-jdk11 gradle init

すると以下のように色々と選択肢が現れるので、必要のものを選択するだけです。

Welcome to Gradle 5.6.4!

Here are the highlights of this release:
 - Incremental Groovy compilation
 - Groovy compile avoidance
 - Test fixtures for Java projects
 - Manage plugin versions via settings script

For more details see https://docs.gradle.org/5.6.4/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Swift
Enter selection (default: Java) [1..5] 3

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4] 4

Project name (default: gradle): sample_app
Source package (default: sample_app):

> Task :init
Get more help with your project: https://docs.gradle.org/5.6.4/userguide/tutorial_java_projects.html

BUILD SUCCESSFUL in 29s
2 actionable tasks: 2 executed

これでカレントディレクトリにGradleで生成された初期ファイル群が生成されます。

$ ls -l
total 40
-rw-r--r--  1 miyohide  staff   929 11 22 13:41 build.gradle
drwxr-xr-x  3 miyohide  staff    96 11 22 13:40 gradle
-rwxr-xr-x  1 miyohide  staff  5960 11 22 13:40 gradlew
-rw-r--r--  1 miyohide  staff  2942 11 22 13:40 gradlew.bat
-rw-r--r--  1 miyohide  staff   355 11 22 13:41 settings.gradle
drwxr-xr-x  4 miyohide  staff   128 11 22 13:41 src

Spring Boot 2.1.xから2.2.0に更新すると、PUTメソッドやDELETEメソッドがRequest method 'POST' not supportedとなる問題の解決

ドハマリしたので、ブログにも書いておきます。

Spring Boot 2.1.xではHTTPのput/deleteメソッドがうまく動いていたアプリをSpring Boot 2.2.0に更新すると動かなくなりました。

簡単なサンプルアプリを以下に置きました。

github.com

例えば、Thymeleafにて下記のコードのようにth:method="put"と指定しておいて...

<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <title>編集</title>
</head>
<body>
<div class="container">
    <form th:action="@{/todo/{id}(id=*{todoId})}" th:method="put" th:object="${todo}">
        <div class="form-group">
            <label class="control-label">タイトル</label>
            <input type="text" class="form-control" th:field="*{todoTitle}">
        </div>
        <button class="btn btn-primary" type="submit">更新</button>
    </form>
    <a href="/todo" class="btn btn-primary">一覧画面へ</a>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>

controllerで@PutMappingを指定します。

    @PutMapping("{id}")
    public String update(@PathVariable Integer id, @ModelAttribute Todo todo) {
        todo.setTodoId(id.toString());
        todoRepository.save(todo);
    }

Spring Boot 2.1.xでは動きますが、Spring Boot 2.2.0ではorg.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supportedという例外を吐きます。

色々と検索したのですが答えが出ず、Twitterで聞いてみたら@fukai_yasさんが速攻で回答をくれました。

@fukai_yasさんが示されたStackOverFlowがそのままの答えだった。spring.mvc.hiddenmethod.filter.enabled=trueapplication.propertiesに書けば動きました。

stackoverflow.com

ちゃんとリリースノートにも記されていたorz...

github.com

「ファクトフルネス」を読んだ

今更感がありますが、「ファクトフルネス」を読みました。

FACTFULNESS(ファクトフルネス) 10の思い込みを乗り越え、データを基に世界を正しく見る習慣

FACTFULNESS(ファクトフルネス) 10の思い込みを乗り越え、データを基に世界を正しく見る習慣

著者の名前にどこか聞き覚えがあるなと思ったら、TEDのビデオでした。

www.ted.com

チンパンジークイズ」も話題になりました。本を読む前にやっておくと面白いかと思います。

factquiz.chibicode.com

日本独自の問題として「ニホンザルクイズ」も用意されています。私は読了後に読んだのですが、なかなかどうして、結構難しい。

factquiz-jp.chibicode.com

個人的に印象深かったのは「第9章 犯人捜し本能」と「第10章 焦り本能」。マスコミとか政治家とか官僚とか目に見える人を糾弾するのは簡単だけれども、きっと本質はそこにはないとか、見えている問題に対して「すぐさま手を打たなければ」ってやってしまうことは多々あるので本当に気をつけないと。

今更ながらおすすめの一冊。

第103回 Yokohama.rbにてみんなで問題を解いてみた

月次で開催しているYokohama.rbにて@Nabetaniさんに用意して頂いた問題をみんなで解いてみるということをやってみました。

yokohamarb.doorkeeper.jp

用意して頂いた問題は以下のもの。

nabetani.sakura.ne.jp

問題としては単純なものです。ですが素朴に問題を解くと計算量が多くなるので、問題を速く解くためにはなんらかの工夫が必要という良問と思いました。

以下、回答編。問題を解きたい方はスクロールはしないでください。

.

..

...

.

..

...

.

..

...

.

..

...

.

..

...

.

..

...

.

..

...

さて、回答編です。

私が解いたのは以下のもの。愚直な実装です。

http://nabetani.sakura.ne.jp/yokohamarb/103mask/ の ...

会場では愚直な実装で解かれた方が多かったのですが、早々に@hamaknさんが高速な実装を行い参加者が皆驚いてました。

gist.github.com

@Nabetaniさんの実装例は以下の通り。

qiita.com

正直、一度読んだだけではよく理解できなかったので、手元で動かしながら理解していこうと思います。

こういう問題を解いたりすることをこれからもやりたいと思っています。ご興味ありましたらYokohama.rbにご参加いただけますと嬉しいです。

yokohamarb.doorkeeper.jp

「Docker for Rails Developers Build, Ship, and Run Your Applications Everywhere」を読み終わった

「Docker for Rails Developers Build, Ship, and Run Your Applications Everywhere」を読み終わりました。

Docker for Rails Developers: Build, Ship, and Run Your Applications Everywhere

Docker for Rails Developers: Build, Ship, and Run Your Applications Everywhere

The Pragmatic Bookshelfにある本書のページには本書をBeginnerレベルに位置づけられています。その位置づけ通りはじめてDockerを使ってRailsアプリを構築する人でもサクサク読み進められる本であると感じました。Rails Tutorialを一通りこなしたぐらいの経験は必要かと思いますが、Dockerに関する前提知識はいらないかなと思います。

洋書なので、当然英語を読む必要があります。ですが、本書の前半はチュートリアル形式で読み進めることができるので、コマンドやソースコードを写経していけば本書を進めることができます。わからないコマンドやオプションは適宜検索して母語の情報を漁ればいいかなと思います。

一方、本書の後半にある「Toward Production」からは英語を読むところが増えてくるので、英語を読み進める必要があります。頑張りましょう。

個人的には、Dockerfileの書き方の説明がかなり丁寧に書かれていたり、テストの部分もしっかり書いているので好感を覚えました。

Azure App ServiceでRailsアプリを動かしてみる

概要

Azure App ServiceのLinux版にてFree版が提供されました。

blogs.technet.microsoft.com

物は試しと先日のYokohama.rbにてRailsアプリを動かしてみました。

yokohamarb.doorkeeper.jp

ただ、SQLite3がロックされた状態になり、データの書き込みができない状態でしたので完全に動いたとは言えない状態です。

環境を作る

Azure PortalからApp Serviceを選択します。Rubyが2.3か2.4しかないのが寂しいところ。

f:id:miyohide:20190519100215p:plain

Free版はJapan Eastには無いみたいでApp Serviceを作成しようとするとエラーが発生して作成できませんでした。場所をEast Asiaにすると作成できました。

準備

ローカルのGitからApp Serviceにpushすることでアプリケーションのデプロイができます。「デプロイセンター」の画面から画面に従い操作をするとクローン先や認証情報が取得することができます(スクリーンショット取り忘れた...)

また、簡単のために環境変数RAILS_ENVdeploymentにします。「構成」の場所にて設定する場所があるので環境変数を設定します。

f:id:miyohide:20190519100740p:plain

他のページは日本語化されているのに、このページが英語なのはなんでなんだろう...

Railsアプリの作成

App Serviceで動いているRubyは2019年5月18日現在、2.4.5なので、それに合わせてRailsアプリを作ります。また、bundlerのバージョンも2.0.1ではなく、1.x系を使っています。このため、何も考えずに最新のRuby・bundlerでRailsアプリを作るとRubyやbundlerのバージョン不一致でgit pushしたときに異常終了してしまいます。rbenvを使っているのなら、

$ rbenv install 2.4.5
$ rbenv local 2.4.5
$ gem install bundler -v 1.17.3
$ gem install rails
$ rails new azure-app

といった感じでRailsアプリを作るのが良いでしょう。

また、アプリのルートにpackage.jsonがあるとRailsアプリとは認識されず、node.jsアプリとして認識されます。これを解決できなかったので、package.jsonファイルを消すことで対処しました。

App Serviceにpush

あとは

$ git remote add azure デプロイセンターで提示されたクローン先
$ git push azure master

とすると、App ServiceにRailsアプリがpushされ、自動的にbundle installが行われ、Railsアプリが起動します。App ServiceのURLにアクセスするとRailsの初期画面が表示されます。

f:id:miyohide:20190519101922p:plain

RDBMSへのCRUD操作

Railsscaffoldを使ってRDBMSへのCRUD操作をするアプリを自動生成させ、App Service上で動かしてみます。

$ rails g scaffold post title:string body:text
$ rails db:migrate

App ServiceにRailsアプリをpushしたとき自動的にdb:migrateは走らないのでとりあえずローカルでできたSQLite3ファイルをApp Serviceにpushするようにします。.gitignoreファイルを編集して/db/*.sqlite3ファイルをGitの管理対象外からGit管理対象とし、git pushします。

ただこの方法では、テーブルに値を書き込む際にロックが掛かってしまって書き込みができない問題が発生します。

f:id:miyohide:20190519102822p:plain

そもそもローカルで作ったSQLite3ファイルを無理やりApp Serviceに送っているのでこれは無理も無いことでしょう。

考察

ざっくりとAzure App ServiceでRailsアプリを動かすことをやってみました。短い間でのトライでしたが、とりあえず動かすことまでにたどり着けたのは一つの成果と思います。

あとで調べると、Azure App ServiceにRailsアプリをpushしたときに動く処理は以下のGitHubリポジトリに説明が書かれていました。

github.com

例えばpush時にdb:migrateをさせるには環境変数APP_COMMAND_LINEを独自に設定すれば良さそうです。

ただ、Rubyのバージョンが古いことやpackage.jsonと同居できないことから実際にはRailsアプリをDockerイメージ化して動かすのがよいのでは?とちょっと思っています。

JavaScriptコードレシピ集を読んだ

技術評論社から出ている『JavaScriptコードレシピ集』を読み終わりました。

gihyo.jp

紙版は600ページを超える厚さなので、電子書籍版で。

jQueryを使ったWebアプリはそれなりに書けるけど、thisの扱いがよくわからなかったり、最近の脱jQuery化の流れやES2015などの最近のJavaScriptについてはよく分からないなあと思っていたのですが、なかなか勉強するため のモチベーションが上がらず。そこで小難しい文法書よりもすぐ実践に結びつきそうなレシピ集で学んでみようと思い本書を手に取りました。

レシピ集なのでまずはパラパラとどのページに何が書かれているかを大雑把に把握。その後は必要に応じて写経するという読み方を取りました。

具体的にはWebアプリでのJavaScriptの利用が多いので、

  • 「Chapter 8 HTML要素の操作方法」
  • 「Chapter 9 フォーム要素の操作方法」
  • 「Chapter 14 さまざまなデータの送受信方法」

を中心に写経。

文法的な箇所としては、

  • 「223 非同期処理を行えるPromiseを使いたい」
  • 「267 thisが参照するものを固定したい(アロー関数)」
  • 「Chapter 19 JavaScriptをより深く知る」

が断片的な情報でしか把握してなかったので大変勉強になりました。

個人的には「JavaScriptのテスト」みたいな章が欲しかったところ。

しかしながら、当初の目的である最近のJavaScriptについてはなんとなく分かってきた感じ。手元において日々の開発に役立ちそうです。