Laravelのイベント&リスナについてまとめてみた

こんにちは、 株式会社SCOUTERエンジニアの佐藤(@r_sato1201)です

今回は、Laravelのイベント機能についてまとめたいと思います。

Laravelのイベントとは?

ReaDouble(公式リファレンスサイトを和訳したサイト)には以下のように記述してあります。

Laravelのイベントはシンプルなオブザーバの実装で、アプリケーションで発生する様々なイベントを購読し、リッスンするために使用します

参考:Laravel5.7 イベント

Laravelのイベント機能はObserverパターンで実装されています。
Observerパターンとは、観察される側(Subject)と観察する側(Observer)の2つの役割が存在し、観察される側の状態が変化した際に、観察する側に通知されるデザインパターンです。
Laravelではイベント(観察される側)とリスナ(観察する側)とに分かれており、イベントの変化をリスナが補足することで処理を行うという流れになっているようです。

イベント、リスナの登録

ここからは、「アカウント登録した際に、ユーザーに登録完了メールを送信する」機能を例に説明したいと思います。
まずはイベントとリスナの登録です。Laravelでは基本的にEventServiceProviderで管理されているので、listenプロパティに以下のように記述します。

app/Providers/EventServiceProvider.php

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    // アカウント登録
    Events\RegisterAccount::class => [
        Listeners\SendRegisterAccountNotification::class,
    ],
];

イベント、リスナの作成

次は、イベントとリスナの作成です。

php artisan event:generate

上記のコマンドを実行することで、EventServiceProviderに記述してあるイベントやリスナを生成してくれます。なお、既に作成済みのものには、変更を加えません。
app配下にEventsディレクトリとListenersディレクトリが生成され、RegisterAccount.phpとSendRegisterAccountNotification.phpが生成されます。

イベント定義

次に、イベントの定義をしていきましょう。

app/Events/RegisterAccount.php

<?php

namespace App\Events;

use App\Entities\User;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;

class RegisterAccount
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * @var User
     */
    private $user;

    /**
     * Create a new event instance.
     *
     * @param User $user
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function getUser()
    {
        return $this->user;
    }
}

メンバ変数のuserを定義して、getUser()でいつでも取り出せるようにしています。

リスナ定義

次に、リスナの定義です。

app/Listeners/SendRegisterAccountNotification.php

<?php

namespace App\Listeners;

use App\Events\RegisterAccount;
use App\Notifications\RegisterAccountMailNotification;

class SendRegisterAccountNotification
{
    /**
     * Handle the event.
     *
     * @param  RegisterAccount $event
     *
     * @return void
     */
    public function handle(RegisterAccount $event)
    {
        $user = $event->getUser();
        $user->notify(new RegisterAccountMailNotification($user));
    }
}

ここでは、Eventでキャッチした$userを、ユーザーにメール送信するNotificationである RegisterAccountMailNotificationに渡しています。
※RegisterAccountMailNotificationの内容はここでは省きます。

ちなみに、app/Entities/User.phpで、Notifiableトレイトを定義しておかないとNotificationが動かないので注意してください。

class User extends BaseModel 
{
    use Notifiable {
        notify as traitNotify;
    }
}

イベント発行

最後に、これまで記述してきたイベント処理を発行させる処理を記述します。
app/Http/Controllers/Api/RegisterController.php

<?php

namespace App\Http\Controllers\Api\Company;

use App\Events\RegisterAccount;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class RegisterController extends Controller
{
    /**
     * Create a new user instance
     *
     * @param array $data
     *
     */
    protected function create(Request $request)
    {
        $user = ([
            'email' => $request['email'],
            'password' => $request['password'],
        ]);

        RegisterAccount::dispatch($user);
    }
}

先程作成したイベントファイル(RegisterAccount)をuseし、dispatchしています。 これで、ユーザーがアカウント登録をした際に、ユーザーに対してアカウント登録メールを送信することができるようになりました。

まとめ

以上で、「アカウント登録した際に、ユーザーに登録完了メールを送信する」機能を一通り実装することができました。

今後は、

・イベントリスナのキュー投入
・ブロードキャスト

などを学び、理解してアウトプットしていけたらと考えています。

さいごに

現在、株式会社SCOUTERでは、エンジニア、デザイナーの募集をしております。

興味のある方は、是非下記からご応募お願い致します!

www.wantedly.com

www.wantedly.com

www.wantedly.com

参考資料

saml2awsを使ったセキュアなTerraform管理

saml2awsを使ったセキュアなTerraform管理

こんにちは kotamatです。

