ナガモト の blog

Full Cycle Developerを目指すエンジニアが有用そうな技術記事や、ポエムのようなよしなしごとを投稿するブログです。

npm modulesに自身で変更したforkを設定する

背景

上記のとおり、自身のポートフォリオで使用しているCSS Frameworkの新versionがリリース*1されたので、喜び勇んでアップデートしていました。 すると本番ビルド時にWARNINGが発生しており、スタイルが思ったように適用されないようになったため、独自に変更したNES.cssを読み込むようにしました。

↓詳細はこちら↓

github.com

設定方法

package.jsonを次のとおり書き換えましょう。

{
~
    "dependencies": {
        "module名" : "git+forkしているリポジトリのURL#変更したブランチ名"
    }
}

実際の変更はこちら

use nes.css from my fork by nagamoto · Pull Request #5 · nagamoto/portfolio · GitHub

あとはnpm installなどのコマンドで再インストールするだけです。

補足

本番のビルドがうまくいかなかったのは、本番のみビルド設定がWARNINGも認めない厳密なものだったためでした。 優しすぎるダーシノ (@bc_rikko) | Twitterさんの回答はこちら。*2

*1:https://twitter.com/bc_rikko/status/1096742179735629824

*2:今後は優しさに甘えすぎず、自分で十分に調べてから質問したい

FLEXBOX FROGGYが超COOLでflexboxの勉強が捗ったので推したい

HTML, CSSに疎く、特にレイアウト周りの勉強をしたいと思っていたところ、 yoshitaku-jp.hatenablog.com こちらでFLEXBOX FROGGYというサイトが紹介されていたのでやってみました。 flexboxfroggy.com

FLEXBOX FROGGYの紹介は前述の記事で十分で、記事を書くこともないと思っていましたが、実際にやってみたら超COOLで最高なサイトだと感じ、少しでも布教したいと思い立ち、筆を取りました。

↓リアルタイムな感想↓

FLEXBOX FROGGYとは?

テキストの解説と共に問題に回答する形式でflexboxを勉強できるサイトです。

どんな人におすすめか?

HTML, CSSの基本を理解していて、読めるけど自分でコーディングするのは苦手な人です。具体的にはCSS Flameworkを使用していてレイアウトをググってコピペでなんとかしているようなレベルの人(私)にはかなりオススメです。flexboxの基本を学ぶことで、各Flameworkで呪文のように使用していたclassを名前から意味を理解し、使いこなしやすくなりました。

そもそもCSSの基本がわからない人には少し難しいので注意してください。

なぜCOOLなのか?

COOLすぎてすぐに問題を2周してしまいました。日を空けてもう1周する予定でいるくらいです。なぜこんなにCOOLに感じるのか説明すると次のとおりです。

書いたCSSがすぐ反映されるため、パズル感覚で楽しく勉強できる

私のようなWEBデザインビギナーはCSSコーディング中に頭に浮かべた理想に近づくことができない歯がゆさを強く感じます。それを全く感じることなく、パズルのように考え、小気味良いリズムで解いていくことができるのは非常に気持ちのいい体験でした。

テキストがわかりやすい

flexboxのレイアウトを説明するにあたって、要素・要素間の余白・行・列・行間・列内での配置・etc...説明する場合には難しい言葉の使い分けが必要です。それがほぼ完璧で、慎重にテキストを読めば各CSSプロパティがどういった意図でどういった設定を可能にするかが理解できます。*1

絶妙な難易度設定で成功体験と達成感が得られる

問題が少しずつ絶妙に難しくなっていきます。つまずきは少ないにも関わらず、適度に成功体験が得られます。また、最後の24問目はそれまでの23問の積み重ねなしでは難しい達成感のある問題が設定されています。

↓これ↓を実現できるようになるってワクワクしませんか?

f:id:ngmt83:20190214092731p:plainf:id:ngmt83:20190214092747p:plain
before -> after

総括

flexboxに自信がない人は隙間時間にでもFLEXBOX FROGGYをやってみよう!

付録: 楽しく勉強できるおすすめサイト

グリッドレイアウトの勉強ができるサイトです。作者はFLEXBOX FROGGYと同じようです。 cssgridgarden.com

Gitの勉強ができます。コマンドの使い方ではなく、コマンドがどのような動きをするのかを視覚的に理解させてくれます。 k.swd.cc

