OmniAICreator/Qiita-1.07M huggingface dataset:
配列の中の要素を元にキーとバリューを自由に組み替える方法

どの言語、フレームワークでも使える汎用的なやり方。

```
arrays = ['parent' => ['id' => '1', 'number' => '100']],
         ['parent' => ['id' => '2', 'number' => '200']],
         ['parent' => ['id' => '3', 'number' => '300']]
```

下記のように準備する。

```php
foreach(arrays as array){
   $result[array['キーにしたいカラム'] = array['バリューにしたいカラム'];
}
```
例えば、このように

```php
foreach(arrays as array){
   $result[array['number'] = array['id'];
}

var_dump($result);
```

結果は、


```php
'100' => '1',
'200' => '2',
'300' => '3',
```

キーとバリューを反対にすることができました！
****
ちなみに、CakePHPでは、この1行で上記のようなことができますが、一意性の問題があるので、エラることがあると思います。慣れないうちはforeachで回すやり方でいいと思います。

```php5

$result = Hash::combine($arrays, "{n}.parent.number", "{n}.parent.id");
```
スクリプト作成_ファイル振り分け

<h1>はじめに</h1>
アプリの処理で作成されたファイルを条件に基づいて移動、コピーするスクリプトの作成を依頼された。
前回、前々回とスクリプトの作成スキルがあることを理解してもらえたようで、すぐに自分に依頼が来た。
聞いた限り複雑な条件や仕組みでは無さそうなのですぐ終わりそうです。

<h1>仕様</h1>
①アプリの仕様で下記のようにいくつか命名規則を持ったファイルが作成される
<b> 先頭が「A_」で始まるファイル　例：A_TEST</b>
<b> 先頭が「B_」で始まるファイル　例：B_TEST</b>
<b> 先頭が「AB_」で始まるファイル　例：AB_TEST</b>
<b> それ以外　例：C_TEST</b>

②これらのファイルを仕分けし、以下のような処理を行う
`A_の場合`
・「読み込み用フォルダ」に移動
`B_の場合`
・「その他のフォルダ」に移動
`AB_の場合`
・「読み込み用フォルダ」にファイルをコピーした後、元ファイルを「その他のフォルダ」に移動
`それ以外の場合`
・「エラー用フォルダ」に移動したあと、指定の返り値(ここでは255)を返す
※例外処理はJP1側で実装するため。今回は返り値の指定のみ

③以下のような階層構成になる
/work (作業領域：スクリプト本体やログ、一時ファイルの出力先)
└/test (実際のファイルやフォルダが配置されている)
　̠├/ReadOnly (読み込み用フォルダ)
　├/Other (その他のフォルダ)
　└/Error (エラー用フォルダ)

<b>◆コマンドのピックアップ◆</b>
前回作成した<a href=https://qiita.com/ryoma0218/items/bfd75484e45a1351152e>「スクリプト作成_ファイル・フォルダ情報の確認」</a>から流用する。
一部追加したもののみピックアップします。

```java:findstr
findstr /I /B "A_"
rem /I      :小文字大文字を区別しない
rem /B "A_" :先頭文字列が"A_"のファイルを検索
```
```java:copy
copy DIRPATH1\FILE1 DIRPATH2\FILE1 
rem FILE1 を DIRPATH2 配下にコピーする(robocopyでは単体コピーができないため使用)
```
```java:move
move DIRPATH1\FILE1 DIRPATH2\ 
rem FILE1 を DIRPATH2 配下に移動する
```


<h1>実際に作ってみた</h1>
```java:file_sorting.bat

@echo off
setlocal EnableDelayedExpansion

rem *-------------------------------*
rem 
rem 	ファイル振り分けbat
rem 
rem *-------------------------------*
rem 
rem YYYY.MM.DD	:新規作成

rem 日付表記がYYYYMMDD
set TODAY=%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%
set LOG=H:\work\test\FileSorting_%TODAY%.txt

rem 作業ディレクトリ
set WORKPATH=H:\work\test
set FILELIST=H:\work\LIMS_File.csv
set cnt=0
set err_cnt=0

rem 対象ファイルのピックアップ
dir /b /a-d %WORKPATH% > %FILELIST%

rem 処理開始時間
echo ########## >> %LOG% 2>&1
echo START %TIME% >> %LOG% 2>&1
echo ########## >> %LOG% 2>&1

rem ファイルの振り分け
for /f %%a in ( %FILELIST% ) do (
	set FILENAME=%%a
	set cnt=0

	rem 先頭文字列[AB]
	echo !FILENAME! | findstr /I /B "AB_" > nul
	if not ERRORLEVEL 1 (
		echo !FILENAME! >> %LOG% 2>&1
		copy %WORKPATH%\!FILENAME! %WORKPATH%\ReadOnly\!FILENAME! >> %LOG% 2>&1
		move %WORKPATH%\!FILENAME! %WORKPATH%\Other\ >> %LOG% 2>&1
		set cnt=1
	)

	rem 先頭文字列[B]
	if !cnt!==0 (
		echo !FILENAME! | findstr /I /B "B_" > nul
		if not ERRORLEVEL 1 (
			echo !FILENAME! >> %LOG% 2>&1
			move %WORKPATH%\!FILENAME! %WORKPATH%\Other\ >> %LOG% 2>&1
			set cnt=1
		)
	)

	rem 先頭文字列[A]
	if !cnt!==0 (
		echo !FILENAME! | findstr /I /B "A_" > nul
		if not ERRORLEVEL 1 (
			echo !FILENAME! >> %LOG% 2>&1
			move %WORKPATH%\!FILENAME! %WORKPATH%\ReadOnly\ >> %LOG% 2>&1
			set cnt=1
		)
	)

	rem その他
	if !cnt!==0 (
		echo !FILENAME! is Exception File >> %LOG% 2>&1
		move %WORKPATH%\!FILENAME! %WORKPATH%\Error\ >> %LOG% 2>&1
		set err_cnt=1
	)
)

rem 処理完了時間
echo ########## >> %LOG% 2>&1
echo END %TIME% >> %LOG% 2>&1
echo ########## >> %LOG% 2>&1

del %FILELIST%

rem 例外ファイルが存在した場合
if %err_cnt%==1 (
	goto :Err_call
)

exit /b 0
endlocal

:Err_call
exit /b 255
endlocal
```

<h1>おわりに</h1>
想定したファイルの振り分け、例外ファイルが存在した場合のエラー検知を実現することができた。
今回のスクリプトでは、①ファイル名の識別方法、②条件ごとにアクション、③エラー判定を外部に連携、と比較的わかりすいし、簡単に実装できるものだったのでそこまで時間はかからなかった。
Shopifyオリジナルページの作成方法

#はじめに
今回ご紹介する内容は、Shopifyを既に使用し、基本的なコーディングの知識があることを前提とし、オリジナルページの開発にスポットを当てたいと思っている為、初めてShopifyを触ってみたという方に対しては、情報不足な所が多くなると思いますが、予めご了承ください。

#Shopifyとは（簡単に）
世界中で1,000,000のショップに導入されているECプラットフォームです。
テンプレートがすでにある為、誰でも簡単にお洒落なECサイトを製作できます。
テーマの種類も豊富にあり、自分好みのテーマがきっと見つかるはずです！
EC機能もとても充実していますが、今回は、オリジナルページの作成方法をご紹介します。

#オリジナルページ開発　導入編
テーマをカスタマイズする場合は、必ずテーマを複製してから行いましょう！
**[アクション] > [コードを編集]**するから、コード編集画面に移動できます。
![スクリーンショット 2020-12-17 11.17.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905389/cd08dc1a-dcd8-7a12-c3c2-0cdb50da644b.png)
![スクリーンショット 2020-12-17 11.31.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905389/2de5e717-05b8-0a9a-6d2f-e79693914006.png)

##各ディレクトリのご紹介
Shopifyのテーマは、画面左の７つのディレクトリで構成されています、各ディレクトリに、コードが書かれたテーマファイルが格納されています。

| ディレクトリ名 |  |
|:--|:--|
| Layout  | ページ単位のレイアウト。ヘッダーやフッターなどのテンプレートの大枠となる要素  |
| Templates  | 商品ページやお問い合わせページなど、各ページのテンプレート  |
| Sections  | 各ページのブロック要素  |
| Snippets  | 各ブロック要素のアイコンなどのさらに細かいパーツ  |
| Assets  | cssやjsファイル  |
| Config  | サイト設定の為の.jsonファイル  |
| Locales  | 言語設定の為の.jsonファイル  |

この中で主に使用するのは、以下になります。

| ディレクトリ名 |  |
|:--|:--|
| Templates  | 商品ページやお問い合わせページなど、各ページのテンプレート  |
| Sections  | 各ページのブロック要素  |
| Assets  | cssやjsファイル  |

#オリジナルページ開発　実践編
では実際にコードを編集していきましょう。
まずは**「新しいtempleteを追加する」**から新しいページのテンプレートを追加します。
目的から、「page」を選択すると、titleとcontentのみのファイルが生成されます。
こちら不要であれば全て削除して頂いても大丈夫です。
ここからは我々の得意分野ですね。
あとはここに好きなようにhtmlの記法でコーディングしていただければ、
オリジナルページが作成できます！

![スクリーンショット 2020-12-17 12.16.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905389/1a194d21-ccab-2645-2ee5-9a7ce45425dd.png)
またオリジナルのスタイルを当てたい場合は、Assetsディレクトリで、新しいcssファイルを追加してください。
オリジナルのcssファイルを参照するときは、Shopifyオリジナルの記法ですが、該当ファイルに以下のように記述していただければ大丈夫です。

```html:sample.html
<link rel="stylesheet" href="{{ 'sample.css' | asset_url }}">

<h1 class="sample_title">サンプルタイトル</h1>
<p class="sample_text">サンプルテキスト</p>
```
例えば以下のようにスタイルを当てたとして、

