PHPフレームワークLaravel入門を読みました

「これがいいらしいですよ」と雑に推したら仕事で使うことになったのでザーッと読みました。

PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

TOC

  • はじめに
  • 1: Laravelを準備する
  • 2: ルーティングとコントローラ
  • 3: ビューとテンプレート
  • 4: リクエスト・レスポンスを補完する
  • 5: データベースの利用
  • 6: Eloquent ORM
  • 7: RESTfulサービス / セッション / ペジネーション / 認証 / テスト

はじめに

1: Laravelを準備する

2: ルーティングとコントローラ

世にあるフレームワークと一緒なので割愛。

3: ビューとテンプレート

Bladeというテンプレートエンジンで描画する、あとは難しいことはない。

4: リクエスト・レスポンスを補完する

  • ミドルウェアはリクエストがコントローラのアクションに届く前(または後)に配置されるプログラム
  • ミドルウェアを用いてアクションが実行される前のリクエスト・アクション実行後のレスポンスに指定の処理を実行させることができる
  • その他のリクエスト・レスポンス処理としてクッキーの利用、リダイレクトなどに触れている

5: データベースの利用

  • LaravelはMySQL, PostgreSQL, SQLite, SQL Serverに標準で対応している
  • DBクラスとEloquent(エロクアント)というクラスがある。DBクラスはシンプルなクエリビルダで、EloquantはORM
    • 業務で使うならいろいろ鑑みてDBクラスのほうかな
  • 本書ではSQLiteに接続して進める。GUIツールとしてDB Browser for SQLiteを紹介している
  • .envにDB接続情報を記載する
    • いい感じ。でもこれがOKで.NetのWeb.configを気持ち悪く感じるのはなんでだろう
  • DBクラス(クエリビルダ)の使い方は通常のプログラムなので割愛
  • マイグレーションとシーディングもできる
    • シーディングはLaravelで初めて聞いた。テーブルに初期レコード(シード)を作成する機能とのこと

6: Eloquent ORM

使わないので割愛

7: RESTfulサービス / セッション / ペジネーション / 認証 / テスト

具体的な実装手順についてなので割愛。

ページネーション以外は確実に使うので開発するときに読み返します。

所感

この手のフレームワーク入門本はどの程度端折る⇒入門要素として取り上げるかに筆者の個性が出ると思うんだけど、こちらの本はインストール、ルーティング、描画、データストアの基本機能の説明のバランスが程よく、用語の説明も簡潔かつ丁寧で、また脇道にそれないのですっと内容を飲み込めて非常にわかりやすかったです。1時間くらいで読めたのでWAF自体の入門者でもそれなりの時間でやりきれて力がつくと思う。とてもよかった。

ライフゲーム作った

f:id:Cormorant:20180617132349p:plain

ホームページのコンテンツが思いつかなかったのでライフゲーム作りました。

サイトのコンテンツがない

先月、https://u.chimata.org/ をVuePress化したのだけど、そのときは単純に今までのサイト構成を再現するにとどめていて、これといったコンテンツがなくて寂しいホームページになっていた。寂しいホームページは10年近く続いてたんだけど。

そうだ、ポートフォリオサイトにしよう

「せっかくVuePressで簡単に静的サイトを更新できるようになったんだから、ちょっとした文章とサーバーサイドの処理が不要なコードが出てくるものを作ろう」と思い、じゃあデザイナーとかフロントエンドエンジニアがやってるポートフォリオサイトにしようということに。エンジニアもすなるポートフォリオサイトというものを端くれとしてかいてみんとてするなり。

物足りないので動きがほしい

とりあえず第1段として、自己紹介と自分の連絡先になるSNSサイトへのリンク、そしてエンジニアっぽくよく使う技術をリストにしてみたらあっというまにできてしまった。Markdownを書くだけでウェブサイトになるので静的サイトジェネレータはほんといい。でもこれだけだと面白みがないし、なによりエンジニアーって感じがしないので、トップになんかワチャーっと動くものがほしくなりました。そしたらじゃあ作ったことないけどライフゲームやってみるか、となった。