本日発売の WEB+DB PRESS Vol.111に 【第2回】コードの書き方の統一 ……PHP_CodeSnifferによる規約への準拠,PHPStanによる静的解析……というタイトルで寄稿させていただいております。

gihyo.jp

PHPをチームで開発されている方にはぜひ読んでいただければと思っております! が、今日は最近触っているインフラに関して、工夫したところを紹介させていただきます。

Terraform の provider管理

インフラ構築をよりセキュアにするために、SARDINE全体的にインフラを再構築しました。 今までTerraformでインフラを構築してきましたが、providerを下記のようにAWS のIAM keyを用いて実装してきておりました。

provider.tf

# Configure the AWS Provider
provider "aws" {
  region     = "ap-northeast-1"
  access_key = "my-access-key"
  secret_key = "my-secret-key"
}

GitHubでインフラ構成を管理しているのですが、もちろんこれだとコードベースにkeyがコミットされてしまい、必要以上のメンバーに共有されてしまいますので、Terraformのvariableを使い、コミットしない形で運用しておりました。

provider.tf

provider "aws" {
  region     = "ap-northeast-1"
  access_key = var.access_key
  secret_key = var.secret_key
}

variable.tf

variable "access_key" {}
variable "secret_key" {}

こうすることによって、対象のユーザごとにIAMユーザを作成し、適切な権限のみを与えることによってユーザを管理する事ができました。不必要になったタイミングで当該ユーザを消したりaccess keyを失効することによってログイン出来ないようにできますが、このような運用は頻度が多くなると大変ですし、なんといってもアカウント発行、失効の属人性も上がり、更にはPC側にkeyが残ってしまうことによって端末紛失などに耐えられない構成となっていることが課題でした。

この問題を解決するために、applyユーザだけはステップサーバーなど別のインスタンスだけで実行できるようにし、自動的にapplyが走るという環境を整備されているところもありますが、いくらplanやvalidateをしているとはいえ、apply時に実行時エラーが出ることもあるため、何かが発生したときの対応が難しく、やはりある程度は手元で実行できるようにしておきたいです。

AWS SSO as SP

そこで、今回導入したのが、SAMLベースでの認証形式を用いた構成です。 AWSにはSSOの仕組みがありますが、通常はIdPをAWSのIAMとした上でのSSOの構成を行うと思います。 ただ、逆にAWSのIAMにIdPを登録することによって、SAML形式かOpenID Connect形式によるAWSへの認証を行うことができます。

詳細の設定方法はAWSのブログが詳細を紹介されておりますので、こちらをご覧ください。

aws.amazon.com

こちら見てもらえるとわかりますが、ユーザごとにSession時間を設定する項目があり、デフォルトは1時間ですが、Terraformの設定中は1時間以上の作業時間を設ける事があると思いますので、こちらの設定項目を随時変更する事によって作業時間中にセッションが切れることがなくなります。

SSOをどうやってつかうのか

通常SSOはコンソール上で使用しているため、webの画面で使用するものかと思います。 しかしsaml2awsというものを使うことによって、任意のプロバイダーでのSSOログインをCLI上のみで行い、かつそのユーザをセッション付きで ~/.aws/credentials に保存することができ、そのユーザを用いてTerraformのproviderを設定することができます。

内部構造としては、go queryを用いてWebページにアクセスし、認証しているようです。

具体的な使用方法

saml2awsの設定

まずはsaml2awsに使用するIdPを設定します。

~/.saml2aws

[gsuite]
app_id               =
url                  = <GSuite側のログインURL>
username             = <GSuiteアカウント>
provider             = GoogleApps
mfa                  = Auto
skip_verify          = false
timeout              = 0
aws_urn              = urn:amazon:webservices
aws_session_duration = 3600 # 秒。必要であれば伸ばす
aws_profile          = saml # 使用したいprofile名
resource_id          =
subdomain            =
role_arn             =

設定後下記のコマンドでログインします。

saml2aws login -a gsuite

もしユーザ名、パスワード入力を省略したい場合は下記のようにします(端末にパスワードが残ってしまうので、あまりおすすめはしません)

saml2aws login -a gsuite --username=username --password='password'

Using IDP Account gsuite to access GoogleApps <GSuite側のログインURL>
To use saved password just hit enter.
? Username username
? Password

Authenticating as username ...
Open the Google App, and tap 'Yes' on the prompt to sign in

MFAを有効にしている場合、こちらが出たら端末側でYesをおします。

? Please choose the role  [Use arrows to move, type to filter]
  Account: XXX / role1 
  Account: XXX / role2 
  Account: XXX / role3 