```css:sample.css
.sample_title {
  color: red;
  text-align: center;
}

.sample_text {
  color: blue;
}
```
![スクリーンショット 2020-12-17 13.07.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905389/e858b965-1f58-faf4-41e8-c7f525f6e916.png)
ちゃんと反映されていることが確認できます。

#さいごに
最後まで見ていただきありがとうございます。
今回オリジナルページを1からつくる方法をご紹介しましたが、そのほかにも、
トップのセクションを、他ページに使うことも可能だったりします。
こちらの紹介をすると、またさらに深い話となり、長くなってしまいますので、
また改めてご紹介します。

#参考
+ [Shopify](https://www.shopify.jp/free-trial?&term=shopify&Network=Search&SiteTarget=&mt=e&adid=443123476693&adpos=&CampaignId=1477729662&branded_enterprise=1&BOID=brand&gclid=CjwKCAiA_eb-BRB2EiwAGBnXXgVzHqd9HHcJOuvjbi1NWjYnfPs20nrPaavPttTmYVEcOJgGLpBBMhoCFvYQAvD_BwE "Shopify")
+ [【Shopify】テーマのコード編集のススメ【カスタマイズ】](https://www.sumahoya.net/ec-blog/creative/3586.html "【Shopify】テーマのコード編集のススメ【カスタマイズ】")
+ [Shopifyのカスタマイズ。デザインを変えて売れるECサイトを作る方法
](https://commerce-media.info/blogs/ec/shopify-customize "Shopifyのカスタマイズ。デザインを変えて売れるECサイトを作る方法
")
【Keras】model.save時にAttributeError: module 'keras.optimizers' has no attribute 'TFOptimizer'

Kerasでmodel.saveをしようとすると```AttributeError: module 'keras.optimizers' has no attribute 'TFOptimizer'```とエラーが出る．


```Python
import keras
from keras import optimizers
```
を

```Python
from tensorflow import keras
from tensorflow.keras import optimizers
```

に変える．
TensorFlowに組み込まれているKerasを使用するようにすればおｋ
【React Native】開発環境構築(Expo CLI編)

WindowsでReact Nativeを開発するために必要な設定。
node.jsとAndroid Studioはインストール済みであること。

# Expo CLI入れる
```bash
$ sudo npm install -g expo-cli
$ expo -V
4.0.13
```

# ワークスペースを作る
```bash
$ mkdir tutorial-react-native 
$ cd tutorial-react-native
$ expo init myproject
```

# エミュレーターを起動する
```bash
$ expo login
$ expo start --tunnel
```
【Git】一番最初のコミットを編集したい 。


業務では使うことは滅多にないだろうけど
また同じような状況になったときにすぐに使えるようにしたい

## 状況

プライベートで開発しているリポジトリの履歴が汚くなってるから
一番最初のコミットにまとめてコミットメッセージを編集したい。

```
$ git log --oneline

85c88ce コミットメッセージ3
1a6fc87 コミットメッセージ2
23f8c8a 一番最初のコミット 
```

（上記、`23f8c8a`のコミットメッセージ)

`git rebase -i コミットID` では最初のコミットを編集できなかった。

## 解決方法
```--root``` を指定してあげると、最初のコミットが無事編集できた。

```
$ git rebase -i --root
```

変更できない歴史はなかった…😇
【ポートフォリオ】環境構築編_その1_AWSの利用

[link-1]:https://qiita.com/HIDE03/items/2ce3971fe0b5e21a915a
[link-2]:https://qiita.com/HIDE03/items/2b8c03d764b1e39cb93f


# はじめに
[前回][link-1]では全体的な流れを確認しました。
次に、WEBアプリケーションを公開するための環境を構築していきます。
今回はAWSを利用できるようにするのが目標です。

__※基本、全体的に詳細省いてますが、時間があったら詳細書くかもしれません。__


# 1. AWSの利用
WEBアプリケーションを作る場合、作るまでの順番が色々あるとは思いますが、公開する以上、何はともあれWEBサーバが必要です。
昔はレンタルサーバを使ってブログとか作りましたが、今はAWSとかGCP使うことが多いみたいです。
どちらを使うか迷いましたが、国内の会社はAWSを利用していることが多いように感じたので、今回はAWSを使用することにします。
ちなみにAWSは無料枠があるので、今回はそちらを利用します。

# 2. AWS利用までの手順
流れは下記の通りです。

1. AWSのアカウントを作成する
* Linux仮想マシンを起動する
* パブリックIPアドレスを設定する
* SSHによるリモートアクセスを行う
* Apacheを起動する
* SCPによるファイル転送

# 3. AWSのアカウント作成
まずはアカウントを作成します。下記を見ながら作成しました。
https://aws.amazon.com/jp/register-flow/
特に難しいことは無くて数分で完了しました。

# 4. Linux仮想マシンの起動
下記の手順でインスタンス（Linux仮想マシン）を作成しました。

1. __AWSコンソール__にアクセスする
* __EC2__仮想サーバ を選択する
* __東京リージョン__を選択する
* __Amazon Linux AMI__を選択する
* 無料枠のインスタンスである__t2.micro__を選択する
* キーペアを作成してDLする
* インスタンスを作成する

# 5. パブリックIPアドレスの設定
インスタンスにアクセスする際に使用するIPアドレスは、インスタンスを再起動すると変わってしまう可能性があるため、下記の手順で固定のパブリックIPアドレスを設定します。

1. __EC2ダッシュボード__にアクセスする
* __Elastic IP__のメニューを開く
* 新しいIPアドレスを割り当てる（作成する）
* 先ほど作成したインスタンスにIPアドレスを関連付ける
* セキュリティタイプに__HTTP__を追加設定する

# 6. SSHによるリモートアクセス
試しに、下記手順でリモートアクセスをしてみます。
ちなみに、自分はWin環境なので、GitBashでターミナル利用しています。

1. ローカルルートディレクトリに__.ssh__フォルダを作成する
* .sshフォルダにDLした__キーペア__を移動する
* （キーペアの権限設定して自分以外は編集不可にしとくと良いらしいです）
* ターミナルから__ssh__で接続する
* アクセス成功

# 7. Apacheの起動
リモートアクセスできることが確認できたので、下記の手順でApacheをインストールします。

1. ターミナルから__SSH__でインスタンスに接続する
* __Linux__をアップデート
* __Apache__をインストール
* __Httpd__の起動確認をする
* デフォルトでHttpdが起動するように設定する
* Apacheの動作確認をする
* __htmlフォルダ__に__index.html__を作成する
* アクセスして確認する

# 8. SCPによるファイル転送
ローカルファイルとインスタンス間のファイル転送をしてみます。
ただ、最初はインスタンスのwwwフォルダに書き込み権限が無いため、色々設定します。

1. インスタンスのWWW以下フォルダに権限設定を行う
* ターミナルからSCPでローカルにindex.htmlをDLする
* index.htmlを編集して、インスタンスにULする


# まとめ
* AWSでインスタンスが利用できるようになりました
* ローカルとインスタンス間でファイル転送ができるようになりました

[次回][link-2]はLAMP環境を構築したいと思います。


# 参考
paizaラーニング -AWS入門編1:Webサーバーを構築しよう-
https://paiza.jp/works/aws/primer/aws1
【Salesforce】PDF出力の際にApexで動的にCSSを設定したい

apex:pageのrenderas="pdf"の場合、リファレンスに下記の記載が・・・

>  JavaScript が必要なコンポーネントは使用しないでください。

PDFのsizeを動的にしたかったのですが、どうしよう・・・

と思ったらサクッとできました。

```Java:test.cls

// クラス変数にPDFのsizeを用意
public String size { get; private set; }

// あとはメソッドなどで値を代入
this.size = '100mm';

```

```CSS:test.page

@page {
    size: {!pageSize};
}

```

ここまで来るのに１日使った・・・

以下、ボツです。

```CSS:test.page
@page {
    size: 80mm auto;
} 
```

これ動いたらすぐ終わったんだけどなあ。

```HTML:test.page
.c {
  page-break-inside: avoid;
}
<div class="c">
    /* 対象のテーブル */
</div>
```

page-break系はめっちゃ試したのですが駄目でした。

# リンク

[apex:page](https://developer.salesforce.com/docs/atlas.ja-jp.pages.meta/pages/pages_compref_page.htm)
インスタンスメソッドと、selfについて調べる

ふとたまにみるselfはなんだろう、言語化できないなと
思ったので調べてみることにしました。

あと、インスタンスメソッドにも理解が浅いなと感じたため
調べて記事にしました

以下のモデルを例に進めていきます

```rb:app/models/user.rb
class User < ApplicationRecord
  #Article(記事)モデルとの紐付け
  has_many :article
  
  validates :name, presence: true
  validates :email, presence: true 
end
```

##インスタンスメソッド

下記のようなデータが中に入っていたとする

|カラム名            |データ            |
|:-----------------:|:-----------------:|
|name              |test1              |
|email              |test1@mail.com             |
|age              |19              |
|password       |test1              |


```rb:app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    #IDが1のuserを検索
    @user = User.find(1)
    #「.call_age」とは…
    @my_age = @user.call_age 
  end
end
```

「**call_age**」メソッドは**モデルに書いたメソッド**で
コントローラーから呼び出しています


```rb:app/models/user.rb
class User < ApplicationRecord
  #Article(記事)モデルとの紐付け
  has_many :article
  
  validates :name, presence: true
  validates :email, presence: true 

  def call_age
    if self.age >= 20  #20歳以上の場合
       return "私は大人です" 
    else  #20歳以下の場合
       return "私は子供です"
    end
  end
end
```

###では、インスタンスメソッドとは
その名の通りに`インスタンス`に対して使用するメソッドのこと

通常のメソッドは、プログラム中からならいつでも呼び出せるのに対して
インスタンスメソッドは、`作成されたオブジェクト`からしか呼び出すことが出来ない


##メソッドの中身を見ていく
そして、メソッドの内容を見ていく

```rb:app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    @user = User.find(1)
    @my_age = @user.call_age 
  end
end
```

```rb:app/models/user.rb
class User < ApplicationRecord
  has_many :article
  
  validates :name, presence: true
  validates :email, presence: true 

  def call_age
    if self.age >= 20
       return "私は大人です" 
    else
       return "私は子供です"
    end
  end
end
```

コントローラー内の「`@user`」と、モデル内の「`self`」は
中身が同じ

```
id: 1, name: "test1", email: "test1@mail.com", age: 19
```
という中身が入っています

インスタンスメソッドの結果は、現在「`self.age`」には「**19**」というデータが
入っていますので、条件ではelseを通り「私は子供です」という結果が得られます

```rb:app/models/user.rb
class User < ApplicationRecord
  has_many :article
  
  validates :name, presence: true
  validates :email, presence: true 

  def call_age
    if self.age >= 20
       return "私は大人です" 
    else
       return "私は子供です"
    end
  end
end
```

コントローラーにデバックを挟む

```rb:app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    @user = User.find(1)
    @my_age = @user.call_age 
    #デバックを挟む
    binding.pry
  end
end
```

```
[1] pry(#<UsersController>)> @user.call_age 
[2] pry(#<UsersController>)> "私は子供です"
```

という結果が得られているので大丈夫そうですね

##まとめ
・selfは、クラスから作成されているインスタンスと中身が同じ
・インスタンスメソッドは、作成されたオブジェクトからしか呼び出すことが出来ない

それと、コントローラーでも
モデルに書いたインスタンスメソッドを書くことはできます。
しかし、なるべく**DBとのやりとりをするようなメソッドはモデルに
書くほうがいい**ので、今回はモデルにメソッドを作成しました。

使い分けれるように勉強していきたいです

##参考記事
チェリー本
https://qiita.com/leavescomic1/items/99f32f45cd04035f146c
https://qiita.com/tbpgr/items/56eb65c0ea5882abbb07
https://qiita.com/right1121/items/c74d350bab32113d4f3d
GitHub Desktop の使い方（インストール編）

DRONEBIRD Advent Calendar 2020 12月4日分の記事です。

今回は、昨年のアドベントカレンダーで「次に書く、たぶん」と宣言？していた  **GitHub Desktop の使い方（インストール編）** ということで、GitHub Desktop を利用するための、はじめの一歩を書こうと思います。
DRONEBIRD での GitHub の利活用がなかなか普及が進んでいないのですが、「こんなに便利なんだよ！」ということを感じてもらって GitHub の活用を進めていきたいと思います！！


※なお、この記事は既に GitHub アカウント作成が済み、自力でログインできる方向けの記事です。アカウントをお持ちでない方は [GitHub の使い方（超初級編）](https://qiita.com/fairlaterfair/items/073493f0a67fb0bbb02f) を参照してアカウントを作成し、DRONEBIRDの Organization に join してください。

## GitHub Desktopの使い方
### GitHub Desktopとは
GitHub Desktop は、ブラウザ上で行っている GitHub の処理を自分のPCでも実行できるアプリケーションです。「レポジトリ」を自分のPCにコピーして、フォルダやファイルの操作を行うようにファイルの更新・追加等を行い、その差分を検出してブラウザ上の GitHub にアップロードをすることで、ブラウザ上
（イラスト入れる）

ファイルの更新など、Webブラウザ上では難しい処理もGitHub Desktopを使うと簡単に視覚的にもわかりやすく実行できておすすめです。

### GitHub Desktop のインストール （Mac）
※macOS 10.10 以降にインストールできます。
1. https://desktop.github.com/
 にアクセスして、ダウンロードページを開き [Download for macOS] をクリックします。
![スクリーンショット 2020-12-14 18.37.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115920/f9a57bac-59b1-d6a9-4e18-48423d8a15df.png)
2. ダウンロードフォルダに GitHubDesktop.zip がダウンロードされるので、ダブルクリックしてファイルを解凍します。
※ アプリケーションファイルも「ダウンロード」に解凍されるので、私は他のアプリケーションと同様に「アプリケーション」フォルダに移しました。
3. インストールが完了したら GitHub Desktopをダブルクリックしてください。GitHub Desktop が起動すれば、インストール成功です^^

### GitHub Desktop のインストール （Windows）
※Windows 7 64-bit 以降のOSにインストールできます。
※64ビットのオペレーティングシステムが必要です。
1. https://desktop.github.com/
 にアクセスして、ダウンロードページを開き [Download for Windows (64biit)]をクリックします。
![130813199_2733153376898595_9104507012936161630_n.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115920/10a7c3ef-1147-df1f-676b-b6e5dc488310.png)
2. ダウンロードフォルダに [GitHub Desktop] セットアップファイル（[GitHubDesktopSetup.exe]） がダウンロードされるので、ダブルクリックしてファイルを解凍します。
3. インストールが完了して GitHub Desktop が起動すれば、インストール成功です^^

### GitHub Desktop の初期設定
1. GitHub Desktop が起動したら [Sign in to GitHub.com] を押して、自分のアカウントにログインします。
![131350068_202664204729196_4570030433671930269_n.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115920/06f69126-8177-3189-a68b-e6e7167c18b7.png)
 
これで、ひとまず GitHub Desktop の初期設定が完了し、ブラウザ上での作業と同期が取れる環境が整ったことになります。

次回、ブラウザ上で作成したレポジトリを自分のPCに「cloneを作る」方法で、処理をしてみたいと思います。本日はここまで！
QRコードの効果測定（QRコード→Web編）


「チラシにQRコードを貼ってみたけど、コレってどのくらい読み込まれているの？:thinking:」
「わかりません:tired_face:」

これではせっかく作ったチラシの効果がわからずもったいないです。
というわけで、印刷物に貼ったQRコードのアクセス解析をする方法をまとめました。


#１. QRコード生成サービスを使う
簡単に測定したい場合はQRコード生成サービスが提供するアクセス解析の利用がおすすめです。
ただし、**「データをダウンロードができない」「データ閲覧期間に制限がある」**などのデメリットがあります。

[クルクルmanager](https://m.qrqrq.com/)
※アクセス解析はcookieを削除すると見れなくなる。永続的に利用するにはアカウント登録が必要。
※CSVやExcelデータのダウンロードは不可

[QRのススメ](https://qr.quel.jp/pv.php)
※30日間まで。
※CSVやExcelデータのダウンロードは不可。

#2. GoogleアナリティクスとCampaign URL Builderを使う
Excel等で集計したいときはURLにパラメータを仕込んでGoogleアナリティクスで表示させる方法がおすすめです。

URLをそのままQRコード化するとGoogleアナリティクスではdirect/none(参照元不明）と表示されてしまいアクセス情報がわかりません。

そこでGoogleアナリティクスに参照元がQRコードであることを伝えるためのパラメータをURLに仕込みます。そうすると、Googleアナリティクスでアクセスデータを参照できるようになります。

### パラメータの種類
QRコードからの流入を調べるには以下の3つのパラメータを設定すればよいです。

* **utm_source**：広告主、サイト、出版物などの識別に使用
* **utm_medium**：メディアの識別に使用
* **utm_campaign**：商品のキャンペーン名、プロモーションコードなどを指定

### パラメータの設定例
以下のようにパラメータと値のペアを使います。

* utm_source = qrcode：QRコード経由のトラフィックを識別
* utm_medium = flyer：チラシ経由のトラフィックを識別
* utm_campaign = 202012：キャンペーンのトラフィックを識別

これらのパラメータを使用すると、URLは次のようになります。
https://www.example.com/?utm_source=qrcode&utm_medium=flyer&utm_campaign=202012

### URL生成ツールでパラメータ設定をする
パラメータ付きURLは手動でも作れますが、[Campaign URL Builder](https://ga-dev-tools.appspot.com/campaign-url-builder/)を使えばフォームを埋めるだけで作れます。
以下のように情報を埋めるとURLが生成されます。
![URLビルダー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241418/60f9e8e5-b827-af20-6e5d-2b5143cb7c53.png)
**Campaign URL Builder**
https://ga-dev-tools.appspot.com/campaign-url-builder/

### Googleアナリティクスで確認する
utm_sourceとutm_mediumは、**集客＞すべてのトラフィック＞参照元/メディア**で確認ができます。
utm_campaignは、**集客＞キャンペーン＞すべてのキャンペーン**で見れます。

### 【注意】URLが長過ぎるとQRコードが複雑になる
パラメータを付与するとURLが長くなると思います。
以下の例のようにURLが長過ぎるとQRコードが複雑になります。複雑すぎるQRコードは**縮小すると潰れて読み取れないこともある**ので注意が必要です。
![QRコード例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241418/3a5da3a1-7884-7b0a-e39a-fede2be1aba2.png)
複雑すぎて読み取れない場合はURL短縮サービスを利用してURLを短くしてからQRコードにしましょう。



おわり
ひたすら楽してnetbox

この記事は [さくらインターネット Advent Calendar 2020](https://qiita.com/advent-calendar/2020/sakura) 17日目の記事です。

みなさん、IPAMとかDCIMとかどうしているでしょうか。
管理するネットワークとかサーバーとかスイッチの数が多いとなんだか頭が痛くなってきませんか。
そこで、[さくらの専用サーバ PHY](https://server.sakura.ad.jp/)では裏側の管理の仕組みの１つとして[netbox](https://github.com/netbox-community/netbox)をつかっています。netbox、とても便利ですよね。
とても便利なのですが、netboxにポチポチ登録するのは面倒ですし、頻繁にデータ登録を行って継続的にメンテナンスするのも大変です。

そこで、ひたすら楽してnetboxの運用していくためのいくつか工夫を本記事では少しご紹介します。

※この記事は2020年10月23日に行われたオープンソースカンファレンス2020 Online/Fallの発表とも関連があります。もしご興味のあるかたは以下よりご参照ください。

* [さくらの専用サーバPHYとその裏側 〜物理ホスティング環境構築自動化の取り組み〜 (前編)](https://knowledge.sakura.ad.jp/26536/)
* [さくらの専用サーバPHYとその裏側 〜物理ホスティング環境構築自動化の取り組み〜 (後編)](https://knowledge.sakura.ad.jp/26550/)


# 環境

まずnetbox環境の構築ですが、公式のdocker-composeがあるのでこれを使います。楽ですね。
https://github.com/netbox-community/netbox-docker

この `netbox-docker` ですが、startup_scriptsとinitializerという仕組みがあり、これで何ができるのかというと、`docker-compose up`で起動させると予めデータが入った状態で起動させることが出来るというものです。

# startup_scriptsとinitializerを使った運用
startup-scriptとinitializerの仕組みについて軽く掘り下げます。

`netbox-docker` には、`initializers` というディレクトリがあり、YAMLファイルが保存されています。
`docker-compose up` すると、`startup_scripts` ディレクトリ内のPythonスクリプトが逐次実行されていき、`initializers`以下のYAMLファイルの内容を読み取りながら、netboxにデータ登録を行っていく、という流れです。

[さくらの専用サーバ PHY](https://server.sakura.ad.jp/)で管理のための運用しているnetboxでは、このstartup_scriptsとinitializerを全面的に用い、ReadOnlyなnetboxを利用しています。

ReadOnlyにしている理由は端的に言うと楽をするためです。

* GUIからの手入力は一切やらない（むしろ出来ないようにする）
  * 手入力を認めるとデータを完全なものにする継続的な努力が必要になるのでやらない
* リアルタイムではない
  * デプロイされた時点での情報のみ掲載されるsnapshot的なもの
  * 定期的にデプロイしなおすことで解決（数時間の反映ラグは許容する）

# データの準備
データは `initializer` 以下のYAMLファイルに記載していきます。なおYAMLファイルはGitで管理しています。

## ネットワーク

管理したい情報としては、主にVLANやプレフィックス情報かなと思います。
これらはそれぞれ以下のYAMLファイルに記載できます。（ファイルにはサンプルも記載されているのでわかりやすいです）

 * VLAN (`initializers/vlans.yml`)
 * プレフィックス (`initializers/prefixes.yml`)

とはいえ、こういったYAMLを手作業で編集するのも大変なので、`ひたすら楽をする` 実現のため、Gitのブランチを作成してYAMLを編集してくれるCLIツールを作成して利用しています。
これぐらい（/27とか/28とか）のネットワークがほしいな、と思ったときに実行すると、未割り当ての空きがあるネットワークプールからネットワークを割り当て、かつVLANアサインまでしてくれます。楽ですね。


## サーバーとかスイッチ

サーバやスイッチで管理したい情報としては、主に以下のような情報かと思います。それぞれYAMLファイルに記載できます。

 * 設置したラック (`initializers/racks.yml`)
    * ラックの役割(`rack_roles.yml`)やグループ分け（`rack_groups.yml`）もある
 * 設置した機器の名称や位置など (`initializers/devices.yml`)
 * 機器に設定したIPアドレス (`initializers/ip_addresses.yml`)
 * 機種名  (`initializers/device_types.yml`)
 * 装置ベンダー (`initializers/manufacturers.yml`)



ただし、[さくらの専用サーバ PHY](https://server.sakura.ad.jp/)ではそれなりの数のサーバやスイッチを運用しています。サーバやスイッチは日を追う毎に増えていくため、都度都度YAMLファイルを編集するのでは面倒です。
そこで、日々の運用によって増えるサーバやスイッチは、元データとして上記のYAMLファイルではなく「DHCPサーバが参照する構成管理ファイル」を参照してnetboxにデータ登録を行っています。
この構成管理ファイルについては、[さくらの専用サーバPHYとその裏側 〜物理ホスティング環境構築自動化の取り組み〜 (後編)](https://knowledge.sakura.ad.jp/26550/)に具体的な内容がありますのでご参照ください。
ちなみに、全く上記のYAMLファイルを使っていないのかというとそうではなく、台数が少ないものや頻繁に追加が行われないような装置についてはYAMLファイルに記載して管理しています。

「DHCPサーバが参照する構成管理ファイル」を読み取ってnetboxに登録するPythonスクリプトをstartup_scriptsの下に置いておくと、設置したサーバーやスイッチがnetboxに反映されていきます。楽ですね。

# おわりに
startup-scriptとinitializerの仕組みをつかって楽なnetbox運用をめざしました。
たぶんこれが一番楽というわけではないと思いますが、概ね楽かなと思います。
ただnetboxは機能が豊富でまだまだ利用していない機能があるので、
さらにデータ登録を進めていきたいと思っています。
【VS Code】多段タブを実現する方法 on Windows

# はじめに
VS Code 1.53.0 から標準で多段タブ（タブの折り返し/Wrap tabs）機能が実装されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36808/9d96dfb8-cd6e-cf52-c6fa-24cf72cd1874.png)
以下はそれ以前のバージョン用の方法となります。

----


基本的なところは [【VSCode】複数ファイルを開いている時にタブを多段表示する方法(Mac) - Qiita](https://qiita.com/tmasuyama/items/d9a26e0c43bd3606ab90) に書いてある通りですが、Windowsの場合(?)はもう少し手数が必要でしたので、その追加分だけをまとめておきます。

# Windowsの場合の追加手順

### 1. settings.json

Windowsの場合はドライブ名を以下のように記述します。

```json:settings.json
"vscode_custom_css.imports": ["file:///C:/Users/ユーザー名/custom.css"],
```

### 2. 管理者権限で VS Code を再起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36808/cc575111-0343-7723-6285-5ad6f6c30a68.png)

### 3. cssのリロード

コマンドパレットから `Reload Custom CSS and JS` を実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36808/081e84fd-76a9-d631-ff6c-e6ec6a63bad6.png)

### 4. VS Code を再起動

以上でタブが多段になります。

# 注意

この拡張機能『Custom CSS and JS』をインストールすると、VS Codeが「サポート対象外」になるようです。ウィンドウタイトル部分に `サポート対象外` と表示されます。
色々な角度から見た GraphQL

この記事はGraphQL Advent Calendar 2020の17日目の記事です。
前回の記事は @Quramy さんの [Incremental Data Delivery with GraphQL defer and stream](https://quramy.medium.com/incremental-data-delivery-with-graphql-defer-and-stream-d779b5e38833)でした。

# この記事の経緯
私が GraphQL という言葉を最初に認識したのは2017年頃だと思います。

当時の GraphQL に関しての知識は API の I/F というより
NoSQL のデータ取得のクエリの書き方というように認識していました。
（多分何かの記事のチラ見で勉強不足でした）

2020年になり、色々な文脈で GraphQL という言葉を聞く機会が増えてきて
いま GraphQL を利用し始めるなら？と思いプラクティスをまとめようと考えました。

あなたの目線から GraphQL の可能性を覗いてみて、
今日から GraphQL を使い始めてみませんか。

# React.js を利用するエンジニアから見た GraphQL
React.js は現在のスタンダードなフロントエンド技術の一つですよね。
React.js で GraphQL はどう使えるのかと言うと、
Apollo Client を利用することで劇的に便利になります！

接続する API が GraphQL によって通信可能なら
たった数行でリクエストが実装できます。

更に Apollo Client はキャッシュ機構が強力で、
データの取得元をインメモリと外部リソースの区別を意識せずに、
Redux の Store のような state 管理としての利用が可能です。

少し気になってきましたか？是非コードを書いてみましょう :keyboard: 
https://www.apollographql.com/docs/react/get-started/

# バックエンドを開発するエンジニアから見た GraphQL
GraphQL は、ほとんどの言語でサポートされています。
きっとあなたが今日書いた言語でも。
https://graphql.org/code/

もしデータベースに NoSQL を利用していて、あるキーに対して JSON が返るような設計をしているなら
そこでも GraphQL の出番です。

そして何より、クライアント開発者に graphql-code-generator で作成された
インターフェースを渡して、その形に則った開発を進めることで、
おそらく Swagger を利用するより高速に、スキーマ駆動開発が可能です。

※ Node.js の選択肢があるなら、個人的には NestJS がおすすめです。モダンな技術スタックを採用したフレームワークで、もちろん GraphQL も喋れます。

# AWS を使うエンジニアから見た GraphQL
AWS 文脈で GraphQL といえば AppSync ですね。
これは GraphQL に特化した AWS のサービスで、
バックエンドをほとんど意識せずに開発を進めることができ、とても便利です。
最近はこれを使うために GraphQL を学習する意味がある、と個人的に感じます。
WebSocket による双方向通信の実装や認証などもこれ一つでできるのは素晴らしいです。

公式ドキュメントのクイックスタートから、是非試してみて下さい。
https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/quickstart.html

# アーキテクトから見た GraphQL
マイクロサービスな設計になる際、
スキーマ駆動開発という選択肢は強く惹かれる要素かと思います。
スキーマの定義も、 gRPC ほど厳格ではなく、 Rest API ほど緩くないと感じます。

コンポーネントによってページングのクエリが異なる？ GraphQL で統一しちゃいましょう。

Facebook 発 OSS で、運用期間までメンテナンスが残りそうなのもポイントですね。

既存の Rest API と混ぜにくいという課題もありましたが、
GraphQL Mesh というメッシュサービスも開発されています。
https://qiita.com/G-awa/items/dba92983ba03ee8daec6

# まとめ
もう GraphQL は web 開発の随所に存在しています。

現在開発しているスキーマを変更しなくても、
React.js 単体でも、 AWS クライアント単体でも GraphQL の利用が始められます。

まだまだ日本だと開発に採用しているチームが少ない印象ですが、
これから利用ケースが増えて便利になることは間違いないと思います。

是非 GraphQL 取り入れてみましょう！
ASP.NET Core で Application Insights を手動で構成する手順

以下のページのサマリ
[Application Insights for ASP.NET Core アプリケーション](https://docs.microsoft.com/ja-jp/azure/azure-monitor/app/asp-net-core)

## NuGet の追加

以下のパッケージを追加します

- Microsoft.ApplicationInsights.AspNetCore

## Startup.cs への AppInsights 有効化の処理の追加

以下のコードを追加

```csharp
public void ConfigureServices(IServiceCollection services)
{
    services.AddApplicationInsightsTelemetry();
    services.AddRazorPages();
}
```


この時点で実際の Azure には行かないけどローカルでデバッグ実行すると Visual Studio で確認できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/94d702d6-bbea-d8af-170f-616072c92fb6.png)

## ILogger 用のログレベルの調整

デフォルトで警告以上が対象なので、もうちょっと詳細な情報が欲しい場合は `appsettings.json` の Logging の下に ApplicationInsights を追加してログレベルを構成できます。
こんな感じになります。

```json:appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "ApplicationInsights": {
      "LogLevel": {
        "Default": "Information"
      }
    }
  },
  "AllowedHosts": "*"
}
```

例えば今回は Razor Pages のプロジェクトを作ったので Index.cshtlm.cs の OnGet で以下のようなログを仕込むと…

```csharp:Index.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApplication10.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;

        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
            _logger.LogInformation("★(^_-)-☆★");
        }
    }
}
```

こんな風に出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/256c41c4-cb10-4b2b-8f9f-bb26d824f0f2.png)

## Azure にデプロイしたときは Azure の Application Insights に行くようにしたい

Application Insights を作成すると接続文字列が取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/e5b87f26-4208-c47c-613d-d94b08617fb2.png)

接続文字列を、`APPLICATIONINSIGHTS_CONNECTION_STRING` 環境変数に設定します。Azure Web Appsだと構成のアプリケーション設定で設定しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/f10e8db9-5b42-dcfe-7355-0f0794f4c07f.png)

アプリをデプロイして実行するとログが Application Insights に出るようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/52548f61-8166-8e39-5c86-2c39b5a9d2a0.png)

以下のようにクエリも出来ます。ルールを設定すれば指定の条件を満たしたときにメールなどで通知することも出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/06ed31eb-cebf-ef40-e876-dbf143ab6e72.png)

## まとめ

とりあえず必要最低限の手順はこんな感じっぽいです。
ビルトインコマンドの一覧を"見やすく"見る方法

#前書き

ビルトインコマンドの一覧を見る際のコマンドを"見やすく"見る方法をこの記事で紹介します。



#Zshの場合

以下のコマンドで一覧を見ることができます。

```zsh
% man zshbuiltins
```


#Bashの場合

以下のコマンドで一覧を見ることができます。

```bash
help -m "*" | less
```
食品開発とソフトウェア開発におけるテスト

はじめまして。サイボウズ株式会社でQAをしている[@hitomi___kt](https://twitter.com/hitomi___kt)です。
自社クラウドサービスのkintoneを開発するチームに所属しています。
QAになって2年目ですが、前職は食品メーカーで開発（食品の配合や製法を考える仕事）を担当していました。
食品開発にもソフトウェア開発にも「テスト」が存在するのですが、今回は私が感じた両者の違いと共通点をご紹介します。

## 前提
私の経験した食品開発では、開発者と企画者がペアを組んで製品開発をします。
開発者は企画者からフィードバックを受けながら試作を重ね、レシピを決定します。
決定したレシピを元にして工場で製造した製品がお客様に届けられます。
テストは主に開発者が実施します。

私の所属するチームのソフトウェア開発では、スクラム開発を採用しています。
新規機能開発の場合、プロダクトマネージャーが作るバックログを元にプログラマが実装し、QAがテストを実施します。

### 注意
ここに書く「食品開発」「ソフトウェア開発」は、あくまでも私が経験したものです。
業界・会社・製品によって異なることをご了承ください。

## 違い

### 工場の有無
食品は工場で製造されたものがお客様に届けられます。
どんなに試作段階で高い評価を得ても、工場で再現できないレシピでは製品になりません。
試作段階でもできるだけ工場を意識しますが、使う機械・製造場所の温度・製造量など違う要素も多いので、必ず工場での製造テストを実施します。
製造テストでは試作の何倍もの原材料を使う上に、工場の設備や人を動かすので、お金も時間もかかります。
何回もできるものではないので、製造テストを成功させなければ、というプレッシャーは大きかったです。

一方でソフトウェアには工場がありません。
完成したアーカイブを手元の試験環境で動かせるので、機能が実装されたらすぐにテストすることができます。
もちろん試験環境と本番環境は違うのですが、リリース予定の製品を手元で確認できる点は食品開発とは違うなと感じました。

### リリース後の変更
食品は工場で作られたら完成です。
完成後に個々の製品に対して変更を加えることは、メーカー側ではできません。（お客様側での調理やアレンジによる変更はあります）
食中毒や異物混入など命に関わる事態につながる可能性もあるので、特に安全性のテストは慎重に実施していました。

一方でソフトウェアは、各リリースバージョンにFixはあるものの最終的な完成型がありません。
特にクラウド製品では、リリース後も機能追加やバグ修正など製品に対して変更を加えることができます。
メリットとデメリットを比較しながら柔軟にリリース内容や時期を変更できる点は、食品開発とは違うなと感じました。

## 共通点

### 使用状況や時間経過による影響
食品は、保管状態や時間経過によってカビが生えたり味が落ちたりすることがあります。
そのため保管温度や時間経過による影響を検証する保存テストは必須です。（ちなみに保存テストの結果は、賞味期限・消費期限の決定材料になります）
私が経験した保存テストは数ヶ月〜半年ほどかかりました。

ソフトウェアも、使われ方や時間経過によって状態が変化します。
ソフトウェアは物理的に腐ることはありませんが、アクセス集中による負荷や蓄積したデータベースのデータ量によって問題が出ることがあります。
そのため、使用状況を意識したテストも必要です。
入社当時は「ソフトウェアは腐らないから楽な部分もあるのかな」と思っていたのですが、開発に関わる中で全くの勘違いであることに気付きました。

### 数値化できない要素
食品の味は数値化することができません。
糖度計や味覚センサーで数値化できる部分もありますが、味そのものを数字だけで表すことは難しいです。
そのため、いろいろな人に試食してもらいフィードバックをもらうことで改善点を見つけていきます。
今ふりかえると、試食もテストの1つだったなと思います。

ソフトウェアにも、使い勝手など数値化できない要素があります。
そのため、ユーザビリティテストなどでユーザーからフィードバックをもらうことで改善点を見つけていきます。
入社当時は、ソフトウェアははっきりした判断ができる要素ばかりだと思っていたのですが、開発に関わる中で違うことを知りました。

## 違いをふりかえってみて
製品の特性・開発手法・ユーザーが違えば適切なテストも違います。
一方で業界や製品が違っても、似たような目的で実施しているテストもあります。
どんなテストも、品質向上のために取り組んでいる点は同じです。
この記事を書いてみて、もしかしたらソフトウェア開発に活かせる食品開発の知見もあるかも、と気付きました。
Flutter開発で便利そうなpackageまとめ

この記事は

[CA21 Advent Calendar 2020](https://adventar.org/calendars/5308) の17日目の記事です．



私はAndroidアプリ開発を始めてまだ1年ちょっとですが，最近はiOSアプリも同時に開発したくなることが多々ありFlutterを用いた開発を行っています．

Flutterは比較的簡単ということもあり，手を出している人も多いと思いますが，私がFlutter開発していて便利だなや，Androidアプリ開発のデファクトスタンダードなライブラリと似ていてよく使われてそうだなと思うpackageをまとめたいと思います．


僕が普段Androidをやっているということもあり，Android関連の技術と比較した説明が多めです．
# アーキテクチャ
Flutterのアーキテクチャに関してはAndroidに比べるとまだ戦国時代みたいな感じがします．自分もFlutterを始めて半年くらいしか経っていませんが3つほどアーキテクチャに関してはこれが良さそうというふうに変わってきている気がします．

## provider
https://pub.dev/packages/provider

Remi Rousseletさんによって開発されたpackageです．StatefulWidgetを使ってWidgetと状態管理クラスを混ぜ合わせて状態が変わったタイミングでWidgetを更新していたものを，ViewModelをつくるようにWidget（View）と実際の状態管理している部分（ViewModel）を分けて記述できるようになります．状態管理するクラスをDIするためにも使われます．
ChangeNotifierと組み合わせて使われることも多く見ます．

## state notifier
https://pub.dev/packages/state_notifier

こちらもRemi Rousseletさんによって開発されたpackageです．ChangeNotifierとProviderを使った開発では状態を更新する際に `notifyListeners()`呼ぶ必要がありましたが，StateNotifierではそれが不要です．また，ChangeNotifierとProviderではAndroidで言うViewModelのような構成でLiveDataとそれを更新するロジックが同一のクラスに属していましたが，StateNotifierではLiveDataだけが属するimmutableなクラスとそれを更新するクラスを完全に分離することができます．

## freezed
https://pub.dev/packages/freezed

こちらもRemi Rousseletさんによって開発されたpackageです．StateNotifierで値を更新する際に毎回状態そのものを持っているimmutableなクラスを生成して更新していた手間をシュッとかけるようにしてくれます．

## riverpod
https://pub.dev/packages/riverpod

こちらもRemi Rousseletさんによって開発されたpackageです．providerの上位互換みたいなものです．グローバル変数としてproviderを宣言できるようになって従来のproviderのBuildContextの依存がなくなりとても使いやすくなりました．

## flutter hooks
https://pub.dev/packages/flutter_hooks

React HooksのFlutterバージョンのようなものです．riverpodと一緒に使われることが多いイメージです．

# ローカルDB
これに関しては@kabochapoさんがわかりやすくまとめた記事があるのでそちらを参照してもらいたいと思います．

https://kabochapo.hateblo.jp/entry/2020/02/01/144411



# 通信周り
## dio
https://pub.dev/packages/dio

AndroidのOkhttpっぽくかけるHTTPクライアントpackageみたいです．

## retrofit
https://pub.dev/packages/retrofit

名前の通り，Androidでよく使われるRetrofitにインスパイアされたFlutter版です．

## その他
## image picker
https://pub.dev/packages/image_picker

端末内に保存されている画像を選択して取ってくるやつを作れるやつです．

## url launcher
https://pub.dev/packages/url_launcher

URLをWebViewで表示するようにしたり，ブラウザアプリで表示するようにしたり，事前に定められているフォーマット通りにURLを記述すれば端末内にインストールされているTwitterアプリなどに飛ばしてくれるやつを作れます．

## intl
https://pub.dev/packages/intl

日付や数字などアプリをグローバル化してくれるpackageです．

# おわり
私もまだFlutterに手を出して日が浅いので，「こんなのもあるよ」みたいなpackageあれば教えて下さい．
## PR
内定先のCyberAgentでは22卒のエンジニア採用を行っています！

https://www.cyberagent.co.jp/careers/news/detail/id=25511
理不尽なムチャぶりを全力で回避したいエンジニアのためのサバイバル術

システム開発に携わっていると、大なり小なり理不尽なムチャぶりを食らうことがあります。
「[しわ寄せはいつもエンジニアにくる。。。](https://nlab.itmedia.co.jp/nl/articles/1404/07/news118.html)」と内心憤っている方も少なくないでしょう。

私自身はどちらかというとムチャぶりをお願いしてきた側の人間で、申し訳ない気持ちでいっぱいです。
ただ、一方でこういったムチャぶりを事前に回避し、必ず平和に着地させるすごいエンジニアの方々も数多く見てきました。

なので、今回は「もう二度と理不尽なムチャぶりは食らいたくない」と強く願うエンジニアの皆さんに向けて、平穏な日常を暮らしていく明日から使えるサバイバル術をご紹介します！

## そもそも、なぜムチャぶりを食らうのか

まず、なぜエンジニアばかりが理不尽な目に合いやすいのか。それには構造的な問題があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164449/b3005f3a-7b5d-77e9-f384-19f3210b3cb9.png)

上の図は、ユーザーに商品を提供するまでの工程（バリューチェーンと言います）を表した一例ですが、ここでは開発が一番先頭に位置します。

したがって、一番右にある顧客側で何か問題が発生していたとしても、一番左にいるエンジニアまでに伝達される情報のスピード、精度などは必然的に落ちていきます。

「急に！？」「なんで！？」と感じる **理不尽な** 要求をもらいやすいのは、ここに理由があります。

逆に言えば、それらを華麗に回避するエンジニアは、これらの構造を完璧に把握し、１つ1つ丁寧に手を打っていました。

以下、彼らが実践していた巧みなテクニックの数々を、私が思い出せる限り取り上げいきます。

## 「ゴールってなんでしたっけ？」と空気を読まずに聞き続ける

色んな役割や立場の人がいる場において、目的がずれているとどこかで必ず手戻りが発生します。
「あれ、なんか擦り合ってない？」と気づくタイミングが遅れるほど、そのリカバリーは大変です。

なので、サバイバル能力が高い人ほど、「ゴールってなんでしたっけ？」としつこいくらい聞いています。
若干空気がピリついたりするのですが、後から喧嘩になるよりはマシということです。

## 「やること」以上に、「やらないこと」を宣言する

どんな人も相手が喜んでくれると嬉しいもので、ついつい「やります！」と良いことばかり言いたくなります。
ただ、人は定義されていないことは自分に都合が良く捉えるので、「あれもやるということは、これもやってくれるよね」と勝手に解釈されがちです。

「やること」だけでなく「やらないこと」もあわせて伝える人は、「言った言わない」で後々揉めることが少なかったです。

## エンジニア以外のチームへ、「やってほしいこと」をリクエストする

ユーザーに商品を提供する工程には、マーケティングや営業など色んな役割の人が登場します。
それぞれの人が「これは俺の仕事じゃない」と思っていたとき、誰も対応しないことで最悪のトラブルが訪れます。

「こういった機能制約を、営業時に顧客へ伝えてください」と、自分以外の職種や部署へ明確にリクエストできる人はトラブル回避能力が非常に高いです。
さらに素敵なエンジニアの方は、同時に「ここはエンジニアでがんばります」といったことも言ってくれます。

## 1つの手段にこだわらない

なにかの目的を達成するには、複数の手段が存在します。
自分では一番ベストな手段だと思っていても、別の観点や立場から見るとそうでないケースも多いです。

エンジニアは手段にこだわりを持つべきですが、状況に合わせてそのこだわりさえ捨てられる人は強いです。
とくに半端ない人は、複数の手段を実は隠し持っていたりして、さて困ったぞという局面でさっと差し出してくれます。

## 具体的なものを見せながら話す

抽象的なもの、定性的なものは、どんなに丁寧にすり合わせても必ず解釈に齟齬が出ます。
各人の脳内にしかない”何か”で会話しても、実際に具体化できたタイミングで「なんか違う」が発生します。

システム開発では起こりがちなこの問題は、なるべく早くから具体を示すことで回避できます。
かといって立派なプロトタイプを用意するわけでなく、「ノートに手書きした画面イメージ」や「ざっくりとしたER図」をさっと作ってくれるエンジニアは、同じものを見ながら会話できるので安心感が違います。

## 納期を守る

納期を必ず守ってくれる人は、それだけで絶大な信頼が生まれます。
「どうせ遅れるんだろうなぁ」という前提になってしまうと、あらゆるコミュニケーションが歪みます。

信頼されるエンジニアが「難しい」と言えば、その要求は通らないので、そもそもムチャぶりが生まれません。
結果的に、納期意識が強いエンジニアは、それによって自身や自チームを守っていました。

## おわりに

簡単にまとめると、優れたエンジニアの方々は、「ユーザーに商品を提供するまでの工程」の構造を理解したうえで、「適切な期待値調整をしつづける」というサバイバル術を駆使していたように思います。
したがって、こういった観点を心がければ、理不尽なムチャぶりを事前に防げ、平穏な日々を過ごすことができるはずです。

実はエンジニア限らず、事業に関わる全員がこれらを意識していれば、めちゃくちゃ気持ちの良い職場になるのだと思います。
私自身も、そんな素敵な人たちと日々平穏に働きたいと強く願っている存在なので、そんなエンジニア組織を一緒に作りたいという人がいれば是非ご連絡をお願いします！
【cluster】イベント用にスクリーンの動作確認メモ【スクリーン機能】

# イベント用にスクリーンの動作確認メモ
- スクリーンに表示させるためには、インベントリにローカルからアップロードする必要がある。

![スクリーンショット 2020-12-17 12.14.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/8eacb206-7f23-e79d-677a-21829a64d7e4.png)

---

- PDFファイルは1ファイルで1枚ずつスライドできることが確認できた

![スクリーンショット 2020-12-17 12.15.19のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/4bbfb322-a7f1-3a7c-aa42-7a5ed9947e28.png)

---

- MP4形式の動画は、そこまで制限を気にしなくて良さそう。アップロードは気長に待つ。

![スクリーンショット 2020-12-17 12.14.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/2d79e9fe-8b86-247e-f430-e51bf322b23f.png)

---

- スライドと動画を両方ともスクリーン表示にすれば、スライド選択や動画の再生で、スクリーンが切り替わる。

![スクリーンショット 2020-12-17 12.15.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/6a049705-4f7d-c9d4-8c06-6c5c12810c00.png)

---
iTunesバックアップファイルが復元できない場合の対処法

<h2>iPhoneのiTunesからバックアップが復元できない原因と対策</h2>
<h3>iTunesのバージョンが古すぎ</h3>
<p>iTunesのバージョンが最新ではないと、iPhoneのiTunesバックアップの復元が失敗になる可能性があるので、iTunesバックアップの復元ができないと、まずは、iTunesをアンインストールし、お使いのパソコンに最新バージョンのiTunesをインストールしてやり直してください。</p>
<h3>USBケーブルの不具合</h3>
<p>USBケーブルに不具合があったら、iPhoneとiTunesとの接続が不安定になりやすいです。その結果として、接続エラーなどでiPhoneのiTunesバックアップからの復元が中断されたりします。</p>
<h3>iPhoneには十分な空き容量がない</h3>
<p>iPhoneをiTunesバックアップから復元する場合、そのiTunesバックアップが直接にiPhoneに復元されますので、iPhoneには十分な空き容量がないと、iPhoneのiTunesバックアップの復元が終わらないか、失敗になります。</p>

<p>もっと詳細の内容は、<a href="https://www.4videosoft.jp/tutorial/iphone-wont-restore-from-itunes-backup.html">iPhoneのiTunesからバックアップが復元できない原因と対策</a>までご参考ください。
【Ruby】レシーバとオブジェクトの違い。RubyのオブジェクトとJSのオブジェクトの違い

個人メモです。

- レシーバとは何か？
- レシーバとオブジェクトの違い
- RubyとJavaScriptのオブジェクトの違い

##レシーバとは何か？

メソッドの左側のデータをレシーバと呼ぶ。

`レシーバ.メソッド`


####レシーバの例

- `obj.length`の`obj`、
- `arr.present?`の`arr`をレシーバと呼ぶ。


<br>
##レシーバとオブジェクトの違い

Rubyにおけるオブジェクトは**すべてのデータ**のこと。
なので、以下はすべてオブジェクトとなる。

**オブジェクトの例**

- `100`
- `"String"`
- `{:a=>1, :b=>2}`
- `[1, 2, 3]`
- `obj = {:a=>1, :b=>2}`の`obj`
- `arr = [1, 2, 3]`の`arr`
- `range = 1..3`の`range`

つまり、レシーバとは**メソッドの対象になったオブジェクト**のことを指す。



<br>
##RubyとJavaScriptのオブジェクトの違い
一番混乱したのがコレ。JSとRubyでオブジェクトの定義が異なる。

###JSの場合
JSのオブジェクトとは、KV（キー、バリュー）のペアであるプロパティを持ったデータのこと。

例：　`obj = {a:1, b:2, c:"xxx"}`　



###Rubyの場合
Rubyの場合はすべてのデータをオブジェクトと呼ぶ。

JSでいうオブジェクトはRubyではハッシュとなる。


**▼ハッシュ（キーが文字列の場合）**
JSのオブジェクトのプロパティ名を文字列にしたもの。

例：　`obj = {"a" => 1, "b" => 2, "c" => "xxx"}`


<br>
**▼ハッシュ（キーがシンボルの場合）**
JSのオブジェクトのプロパティ名をシンボルにしたもの。

例：　`obj = {:a => 1, :b => 2, :c => "xxx"}`

<br>
JSのように、`obj = {a:1, b:2, c:"xxx"}`　と定義すると、自動でシンボルの形に変換される。

```ruby:ruby
obj = {a:1, b:2, c:"xxx"}
=> {:a=>1, :b=>2, :c=>"xxx"}
```
VirtualBox5系から6.2へ移行して、イメージが起動できなかった件

## はじめに

つい最近まで、なまくらでVirtualBoxを5系で動かしていて、
とうとうWindows10の警告で使えなくなりました。

![rapture_20201217110718.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6846/140474d4-16f4-24c0-30fa-34a7ec6749ac.png)

小手先の回避してもしょうが無いため、最新の6.2系のVirtualBoxに移行しました。
その際に、発生したイメージ起動時のエラーの件を残します。

## 事象

VirutalBoxが起動すると、Windows10 プログラム互換性アシスタントが表示する実行できないという上記のダイアログの「詳細情報」をクリックすると[こちら](https://www.virtualbox.org/wiki/Download_Old_Builds_5_2)に案内されました。
そこから、VirtualBoxの6.2系は、Downlodsメニュー（公式のVirtualBoxサイトのメニュー）をクリックしてダウンロードしてインストールしました。
この際、旧バージョンを消さずそのままインストールしました。

インストール自体は問題なく完了し、
VirutalBox.exeを起動して、コンソールでイメージを起動したところVirtualBoxの起動エラーが発生。
発生したエラーは、起動時のログ・ファイル（VirtualBoxの起動失敗時の詳細情報に記載されているログ・ファイル）に各種出力されていましたが、今回着目したのは最初に出力されていたように見えた下記でした。

```
Error -626 in supR3HardenedWinReSpawn! (enmWhat=3) 
```

## 解決策

1. インストールしたVitualBoxをアンインストールして、
2. VitualBoxのインストーラーの実行時に、右クリックのドロップダウンから__「管理者権限で実行」__を選択してインストールし直した。

以上。

## 参考にしたサイト

結局Google の2つ目結果で解決してしまったため、根本的な原因について調べられていないため、本ページでは記事ではふれません。
とりあえず、きっかけになったサイトだけ記録。

（通常は移行自体にエラーは起こらないみたいということを感じた記事。バージョンが違いますがメジャーバージョンでの影響はほぼないと判断）
https://freebsd.sing.ne.jp/tool/08/02/01/03/03.html

（着目したエラー文言で検索してヒットした2つ目）
[Solved] Problem with VirtualBox 6.0.14 hardening
https://forums.virtualbox.org/viewtopic.php?f=6&t=95246

こちらのコメントの3つ目で、解決策に記載した方法でうまく言ったと質問の当人が書いているので、半信半疑でためしたらうまくいきました。

## その他

別記事でウィルスソフトを止めてとかアンインストールしてとかやってうまくいった記事はありましたが、それは関係なかったのでよかった。
GKEアップグレード通知をメールで受信する

# 概要
[GKEのアップグレード通知をPub/Subで公開する機能](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-upgrade-notifications?hl=ja)がベータ版で用意されているため、
その機能を使用して、GKEアップグレード通知をメールで受信する方法を記述する。

下記のサービスを使用する。
・GKE
・Cloud Pub/Sub
・Cloud Functions
・Stackdriver Logging
・Stackdriver Monitoring

# 設定手順

## Pub/Subのトピックを作成する

```
gcloud pubsub topics create gke-upgrade-notification
```

## GKEのアップグレード通知を有効にする

```
gcloud beta container clusters update <クラスタ名> --notification-config=pubsub=ENABLED,pubsub-topic=projects/<PROJECT_ID>/topics/gke-upgrade-notification
```

## Cloud Functionsの関数を作成する

トリガーを Cloud Pub/Sub にし、作成したトピック [gke-upgrade-notification] を指定する。

```golang:functions.go
package p

import (
	"context"
	"fmt"
	"log"
)

// PubSubMessage is the payload of a Pub/Sub event. Please refer to the docs for
// additional information regarding Pub/Sub events.
type PubSubMessage struct {
	Data       []byte           `json:"data"`
	Attributes PubSubAttributes `json:"attributes"`
}

type PubSubAttributes struct {
	Payload string `json:"payload"`
}

func OutputLog(ctx context.Context, m PubSubMessage) error {

	// output log
	log.Print(fmt.Sprintf("GKE Upgrade start. Data: %s", string(m.Data)))
	log.Print(fmt.Sprintf("GKE Upgrade start. Payload: %s", m.Attributes.Payload))

	return nil
}
```

## StackdriverLoggingのログベース指標 [info-gke-upgrade] を作成する

```
resource.type="cloud_function" 
AND resource.labels.function_name:"OutputGKEUpgradeLog" 
AND textPayload:"GKE Upgrade start."
```

![スクリーンショット 2020-12-17 12.07.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436850/5a59f760-faf0-de23-542a-e95d30a3876e.png)

## StackdriverMonitoringのアラートを作成する

ログベース指標 [info-gke-upgrade]に基づいてアラートを作成する。
任意のメールアドレスをアラート通知先に設定する。

![スクリーンショット 2020-12-17 12.08.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436850/f7e2b3c6-0b4f-e0ae-5a7d-ca5086c18a79.png)
![スクリーンショット 2020-12-17 12.08.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436850/b515f2c7-854e-10c7-1d17-2bc7aace1ca0.png)

# 動作検証

クラスタのノードプールをアップグレードする。

```
gcloud container clusters upgrade cluster --cluster-version <VERSION> --node-pool <NODE_POOL>
```

アラートで設定したメールアドレスに通知が届く。

# ソースコード

本記事の検証用ソースコードは[こちら](https://github.com/hikarusi/gke-upgrade-detector)
【WordPress】Breadcrumb NavXTでリストの途中に項目を追加する（リンクも追加）

[Breadcrumb NavXTでリストの途中に項目を追加する \- Qiita](https://qiita.com/kuninori-ogino/items/19a95077c277dce57fec)を見て追加してみたものの、リンクが追加されなかったので追加できるようにしてみました

## 何が足りないかを調べる
```php
〜
$breadcrumb->set_url(home_url('test/'));
//追加したい要素の情報をvar_dumpで表示
var_dump($breadcrumb);
```
↓

```php
linked: false
```

こちらがtrueじゃないとリンクしないようでした

## コードの書き換え
```php5

var_dump($breadcrumb);
//↓変更
$breadcrumb->set_linked(true);
```

これで無事リンクにできました
[CDK] Amplifyアプリのビルドエラー(AccessDeniedException)の対処

## 初めに
AWS CDKを利用しAmplifyのアプリケーションを作成した際に
ソースコードのビルドでAccessDeniedExceptionが発生し、ビルドに失敗する事がありました。

権限を追加するだけなのですが、自動で権限設定をしてくれず、あれ？と思ったため
対処法をメモしておきたいと思います。

## エラー内容

エラー内容は抜粋していますが、以下のようなエラーです。

```
Amplify AppID: hoge not found. Please ensure your local profile matches the AWS account or region in which the Amplify app exists.
AccessDeniedException: User: arn:aws:sts::123456789012:assumed-role/[role]/BuildSession is not authorized to perform: amplify:GetApp on resource: [arn]
```

## エラーの原因と解決法

以下のように指定しており、roleパラメータは`Default: - a new role is created`と記載されていていたため、指定していませんでした。

```python
amplify_app = amplify.App(
    self, 'amplify-app',
    app_name=app_name,
    source_code_provider=source_code_provider,
    basic_auth=basic_auth
)
```

結論としては権限が足りないので自分でroleを追加してあげることで対応できます。

```python
role = iam.Role(
    self, 'amplify-app-role',
    assumed_by=iam.ServicePrincipal('amplify.amazonaws.com'),
    managed_policies=[iam.ManagedPolicy.from_aws_managed_policy_name('AdministratorAccess-Amplify')]
)

amplify_app = amplify.App(
    self, 'amplify-app',
    app_name=app_name,
    source_code_provider=source_code_provider,
    basic_auth=basic_auth,
    role=role
)
```

以上です。
roleの設定はほぼ必須？ということがわかりました。
[Git] SourceTreeでLogon failed, use ctrl+c to cancel basic credential promptを解決する方法（for windows）

# 問題

SourceTreeでPUSHをする際に、Logon failed, use ctrl+c to cancel basic credential promptが発生したのでPUSHができない。

## 解決方法

Gitをアップデートをする。

`git update-git-for-windows`

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619610/b14fb90c-5bf5-9af0-2ffb-d18f912c9eee.png)

インストールする画面が表示されると全部デフォルト値のまま、インストールをする。
ofShaderに同タイプのシェーダープログラムを複数食わせる

OpenGLでは、一つのプログラムに複数のシェーダーを含めることができます。

```GLSL:module.glsl
#version 410
float someFunction() {
    return 1.0;
}
```
```GLSL:main.vert
#version 410
float someFunction(); // 実装はmodule.glslにあるので宣言のみ
void main() {
    gl_Position = vec4(someFunction());
}
```

```C++
auto attachShader = [](GLuint program, GLenum type, std::string filepath) {
    GLuint shaderObj = glCreateShader(type);
    std::string source = loadStringFromFile(filepath); // なんかファイル読み込み処理
    const char* sptr = source.c_str();
    int ssize = source.size();
    glShaderSource(shaderObj, 1, &sptr, &ssize);
    glCompileShader(shaderObj);
    glAttachShader(program, shaderObj);
    glDeleteShader(shaderObj);
};
// ひとつのシェーダープログラムに複数のバーテックスシェーダーオブジェクトをアタッチする
GLuint program = glCreateProgram();
attachShader(program, GL_VERTEX_SHADER, "module.glsl");
attachShader(program, GL_VERTEX_SHADER, "main.vert");
```

ところが、これをofShaderでやろうとすると動きません。

```C++
ofShader shader;
shader.setupShaderFromFile(GL_VERTEX_SHADER, "module.glsl");
shader.setupShaderFromFile(GL_VERTEX_SHADER, "main.vert");
shader.linkProgram();
```
```txt:エラー出力
[ error ] ofShader: checkProgramLinkStatus(): program failed to link
[ error ] ofShader: ofShader: program reports:
ERROR: No definition of someFunction in vertex shader
```

これは、ofShaderがシェーダーのタイプ(`GL_VERTEX_SHADER,GL_GEOMETRY_SHADER,GL_FRAGMENT_SHADER,GL_COMPUTE_SHADER`)毎にひとつしかソースを保持しない作りになっていることが原因です。

```C++:ofShader.h(抜粋/注釈)
// https://github.com/openframeworks/openFrameworks/blob/0.11.0/libs/openFrameworks/gl/ofShader.h#L272
class ofShader {
    ...
    // GLenumがシェーダータイプ。unordered_mapなので各タイプ毎に一つしかShaderを保持できない
    std::unordered_map<GLenum, Shader> shaders;
    ...
};
```
```C++:ofShader.cpp(抜粋/注釈)
// https://github.com/openframeworks/openFrameworks/blob/0.11.0/libs/openFrameworks/gl/ofShader.cpp#L375
bool ofShader::setupShaderFromSource(ofShader::Source && source){
    ...
    // 同じタイプのシェーダーを複数setupしようとすると、ここで前のが上書きされる
    shaders[source.type] = { shaderId, std::move(source) };
    ...
}
```

ということなので、ofShader::shadersを使わずに`glAttachShader`してやればOKですね。

```C++
auto attachShader = [](ofShader &shader, GLenum type, std::string filepath) {
    GLuint shaderObj = glCreateShader(type);
    std::string source = ofBufferFromFile(filepath).getText();
    const char* sptr = source.c_str();
    int ssize = source.size();
    glShaderSource(shaderObj, 1, &sptr, &ssize);
    glCompileShader(shaderObj);
    glAttachShader(shader.getProgram(), shaderObj);
    glDeleteShader(shaderObj);
};
ofShader shader;
shader.setupShaderFromFile(GL_VERTEX_SHADER, "main.vert");
attachShader(shader, GL_VERTEX_SHADER, "module.glsl");
shader.linkProgram();
```

これでエラーなくシェーダープログラムがリンクできました。
もちろん普通に`ofShader::begin`と`ofShader::end`で使えます。

ちなみに、`setupShaderFromFile`と`attachShader`の順序を逆にすると、`shader.getProgram()`が空なので正しく動きません。
`ofShader(GLuint program)`みたいな初期化ができると良いんですが・・・。

なお、ofShaderは独自で`#include`をサポートしていてくれたり、OpenGLにも拡張機能で`ARB_shading_language_include`があったりしますので場合によってはそちらの方が使いやすいかもしれません。
VSCodeのターミナルがめちゃ重かった

## 環境

![macOS-11.1](https://img.shields.io/badge/macOS-11.1-brightgreen)

![VSCode-1.52](https://img.shields.io/badge/VSCode-1.52-brightgreen)

## 事象

-   shift+controll+@でターミナルを開くと起動に 2 秒くらいかかる

-   タブキーを押しての入力補完で毎回ラグる

-   ssh した時に特に重くなる

## 解決方法

公式の Issue を参照（Issue 数すごい・・・）

https://github.com/microsoft/vscode/issues/108590

以下のコマンドを実行したら直った

```
codesign --remove-signature /Applications/Visual\ Studio\ Code.app/Contents/Frameworks/Code\ Helper\ \(Renderer\).app
```

ちなみに Insiders 版は下

```
codesign --remove-signature /Applications/Visual\ Studio\ Code\ -\ Insiders.app/Contents/Frameworks/Code\ -\ Insiders\ Helper\ \(Renderer\).app
```

**誰かどういう理屈なのか教えてください（ぴえん）**
Macゴミ箱から削除されたテータの復元方法

<h2>方法 1:「Time Machine」でMacのゴミ箱のデータを復元</h2>
<p>Step 1:アップルメニューから「システム環境設定…」をクリック</p>
<p>Step 2:システム環境設定ウィンドウ画面で Time Machine をクリック</p>
<p>Step 3:「Time Machine」環境設定を「入」になっているかチェック</p>
<p>Step 4:右上メニューバーのTime Machineメニューから「Time Machine に入る」をクリックすると、Time Machine のフォルダウィンドウの右側にバックアップデータの日付が現れます</p>
<p>もっと詳細の内容は、<a href="https://www.aiseesoft.jp/tutorials/dustbin-recover-mac.html">「Time Machine」で削除したデータを復元する</a>までご参考ください。</p>
<h2>方法 2:専用の復元ソフトでMacのゴミ箱のデータを復元</h2>
<p><a href="https://www.aiseesoft.jp/data-recovery/">「Aiseesoft Macデータ復元」</a>はパソコンや外付けHDDなどの設備から写真、動画、音楽、ドキュメント等のデータを安全に復旧できるソフトです。削除だけでなく、HDDクラッシュ、RAWハードドライブなどの原因でパソコンのデータが消えてしまいましたら、データ復元ソフトは簡単にデータを復元できます。</p>
<p>もっと詳細の内容は、<a href="https://www.aiseesoft.jp/data-recovery/tutorial.html">「Time Machine」で削除したデータを復元する</a>までご参考ください。</p>
【WordPress Ping Optimizer】PHPを7.2以上にするとエラー文が表示される解決方法

PHPを7.2に上げると、プラグインの「WordPress Ping Optimizer」の不具合でページ上部にエラー文が表示される現象が起こります。

この記事では、そのエラーの原因と解決方法について解説していきます。

<h2>WordPress Ping Optimizerのエラー文がページ上部に表示される原因</h2>
![IMG_5866.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564199/e482a63d-e132-ee32-3985-86e8ffe3580c.jpeg)
ページ上部にエラー文が表示される現象についてですが、以下のように表示されていると思います。
<code>Warning: count(): Parameter must be an array or an object that implements Countable in /home/ホスト名/ドメイン名/public_html/wp-content/plugins/wordpress-ping-optimizer/cbnet-ping-optimizer.php on line 533</code>
このエラー文を読むと、WordPress Ping Optimizerの「cbnet-ping-optimizer.php」というファイルの533行目に問題があるということがわかります。

これはWordPress Ping OptimizerのプラグインとPHPの7.2の仕様の不具合によって起こっているエラーです。
<h2>WordPress Ping Optimizerのエラーの解決方法</h2>
![ada8e5098f69c4d2ce9f604c0c001efc.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564199/1ed30bc1-8529-78ac-8bba-732e7f70557b.jpeg)
エラーとなっているコードを書き換えることでエラーを解決することができます。

まず、コードを書き換える前にWordPress Ping Optimizerのプラグインを停止してください。

FTPソフトを通して書き換えるのがいいですが、WordPressのダッシュボードからも書き換えることができます。
<h3>問題のコードを書き換える</h3>
![1b2105ca686f7b9d095c180a331693aa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564199/79ff839f-f960-cd13-4126-2158dfe184ad.jpeg)

「プラグイン」→「プラグインエディター」と進みます。
そして、「編集するプラグインを選択」という場所で「WordPress Ping Optimizer」を選択して「選択」をクリック。

533行目にある以下のコードを修正します。
<pre class="lang:php decode:true "><code>$pingCount=count($this-&gt;cbnetpo_future_pings);</code></pre>
このコードをを以下のように書き換えてください。
<pre class="lang:php decode:true "><code>$pingCount = $this-&gt;cbnetpo_future_pings ? count( $this-&gt;cbnetpo_future_pings ) : 0;</code></pre>
書き換え終わったら、プラグインを有効化します。

これでページ上部に表示されていたエラー文はなくなります。
<h2>WordPress Ping Optimizerのエラー文の解決方法まとめ</h2>
PHPを7.2にアップデートしたときに「WordPress Ping Optimizer」のプラグインが原因でページ上部にエラー文が表示される解決策を説明しました。


WordPress Ping Optimizerをアップデートしたら、書き換えたコードは元通りになってしまうので注意してください。!