ライフゲームについて

ライフゲームの仕様を大雑把に書くと、格子状のセルを用意して、それぞれのセルに生存/死亡の状態を持たせ、初期値としてどちらかを与えた上で、

  1. 生存しているセルに対して
    1. 周囲8マスのうち、生存しているセルが2つまたは3つある場合は次世代でも生き残る
    2. それ以外の場合は死亡する
  2. 死亡しているセルに対して
    1. 周囲8マスのうち、生存しているセルが3つある場合は新たに生存したセルが誕生する(セルを生存状態にする)

というルールで世代交代をひたすら繰り返していくというものです。そうすると上記のようなセルがうねうねする画像が手に入ります。

そんな感じで初めてライフゲームを作ってみたんだけど、思いの外あっさりできてしまった。ライフゲーム、見た目は複雑っぽく見えるので、昔はもっと難しいプログラムだと思ってたんだけど、やってみると大したことない。上の仕様を実装するのはそれほど難しくなくて、それをどう絵にするかが悩みどころだなと思いました。JavaScript+HTMLならCanvasがあるのでググりながらで簡単に行けると思います。

以上です

あまりにも手が動かないためどこかに晒しながらやるかと思い、年始頃VTuberを目指して準備した配信環境を使ってニコ生で作業配信して作りました。抱きまくら(嫁)のブログ見ましたとか言われて恥ずかしかった。

抱きまくら買った

カバーに嫁が書いてあるやつじゃない方の抱きまくらの話です。

眠りの質が悪い

最近夜中に途中で何度も起きてしまって、掛け布団が毛布しかないのでクソ暑いせいだなと思い掛け布団無しで寝ているんだけど、そうすると「何かに包まれてる」という幸福感が薄れてしまい、睡眠の質が下がった気がしていた。でも暑いので掛け布団は嫌だからどうしようかなと思っていました。

はやくこれになりたい

そうしたらAmazonのタイムセールで抱きまくらが売っていて、「要は何かに触れていれば幸福感が高まるのでは」と思い、ポチポチと抱きまくらの関連商品を眺めていたらこの画像に出会った。

f:id:Cormorant:20180608055926j:plain
はやくこれになりたい

抱きまくら買った報告

うれしそうですね。

一晩寝てみて

一晩寝てみた感じ、なにかに触れてると安心感があり、すごく心地よく眠れて大変よかったです。ただあんまりがっつり抱きついてると寝返りが打てないので体が痛くなるかもしれない。そのあたり注意しないといけない。

あと衝動的に買ったので置き場のことを考えてなかった。スペース確保できて抱きつく相手がいない場合はおすすめ…ウグッ(息が詰まる音)。まあつまりこれは抱きつくための動かない死体を買ったということであり、動かない死体としての抱きまくらならそれはカバーにWaifuが描かれているタイプの抱きまくらと実質同じではというところに思い至ったのでこの話はおしまい、おしまいなんです。はい解散!

Qiitaで週間ユーザーランキングに載った

滅多に話題になることないので記念になってよかったですという話です。

おもいのほか伸びてビビった

先週末、Dockerfileを書くときに気をつけていること10選という記事を書いたところ、想定の10倍くらい伸びて、一時トレンドのトップ、3日で週間ユーザーランキングの4位に載りました。はてブも160ちょっとついてて、昨日一昨日は「こんなこと初めてだわ…」ってずっと言ってた。

普段はなかなか技術記事なんて書かないので、ふと書いてみたらあたっちゃったものだから、伸び始めたあたりではいつマサカリが飛んでくるかとかなりヒヤヒヤしてました。現在の段階でまったく飛んできてない。優しいインターネットでよかったですね。

なんで伸びたのか