❯ Account: XXX / role4 
  Account: XXX / role5 
  Account: XXX / role6 
  Account: XXX / role7 

そうすると、当該ユーザに紐付いているroleの一覧が表示されるので、適切なユーザを選択するだけです。

そうすることによって、 ~/.aws/credentialsに saml2awsに設定したprofile名でcredentialが保存されます。

Terraformのproviderを修正

最後にproviderの設定を修正します。

provider "aws" {
  region     = "ap-northeast-1"
-  access_key = var.access_key
-  secret_key = var.secret_key
+  profile = "saml" # saml2awsで設定したprofile名
}

Terraformの設定ファイル上では、saml2awsの内容ではなく、あくまでAWSのprofile名という抽象レイヤーで記述するので、他ツールに移行も簡単なのが便利ですね。

ログイン情報の除去

いくらSTSで期限付きのユーザを発行したとはいえ、ログイン情報をアカウントに保持させ続けるのは不安です。 そういった場合でも、GSuiteなどのIdP側のAttributeから、当該ロールを除外してあげるだけで、そのユーザからは二度とログインができなくなり、実質Terraformの実行権限がなくなります。

まとめ

AWS STSを用いたログイン方法を紹介させていただきました。 Terraformのベストプラクティスは結構各々実装しており散在している印象です。 この記事がなにかの手助けになれば幸いです。

最後に

弊社ではエンジニアを募集しております!

ぜひご応募ください!

www.wantedly.com

Flux パターンが解決した課題

SCOUTER 社でエンジニアをしている匠平(@show60)です。

突然ですが、私は Flux の無い世界を知りません。

エンジニアとして物心ついた時には、すでに世の中に Flux が存在していました。

開発業務では Vue.js (Nuxt.js) で Vuex を使用して開発していますが、改めて Flux の登場した背景を知ることは Vuex や Flux を理解する上で重要かと思いますので、あらためて調べてみました。

Flux が解決した問題

Flux が広く世に出たのは 2014 年の Facebook の開発者カンファレンス「 F8 」です。

既存の MVC パターンを放棄し、より機能的なアーキテクチャを支持する方法として紹介されています。


Hacker Way: Rethinking Web App Development at Facebook