*1:開発者は日本人ではないらしいけれど本当に日本語の質が高い。翻訳は別人なのだろうか

Ruby on Railsで状態を扱うStatefulEnum gem

StatefulEnumというgemを紹介されたので使ってみました。他のgemと比較して違いや使い心地も伝えたいと思います。

以前書いた類似gemの紹介記事はこちら ngmt83.hatenablog.com

SNSのアカウントを想定したAccountモデルを例に実装します。

リポジトリはこちらです。 github.com

クラス図

f:id:ngmt83:20190212100220p:plain
Account関連クラス図

ソース

状態遷移図

f:id:ngmt83:20190212100252p:plain
Account状態遷移図

ソース

クラス図や状態遷移図はPlantUMLで作成しています。 ngmt83.hatenablog.com

ActiveRecord::Enumで状態を設定する

Accountモデルにintegerstatusカラムを追加

ActiveRecord::Enumでは状態を表すinteger型のカラムが必要です。カラムがなければマイグレーションで作成しましょう。railsコマンドであれば次のコマンドでカラムが追加できます。

rails g migration AddColumnToAccount status:integer

実際に作成したマイグレーションファイルはこちらです。

class AddColumnToAccount < ActiveRecord::Migration[5.2]
  def change
    add_column :accounts, :status, :integer, null: false, default: 0
    add_index :accounts, :status
  end
end

statusを持たないものは存在しない前提でnull: falseと初期状態として0を指定し、statusによる絞り込みを想定してインデックスを追加しています。*1

状態を定義

次のような記述方法で状態を定義します。

enum status: { registered: 0, active: 1, suspended: 2, banned: 3, inactive: 4 }

ActiveRecord::Enumはステータスを整数に変換してDBに保存するため、どのステータスが整数で何にあたるのかを定義しています。 *2

この定義により、次のようなメソッドが使用可能になります。

# account は Accountのインスタンス
account.suspended! # statusをsuspendedに変更する
account.suspended? # statusがsuspendedかどうかを真偽値で返す
account.status # statusを文字列で返す

課題

ActiveRecord::Enumのみでは次のような課題が存在します。

  • 状態遷移を表すメソッド(hoge!)の名前が動詞節にならない(hogeは状態を表す単語であり過去分詞形か形容詞)
  • 状態遷移の前と後の状態をわかりやすく制限できない
  • 状態遷移の条件を設定できない

これらを解決できるのがStatefulEnum gemです。

StatefulEnum gemを導入する

gemインストール

Gemfileに下記の通り記述し、

gem 'stateful_enum'

bundlerでインストールしましょう。

bundle install

状態遷移の定義

状態遷移を伴う操作をeventとし、transitionsで状態遷移を記述します。

  has_one :active_suspension, lambda { where(removed_at: nil) }, class_name: 'AccountSuspension'
# 中略
    event :suspend do
      before do
        suspensions.create!
      end
      transition :active => :suspended, unless: -> { active_suspension }
    end

https://github.com/nagamoto/state-machine-sample/blob/a8d701446476f27ad7ac2ac54ecf8c4a8fcf937c/app/models/account.rb#L17

このコードを解説すると次のとおりです。

active状態で、active_suspensionがfalseとなる場合のみsuspendというイベントを実行可能。実行時すると関連モデルsuspensionを生成し、suspended状態に遷移する。」

定義されるメソッド

# account は Accountのインスタンス
account.suspend # suspendイベントを実行する。事前条件を満たさない場合falseを返す
account.suspend! # suspendイベントを実行する。事前条件を満たさない場合<RuntimeError: Invalid transition>をraiseする
account.can_suspend? # suspendを実行できるかどうか(事前条件の結果)を真偽値で返す
account.suspend_transition # suspend時に遷移する状態を返す

事前条件は次のとおり

account.active? && !account.active_suspension

使えなくなるメソッド

account.suspended! # NoMethodError

標準のEnumが定義する状態遷移メソッドは使用できなくなっています。動詞節のメソッドで状態遷移したいがためにStatefulEnumを利用しているので、むしろありがたいです。

比較

次の2つのgemを比較しました。

StatefulEnum gemのメリット