ありそうでなかったところに偶然ハマったというような印象。Dockerは割と人気のタグにもかかわらず、それほど投稿数が多くないというのと、Dockerfileの書き方という記事はネットに結構あるけど「こういう場面ではこう対処する」といったようなTipsの記事が多く、具体的な書法、書き方の記事が少なかったため、そこにポッと出てきた私の記事が人気になったのかなというように見えました。Dockerfileを書こうと思っているもののどう書いたものか悩んでるエンジニアが結構いたのかなと思います。実際はてブもコメント全然つかないしタグも"あとで試す"が多いので、みんな結構悩んでたんだなーと。あと、「〇〇を〇〇する10の方法」ってやっぱり好きなんですね。

内容について

とりあえず10個挙げよう、と思って書き出したらさっと8個くらい埋まったので、3時間くらいかけて10個に整理して公開しました。記事に挙げた気をつけていることは、実は初めてDockerfileを書き始めて1ヶ月くらいで調べて身につけたもので、その後1年かかって「これで間違いはなさそうかな」と思える様になってきたので記事にしました。なので全然難しいことは書いてない。だからこその当たりかもしれませんが。ベストプラクティスからあまり大きくは外れてないはずです。

Qiitaの問題点

ぶっちゃけそんな大したことを書いているつもりはなかったんだけど、それでも伸びるのは、あの手の具体的な技術知識をまとめた記事が不足している側面もあるんじゃないかなと思っています。最近のトレンドを見ていると、どうしてもポエムとか和訳とかライフハックみたいな記事が多くて、技術についての知見を整理したものがあんまり当たってない印象を受けます。悲しい。Qiitaがポエムを許したんだからまあそうなるよな。

おしまい

f:id:Cormorant:20180607021116p:plain
記念撮影
✌('ω' )✌

最近やったこと

ここに何書いたらいいかわからないので最近やったことを書いていきます。

QiitaにDockerの記事を書いた

最近はDockerとかなり仲良くしていました。
といっても個人開発とか開発環境の配布に利用しているので、大規模開発でDockerコンテナを利用してサービスをクラウドサーバにデプロイしましたみたいなすごそうなことはやってない…あくまで開発者向け/サーバ向けアプリケーションの配布手段としていいかもなって思って使っています。

そういうことを思って使ってるうちにちょっとしたノウハウが溜まってきたので、TipsとしていくつかDockerの記事を書きました。

他にも何個か書いてます。自分の備忘録的面が強いけど、いつかどこかで誰かの役に立つといいな。

Dockerに関連して、OpenFaaSがいまちょっと気になっています。

多分クラウドサーバや任意のインターネットから叩けるグローバルなコマンドがほしいときに役立つんだと思うんだけど、いまのところそういった欲求がないので手が出てない。そのうち試したいです。

ホームページのサーバを移転した

10年近くずっとロリポップレンタルサーバー(当時はチカッパ!レンタルサーバーだったけどサービズ統合された)を借りていたんですが、どうしてもCGIじゃない常駐サーバ型のウェブサービスを作りたくなり、同じGMOグループのサービスであるConoHaでVPSを借りました。

チカッパ優待プランからの移行なので、月+100円で自分で自由に構築できるサーバを手に入れたことになります。現状、移行前後で不都合は起きてないのですが、サーバースペックが大きく様変わりしたのが若干気になるところです。

変わったところでいうと、サーバーの容量が120GB→20GBに大幅ダウンしたんだけど、別に120GBも容量使いきれる気がしてなかったのでどうでもいいし、むしろSSD化された?ことのほうが魅力的かも。これがサーバの応答速度にどれくらい影響するかは不明です。というか、今まで応答速度が気になるものをロリポップに配置したことがない…(高負荷のものは禁止されていたので)。メモリが512MBなのもちょっと気になるけど、共有サーバーに比べたらおそらくマシでしょう。

ConoHa自体の話は別の記事でやるかも。

Webサービス作り始めた

「どうしてもCGIじゃない常駐サーバ型のウェブサービスを作りたくなり」の部分の話。とあるVTuberのファンサイトをつくりたくて、でもやりたいことを実現するためには技術的ハードルをいくつか乗り越えないといけない、ということで、共有サーバーでは出来ないことがあり、サーバ移転をしました。課題が多くて難航しています。先週からほとんど調査ばかりしていて、まったくサービスのコードは書けていない…ぼちぼち走り出します。