(YouTube, 2014/05/04)](https://youtu.be/nYkdrAPrdcw)

Delivering reliable, high-performance web experiences at Facebook's scale has required us to challenge some long-held assumptions about software development. Join us to learn how we abandoned the traditional MVC paradigm in favor of a more functional application architecture.

React 以前のアーキテクチャ

JavaScript のフレームワークとして人気となった AngularJS の登場が 2010 年 10 月。

当時のフロントエンドのフレームワークにおけるアーキテクチャの原則は、すでにサーバーサイドで確立されていた MVC モデルを拝借する形で作られていました。

They borrowed practices that were already well established for server-side architecture. And at that moment, all the popular server-side frameworks involved some sort of implementation of the classic MVC model (also known as MV* because of its variations).

参考: Is Model-View-Controller dead on the front end?

React の登場

AngularJS の登場から約 2 年半後の 2013 年 5 月、 JSConf US で React が オープンソース化されました。

Facebook は、この MVC モデルをあらゆる箇所で実験したが、コード量が多く、開発が大きくなるとあらゆることが急激に複雑になることが分かったそう。

上記の動画では、そのデータフローについて "unpredictable" 、「予測不可能」という言葉を使い、フロントエンドフレームワークと MVC モデルが不適合であることを表現しています。

f:id:show-hei:20190612003637p:plain

この問題を解決するため、 Flux パターンが考えられました。

Flux is a pattern for managing data flow in your application. The most important concept is that data flows in one direction.

Flux とはアプリケーション上のデータを管理するパターンの一つ。

最も重要なコンセプトは、データの流れを単一方向にする、ということです。

Flux はどのように問題を解決するか

Flux とは設計概念と原則のことで、その実装方法を限定しているものではありません。

データの流れを単一方向にすることを設計概念とし、 データの流れを Action, Dispathcer, Store, View で構成することを原則としています。

flux/examples/flux-concepts at master · facebook/flux · GitHub

データの状態は Store が持っていますが、 Action から Dispatcher を経由しないとそれに変更を加えられないという強い制約があります。

f:id:show-hei:20190612003913p:plain

Flux がデータの流れにこの強い制約を与えることで、 Store を安全な状態に保つことができます。

Store の状態を予測可能にできることで、 MVC モデルで抱えていた複雑さの問題を解決しているというわけです。

Vuex と Flux

React で Flux パターンを実現するためのライブラリとして最も人気のあるのが Redux。

Vuex は Flux, Redux などから影響を受けた状態管理のライブラリです。

上記の通り、 Flux はその実装方法を限定していませんが、 Vuex もその構造化する方法を制限していません。

「原理原則を守ろう」と強調しています。

  1. アプリケーションレベルの状態はストアに集約されます。
  2. 状態を変更する唯一の方法は、同期的に処理を行うミューテーションをコミットすることのみです。
  3. 非同期的なロジックはカプセル化されるべきであり、それはアクションによって構成されます。

アプリケーションの構造 | Vuex

これらのルールに従っている限り、プロジェクトをどのように構造化するかはあなた次第です。 と記述されており、制限を持ちながらも柔軟な実装方法を許可しています。

開発チームやプロジェクトによって変えられるということは、チームやプロジェクトによって一定のルールを決める必要があるということですね。

最低限持つべきルールとして、 弊社の石岡が書いた記事がとてもわかり易いので、ぜひこちらもご参考ください。

techblog.scouter.co.jp

まとめ

過去の記事を振り返って見ると、フレームワークの登場からしばらくの間、フロントエンドのアーキテクチャは長い答え探しのだったようにも思えます。

Flux パターンが世に出て 5 年が経ち、 React のみでなく Vue.js やそのユーザーからも支持されているということは、フロントエンドのアーキテクチャの一つの答えであるということでしょう。

その恩恵を受けて楽しく開発ができていることに、感謝を惜しんではいけません。

Flux を考えた人たちに足を向けて眠れないですね。

さいごに

私達 SCOUTER では、一緒にプロダクト開発を行うエンジニア、デザイナーを募集しています。

ぜひご応募ください!

www.wantedly.com

www.wantedly.com

Laravelのテストで使うFactoryのstateのちょっと細かい話

こんにちはみなさん
@niisan-tokyoです。

Laravelを使うなら、当然テストも一緒に書くわけですが、テストの条件とかがどんどん複雑になってくると、可読性も落ちていろいろとやりにくくなります。
Laravelのテストデータを作成するFactoryには、複雑さを緩和するためにstateという機能があって、各条件・状態ごとに名前をつけることができ、そのstateごとに値を変えたり、後処理を入れたりすることができます。 ということで、今回はそのFactoryに実装されるstateをどのように使っていくか見てみましょう。

Factoryのstate

早速Factoryのstateを使ってみましょう。
まず、普通にUserのFactoryを作ると以下のような感じになります。

<?php
use Faker\Generator as Faker;

$factory->define(App\User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => bcrypt('secret')
        'is_admin'   => false
    ];
});

こうして作成されたユーザーはis_adminfalseになります。ここでis_adminが管理者フラグを表すとすれば、Factoryで作られたユーザーは管理者ではありません。 管理者ユーザーをFactoryを通して作成するためには、テストの中で以下のように書きます。

<?php
//...
$user = factory(User::class)->create(['is_admin' => true]);

データを作るたびに['is_admin' => true]を書くのはちょっと面倒くさいです。
そこで、「ユーザーが管理者である」という状態をFactoryに追加します。

<?php
//...
$factory->state(App\User::class, '管理者', function () {
    return [
        'is_admin' => true
    ];
});

これを追加しておくことで、テストでは

<?php
//...
$user = factory(User::class)->state('管理者')->create();
$this->assertTrue($user->is_admin);

のように書けます。

複数stateの持ち方

公式マニュアルにないので使って良いものかとは思うのですが、複数のstateを指定する方法もあります。 まず、

<?php
//...
$factory->state(App\User::class, 'Bob', function () {
    return [
        'name' => 'Mr. Bob'
    ];
});

こんな感じのstateを定義したあと、

<?php
//...
    public function testMultiState()
    {
        $user = factory(User::class)->states('管理者', 'Bob')->create();
        $this->assertTrue($user->is_admin);
        $this->assertEquals('Mr. Bob', $user->name);
    }

のように書くことで、複数のstateを同時に指定できます。

なお、複数stateでのmakeやcreateの実装を見ると、stateによる生成データの上書きは後勝ちになるため、

<?php
//...
$factory->state(App\User::class, 'Bob', function () {
    return [
        'name' => 'Mr. Bob',
        'is_admin' => false
    ];
});

のように、重複要素が指定されると、statesの引数の順番によってデータの状態が変わります。