AASM gemのメリット

  • モデル内で状態の初期値を設定できる
  • include AASMしたモデルでのみ有効化できる
  • 状態をstringで保持することもできる
  • コールバック・ロック・トランザクションなど豊富な詳細設定が可能

所感(使い分け方)

どちらも使い心地はよかったです。

とはいえ、基本方針としてRails wayに乗って継続的に開発するために、可能な限りシンプルなgemのみを使用した方がいいと考えているため、豊富な詳細設定が不要であればStatefulEnumがいいかと思います。また、コールバック・ロック・トランザクションを細かく取り扱おうとするとモデルにすべておさまるとは思えません。*5そのため、細かく取り扱う場合はドメインロジックを別クラスに移譲することになると思うので、詳細設定が必要でもシンプルなStatefulEnumでいいのではないかと思います。

例外として、状態をstringで保持したい場合にはStatefulEnumでは対応できないため、AASMを用いていいかと思います。*6

*1:https://github.com/nagamoto/state-machine-sample/blob/a8d701446476f27ad7ac2ac54ecf8c4a8fcf937c/db/migrate/20190211150628_add_column_to_account.rb

*2:https://github.com/nagamoto/state-machine-sample/blob/05c16fe03276b80e76dd857e12bea12927de9923/app/models/account.rb#L9

*3:ngmt83.hatenablog.com

*4:日本人エンジニア的には何かあったときに聞きやすい

*5:ファットモデルは避けたい

*6:DB上でも状態がわかりやすいのは大きなメリット。その代わりパフォーマンスが多少落ちる可能性はある

「Railsでモデルのステータスを扱うベタープラクティス」というLTしてきました

omotesandorb.connpass.com

こちらでLTしてきました。資料は↓こちら↓

speakerdeck.com

LTに至る経緯など書いていきたいと思います。

LTに至る経緯

非常に単純な理由です。ステータス管理で何度も困ってきたからです!

また、ブログで取り上げていたものがLTにちょうど良さそうだったためでもあります。

関連記事

ngmt83.hatenablog.com ngmt83.hatenablog.com

LTの構成について

gemの紹介が大きく、その部分はコードベースで説明できるのでストレートにしました。結論から書いたのは伝わりやすさのためでもありますが、スライドの構成しやすさのためでもありました。

コードベースの具体例について、ステータス名を違和感ない英語でちゃんと書こうとし、ああでもないこうでもないと悩んだため時間がかかりました。LTの大筋には影響しなかったので、あんまり力を入れなくてもよかったかもしれません。

反省

オリジナリティ0で、完全にAzusaですという見た目の資料になってしまいました。*1

また、具体的な問題点はサンプルコード部分がシンタックスハイライトされていないので見にくかったことです。Keynoteシンタックスハイライトされたコードを貼る方法を探しておきたいです。

反響

みんなが踏み抜く地雷ですよね、私ももちろん踏みました(白目)

先人のようなので具体的に話を伺いたかったです。気付くのに遅れたのが残念です。

可視化することで「複雑すぎるからどうにかしようぜ」というリファクタリング推進に役立つのはその通りですね。非エンジニア(例えばCS)にとってもステータスの多さはオペレーションの負担になりますし。

全く正規化しなかったゴリ押しクラス図(クラス1つ)に対してのリアクションですね。仕様がシンプルなうちはさほど辛く無いし、納期に追われるととりあえずやってしまいますよね。

参考情報を補足してもらえたのも嬉しいですし、役に立てたようでとても嬉しい反響です。

謝辞

Sansanさんには感謝しかありません。

また、表参道.rbは本当にいいイベントだと再認識しました。つよつよエンジニアが何人もいるのに優しく暖かいリアクションとアドバイスをいただけるのは最高です。 表参道というおしゃれの塊みたいな街は私には合いませんが

最後に

懇親会でさらに具体的なアドバイスをいただけましたので、このgemは早速試したいと思います。 github.com

Ruby on Railsで状態を扱うAASM gem

github.com 上記のAASMというgemを使用して状態遷移を扱う方法を紹介します。

gem導入

Gemfileに下記の通り記述し、

gem 'aasm'

bundlerでインストールしましょう。

bundle install

使い方

下記のようなSNSのUserモデルを例に実装します。

リポジトリはこちらです。 github.com

クラス図

f:id:ngmt83:20190208084313p:plain
クラス図