課題の調査のために作ったWebチャット → Web chat system written in Elixir / Phoenix (for study)

とりあえず、上記が動いていればサービス公開の環境が整ってることになります。あとはコードを書くだけ。

Scrapboxを日記帳代わりに使い始めた

日記を書きたいけど日記帳がない問題を抱えていて、Twitterをお休みしたためにその不満が爆発した。

そんなわけで日記をScrapboxで書いてます。今日の日記はこれ。やってることTwitterとなんもかわらん。PWAに対応しているのかな?スマホのホーム画面に追加してポチポチしてます。

他にはBanishedの実績解除にチャレンジしたりとか、ふつうのWikiっぽい?使い方もやってます。まさにScrap。

おしまい

そんなところです。なんか元気になってきたし、ひとりでインターネットしてるのも寂しいので、6月になったらTwitter再開するかも。

「Elixir/Phoenix初級(1)はじめの一歩」を読みました

Phoenixがわからないせいで個人開発がストップしたのでお勉強していきます。

Elixir/Phoenix 初級?: はじめの一歩 (OIAX BOOKS)

Elixir/Phoenix 初級?: はじめの一歩 (OIAX BOOKS)

成果物はこちら → c18t/hello-phoenix

TOC

  • はじめに
  • 01: Elixir/Phoenixへの誘い
  • 02: 各種ソフトウェアのインストール
  • 03: Elixirの初歩
  • 04: 基本データ型
  • 05: Hello, world!
  • 06: 経路設定の初歩
  • 07: コントローラとアクション
  • 08: HTMLとテンプレート
  • 09: パラメータ
  • 10: HTML文書の区分とスタイルシート
  • 11: BootstrapとFont Awesome
  • 12: モジュールと関数
  • 13: リストとタプル
  • 14: マップとキーワードリスト
  • 15: ビューモジュール
  • 16: ページ間のリンク
  • 17: 画像
  • 付録A: Chromeデベロッパーツール
  • 付録B: ベンチマークの計測
  • 付録C: Homebrewのインストール
  • 付録D: Node.jsのインストールと更新
  • 付録E: 本番モード(prod環境)

はじめに

  • 本書の対象はWebアプリ開発にはじめて挑戦する人
    • マジか。ElixirでWebアプリ開発の学習を初めてやる人なんてどれくらいいるんだ…
  • 第1巻では下記のテーマは扱わない
    • パターンマッチング
    • パイプ演算子
    • 再帰
    • 並行プログラミング
  • OIAX BOOKS『Ruby on Rails 5.0 初級①』をベースに、内容をElixir/Phoenix向けに書き直しているため、本文にかなりの重複がある
    • なるほどそれで対象読者がそうなったのか
  • ソフトウェアのバージョンはガンガン無視していきます

01: Elixir/Phoenixへの誘い

02: 各種ソフトウェアのインストール

割愛。Hex, rebar, Phoenixをインストールしました。

03: Elixirの初歩

お試しのスクリプト

n = 1
n = n + 1
IO.puts n

Erlangでは変数に再代入できなかったけど、Elixirでは可能。参照が差し替わるだけだからやらかしは起きないはず。

$ elixir primer/v01/ch03/variable.exs
2
  • IOはモジュール。
  • .putsは関数。関数のカッコは省略可能。
  • 式の終端は改行またはセミコロン
  • #以降はコメント
  • =begin ... =endで複数行コメント
    • 丸っきりRubyだ。

04: 基本データ型

割愛。整数、文字列、アトム。

Hello, world!