<?php
//...

    /**
     * @test
     */
    public function 後勝ちなのでadminになるケース()
    {
        $user = factory(User::class)->states('Bob', '管理者')->create();
        $this->assertTrue($user->is_admin);
    }

    /**
     * @test
     */
    public function 後勝ちなのでadminにならないケース()
    {
        $user = factory(User::class)->states('管理者', 'Bob')->create();
        $this->assertFalse($user->is_admin);
    }

statesにたくさんの引数をもたせると、問題になるケースはありそうですので、最小限のstateにしぼりましょう。

afterCreating**

テストデータ生成後に追加で他のデータを生成したり、何らかのコールバック処理をしたい場合はafterCreatingを使ってコールバックを定義できます。
(なお、afterMakingでも同じような議論ができますが、割愛します。)

コールバック処理の定義は以下のようにFactoryに書きます。

<?php
//...
$factory->afterCreating(App\User::class, function ($user) {
    factory(App\Post::class)->create(['user_id' => $user->id]);
});

一方で、特定の条件下でのみコールバック処理したい場合はstateを利用することができます。

<?php
//...
$factory->afterCreatingState(App\User::class, 'Bob', function ($user) {
    echo $user->name;
});

このように定義することで

<?php
//...
$user = factory(User::class)->state('Bob')->create();
// Mr. Bob

「Bob」というstateを指定したときだけ、標準出力にMr. Bobというユーザー名が出力されるようになります。

afterCreatingの実施順

基本的に、実施する順番に依存するのはよくないのですが、そうも言ってられない場合があります。
実際にどのようにコールバック処理が実施されるかを検証してみましょう。

<?php
//...
$factory->afterCreating(App\User::class, function ($user) {
    \Log::debug('no state');
});

$factory->afterCreatingState(App\User::class, '管理者', function ($user) {
    \Log::debug('管理者');
});

$factory->afterCreatingState(App\User::class, 'Bob', function ($user) {
    \Log::debug('Bob');
});

のようにコールバック処理を定義したとき、以下の処理を実行してみます。

<?php
//...
        factory(User::class)->create();
        //  no state

        factory(User::class)->state('管理者')->create();
        //  no state
        //  管理者

        factory(User::class)->states('管理者', 'Bob')->create();
        //  no state
        //  管理者
        //  Bob

        factory(User::class)->states('Bob', '管理者')->create();
        //  no state
        //  Bob
        //  管理者

コメントアウトしたものがログに出力されたものになります。
afterCreatingで設定された処理は必ずデータ生成後にはじめに呼び出され、その後、stateごとのコールバックが呼び出されます。
複数のstateを設定している場合はstatesの引数に指定した順にコールバックが呼び出されます。

defaultの扱い

stateにおいて、「default」という名前は特殊な扱いを受けます。
おもむろに

<?php
//...
$factory->afterCreatingState(App\User::class, 'default', function ($user) {
    \Log::default('default');
});

と書いて、先の実施順の処理を実行すると

<?php
//...
        factory(User::class)->create();
        //  no state  
        //  default  

        factory(User::class)->state('管理者')->create();
        //  no state  
        //  default  
        //  管理者  

        factory(User::class)->states('管理者', 'Bob')->create();
        //  no state  
        //  default  
        //  管理者  
        //  Bob  

このように、どんなときでも「default」で指定した処理が流れます。
実装上はafterCreatingの内部ではafterCreatingState($class, 'default', $callback)が呼ばれているので、さもありなんです。

defaultはもともと一番はじめのstateのない状態なので、明示的に定義する必要はないと思いますので、stateに定義したり、使用したりしないほうがいいでしょう。

まとめ

というわけで、LaravelのFactoryのstateの細かい話をしました。
LaravelのFeatureテストを書いていると、テストデータ作成がどんどん膨らんでいくので、そのあたりをstateを使って効率化したいところです。
また、マニュアルにはないものの、複数の状態をもたせることもできるので、stateの定義数も最適化していけるといいと思います。

最後に

弊社は急速に成長しているプロダクトを複数抱えており、この成長を支えてくれるデザイナーやエンジニアを募集しています。

www.wantedly.com

www.wantedly.com

SCOUTER Conference vol.1を開催しました

こんにちは、株式会社SCOUTERの石岡将明( @masaakikunsan )です。

2019/05/28に、弊社にて SCOUTER Conference という新しいイベントを開催しました。

connpass.com

今回は、準備から実際にどうだったかをまとめていきます!

SCOUTER Conferenceとは

まず、SCOUTER Conference について説明します。 NuxtMeetupやLaravueやこのSCOUTER開発者ブログで徐々にSCOUTERの認知は上がっていっているが、結局何してる会社なの?どういう人がいるの?って思ってる方が多いと思います。

