備忘録

働きたくないでござる

Elixir, Phoenix でデフォルトで created_at を使う方法

Rails から Elixir に移行しようと思っているので、 inserted_atではなく created_at を使いたいと思っています。
ただ、 Ecto で created_at を使うにはマイグレーションとモデルに timestamps(inserted_at: :created_at) にわざわざ書かないといけないので事故りそうです。

めんどうなのでデフォルトで created_at を使うようにしたいのですが、結論から書くとは現行の安定バージョンではできないようです。 しかし、 elixir_ecto の v2.2.0-rc.1 では migration_timestamps というパラメーターが追加されています。
ecto/migration.ex at v2.2.0-rc.1 · elixir-ecto/ecto · GitHub

現状の Phoenix では

Failed to use "ecto" (version 2.2.0-rc.1) because
  phoenix_ecto (versions 3.2.0 to 3.2.3) requires ~> 2.1 *
  mix.exs specifies ~> 2.2.0-rc.1

と怒られるので使用できませんが、今後使えるようになるようですね。

ちなみに使用する時は config/config.exs に以下のように書けばいいような雰囲気を感じています。

config :sample, Sample.Repo,
  migration_timestamps: [inserted_at: :created_at]

migration_primary_key も追加されているのでプライマリーキーを変更することもできそうですし、タイムスタンプnaive_datetimeutc_datetime に変更することもできるようです。

所感

Elixir を初めてまだ2日目ですが、 Elixir や Phoenix などの進化速度の速さに驚いています。 前情報ではエコシステムの小ささがネックと聞いていましたが、今のところあまり不満は感じていないです。

Elixir チュートリアル (3) Phoenix 導入

過去記事 giraphme.hatenablog.com giraphme.hatenablog.com

今回は Phoenix を使えるところまで進めたいと思います。

Phoenix のインストール

公式の言う通り これで最新版のアーカイブを取得できます。

$ mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez

もちろん、任意のバージョンを探してきて取得することも可能です。
GitHub - phoenixframework/archives: Holds archives for released Phoenix versions

プロジェクトを作成

Mix でプロジェクトを作成します。

$ mix phoenix.new sample
* creating sample/config/config.exs
* creating sample/config/dev.exs
* creating sample/config/prod.exs
* creating sample/config/prod.secret.exs
* creating sample/config/test.exs
* creating sample/lib/sample.ex
...
Fetch and install dependencies? [Yn] Y
* running mix deps.get
* running npm install && node node_modules/brunch/bin/brunch build
We are all set! Run your Phoenix application:

    $ cd sample
    $ mix phoenix.server

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

    $ iex -S mix phoenix.server

Before moving on, configure your database in config/dev.exs and run:

    $ mix ecto.create

この状態で mix phoenix.server しても自分の環境では