ソース

状態遷移図

f:id:ngmt83:20190208084349p:plain
状態遷移図

ソース

クラス図や状態遷移図はPlantUMLで作成しています。 ngmt83.hatenablog.com

Userモデルにaasm_stateカラムを追加

状態を表すカラムがない場合は下記のrailsコマンドで作成できます。

rails generate aasm user

実際のdiffはこちらです。

CMD: rails generate aasm user · nagamoto/state-machine-sample@2f28fe4 · GitHub

初期状態とすべて状態の定義

stateに状態を列挙し、初期状態をinitialで指定します。

    state :registered, :initial => true
    state :active, :suspended, :banned, :inactive

https://github.com/nagamoto/state-machine-sample/blob/1e3cbcc34eee14ade24a92f6f2de61fe2f18d1ce/app/models/user.rb#L12

状態遷移の定義

状態遷移を伴う操作をeventとし、transitionsで状態遷移を記述します。

    event :ban do
      transitions from: [:active, :suspended], to: :banned, guard: :build_ban
      after do
        create_ban!
      end
    end

https://github.com/nagamoto/state-machine-sample/blob/1e3cbcc34eee14ade24a92f6f2de61fe2f18d1ce/app/models/user.rb#L38

activesuspend状態のもののみ、banという操作でbanned状態に遷移できます。指定と異なる状態で操作を実行しようとするとAASM::InvalidTransitionという例外が発生します。

また、afterなどを用いて状態遷移の前後に操作を記述することもできますし、guardで状態遷移のためのより詳細な条件をチェックすることができるため、誤った状態遷移を起こさないようにすることもできます。 *1

動的に生成されるメソッド

モデルがxx状態であるか確認するxx?メソッドやeventが実行可能かを確認するmay_xxメソッドなどが使えるようになります。

# userはUser aasm_state=activeのインスタンス
user.active? # => true
user.banned? # => false
user.may_ban? # => true
user.ban
user.active? # => false
user.banned? # => true
user.may_ban? # => false
user.ban # => raises AASM::InvalidTransition

使い心地

状態遷移時の条件や操作がevent単位でまとめて記述されるため、見通しが良くなった実感があります。また、必要なメソッドが動的に定義され、コード量が少し減るのもありがたいです。

最後に

このように別の状態管理gemを教えていただいたので、こちらも試してブログに書きたいと思います。*2

※勧められたStatefulEnumについて記事書きました! ngmt83.hatenablog.com

*1:after内の操作で例外が発生した際に状態をロールバックさせるなどは考慮する必要があります。

*2:matsudaさんが作ったgemなら間違いないですね!

PlantUML + Visual Studio Codeでモデリング環境構築

当記事ではPlantUMLを利用してモデリングを行うための環境構築をします。

PlantUMLとは

PlantUMLはオープンソースUMLダイアグラム作成用のテキストベースの言語である。*1

そもそもUMLとは

統一モデリング言語(とういつモデリングげんご、UML、英: Unified Modeling Language)は、主にオブジェクト指向分析や設計のための、記法の統一がはかられた(Unified)モデリング言語(Modeling Language)である。*2

記法が統一されており、UMLに則って記述すると誰でも(知っていれば)同じように読めるため、チーム開発で設計図を残す際は非常に便利です。

PlantUMLをおすすめする理由

  • GUIツールと比較して動作が軽い
  • テキストのため、使い慣れたエディタを使用できる
  • テキストのため、Git管理と相性がよい
  • GitHubでのPullRequestレビュが行いやすい

「テキストなので環境を選ばず軽快に読み書きでき、チームでの設計共有・管理もしやすい」ということです。

おすすめ動作環境

私はVisual Studio Code(以下VSCode)で、PlantUML extensionを利用しています。好きなエディタを使っていいですが、ペアプロにも利用できる*3ため、VSCodeをサブエディタとして使えるようになっておくと捗ります。

環境構築

macOS Mojave version 10.14.2、パッケージマネージャーはhomebrewで環境構築を行いました。

動作させるには下記の3つをインストールする必要があります。

Java SE Development Kit

Java SE Development Kit 8 - DownloadsからMac OS X x64のものをダウンロードしてください。ダウンロード後はdmgファイルをダブルクリックして指示に従うだけでいいです。