そこで、今回弊社エンジニアと話せるイベントを開催することでSCOUTER社のことメンバーのことを知ってもらえる機会を設けようと思い開催に至りました。

開催準備

今回イベント公開まで一日という爆速で準備をしました。

開催に至り、考えていたコンテンツは以下です。

  • SCOUTER社についての説明
  • メンバー紹介
  • メンバーとお酒を呑みながらワイワイ
  • 希望者はCTOとカジュアル面談

このコンテンツを元に、バナーを作成しました。 バナーでは、イベント名、何があるのか、お酒を飲んでワイワイする雰囲気が伝わるようなものを想定し、作成しました。

僕がまず手書きでイメージを作成し、デザイナーにそれをいい感じでデザインしてもらい、一緒にfontを選ぶ流れで大体3時間ぐらいで作成できました。

f:id:masaakikunsan:20190529151904p:plain

あとは、イベントページを connpass で公開し当日のお酒や食べ物の準備をしました。

今回はSCOUTER社のメンバーとつながりがない方の参加も想定していたので誰かわかるようにネームプレートを用意しました。 connpassからアイコンを入手し、バナーのメインカラーに合わせデザインしました。

f:id:masaakikunsan:20190529152243p:plain

イベントの模様

20人の募集に対し、22人の応募があり実際の参加は16人でした。 当日は雨も降っていたのでもう少し来ないかと思っていたのもあり、参加率は悪くなかったと思います。

最初の挨拶

今回企画を進めていた僕の方から軽い挨拶と会場についての説明をさせていただきました。

f:id:masaakikunsan:20190529153953j:plain

SCOUTERの事業紹介

SCOUTER社についての説明はCTOの松本からしていただきました。

SCOUTER社の生い立ち、SARDINE事業・back check事業、開発組織としてなにを目指しているのかをスライドと共に発表しました。 今回はそのスライドから見せてもいいところのみ抜粋します。 詳しい話を聞きたい方は是非vol.2にご参加ください。

f:id:masaakikunsan:20190529154346p:plain f:id:masaakikunsan:20190529154413p:plain

メンバー紹介

メンバー紹介のスライドは僕が作成させていただきました。 メンバー紹介は顔とその人が一致するようにしてほしいと思いもあり、写真撮影、自己紹介の内容から作成しました。 以下当日発表したメンバー紹介のスライドです。

docs.google.com

メンバーとの交流

参加者とメンバーでご飯とお酒を呑みながらワイワイと盛り上がっていろいろな話をしました。

f:id:masaakikunsan:20190529155607j:plain

大変私ごとで恐縮ですが、イベントの日が誕生日でして、知り合いの参加者がわざわざケーキを買ってきてくれたのでみなさんで美味しくいただきました。 本当にありがとうございました。

f:id:masaakikunsan:20190529155708j:plain

まとめ

SCOUTER社やメンバーや会社の雰囲気を知っていただくいい機会になったかなと感じています。

vol.2に関してはまだ未定ですが、今後もこういう場をやっていきたいと思うのでSCOUTER社をどうぞよろしくお願い致します。

最後に

SCOUTER社では一緒に頑張ってくれる方を募集しております。 デザイン、エンジニアの皆さん興味のある方はご応募お願いします!

www.wantedly.com

www.wantedly.com

Laravel/Vue.js勉強会#9 開催しました!

こんにちは、株式会社SCOUTERの佐藤( @r_sato1201 )です。

先日、Laravue勉強会#9を開催いたしました。 はやいもので、今回で第9回目。今回もたくさんの方に参加していただき、とても有意義な勉強会になりました。 今回はその模様を報告させて頂きたいと思います。

laravue.connpass.com

会場

今回は、カオナビさんのオフィスをお借りしました。 f:id:ryonnsui1201:20190523111947j:plain

写真が少なく、内観が伝わらないかもしれませんが非常に綺麗で、素敵なオフィスでした。 今回のLaraVue勉強会以外でも、勉強会などをカオナビさんのオフィスで実施するようなので、是非行って確認してみてください!

発表内容

スポンサー枠も含め、7人のかたに発表していただきました。 発表資料が公開されている中で、特に印象に残った発表を抜粋して報告したいと思います。

SSRの話(@kahirokunnさん)

f:id:ryonnsui1201:20190523113242j:plain

トップバッターは @kahirokunnさん。 SSRまわりの話をしていただきました。