$ mix phoenix.new modest_greeter --no-ecto
* creating modest_greeter/config/config.exs
* creating modest_greeter/config/dev.exs
* creating modest_greeter/config/prod.exs
* creating modest_greeter/config/prod.secret.exs
* creating modest_greeter/config/test.exs
* creating modest_greeter/lib/modest_greeter.ex
* creating modest_greeter/lib/modest_greeter/endpoint.ex
* creating modest_greeter/test/views/error_view_test.exs
* creating modest_greeter/test/support/conn_case.ex
* creating modest_greeter/test/support/channel_case.ex
* creating modest_greeter/test/test_helper.exs
* creating modest_greeter/web/channels/user_socket.ex
* creating modest_greeter/web/router.ex
* creating modest_greeter/web/views/error_view.ex
* creating modest_greeter/web/web.ex
* creating modest_greeter/mix.exs
* creating modest_greeter/README.md
* creating modest_greeter/web/gettext.ex
* creating modest_greeter/priv/gettext/errors.pot
* creating modest_greeter/priv/gettext/en/LC_MESSAGES/errors.po
* creating modest_greeter/web/views/error_helpers.ex
* creating modest_greeter/.gitignore
* creating modest_greeter/brunch-config.js
* creating modest_greeter/package.json
* creating modest_greeter/web/static/css/app.css
* creating modest_greeter/web/static/css/phoenix.css
* creating modest_greeter/web/static/js/app.js
* creating modest_greeter/web/static/js/socket.js
* creating modest_greeter/web/static/assets/robots.txt
* creating modest_greeter/web/static/assets/images/phoenix.png
* creating modest_greeter/web/static/assets/favicon.ico
* creating modest_greeter/test/controllers/page_controller_test.exs
* creating modest_greeter/test/views/layout_view_test.exs
* creating modest_greeter/test/views/page_view_test.exs
* creating modest_greeter/web/controllers/page_controller.ex
* creating modest_greeter/web/templates/layout/app.html.eex
* creating modest_greeter/web/templates/page/index.html.eex
* creating modest_greeter/web/views/layout_view.ex
* creating modest_greeter/web/views/page_view.ex

Fetch and install dependencies? [Yn]
* running mix deps.get
* running npm install && node node_modules/brunch/bin/brunch build

We are all set! Run your Phoenix application:

    $ cd modest_greeter
    $ mix phoenix.server

You can also run your app inside IEx (Interactive Elixir) as:

    $ iex -S mix phoenix.server

modest_greeterプロジェクトが出来たので動かしてみる。

$ cd modest_greeter
$ mix phoenix.server

12:22:04.503 [info]  Compiling file system watcher for Mac...

12:22:06.052 [info]  Done.
==> file_system
Compiling 7 files (.ex)
Generated file_system app
==> gettext
Compiling 1 file (.yrl)
Compiling 1 file (.erl)
Compiling 20 files (.ex)
Generated gettext app
===> Compiling ranch
warning: String.strip/1 is deprecated, use String.trim/1
  /Users/private/Projects/github.com/c18t/hello-phoenix/modest_greeter/deps/poison/mix.exs:4

==> poison
Compiling 4 files (.ex)
warning: Integer.to_char_list/2 is deprecated, use Integer.to_charlist/2
  lib/poison/encoder.ex:173

Generated poison app
==> phoenix_pubsub
Compiling 12 files (.ex)
Generated phoenix_pubsub app
===> Compiling cowlib
src/cow_multipart.erl:392: Warning: call to crypto:rand_bytes/1 will fail, since it was removed in 20.0; use crypto:strong_rand_bytes/1

===> Compiling cowboy
==> mime
Compiling 1 file (.ex)
Generated mime app
==> plug
Compiling 1 file (.erl)
Compiling 48 files (.ex)
warning: function :cowboy_stream_h.data/4 is undefined (module :cowboy_stream_h is not available)
  lib/plug/adapters/cowboy2/stream.ex:9

warning: function :cowboy_stream_h.info/3 is undefined (module :cowboy_stream_h is not available)
Found at 2 locations:
  lib/plug/adapters/cowboy2/stream.ex:13
  lib/plug/adapters/cowboy2/stream.ex:21

warning: function :cowboy_stream_h.init/3 is undefined (module :cowboy_stream_h is not available)
  lib/plug/adapters/cowboy2/stream.ex:5

Generated plug app
==> phoenix_html
Compiling 8 files (.ex)
Generated phoenix_html app
==> phoenix
Compiling 74 files (.ex)
warning: Enum.partition/2 is deprecated, use Enum.split_with/2
  lib/phoenix/endpoint/handler.ex:39