Graphviz

下記のコマンドでインストールします。

brew install graphviz

PlantUML

下記のコマンドでインストールします。

brew install plantuml

brew infoで正常に動作する状態か確認できます。何か問題があれば確認しましょう。

brew info plantuml

JREと勘違いして、JDKがインストールされていないことがよくあります。その場合は上記コマンドで「Javaが実行できない」という趣旨のエラーがでます。そのときはJDKをインストールしなおしましょう。

VSCode上の環境構築

marketplace.visualstudio.com

上記のリンクからエクステンションをインストールします。(VSCodeアプリ上のExtensionsから検索しても構いません)

f:id:ngmt83:20190203165204p:plain
PlantUMLエクステンション

VSCode上での操作例

.pumlファイルを開いているときに「option + d」でプレビュー画面が開きます。

f:id:ngmt83:20190203170654p:plain
Preview画面

画像をエクスポートしたいときは「command + shift + P」でコマンド入力を開き、「ダイアグラムをエクスポート」を実行すると画像が作成されます。

f:id:ngmt83:20190203171202p:plain
エクスポートコマンド選択画面

最後に

まずUMLについてしっかり理解したい場合は1. UMLの基礎 1 | TECHSCORE(テックスコア)がおすすめです。

PlantUMLを軽く試してみたい、記法を調べたいといった場合には下記のサイトをおすすめします。 plantuml.com

細かい記法を覚えて丁寧に書けずとも、クラス図など特に重要な図をざっと書けるようになるだけで設計の共有・レビュが捗るようになるのでおすすめです。

「みてね」を推すLTをしてきました

web-engineer-meetup.connpass.com

こちらでLTしてきました。資料は↓こちら↓

speakerdeck.com

LTに至る経緯など書いていきたいと思います。

LTに至る経緯

ぼんやりと、なんとなーく勉強会を探していて一度行ってみたいと思っていた勉強会を見つけたのがきっかけでした。

前座LTというハードルの低そうなLT枠に惹かれつつ、とはいえネタがないな・・・と悩んでいました。しかし会場がmixiさん提供とのことで、最近ヘビーユーズしている「みてね」というアプリがなぜこんなに使いやすいのかを解説してみれば面白いのではないかと思い、申し込みました。*1

LTの構成について

「みてね」を大好きすぎる私が、エンジニア視点と1ユーザ視点とでUI/UXを解説する形式でスライドを作っていました。しかし私はデザインの専門家ではなく説得力に欠けていたため、過去に読んだ「融けるデザイン」を読み直し、その内容を引用しつつ解説することにしました。

「融けるデザイン」の読書エントリは↓こちら↓ ngmt83.hatenablog.com

本の力を借りることで、説得力0の独りよがりな解説にはならずに済んだのではないかと思います。

LTの補足

LT冒頭で「みてね」を知っている人に挙手を求めましたが、あまりいなかったのは少し驚きました。個人的には今もっとも勢いのあるスマホアプリの1つだと思っています。使用機会がないとしても触っておくとエンジニアとして学びがあると思います。

反響

やはり言いたいことが伝わって共感が得られるのは非常に気持ちがいいですね!

反省

特に悪かったのは、Macbook Airで画面を出力できず、慌てて主催者にファイルを送信してどうにか対応したことです。主催者様には感謝しかございません。そこでテンパってしまったため、LT中も必要以上に緊張していました。

また、スライドを作るのが遅れ、添削を依頼できませんでした。前倒し前倒しでやっていく習慣がまだまだついていないのも原因の1つではありますが、LTのアウトラインができてから申し込むようにしたほうがいいように思いました。

謝辞

主催者やスタッフのみなさまが登壇者へのサポート、場を温めるなど非常に親切でした。場を提供していただいたこと改めて感謝いたします。また、私のLTを優しく聴いてくれた参加者のみなさまもありがとうございました。

最後に

今後の予定ですが、技術ネタを見つけたのでちゃんと技術的な発表をしたいと思っています。 「Railsでモデルの状態(status)をどう扱うか」というテーマで私なりのベタープラクティスを紹介する予定です。 omotesandorb.connpass.com

*1:つまらなかったとしても前座だし、mixiさんの会場で「みてね」を褒めるLTして怒られることはないだろうと打算的な考えもありました