サーバーサイドで描画した後、その結果をjsonとしてhtmlに埋め込み、クライアントサイドではその結果を流用してすばやくDOMを再現することができるハイドレーションという機能は恥ずかしながら初めて知りました。とてもおもしろい内容で、SSRまわりに関してもっと理解を深めなくてはいけないと感じました。

slides.com

Optional Chaining + Laravel FormRequestでバリデメッセージを表示する (@kotamat)

 f:id:ryonnsui1201:20190523113327j:plain

弊社CTO、松本の発表です。

LaravelのFormRequestは非常に便利だが、ネストしたエラーメッセージはハンドリングが辛いためOptional Chainingを使うと非常にハンドリングしやすいという内容でした。
冗長なコードを避ける、ベストなプラクティスだと思います。 ただし、Optional ChainingはBabel7から入ってきたもので、Vue2系だとテンプレートにBabelは入っていません。その際の回避策として、optional-valueを使うといいようです。

slides.com  

Laravel+Dockerを本番でも使いたい!(@moyashidaisukeさん)

f:id:ryonnsui1201:20190523113438j:plain

LaravelでDockerを本番でも使う際の知見を発表していただきました。
LaraDockとAWS Fargateは相性が悪く、LaraDockはVolumeを使ってホストのディレクトリをマウントすることが前提になっているが、fargateはホストという概念がないためそれができないそうです。 自分でDockerfileを書くときの設定など、とてもわかり易くまとまった内容でした。

docs.google.com 

Laravel 初めての業務で遭遇したハマりポイント×2(furuichiさん)

f:id:ryonnsui1201:20190524045933j:plain

業務上で遭遇したハマりポイントを発表していただきました。
Eloquentは主キーのカラム名idを想定しており、それ以外の名前を主キーに設定したい場合は、モデルの中に明示的に追加しなくてはならない、というのは初めて知りました。 さらに調べたところ、デフォルト状態で主キーは自動的にintへキャストされるので、自動増分、整数値でない主キーを使う場合、モデルにpublicの$incrementingプロパティを用意し、falseをセットする必要があるようです。とても勉強になりました。

speakerdeck.com

懇親会

f:id:ryonnsui1201:20190523104416j:plain f:id:ryonnsui1201:20190523112423j:plain

発表後は、カオナビさんが提供してくれた飲食を囲み懇親会をしました! 多くの方に残っていただき、懇親会で親交を深めていただきました。

まとめ

初学者からエンジニア歴が長い人まで、各々の知見を共有できた素晴らしい勉強会になったと思います。 スポンサーして頂いた、カオナビさんありがとうございました!

詳細な日程は未定ですが、次回は7月頃にheyさんの会場をお借りして開催いたします!

最後に

SCOUTER社では一緒に頑張ってくれる方を募集しております。 デザイン、エンジニアの皆さん興味のある方はご応募お願いします!

www.wantedly.com

www.wantedly.com

 

Vue Devtools で快適なデバッグ

こんにちは、 SCOUTER エンジニアの匠平@show60です。

SCOUTER のフロントエンドの開発は Nuxt.js を使用しており、デバッグの際に Vue Devtools というツールを使っています。

今回はこの Vue Devtools で、開発に普段使いしてもらいたい機能をいくつかご紹介したいと思います。

Vue Devtools の導入

最も人気がありシンプルなのは、Chrome 向け および Firefox 向け の優れた Vue.js devtools を使用することです。

VS Code によるデバッグ — Vue.js

Vue Devtools の導入には、拡張機能とデスクトップアプリケーションの2つの方法があります。

Chrome と Firefox は拡張機能が提供されており、普段の Devtools と同じように開けるのでこちらが便利でしょう。

他のブラウザをお使いの方は、デスクトップアプリで使用することになります。

ここでは Chrome 拡張機能を用いて、以下のとおりシンプルな Nuxt.js アプリケーションを例にしたいと思います。

f:id:show-hei:20190514212914p:plain

Vue Devtools の基本機能

Devtools とは、ブラウザで使用できるデバッグツールで、主にフロントエンド開発に使用します。

3月末に Vue Devtools が ver 5 にアップデートされ、新しい機能が追加されました。

基本機能に大きな変更はありませんが、新たに追加された機能、強化された機能を織り交ぜて紹介します。

  • イベントの動作をレコーディング
  • パフォーマンスタブでレンダリング時間を計測
  • Vuex 内のデータを編集
  • 試してほしい便利機能

イベントの動作をレコーディング

このタブでは、アプリ内で行われたイベントをレコーディングし、それらの動作によって正しくデータが渡されているかを確認することができます。