warning: Enum.partition/2 is deprecated, use Enum.split_with/2
  lib/mix/tasks/phoenix.gen.model.ex:155

warning: Enum.partition/2 is deprecated, use Enum.split_with/2
  lib/mix/phoenix/schema.ex:234

warning: Plug.Conn.WrapperError.reraise/3 is deprecated. Use reraise/1 or reraise/4 instead.
Found at 2 locations:
  lib/phoenix/controller/pipeline.ex:138
  lib/phoenix/router.ex:280

Generated phoenix app
==> phoenix_live_reload
Compiling 4 files (.ex)
Generated phoenix_live_reload app
mix phoenix.server is deprecated. Use phx.server instead.
==> modest_greeter
Compiling 11 files (.ex)
warning: Plug.Conn.WrapperError.reraise/3 is deprecated. Use reraise/1 or reraise/4 instead.
Found at 2 locations:
  web/router.ex:4
  web/router.ex:12

Generated modest_greeter app
[info] Running ModestGreeter.Endpoint with Cowboy using http://0.0.0.0:4000
12:22:20 - info: compiled 6 files into 2 files, copied 3 in 815 ms

f:id:Cormorant:20180526184453p:plain

動いた!

Hello, world!をやるため、不要なファイルを削除していく。

rm web/controllers/page_controller.ex
rm web/static/css/phoenix.css
rm web/views/page_view.ex
rm -rf web/templates/page/

続いて、router.exの修正

defmodule ModestGreeter.Router do
  use ModestGreeter.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  scope "/", ModestGreeter do
    pipe_through :browser
  end
end

レイアウトテンプレートの修正

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>ModestGreeter</title>
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
  </head>

  <body>
    <%= render @view_module, @view_template, assigns %>
    <script src="<%= static_path(@conn, "/js/app.js") %>"></script>
  </body>
</html>

経路の作成

web/router.exget "/hello", HelloController, :showを追加。

アクションの作成

defmodule ModestGreeter.HelloController do
  use ModestGreeter.Web, :controller

  def show(conn, _params) do
    render conn, "show.html"
  end
end

ビューの作成

defmodule ModestGreeter.HelloView do
  use ModestGreeter.Web, :view
end

テンプレートの作成

<p>Hello, world!</p>

再度サーバー実行

mix phoenix.server

http://localhost:4000/hello にアクセスすると

f:id:Cormorant:20180526184735p:plain

テンプレートの内容がレイアウトに沿って出た!

06: 経路設定の初歩

割愛。よくあるフレームワークのルーティングと同じように定義する。

07: コントローラとアクション

割愛。リクエストの構造体connについては8章、16章、そして次巻で取り扱う。 メタプログラミングのコラムあり。

08: HTMLとテンプレート

HTML自体の説明とテンプレートについて。erbとだいたい一緒。

テンプレートに値を渡すには、アクションのrender関数の第3引数にキーワードリストを渡す。テンプレート内ではキーワードで要素にアクセスできる。

アクションの修正

defmodule ModestGreeter.HelloController do
  use ModestGreeter.Web, :controller

  def show(conn, _params) do
    render conn, "show.html", name: "Alice"
  end
end

テンプレートの修正

<p>Hello, <%= @name %>!</p>

f:id:Cormorant:20180526184807p:plain

テンプレート中の @ はマクロであり、キーワードリストの値を取得するコードに展開される。

レイアウトテンプレートでも渡されたキーワードリストを参照できる。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>ModestGreeter (<%= @name %>)</title>
    ...

f:id:Cormorant:20180526184948p:plain

ライブリロードされることも確認できた。

09: パラメータ

クエリパラメータを受け取るにはこうする。

defmodule ModestGreeter.HelloController do
  use ModestGreeter.Web, :controller

  def show(conn, params) do
    render conn, "show.html", name: param["name"]
  end
end

f:id:Cormorant:20180526185034p:plain

URLパスにパラメータを埋め込むにはこうする。

