Wondershake 開発者ブログ

LOCARI(ロカリ)の運営会社の開発者ブログです。

Ruby の Refinements 使ってみた

この投稿は Wondershake Advent Calendar 2016 12日目の記事です。

mmyoji です。今日含めてあと3回、がんばります。

今日は Ruby の Refinements について、「こんな感じで使ってますよー」という紹介をできればと思います。

簡単にいうとクラスを「特定の箇所(ファイル)でだけ拡張したい時」に使うもの、と思っていただければいいと思います。もっと詳しく知りたい方は最後に挙げてある References を確認していただけると理解がしやすいかと思います。

自分も最近ようやく使ってみた、という感じなのでこれが適切な使い方なのかは怪しいです。。。ただ使ってみてかなり「気持ちよかった」のでやっぱり Ruby は最高ですね。最高です(大事なことなので(ry

具体例

LOCARI の記事1つ1つに対して、ライターが一人いて、それを記事一覧で表示するんですが、記事の状態などに応じて出し分けをする必要があります。その ライターの情報Post::ListProfile というクラスで表現するようにしていて、そのプロフィールに種類があります。

ListProfile を特定するために記事の状態をチェックする必要がありますが、そこでしか使われないため、単に記事クラス( Post )にメソッドを生やしたくない、と思い、 Refinements を使ってスコープを制限しました

(以下微妙に実際のクラス名、メソッド名とは異なります)

# app/models/post.rb
# 記事クラス
class Post < ApplicationRecord
  # ...
end

# app/models/post/list_profile_detector.rb
# 記事を元にライター情報を特定するクラス
class Post::ListProfileDetector
  attr_reader :post

  def initialize(post)
    @post = post
  end

  def call
    if post.show_username?
      return Post::ListProfile::External.new(post)
    end

    if post.shared?
      return Post::ListProfile::Shared.new(post)
    end

    if post.default?
      return Post::ListProfile::Default.new(post)
    end

    Post::ListProfile::Official.new(post)
  end
end


# こんな感じで使う
post    = Post.find(12)
profile = Post::ListProfileDetector.new(post).call
#=> #<Post::ListProfile::Default:0x007f983e757550

上記の ListProfileDetector 内で使った post に生えているメソッドを Refinements を使って定義します

# app/models/post/list_profile/detectable.rb

module Post::ListProfile::Detectable
  refine ::Post do
    def show_username?
      # ...
    end

    def shared?
      # ...
    end

    def default?
      # ...
    end
  end
end

簡単ですね 😁

で、実は Post::ListProfileDetector には足りていない行があったので一行追加します

# app/models/post/list_profile_detector.rb

class Post::ListProfileDetector
  # `using` で refine を使う宣言をする
  using Post::ListProfile::Detectable

  attr_reader :post

  # ...
end

これで一応は使えるようになりました。今度はテストです。

Post::ListProfileDetector はそのままテストを書いて問題ないですが、 Detectable モジュールはどうテストしましょう?(そんなに難しいものではないですが 😅 )

# spec/models/post/list_profile/detectable_spec.rb

require 'rails_helper'

describe Post::ListProfile::Detectable do
  ## これがないと有効にならない! ##
  using Post::ListProfile::Detectable

  let(:post) { create(:post) }

  describe '#show_username?' do
    # いつものように example を書く
  end
end

Refinements は ファイル毎 にスコープを指定するため、メソッド呼び出しを行いたい場合は各ファイルで using を宣言する必要があるため、テストでも上記のようにする必要があります。

気づいてないだけで意外と使えるところはたくさんあるのかなーと思うので、これからもガシガシ使っていきたいですね!

以上になります。明日は Eric さんがリモート以外のテーマで何か書いてくれるみたいです。楽しみ 😁 ❤️

References

デザイナーのリモート事情

こんにちは、業務委託でお世話になっておりますデザイナーのこけしです。(本名は長谷部えりです) この記事は Wondershake Advent Calendar 2016 の8日目の記事です。

普段はフリーランスとしてフラフラと出歩いていますが、アドベントカレンダーに参加させていただきました。 リモート記事が続いてネタに困りだすけど、私デザイナーなので楽勝だぜ!という雰囲気でお送りします。

話すこと

  • デザイナーの出勤/リモートの状況
  • リモート環境
  • リモート時にテンションを上げるには

Wondershakeデザイナーのリモート状況、あと私はリモート可の状況で働いている歴がおそらく短めだと思うので リモート初心者向けに、ゆる〜〜く自己流のリモート時のテンションの上げ方をお話します。

デザイナーの出社/リモートの状況

デザイナーもエンジニアと同様に出社は自由です。ミーティングがある日だけ出社でもOK。 でも私はなるべく出社したい派で、だいたい週2、3日くらいオフィスに出社させていただいています。

出社理由としては以下の通りです。

個人的な理由

  • 自宅に居すぎると気が滅入るタイプ
  • 太った(⌒▽⌒)(ので少しでも外に出たい)

仕事的な理由

  • デザインの目的確認のための細かいすり合わせがしやすい
  • 微妙なデザインの修正など口頭の方が早い場合がある(1pxつめて、とかとか)

とはいえ仕事的な理由はリモートでもカバーできると思うので、個人的な理由のほうが強いです。

リモートをする場合は集中して手を動かしたいとき、 または体調や家庭の事情で自宅に居たいときにしています。

もちろんデザイナーチームとしてもリモートはだめだとかそういう風潮もなく、 都合に合わせてのびのびとお仕事をさせていただいています。

リモート環境

PCはいろいろなところで作業することが多いのでMBP Retina 13inchを使っています。 自宅ではLGの27inchモニターを使ってデュアルディスプレイ化しています。

常に机の上が汚い・綺麗なデザイナーは優秀かどうかという議論がありますが 自宅の机はもっぱら汚い派です。ものがたくさんあります。 多分このまま生きていくのだと思います。

机や椅子は全くこだわってなくて両方ともIKEAの一番安いものを使っています。 椅子は変えたいのでamyroiさんの記事を参考にさせていただこうと思います!

リモート時にテンションを上げるには

自分は今年度からフリーランスになったので、最初自分のペースを作るのに四苦八苦しました。(未だにしてますがorz) リモート初心者向けに、いろいろ試してみてよかったなと思うもの、作業時にテンションを上げられる方法を話してみます。

  • 朝、動いてから仕事する
  • 仕事のスイッチを決める
  • ちゃんと休む
  • 作業のおしりは決めておく

朝、動いてから仕事をする

実践されている方が多いかもですが、家で仕事をする場合なにかしら動いてからやります。 洗濯物を干すのが好きなので、やるついでにおひさまを浴びてほっこりしてから仕事します。 健康な人間になった気がしてとても良いです(⌒▽⌒)

仕事のスイッチを決める

自分の場合、仕事するぞ!と意気込んで机に向かうタイプなので仕事を始める際に絶対にコーヒーを入れています。 これがスイッチになって集中できるし、メールやslackをチェックしながらコーヒーをいただくととっても優雅で自分がおしゃれだと錯覚できます(⌒▽⌒)

ちゃんと休む

リモートの最大メリットは、"自宅で自分のペースで仕事ができること"だと思っています。 そのため集中力切れたなー、単純作業眠いなーとなるとしっかり休憩します。 最近は「絶対に好きにならないぞ!」と思っていた星野源にハマっているのでYoutubeをでかでかと流して気分転換もしています(⌒▽⌒)

作業のおしりは決めておく

私は家庭の事情で8時前後くらいにはなんとなく夕ご飯な感じになります。 トラブルなど、どうしても急を要する作業でない場合はそこに合わせて仕事をやめるようにしています。 ちゃんと終わらせればお酒が最高にうまいぞー!と思うとダレないし、がんばれます(⌒▽⌒)これが一番だいじ。

また、細かい時間管理は皆さんやっているポモドーロも試しましたが、集中しているとアラーム音にびっくりするのでやめました。 基本的にちゃんとスタートできれば自分の意欲任せで案外いけています。

結構よくある内容になっちゃいました。でも当たり前のことを当たり前にできないとかなって思います。(どや?)

さいごに

明日はyosuke_kabutoさんのリモートについて北海道編です。 作業の途中でサッポロビール飲んじゃうとかかな?(すごく勝手なイメージ)楽しみです!

Wondershakeエンジニアのリモートワーク

こんにちは。佐々木です。
この記事は Wondershake Advent Calendar 2016 の5日目の記事です。
今週はリモートワークネタが続くようで、その2日目になります。

リモートネタ1日目のmmyojiさんの記事はこちら。

engineering.wondershake.com

この記事では普段私がどんな感じで働いているかを紹介します。

私の働き方

WondershakeではフルリモートワークOKな環境なので、ミーティングがある木曜日以外は基本的に家で作業しています。

実装レベルのタスクは Pivotal Tracker で管理されていて、1日の始まりにチケット一覧を眺めながら優先度の高いタスクを消化していく形です。
このチケットの優先順位を決めるミーティングが木曜に行われています。

開発フロー的には Github Flow が近いです。 チケット毎にブランチを作り、作業途中のものであっても1日の終りにはWIPを付けてpushします。

コミュニケーションツールにはSlackを使っていて、Githubの通知を通知専用のチャンネルに垂れ流すことであの人は今こんなことをやってるんだと分かるのが良いです。

自宅の作業環境

f:id:sskyu:20161205021019j:plain

参考までに自宅の作業環境をご紹介。

  • 椅子
    • Meda Chair
      • 座面が広くてあぐらしやすい
    • fantoni GT W140
      • 堅牢で揺れないし拡張性もあり良い
  • PC
    • MBP 15inch, 2014 Mid
  • 外部ディスプレイ
    • Dell 24inch FHD Display
      • 解像度足りないので買い替えたい
    • ♀ 2015/8/15 生まれ
    • 作業中に椅子の後ろをガリガリして邪魔してくる

とある1日のタイムスケジュール

午前中は仕事をしません。いつもギリギリまで寝てるか読書などしてます。
私の場合は夜のほうがパフォーマンスが出るので十分な睡眠をとって、仕事中に眠くならないようにしてます。
下手に早起きして睡眠不足で仕事を始めても集中できないし、思考にモヤがかかった状態で作業するとバグを含めるリスクもあります。
大体10時過ぎに起きて、12時頃に昼ごはんを食べます。 13時前後に仕事を開始して、21時前後に上がります。

ポモドーロテクニック

自分のパフォーマンスを測る目安としてポモドーロテクニックを使っています。
25分仕事して5分休憩を1ポモドーロとして、4ポモドーロ毎に15分休憩をとるやり方です。
私の場合、1日の集中が続く限界が14ポモドーロくらいで、12ポモドーロで結構な疲労を感じ、8~11ポモドーロだと無理なく仕事した感が得られるので、このあたりを目安に作業をしています。

Macアプリにはこちらを使ってます。

Be Focused Pro - 仕事および勉強用の Focus Timer を Mac App Store で

オフィスにある仕事用Macと自宅のMacでTODOを共有できたり、メニューバーに常駐して使い勝手が良く気に入ってますが、休憩時間になったことに気づかないことが多いのが難点です。
(ポモドーロタイマーをElectronで作りたいなぁ。)

Wondershakeでのリモートワーク

個人的にはリモートワーク最高なのですが、あえてメリット・デメリットを上げてみます。

メリット

  • 通勤時間がゼロになる
    • その分稼働時間にまわせて退社時間を早められる
  • 個人の裁量で働く時間を好きなように設定できる
    • 突然の用事にも柔軟に対応できる

デメリット

  • 存在感を出すのが難しい
    • 日報を書く、毎日コミットをpushしてやっていることをシェアする等を意識的にすると良いと思います
  • 運動不足になる
    • 平日はあまり運動しない+家でのリモートワークのコンボで運動不足になります
    • 結構深刻で、リモートワーク中の1日の歩数を数えたら1200歩前後でした..(1日8000歩が良いとされる)
      • 改善のためポモドーロの大休憩で散歩を取り入れてみます

おわりに

リモートワークによって時間に縛られず自由に働ける反面、自分を律して作業するためにポモドーロなどのルールが私には必要でした。
直近の課題は運動不足による身体の衰えを防ぐことです。

明日はamyroiさんで引き続きリモートワークネタです。楽しみ!

qiita.com

リモートワークで気をつけていること

この記事は Wondershake Advent Calendar 4日目の記事です

2日目に続き、 mmyoji がやっていきます。今日から一週間はなぜかリモートワーク話が続きます。

話すこと

  • Wondershake の労働環境(主にエンジニア)
  • リモートワークする上で気をつけていること

リモートワークの pros / cons 話そうかと思ったんですが散々話し尽くされているのでやめておきます。今回も短めです。

Wondershake の労働環境

開発者に限らず、全員がリモートワークをいつしてもおkな感じです。(たしか)

部署によっては上長の許可等必要かもしれませんが、少なくとも開発チームは特に許可を取る必要性はありません。

働く時間に関しても完全にフレックスとなっているので自由度は本当に高いです。僕はどちらかというと朝方なので早いときは6時ぐらいから仕事開始して昼過ぎぐらいには上がったりします。逆に夕方から働き始める方もいます。

僕は家がオフィスからそんなに近くないので基本リモートで仕事していて、ミーティングがある時だけオフィスに行ってます。(大体週1)

ただリモートワークもメリットばかりあるわけじゃないので、ある程度仕事回す上で自分が気をつけていることを以下ダラダラ書いておきます。

リモートワークで気をつけていること

  • プレゼンスを出す
  • 働きすぎない

プレゼンスを出す

要するに自己主張していきましょうということです。

ただでさえ「何やってるかわからない」と思われがちなので、 Slack には頻繁に顔を出すようにしたり、ウザいくらい github に push しまくって(もちろん常識の範囲内で)「俺ちゃんと生きてますよ」アピールをします。

これに関しては「オフィスに行ったら偉いの?」問題が絡んでくるのでリモートだからどうのこうの、という話ではなくお互いに気をつけるべきなのですが、未だにリモートワークしてる側が立場的に低いと感じるので仕方ないのかなーという気がしてます。逆にオフィスいる勢は何やってるか全然わからないので、苦しいところではあります。「リモートだから / オフィスに行ってるから」という不毛な対立関係がなく、お互いを尊重できる世界が早く来るといいなーと思ってます。

あと弊社は Qiita:Team を情報共有ツールとして導入しているのですが、そこに定期的にポエムを投げるようにしてます。 プレゼンスを出す、という意図のほかに、「Qiita:Team は日報を投稿するだけのツールじゃないんだよ」ということをアピールするためにもやってますが、まだ効果が出ていません。どんどん埋もれていきます。かなしみ

働きすぎない

(こんなこと書くとシメられそう)

これはフリーの時から共通して持ってた問題意識なんですが、時間を忘れて働きすぎてしまうのでそうならないように注意するようにしてます。

自分の場合早朝から仕事し始めるので、他のエンジニアと働く時間が割とずれます。なので夜遅くに Github が賑やかになってきて思わずつられて働きそうになるんですが、がんばってこらえてます。ここらへんは未だにさじ加減が難しいなぁと感じる部分です。

適度に休憩入れることも大事で、一時期ポモドーロを導入してました。が、自分は誰かに作業を中断されるのがかなり苦痛に感じるタイプだとわかって2~3ヶ月試した後やめました。

オフィスにいるとできないような方法で休憩を入れるようにしてます。カフェなどで仕事する場合は難しいんですが、家で仕事する日は筋トレしたり、ベースを弾いたり、散歩をしたりしてリフレッシュするようにしてます。オフィスにも筋トレ器具とかスタジオ欲しい...

ただでさえ日本人働きすぎなので1日8時間の労働で満足しましょうという話でした。

さいごに

明日はフロントエンドエンジニアの yutapon 氏です。多分 🐈 の話だろーなーと思ってます 😎

LOCARI のテストで気をつけてること

この記事は Wondershake Advent Calendar 2日目の記事です。

先日分は間に合わなかったみたいですmm 代わりに謝罪しておきます 🙇

普段 RailsLOCARI のサーバーサイドを主に書いている mmyoji です。やっていきます。

話すこと

  • LOCARI のテストどーなってんの
  • 自分がテスト書く時に気をつけてること

Wondershake(LOCARI)のテスト環境

現在 Wondershake で一番コードベースが大きいプロジェクトが LOCARI という女性向けのメディアサービスのサーバーサイドを含む Rails アプリになってます。自分は最近までフリーランスだったのですが、ほとんどの現場でテストが書かれていませんでした。が、こちらは Coverage 85% 強となってて、比較的安心して開発が進められる環境となってます。(「低い!」と思われる方、幸せですね 😇 )

現状 Rails アプリはいくつかありますが基本的にすべて RSpec を使っています。 LOCARI に関して言えば本当は MiniTest 使いたいなーという意見(主に自分)もありますが RSpec のコードが結構沢山あってなかなか踏ん切りがつかないという状況です。

あと LOCARI アプリに関しては独特で以下の例でも見られると思いますが、 MiniTest に寄せたい思惑からか、expect ではなく assert を使って書いてたりします。このキモい感じが僕は割と気に入ってます 😈 ❤️ (読みづらいかもしれませんがご了承ください...)

で、本題に入りますが普段テスト書いてて気をつけてることとかを雑に書いていこうと思います。

こんなことを気をつけてます(個人的に)

賛否両論あるかと思いますがご容赦ください 🙇 あくまで 僕個人 が気をつけていることになりますmm

  • vcr ガンガン使う
  • 極力 example をまとめて test の実行速度を速くする
  • 意味が被るようなテストコード書かない
  • let(!)before を正しく使い分ける

vcr ガンガン使う

まず vcr の説明を簡単にしておくと、外部 API との通信を yaml ファイルにダンプしておいて、1回目以降はそちらのファイルを参照して実際に通信したかのようにテストを実行してくれる便利なライブラリです!

外部の API と通信を行う際に stub で済ませちゃうこともあると思うんですが、結構ガシガシ vcr に任せてしまいます(なので spec/cassettes が結構膨れてます...)

ただそうすることで少なくとも一回は実際のリクエストをテストできるので、例えば「ドキュメントに書いてあるレスポンスと違った!」みたいなことが防げたり、安心感があります。

あと小手先ですが、生成されるテストデータが微妙に異なるせいで、リクエストに含むパラメターが変わり、 vcr がうまく動かない(「異なるリクエスト」として扱われてしまう)こともあるので、そういう時は match_requests_on オプションを活用しています。このオプションに関しては以下を参考にしてみてくださいmm

以下のようなオプションの付け方してる箇所が多いイメージ

describe '#notify', vcr: { match_requests_on: [:host, :method] } do
  specify 'requests to external API' do
    # 処理
  end
end

極力 example をまとめて実行速度早くする

「どこでテストが落ちたのかわかりづらい!」と言う人もいるのでデメリットも多少ありますが、テストの初期化コストが大きく、且つまとめてしまえる場合などは特に example をまとめてしまう方がテスト実行時間減らせてオススメです。

API テストの例(あまりいい例ではないです。色々と省略)

# Before
describe 'GET index' do
  before do
    api_request
  end

  # HTTP status code と response の中身をそれぞれ別 example でチェックしている

  specify do
    assert_resposne 200
  end

  specify do
    assert_json_match(matcher, response.body)
  end
end

# After
describe 'GET index' do
  before do
    api_request
  end

  specify do
    assert_resposne 200
    assert_json_match(matcher, response.body)
  end
end

実際にベンチマーク取ってどれだけ速くなってるか、みたいなの出したかったですすいません

意味が被るようなテストコード書かない

「A がチェックできてたら B は保証されるから無くていいよね」という話です。

ある程度テスト書いてる人からすれば当然のことかもしれませんが、プログラミング書き始めた頃はよく指摘されてたので今でも意識してます。なんでもテストしたがる病ですね。

let(!) と before を正しく使い分ける

これは RSpec 特有の話になってしまいますが、RSpec 使い始めだとなんでもかんでも let(!) で書いちゃう人が一定数いると思ってて、テスト読む際に自分は意識して使い分けてます。

  • let! : example などで1回以上参照される
  • before : example などで参照されない

要するに let! に書いてあれば example 内で参照されたり、値をチェックしてたりするのでテストコード読む際に判断がしやすくなります。逆にそうでなければ before ブロックは読み飛ばして example だけ読めば大体わかるので無駄な時間使わずに済む、ということになりますね?(無理やり)

まとめ

テストはしっかり書きたいけどビルドが長いのは嫌だ、という気持ちを少しでも緩和するためこれからもやっていきます。

あと他の方のテストに関する気遣いを聞きたい今日この頃。

明日は Android エンジニア兼 PO/PM の shirokura です。ちゃんと書いてくれるかな? 😏

ESLint2からESLint3に上げて関連プラグインもアップデートした話

こんにちは。フロントエンドエンジニアの佐々木です。

先日、ESLintまわりを最新にアップデートしたのですが、結構修正することが多かったので備忘録も兼ねて残しておきます。

ちょっと古いですが、ESLintの導入に関してはこちらの記事でご紹介しました。

engineering.wondershake.com

ESLint3へのアップデート

f:id:sskyu:20161026225745p:plain

ESLint導入時には下記のバージョンを使っていました。

  "eslint": "^2.9.0",
  "eslint-config-airbnb": "^9.0.1",
  "eslint-plugin-import": "^1.12.0",
  "eslint-plugin-jsx-a11y": "^1.2.0",
  "eslint-plugin-react": "^5.1.1",
  "babel-eslint": "^6.0.4",

それぞれ最新のバージョンを調べてインストールしました。

  "eslint": "^3.8.1",
  "eslint-config-airbnb": "^12.0.0",
  "eslint-plugin-import": "^1.16.0",
  "eslint-plugin-jsx-a11y": "^2.2.2",
  "eslint-plugin-react": "^6.4.1",
  "babel-eslint": "^7.0.0",

この状態でESLintを走らせると ✖ 108 problems (99 errors, 9 warnings) と、結構な数のエラーが発生してしまいました。
バージョンを上げる前は 0 errors だったので、アップデートに伴ってルールが厳格になっているのがわかります。

.eslintrc を .eslintrc.yml に変換

ESLint3から設定をyamlで書けるようなので書き換えました。
これは好みの問題ですが、jsonよりもyamlの方がメンテしやすいです。

.eslintrc (変更前)

{
  "parser": "babel-eslint",
  "extends": "airbnb",
  "env": {
    "browser": true,
    "node": true
  },
  "globals": {
    "ga": true,
    "$": true,
    "I18n": true,
    "describe": true,
    "it": true,
    "before": true,
    "after": true
  },
  "rules": {
    "new-cap": [2, {
      "capIsNewExceptions": ["Map", "List", "Set", "OrderedSet"] // これはImmutableJS用の記述
    }]
  }
}

.eslintrc.yml (変更後)

---
  parser: babel-eslint
  extends: airbnb
  env:
    browser: true
    node: true

  globals:
    ga: true
    $: true
    I18n: true
    describe: true
    it: true
    before: true
    after: true

  rules:
    new-cap: [2, { capIsNewExceptions: [Map, List, Set, OrderedSet] }]

Lintをパスするよう修正

import/extensions

6:18  error  Unexpected use of file extension "jsx" for "./views/base.jsx"  import/extensions

このエラーは import Base from './views/base.jsx' のように .jsx を読み込んでいる箇所で起きてました。

eslint-plugin-import を見ると import/resolver が必要だとあるのでインストールします。

$ npm i -D eslint-import-resolver-node
# もし webpack を使っていたら eslint-import-resolver-webpack が必要そうです

.eslintrc.yml に追記します。

  # rules と同じインデントレベルに settings を追加
  settings:
    import/resolver: node

これでESLintを走らせれば import/extensions のエラーは回避できます。

class-methods-use-this

34:22  error  Expected 'this' to be used by class method 'comonentWillUnmount'     class-methods-use-this

このエラーの当該箇所は次のようなコードになってました。

class Base extends PureComponent {
  componentDidMount() {
    $(window).on('resize', throttle(this.handleResize, 200));
  }

  comonentWillUnmount() { // NG
    $(window).off('resize');
  }

  // 以下略
}

class methodとして定義されたメソッドのスコープ内で this への参照が無いとエラーになるようです。

componentDidMount でイベントを購読して、componentWillUnmount でイベントの購読を解除するコードなので、これ以上直しようが無いと思ったので warning を出すように変更しました。

.eslintrc.yml の rules に class-methods-use-this: 1 を追記するとエラーから警告に変わります。

根本的に解決するには、状態を持たないJSXは 関数として定義するといいです。

JSX In Depth - React

jsx-a11y/no-static-element-interactions

89:7   error  Visible, non-interactive elements should not have mouse or keyboard event listeners  jsx-a11y/no-static-element-interactions

このエラーは次のようなJSXを書くと発生します。

  render() {
    return <div onClick="this.handleClick" />
  }

div 要素などの本来ユーザーのインタラクションを想定していない要素に対して、onClick などでハンドリングしようとすると発生します。

この場合はHTMLのマークアップ上でクリッカブルな要素ということを示さないといけないので、div の代わりに button などで代替するのがいいでしょう。

  render() {
    return <button onClick="this.handleClick" />
  }

react/forbid-prop-types

6:5   error  Prop type `object` is forbidden    react/forbid-prop-types

ここが一番修正箇所が多いエラーでした。
このエラーは ReactComponent の propTypesReact.PropTypes.arrayReact.PropTypes.object を使っていると発生します。

props に React.PropTypes.array と指定されても、Array型なのはわかりますが配列の中身が何の型なのかがわかりません。
何の型を持った配列なのかを明示的に示さないとエラーになるようになりました。

このLintをパスするには PropTypes.array の代わりに PropTypes.arrayOf(), PropTypes.object の代わりに PropTypes.shape() を使います。

このあたりの書き方は本家のドキュメントが参考になりました。

Typechecking With PropTypes - React

例えば次のようなコードがある場合、

// @file sites.jsx
import React, { Component, PropTypes } from 'react';

export default class Sites extends Component {
  static propTypes = {
    sites: PropTypes.array.isRequired,  // NG
    currentSite: PropTypes.object,      // NG
  }
  // 以下略
}

このように直します。

// @file sites.jsx
import React, { Component, PropTypes } from 'react';

export default class Sites extends Component {
  static propTypes = {
    sites: PropTypes.arrayOf(PropTypes.shape({  // OK
      name: PropTypes.string.isRequired,
      url: PropTypes.string,
    })).isRequired,
    currentSite: PropTypes.shape({              // OK
      name: PropTypes.string.isRequired,
      url: PropTypes.string,
    }),
  }
  // 以下略
}

currentSitesite 型のオブジェクトを値に持つとすれば、sitessite 型の配列を値に持つと言えそうです。

上記のコードは冗長なので、型定義をまとめたファイルを constants/prop_types.js として作りました。

// @file prop_types.js
import { PropTypes } from 'react';

export const site = PropTypes.shape({
  name: PropTypes.string.isRequired,
  url: PropTypes.string,
});

export sites = PropTypes.arrayOf(site);

型定義ファイルを参照するように変更するとすっきりします。

// @file sites.jsx
import React, { Component } from 'react';
import * as pTypes from '../constants/prop_types';

export default class Sites extends Component {
  static propTypes = {
    sites: pTypes.sites.isRequired,
    currentSite: pTypes.site,
  }
  // 以下略
}

react/no-unused-prop-types

PropTypes.shape() を全て外部のファイル(constants/prop_types.js)で定義すればいいのですが、.jsx ファイル内で PropTypes.shape() を定義すると以下のようなエラーが出ます。

6:12  error  'item.key' PropType is defined but prop is never used    react/no-unused-prop-types

このエラーを抑制するためのオプションが用意されているので、.eslintrc.yml の rules に下記を追記して無効化しましょう。

  rules:
    react/no-unused-prop-types: [2, { skipShapeProps: true }]

Code Climate

ESLintのバージョンアップに伴い、CodeClimateの設定で少し悩んだので書いておきます。

CodeClimate上で実行するESLintのバージョンはデフォルトで1系が使われるようです。

Note:

If no channel is specified, ESLint v1.10.3 is used for analysis.

https://docs.codeclimate.com/docs/eslint

ということで、ESLint 3系を使って欲しい場合は .codeclimate.yml に追記します。

---
engines:
  eslint:
    enabled: true
    channel: eslint-3  # ESLint3系 を使うようにする

ちなみにこの eslint-3 で使われる ESLint のバージョンは現時点では 3.6.1 でした。

これでうまく行くはずだったのですが、ローカルでESLintが通っていても CodeClimate 上では import/no-unresolved のエラーが出る現象に悩まされました。

import/no-unresolved が出ている箇所は import React from 'react'; のように、npm module を読み込んでいる箇所で、参照先が絶対パスで始まるとエラーになるようでした。

これはCodeClimate上での結果が正しくないので、.codeclimate.yml に下記を追加してチェックを無効化しました。

---
engines:
  eslint:
    enabled: true
    channel: eslint-3
    checks:
      import/no-unresolved: # このチェックを無効化する
        enabled: false

まとめ

ESLintまわりを最新にアップデートして発生したエラーを無くしていく過程をご紹介しました。

記事が長くなるので紹介できなかったルールもあったのですが、React を使うなら eslint-config-airbnb は入れておいたほうがいいと改めて思いました。
このLint設定で書いていけば最低限のコードの品質は保てると思います。

Wondershake では Web エンジニアや iOSAndroid ディベロッパーを募集しています。 興味が湧いた方は是非こちらからご応募下さい!

www.wantedly.com

非iOSエンジニアが、iOSDC Japan 2016に当日スタッフで参加してきた

去る2016年8月19日&20日、iOSDC Japan 2016が開催されました。
記念すべき第1回目で、TrackBのTK(タイムキーパー)&司会を担当しました、安藤です。

「ブログを書くまでがiOSDC」By@tomzohさん・・・ということで。
今回は、iOSDC Japan 2016に参加するメリットと、スタッフをやった感想について書きます。 f:id:kikoando:20160926233832j:plain

iOSDC Japan 2016とは?

「iOSDC (iOS Developers Conference Japan) は、
iOSとその周辺技術に関するエンジニアのためのカンファレンスです。
iOS関連のカンファレンスを待っていた皆様、お待たせしました。ついにやってきました。

2016年8月20日はiOSエンジニアのお祭りです!
日本中、世界中から公募されたスピーカーがキレッキレのトークを繰り広げます。
トークは「iOSエンジニアが聞いて面白ければ何でもOK」という基準で選定されます。
iOSやSwiftといった王道テーマから、エモい話、デザインの話などもあるかもしれません。

そして、トーク終了後には同じ会場で懇親会が開催されます。

iOSDCはiOSエンジニアであれば誰でも楽しめるカンファレンスです。
皆様のご参加をお待ちしています。
カンファレンス未体験の方も、是非一度参加してみてください。
楽しく、エキサイティングな、忘れられない1日になるでしょう!」

公式サイトより。)

実際、トークの内容は

  • Swift誕生から現在までの軌跡を振り返る王道トーク
  • 個人の経歴をネタにしたトーク
  • アイコンデザインに関するトーク

さらにはコードに全く関係ない肉トーク(!)まで多岐に渡っていました。

※トークの内容は→こちらをどうぞ。

内容のバラエティさもさることながら、
イベント全体を包む空気がまさに「祭り」でした。 f:id:kikoando:20160926234602j:plain

そもそもなぜiOSDCの当日スタッフやろうと思ったの?

ことの始まりは、2016年7月11日。
こんなツイートが。

「イベントの運営経験値を貯めたい。iOSのことを知りたい」
そう思っていた自分には最高の機会だな。ということで、参加表明しました。

締め切り後、当選のメールが来てiOSDCスタッフSlackに招待され
その後は基本Slack上でやりとりをして当日を迎えます。

(8月16日に事前スタッフ顔合わせがありましたが、私は台風の影響で行けませんでしたorz)

参加者のメリット

  • 国内外で活躍されているエンジニアのトークが聞ける
  • 聞くだけじゃなくて、一問一答も出来る
  • 一問一答だけじゃなくて、会話もできる
    (スピーカーに話しかけるタイミングは沢山あります。
     普通に会場内をウロウロしています。懇親会なんて絶好のチャンス)
  • 充実したノベルティ、ビール← f:id:kikoando:20160926233948j:plain f:id:kikoando:20160926235446j:plain f:id:kikoando:20160926234003j:plain

結果

  • 新しい知見が手に入る
  • 悩んでいた問題が解決する
  • 開発へのモチベーションが上がる
  • 技術だけじゃなく働き方の指標にも出会える
  • ごきげんになれる(ビールでなれる人は)
  • 交流の輪が広がる f:id:kikoando:20161002215529j:plain

スタッフのメリット(主観)

  • 楽しい。仲間ができる。 f:id:kikoando:20160926234849j:plain

一言で言うと、これに尽きます。

実際に私がやったこと

1日目

時間の大半を机と椅子の設営に費やしました。
プロジェクターやカメラもほぼセッティングし終えたところで二手に分かれてみんなでランチ。

戻ってきてから、GitHubで配布されていたマニュアルを漁ります。
同じチームリーダーの@koogawaさんと打ち合わせしつつ
アナウンスの練習をしたら、あっというまに開場の時間。
この日はTrackBのTKが自分一人だったので、ずっとスピーカーと時間を気にしてました。
f:id:kikoando:20161002215717j:plain

最後のトークセッションを終えたら、受付に出てたシャツ等を部屋の中に入れ、
そそくさとスピーカーディナー(という名の飲み会)へ。

2日目

TrackBのTKが2人になったので、昨日より余裕が出てきました。
ただ、冷暖房や電気の明るさ調整など、気は抜けません。

この日は、後半TrackAと部屋を結合してからずっと懇親会の設営のことで頭がいっぱい。
1日目に3-4時間かけて並べた机と椅子を、30分で片付けるスケジュールでしたから。。。
実際は・・・スタッフのみなさんの協力のもと、スイスイことは進みました。 f:id:kikoando:20161002212825j:plain

懇親会では、ビールと料理を手に談笑する参加者&スピーカー&スタッフの皆さんを
端から見ては「みんな楽しそうだな。良い光景だな」と思ってました。 f:id:kikoando:20160926234016j:plain

さて、当日スタッフをやると、持ち場によってはほぼトークが見れなかったり(※)します。
また、コアスタッフは前日までの準備に何十時間という時間を費やします。
頭も体も使うから、どっと疲れる2日間です。

※配信管理やHQをされていたiOSエンジニアスタッフさんが「この人のプレゼン参考になるわ〜」とか「あ、そういうやり方あるのね〜」と漏らしてたので、見てなかったのは私だけかもしれません\/(トークは後ほど動画で配信されるので、見れなくても大丈夫ですが!)

でも、この祭りの楽しさを一番享受していたのはコア&当日スタッフだったのではと思います。
某スタッフさんも「こんなに楽しかったのは本当に久しぶり」と言ってましたしね!
みんなでひとつひとつ創っていく様子は、学生時代の文化祭準備を想起させてくれました。 f:id:kikoando:20161002214828j:plain

結果

もっとiOSのことが好きになりました。 f:id:kikoando:20160926234052p:plain (9/14の振り返りMTG後。ごきげん過ぎて画面に収まりきらない)
実際、私はiOSエンジニアではなかったのですが。この後、他のスタッフ主催の勉強会に参加したりして、iOSの世界に足を踏み入れかけています。

・・・iOSDC japan 2016が最高なイベントだったことは伝わりましたでしょうか。
少しでも楽しそうだと思った方は、来年のイベントスタッフ運営してみませんか?
スタッフになる方法?コアスタッフなら、@tomzohさんに聞いてみてください!
当日スタッフなら、きっと来年も公開応募があるかも?公式サイトとツイッターを要チェック!

まとめリンクたち

スピーカーや参加者、他のスタッフのブログはこちら
写真で振り返るiOSDC Japan 2016はこちら
トークセッションの映像はこちら

ここでちょっとお知らせ

11/11(金):ポッキーの日にエンジニア勉強会(もくもく会)を開催します。
もくもく内容は、何でもあり!前回は、お仕事する人や読書する人などもいらっしゃいました。

普段一人で家やカフェでもくもく作業してる人、11/11はみんなでもくもくやりませんか?
最初に今日何をもくもくするかを共有するので(任意)、きっと捗りますよ! daikanyama-mokumoku.connpass.com

また、WondershakeではiOSエンジニアを絶賛募集中です。
(無理に「来年一緒にiOSDCのスタッフやろう」とは言いません。)
一緒に会社を盛り上げてくれる方、Wanted。 www.wantedly.com

最後に

@tomzohさん、リードありがとうございました&大変お疲れ様でした!
f:id:kikoando:20161002215547j:plain