[error] Postgrex.Protocol (#PID<0.3406.0>) failed to connect: ** (Postgrex.Error) FATAL 28000 (invalid_authorization_specification): role "postgres" does not exist

と言われて動かすことができないので、 PostgreSQL の設定をするか MySQL を使えるようにしましょう。

MySQL の設定

私の場合、普段の業務で MySQL を使用しており、環境が整っているので MySQL を使えるように設定しました。

まずは /mix.exsdeps に以下を追記

  defp deps do
    [
      {:phoenix, "~> 1.3.0-rc"},
      {:phoenix_pubsub, "~> 1.0"},
      {:phoenix_ecto, "~> 3.2"},
      ...
      {:mariaex, "~> 0.1"}, # ここ
      ...
    ]
  end

そして config/dev.exs# Configure your database の箇所を以下のように変更します。

config :sample, Sample.Repo,
  adapter: Ecto.Adapters.MySQL,
  username: "ユーザー名",
  password: "パスワード",
  database: "DB名",
  hostname: "localhost",
  pool_size: 10

その後、以下のコマンドを実行してください。

$ mix deps.get
$ mix phoenix.server

これで http://0.0.0.0:4000 にアクセスすると Web サーバーが起動していることを確認できるはずです。

所感

dev, prod など中途半端に省略されていることが多くて気持ち悪い……。

Elixir チュートリアル (2) 用語編

前回: giraphme.hatenablog.com

とりあえず動かすことができたので、今回は Elixir を勉強するにあたって出会ったワードたちについてまとめていこうと思います。 ちなみに、一覧性を重視して深いことは書かないので、詳細はググッてください。決して深いことを書いてマサカリ投げられたくないからではないです。 どうせ後から増えていくので随時追加予定です。

Erlang

細かいことを書き出すと怖い人からマサカリ投げつけられそうなので簡単な紹介にしておきますが、 Wikipedia 曰く並行処理指向のプログラミング言語および実行環境らしいです。 簡単にプロセス生やせてめっちゃ早いって偉い人が言ってました。

Erlang VM

Elixir の説明を見ていると、「Erlang VM(BEAM)上で動く Ruby っぽい関数型言語」っと説明されていることが多いような気がします。
Erlang VM とは Erlang で書かれた仮想マシンで、Erlang/OTP で書かれたプログラムはこの仮想マシン上で動作させます。

Erlang/OTP

OTP is 何

Elixir

公式曰く

Elixir is a dynamic, functional language designed for building scalable and maintainable applications.

らしいです。
Elixir 自体については後日記事を書きながら紹介していきます。

iex

Elixir の REPL です。 Ruby で言う irb や pry。
brew で elixir インストールすると勝手にインストールされます。

mix

Ruby でいう Bundler 的なやつだという説明をよく見ますが、使っているところを見る限りでは Bundler よりも高機能なようです。
こいつも brew で elixir インストールすると勝手にインストールされます。

追記: Bundler はパッケージ管理ツールですが、 Mix はプロジェクト管理ツールのようです。 rails コマンドのようにプロジェクト作成などをできます。

Hex

Elixir 界隈ってググりにくいワード多すg(ry
Elixir, Erlang のパッケージ管理ツールらしいです。

Phoenix

Elixir の Web フレームワークです。

Plug

Web アプリケーションを構成するための仕様と、 Erlang VM 上で動作する Web サーバーとのアダプターらしいです。 Ruby では Rack が RailsWebrick 等の Webサーバーとの間を取り持ってくれますが、同じような役割を果たしてくれると認識しています。

Cowboy

Erlang VM 上で動作する Web サーバーです。

Ecto

Elixir の ORM です。軽量 ORM らしいけど、どこらへんが軽量なのか使ってみてから書きます。

Poison

所感

新しいこと勉強してると積本とブラウザのタブが大量増殖しますよね。
とりあえず、 すごい E 本読まないと感ヤバい。(図書館で予約した。)

Elixir チュートリアル (1) 導入編

Rails 5.1 の記事を書いていましたが、中身がないし旬もすぎてるクソ記事だったので Elixir に方向転換。

まずは導入から。

Elixir を導入

rbenv 風の elixir-buildexenv を使おうと思ったのですが、3年ほどメンテナンスされておらず地雷感満載だったので普通にドキュメントどおりにやりました。 複数バージョン試す必要があったら Docker を使おうと思います。

$ brew update
$ brew install elixir

これで最新版の Elixir がインストールされるはずです(執筆時 v1.5.1)
Releases · elixir-lang/elixir · GitHub

$ elixir --version
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Elixir 1.5.1

Mix をインストール

Mix については後日説明しますが、 Rubyrubygems や Nodejs の npm のようなものだと認識していただけると。

$ mix local.hex

使ってみる

Elixir は iex コマンドで対話式に使ってみることができます。

$ iex
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.5.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> IO.puts 'Hello World'
Hello World
:ok

所感

安定の中身のないクソ記事でしたが、 Phoenix を使って GraphQL な API 作るところまで書けたらいいなと思ってます。

Rails 5.1 で始める SPA (2) rails g

前回
Rails 5.1 で始める SPA (1) rails new, bundle install - giraphme tech blog


タイトルの通り今回はひたすら rails g するだけの簡単なお仕事です。
といってもこのあたりは他に優秀な記事やドキュメントがたくさんあるので Rails tutorial でも見といてください。

無理やり注意をひねり出すとしたら、以下の点ぐらいでしょうか。

  • Rails 5 系から DB のマイグレーション実行のコマンドが bundle exec rails db:* になった。 (これまで通り bundle exec rake db:* も使用できますが、今後 rails コマンドで統一されていくようです。)
  • Rails 5 系からマイグレーションファイルに comment を記載できるようになっているのでちゃんと書く
  • 後から utf8mb4 対応するのは地味面倒なので、 string のカラムに limit: 180 を付けておく(MySQL 側の設定で回避する場合は不要)
  • その他 Rails4 までの知識で DB 設計せず、新しい機能を導入できないか検討すること(Rails5から使えるActiveRecord便利機能 - Qiita
  • この時点でモデルのロジックをサービス層に逃がせる仕組みを準備しておくとなお良い(これについては別で記事にできたらいいなぁ……。)

個人的な意見ですが、 rails g scaffold ではゴミファイルやコメントアウトが大量に作られてしまってつらいので、 rails g コマンドではモデルのみ作成して、コントローラーや View は Rails の規約に則って手動で作るようにしています。


それでは今日はこのへんで。 なんの中身もないクソ記事だった……。

Rails 5.1 で始める SPA (1) rails new, bundle install

新しいサイトを作成するにあたって作業内容をまとめていこうと思います。
執筆時点ではまだ rc2 なので、5.1.0.rc2 を使用しています。
Ruby のバージョンは 2.4.1 です。

(2017-5-9 追記: 5.1.0 にアップグレードしました。)

まずはさいしょのおまじない。

$ rbenv global 2.4.1
$ gem install rails --version '5.1.0.rc2'
$ rails new zooto -d mysql --skip-coffee --skip-turbolinks --webpack=react --skip-test --skip-sprockets
$ cd zooto
$ git add .
$ git commit -m "rails new"

--skip-coffee --skip-turbolinks --webpack=react --skip-sprockets このあたりのオプションで Rails がフロントエンドに対してお節介してこないようにしておきます。
ちなみに私はこれまで rails new する時はいつも --skip-bundle を付けるようにしていましたが、 --webpack=react オプションを付けると自動で実行される rails webpacker:install:react コマンドで死んでしまうようです。

次に Gemfile を編集します。
心機一転、いつもとは違う Gem を使用してみたかったので、 mastodon の Gemfile を参考に記述しました。
Sprockets の呪縛から開放され、 Assets 関連の Gem が消えるだけで随分とスッキリしましたね……。

source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

gem 'rails', '~> 5.1.0'

# DB
gem 'mysql2', '>= 0.3.18', '< 0.5'
gem 'redis', '~>3.2', require: ['redis', 'redis/connection/hiredis']
gem 'hiredis'

# Rack server
gem 'puma', '~> 3.7'
gem 'rack-attack'
gem 'rack-cors', require: 'rack/cors'
gem 'rack-timeout'

# Front
gem 'webpacker'
gem 'hamlit-rails'
gem 'jbuilder', '~> 2.5'
gem 'sass-rails', '~> 5.0'

# Job Queue
gem 'sidekiq'
gem 'sidekiq-unique-jobs'

# Other
gem 'paperclip', '~> 5.1'
gem 'paperclip-av-transcoder'
gem 'aws-sdk', '>= 2.0'
gem 'addressable'
gem 'devise', github: 'plataformatec/devise', branch: :master
gem 'fast_blank'
gem 'httplog'
gem 'kaminari'
gem 'rails-i18n'
gem 'rails-settings-cached'
gem 'simple_form'

group :development do
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  gem 'rubocop', require: false
  gem 'better_errors'
  gem 'binding_of_caller'
  gem 'letter_opener'
  gem 'letter_opener_web'
  gem 'bullet'
  gem 'active_record_query_trace'

  gem 'capistrano', '3.8.0'
  gem 'capistrano-rails'
  gem 'capistrano-rbenv'
  gem 'capistrano-yarn'
  gem 'capistrano-faster-assets', '~> 1.0'
end

group :test do
  gem 'capybara'
  gem 'faker'
  gem 'microformats2'
  gem 'rails-controller-testing'
  gem 'rspec-sidekiq'
  gem 'simplecov', require: false
  gem 'webmock'
end

group :development, :test do
  gem 'byebug', platform: :mri
  gem 'rspec-rails'
  gem 'pry-rails'
  gem 'fuubar'
  gem 'fabrication'
  gem 'i18n-tasks', '~> 0.9.6'
end

group :production, :staging do
  gem 'redis-rails'
  gem 'lograge'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
$ bundle install --jobs=10

以上、今日はここまでにしておきます。
次回からは実装を進めていきますが、その前にサービス設計しないとなぁ……。
(設計の前に実装を開始するクズですいません。)


追記: Gemfile の中身を変更 (Rails 5.1.0 にアップグレード等)