defmodule ModestGreeter.Router do
  use ModestGreeter.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  scope "/", ModestGreeter do
    pipe_through :browser

    get "/hello", HelloController, :show
    get "/hello/:name", HelloController, :show
  end
end

URLパラメータの省略記法はないのでパラメータなしのルートも作成する。

f:id:Cormorant:20180526185144p:plain

デフォルト値を設定するにはこうする。

defmodule ModestGreeter.HelloController do
  use ModestGreeter.Web, :controller

  def show(conn, params) do
    render conn, "show.html", name: param["name"] || "world"
  end
end

f:id:Cormorant:20180526185152p:plain

汚染が気になる…

f:id:Cormorant:20180526185209p:plain

ちゃんと除染されてた。

10: HTML文書の区分とスタイルシート

割愛。HTMLとCSSについて。PhoenixはBrunchでSCSSなどのリソースを変換・出力をしている。

11: BootstrapとFont Awesome

割愛。章タイトルまま。

12: モジュールと関数

モジュールの定義と利用について。

defmodule Hello1 do
  def greet(name) do
    IO.puts "Hello, #{name}!"
  end
end

Hello1.greet "Alice"
Hello1.greet "Bob"
$ elixir primer/v01/ch12/hello1.exs
Hello, Alice!
Hello, Bob!

関数はモジュール外に定義できないので注意。

exファイルをコンパイルするとbeamファイルができる。

defmodule Hello do
  def greet(name) do
    IO.puts "Hello, #{name}!"
  end
end
$ elixirc primer/v01/ch12/hello2.ex
$ ls
Elixir.Hello2.beam modest_greeter     primer
$ iex
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe][kernel-poll:false]