以下のサンプルの input は、 AppInput.vue というコンポーネントとそのラッパーである InputWrapper.vue で構成されています。

f:id:show-hei:20190514214644g:plain

input タグにテキストを入力すると、中央にそのタグ名や時刻などが表示され、右側は event info 、つまりイベントの詳細が書かれています。記録されるイベントは $emit が対象となるようです。

event info の項目

  • name
    • イベント修飾子の名称
  • type
    • イベントの種類 (Vue Devtools の Github を見る限り、表示されるテキストは $emit しかないよう)
  • source
    • イベントを含んでいるコンポーネント名
  • payload
    • 受け渡されたデータ

このサンプルでは単純な構成ですが、複数のコンポーネントを経由してデータを受け渡すことも多いでしょう。

目的のページやコンポーネントまでデータが渡らないというときに、どのコンポーネントまで渡ってきているのかが視覚的に分かりやすくなります。

1動作ごとに記録ができるので、ほしいデータが膨大な記録に埋もれてしまうといった心配もないですね。

パフォーマンスタブでレンダリング時間を計測

パフォーマンスタブ内では2つの方法でパフォーマンスを計測することができます。

Frames per second

Vuex やルーティングなどの動作のパフォーマンスを計測することができます。 レコーディングを Start し、ブラウザ操作を行った後に Stop するとその間のパフォーマンスを秒単位計測することができます。

f:id:show-hei:20190514225955p:plain

アルファベットが書かれた丸いアイコンが、その動作を示しています。

  • E: Events
  • R: Routes
  • M: Mutations

Vuex の Mutations の動作が記録されるため、動作のタイミングを確認したり、重複している動作を見つけるのにも役立ちそうです。

f:id:show-hei:20190514230409p:plain

計測したパフォーマンスは自動的に保存されるため、複数回の計測で比較することもできますが、表示が秒単位なので細かな分析には向いていないかもしれません。

Component render

こちらもレコーディングを Start してから Stop するまでの時間を計測することができますが、コンポーネント単位でのレンダリングを表しています。

f:id:show-hei:20190515034044p:plain

右側には Vue.js の Lifecycle hooks の関数と同名の項目が並んでおり、各項目ごとの処理時間がミリ秒単位で記されています。

手元のコードで動かしてみる限り、 mountRenderupdateRender あたりのレンダリング処理は他の処理と比べて時間がかかるようです。

ページやコンポーネントの処理に時間がかかるなどといった場合のデバッグに利用できそうです。

Vuex 内のデータを編集

以前のバージョンより、 Vuex の state, mutation, getters を確認することができていましたが、 Ver 5 のアップデートからは新たに Devtools 上で Vuex を編集できるようになりました。

f:id:show-hei:20190515044042g:plain

ブラウザ上に表示されるテキストであればブラウザの Devtools で編集してしまうと思います。

そうでない裏側で動いている Vuex のデータで、ちょっと値を変更して確認したいだけなんだよなーってときにはとても便利です。

数値であれば + - で簡単に増減できますし、配列の要素も同様に増やすことができます。

試してほしい便利機能

Vue Devtools の隅っこの見逃しそうな場所に inspect DOMOpen in editor があります。

f:id:show-hei:20190515111448p:plain

ブラウザの横幅を縮めると見えなくなっちゃうのですが、もっと自信を持って表に出てきてもいいくらいの便利機能です。

ブラウザの Devtools にジャンプ

inspect DOM は、今開いているコンポーネント (ここでは <logo>) を通常のブラウザの Devtools の Elements で開いてくれます。

f:id:show-hei:20190515111609p:plain

わざわざ同じ箇所を再度探す必要がないので二度手間が省けてちょっとだけ嬉しくなれます。

見ているコンポーネントをエディタで自動的に開く

Open in editor をクリックすると、今開いているコンポーネントファイルをデフォルトエディタとして登録しているエディタで開いて表示してくれます。

f:id:show-hei:20190516110834g:plain

デバッグで当たりをつけたらこの Open in editor をクリックするだけですぐに修正を書き始めることができます。

これもコンポーネントを探す手間がいらないのでめちゃめちゃ便利です!

さいごに

基本機能を直感で簡単に使えるようになっている分、他の機能に触れることが少ないかもしれません。 かゆいところに手が届く仕様になっていると思うので、ぜひお試しください!

私達 back check チームは、日本の採用文化を変えるために、共にプロダクト開発をしていただけるエンジニアの募集をしております。

興味をお持ちいただいた方はぜひご連絡ください。

www.wantedly.com

www.wantedly.com