Interactive Elixir (1.6.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Hello2.greet "Alice"
Hello, Alice!
:ok
iex(2)>

スクリプトはカレントディレクトリのBeamファイルも読み込む。

Hello2.greet "Alice"
Hello2.greet "Bob"
$ elixir primer/v01/ch12/hello2.exs
Hello, Alice!
Hello, Bob!

後は割愛。引数のアリティとデフォルト値について。また、無名関数について。

13: リストとタプル

割愛。コラムはErlang / Elixirのリストは連結リストだから末尾の参照は遅いよという話。

14: マップとキーワードリスト

割愛。

15: ビューモジュール

割愛。テンプレートから@view_moduleでアクセスできる。

16: ページ間のリンク

割愛。リンクは<a>タグではなくlink関数とパスヘルパーで作ろうねという話。パスヘルパーの最後の引数[]を省略するエレガントなやり方は次巻で。

17: 画像

割愛。

付録A〜D

割愛。

付録E: 本番モード(prod環境)

mix deps.get --only prod
MIX_ENV=prod PORT=4001 mix do compile, phoenix.server

感想

本当にはじめの一歩といった内容で、さすがにWebアプリ開発は全くの初心者ってわけではないのであまり自分向きではなかった。Elixirの言語仕様については他所でやってしまったので、Phoenixの情報を期待していたんだけど、自分にとって目新しいものはルーティングと付録Eくらいか。

Web技術(HTML,CSS)の解説とElixirの仕様解説が程良い塩梅で用意されており、テキスト通りすすめるための準備が大変なのを除けば、順序よくステップアップしていける内容になっているので良いと入門に良いと思います。この本の想定している読者が果たしてElixirに入門すべきかは疑問ですが…素直にRuby on RailsとかLaravelやったほうがいいと思う。ただ、本当に新しめのスタンダートな内容を丁寧に手取り足取り教えてくれるいい本だと思いますので、これからWebを始めようと考えていて、RubyPHPPythonなんてみんながやってる言語は嫌で、やるなら当然モダンでハイパフォーマンスなプログラムを書きたくて、時代は関数型言語だ!って方にならオススメできます。

インターネットやめる(やめない)話と、16歳の少女の自殺について

前回の記事から180度言ってることが変わるが、インターネットをやる(抽象的表現)のがつらくなったので暫く自粛しようと思う。

事の発端は文春が出した、農業アイドルが自殺した事件についての母のインタビュー記事だ1。例の記事を読んでしまい、そのあまりの救いのなさに怒りと悲しみがとめどなく溢れてきて、やるせなさから2日寝込んだ。

医者から楽しいことをやるようにと言われ、ならばと楽しいこと探しをしている最中にあの記事に出会ってしまった。世の中にはつらいこと苦しいことが溢れていて、それは自分の見えないところでも日々起こっているとわかっていたつもりだが、それでも目の前に突きつけられると最悪な気分になるし、つらい。

その時の様子。

こういった出会いはインターネットをやっていればまま有ることで、今回の遭遇も自分にとってはよくあるもののひとつだと思っていたのに、想像以上に衝撃を受けてしまった2

今の自分には痛ましい事件や事故を自分の外側のものとして受け止められないということらしい。普通の状態であれば怒りや悲しみが沸きこそすれ、それで2日も寝込まない。無自覚に危険な行動をとっていて、それで車にはねられたようなものだと思う。交通事故を防ぐためには、ばかみたいに車道に飛び出して歩かないようにする他ないわけで、Twitterや一般ニュースのフィードは暫く見ないことにした。はてブは悪い文化。

日報はいい習慣だと思うので続けようと思う。Twitterは、心に湧いたとりとめのないことを書き残すのにちょうどいいので続けたい気持ちもあるけど、自分はふぁぼり魔なのでタイムラインを見ないようにしててもすぐ見たくなってしまうと思う。だからやらない。時々API叩いて何か出力されるかもしれないけど他の人のツイートは見ていないと思う。とりとめのないことはscrapboxに書いていく。

...

...

...

ここまでが自分の話。

件の母親の告白について、混乱した頭では稚拙なことしか言えないので今言えることは少ないんだけど、それでも。

周囲の大人の対応が、ことごとく16歳の少女に対しての行いではないということが、どれだけ彼女を追い詰めただろうと思うと胸が苦しくなる。 本人には周りの環境が全てだろう、特に子供はそういうものだし、受け入れてしまいがちだが、それでも転校したいとか、(信頼していたという)Sさんがこわいから行きたくないとか、親に訴えるのは尋常ではないということは容易に想像できる。大人がケアしてあげるべきところで逆に責められる環境が、自殺の方法を調べて即実行という、突発的で最悪な選択を彼女にさせてしまった。

16歳は"未成熟な大人"ではなく、"子供"だ。自分はアイドルのことはさっぱりわからないが、夢見る子供はあやふやで向こう見ずだ。同世代で比較して責任感の強い子であってもだ。 普通のアルバイトでさえそのことを考慮して受け入れつつ働かせるのだから、アイドル業界は曖昧で危険な生き物の貴重な時間を借り受けてビジネスをしていることを当然自覚して運営すべきだが、マネジメントはアイドル事務所ですらないという。まっとうな大人がそばに一人でもいれば防げたことだし、それがなかったというところに、農家の出身としては日本の農業が陥っている閉ざされた異常な環境にまで考えが及んでしまう。

母親を責める声があるが、第一に責めるべきはそちらではないだろう。第二に、ということかもしれないが。子供を守る力に乏しい親というのは見ていて切ない。それが怒りになるのかもしれないが、追い詰めるのはやめたほうがいいと思う。

いま悲しみや怒りに苛まされているのは上記のような心境からだと思う。彼女は私にとって全然知らない人だし、私は完全に部外者なのに、どうしようもなく怒りが湧いてくる、ひたすらに悲しい。

つまづいたり失敗したり揺れる子供を、大人が追いつめてしまわない社会であること、少なくとも、少年少女の夢や希望がこんな最悪な形で終わることのない世の中であることを望みます。

大本萌景さんのご冥福をお祈りします。


  1. 母親が告白 農業アイドルだった大本萌景さん(16)は、なぜ自殺しなければならなかったのか | 文春オンライン

  2. 書いていて感じたが、少女の自殺でこんなにも心を揺さぶられてしまうのは、私が過去に自殺で女友達をなくしているからかもしれない。