OmniAICreator/Qiita-1.07M huggingface dataset:
Cloud Storage for Firebaseで特定のユーザーのみ画像をアップロードできるようにする方法

## はじめに

@hecateballさんに[カスタムクレーム](https://firebase.google.com/docs/auth/admin/custom-claims?hl=ja)のが良いと教えていただいたので[カスタムクレーム](https://firebase.google.com/docs/auth/admin/custom-claims?hl=ja)要検証

下記のやりかたはよろしくないかもしれないです。

結論から言ってしまうと、「Firebase Admin SDKを用いてCloud Functions経由でやる」です。
＊ Firebase Admin SDKが使えれば別にCloud Functionsじゃなくてもよいです。

## なぜCloud Storage for Firebaseのセキュリティルールで制限しないのか
誰もが真っ先に考えるのは「Cloud Storage for Firebaseのセキュリティルールで制限する」ってパターンだと思います。しかし、「管理者のみが画像をアップロードできる。管理者かどうかの判断ははadminsコレクションのドキュメントIDで判断する。」というような形でFirestoreを利用している場合には、Cloud Storageのセキュリティルールで制限することはできません。というのもCloud Storageのセキュリティルール内からFirestoreを参照する方法がないからです。exists関数でFirestoreを参照するといったようなことはできません。（できるのだったら教えてほしい）

## 解決策
「はじめに」で述べている通りFirebase Admin SDKを用いてCloud Functions経由でやります。
> 「管理者のみが画像をアップロードできる。管理者かどうかの判断はadminsコレクションのドキュメントIDで判断する。」

雑ですが、上記の要件は具体的には下記のような感じで実装します。
認証されたユーザーか確認して、認証されたユーザーであれば、adminsコレクション確認して存在してれば画像をアップロードするって感じで動きます。

```ts
import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import { Buffer } from 'buffer'
import uuidv4 from 'uuid/v4'

const createCallHttps = (region: string) =>
  functions.region(region).https.onCall

const callHttps = createCallHttps('asia-northeast1')

export const uploadImage = callHttps(
  async (data, context): Promise<{ imageId: string }> => {
    const { auth } = context
    if (!auth) {
      throw new functions.https.HttpsError(
        'unauthenticated',
        'authentication required'
      )
    }

    return await uploadImageFunc({ ...data, userId: auth.uid })
  }
)

const app = admin.initializeApp()

interface UploadImageProps {
  userId: string
  fileId: string
  base64EncodedImage: string
  imageableId: string
  imageableType: string
}

export const base64EncodedImageToBuffer = (image: string) => {
  const [meta, body] = image.split(',')
  const matched = meta.match(/data:(.*)\;/)
  if (!matched) throw new Error('may not base64 encoded image')
  const buf = Buffer.from(body, 'base64')
  return { buf, extension: matched[1] }
}

const uploadImageFunc = async ({
  userId,
  fileId,
  base64EncodedImage,
  imageableId,
  imageableType
}: UploadImageProps) => {
  const db = app.firestore()
  const bucket = app.storage().bucket()

  const adminUser = await db
    .collection('admins')
    .doc(userId)
    .get()
  if (!adminUser.exists) throw new Error('admin not found')
  const { extension, buf } = base64EncodedImageToBuffer(base64EncodedImage)
  const imageId = uuidv4()
  const file = bucket.file(`/images/${imageId}`)
  await file.save(buf, { metadata: { contentType: extension } })

  await db
    .collection('images')
    .doc(imageId)
    .set({ fileId, imageableId, imageableType })

  return { imageId }
}
```

## 終わりに
一般的にありそうなパターンだからできればセキュリティルールでできてほしい。
あとCloud FunctionsのNodeのv10がGAになってほしい。

## 参考情報
* [Is it possible to set storage rules using firestore of Firebase?](https://stackoverflow.com/questions/49053399/is-it-possible-to-set-storage-rules-using-firestore-of-firebase)
* [Firebase Security Rules for Cloud Storage Reference](https://firebase.google.com/docs/reference/security/storage)
関数について

[JavaScript本格入門](https://www.amazon.co.jp/dp/477418411X/ref=cm_sw_r_tw_dp_U_x_wxAJCbT3GGKT9)(ISBN 978-4774184111)で基礎からJavaScriptを勉強するシリーズです。今回はChapter4から関数についてです。

# 関数の定義

方法は主に4つあります。

1. function命令を使う
1. Functionコンストラクタを使う
1. 関数リテラル表現を使う
1. アロー関数(ES2015)を使う

しかし結論として、日常的に使うのは**アロー関数**でよさそうです。

## function命令を使う

```js
function 関数名(引数) {
  関数本体
};
```

```js:例
function myFunc(arg) {
  return arg * arg;
};
let squared = myFunc(3);
console.log(squared);     // 出力:9
```

有名なfunction命令を使った関数定義ですが、静的な構造の宣言であったり意外とトリッキーな動きをします。宣言していないのに関数が使えるような動きをするので**バグを生みやすいので使わないほうがいいです。**

```js:コード解析時に関数の登録が行われるので、先に使おうとしても使える
let squared = myFunc(3);
console.log(squared);     // 出力:9

function myFunc(arg) {
  return arg * arg;
};
```

## Functionコンストラクタを使う

```js
let 変数名 = new Function('引数','関数本体');
```

```js:例
let myFunc = new Function('arg','return arg*arg');
let squared = myFunc(3);
console.log(squared);
```
実行時に文字列をコードとして実行するのは、eval()等と同じく**セキュリティ的によくないので使わないほうがいいです。**

## 関数リテラル表現を使う

```js
let 変数名 = function(引数) {関数本体};
```

```js:例
let myFunc = function(arg) {
    return arg * arg;
}
let squared = myFunc(3);
console.log(squared);
```
function命令を使った場合と似ていますが、無名関数を定義してから`myFunc`という変数に格納しています。
後述のアロー関数が使えない場合はこれを使うのがベターだと思います。

```js:function命令とは違い静的な関数定義とはならない
let squared = myFunc(3);      // ReferenceError: myFunc is not defined　となる
console.log(squared);

let myFunc = function(arg) {
    return arg * arg;
}
```


## アロー関数を使う

ES2015からはアロー関数によるユーザー定義関数が使えます。
functionに比べて、静的な宣言にならず挙動は幾分分かりやすいです。
またthisが固定化されるといった特徴もあります。
利用可能なら**基本的にはアロー関数での定義を使う方がよさそうです。**

これにより、関数の挙動が分かりやすく、バグを減らすことにつながりそうです。

```js
let 変数名 = (引数1, 引数2, ...) => { 関数本体 };
```

```js:例
let getTriangleArea = (base, height) => {
  return base * height / 2;
};
console.log(getTriangleArea(5, 2));
```
引数が1つの場合、括弧が不要だったり色々省力出来ます。

# 関数はデータ型の一種

JavaScriptの世界では、**関数は変数のデータ型の一種**です。

```js
function myFunc1(arg) {                             // 1の方法
  return arg * arg;
};
console.log(typeof myFunc1);

let myFunc2 = new Function('return arg * arg;');    // 2の方法
console.log(typeof myFunc2);

let myFunc3 = function(arg) {                       // 3の方法
    return arg * arg;
};
console.log(typeof myFunc3);

let myFunc4 = () => {                               // 4の方法
    return arg * arg;
};
console.log(typeof myFunc4);
```

```:実行結果
function
function
function
function
```

関数とは言えデータ型のの1種なので、別の型のリテラルを代入すると変数は別の型になります。

```js
function myFunc(arg) {
  return arg * arg;
};
console.log(typeof myFunc);     // 出力:function

myFunc = 1;                     // 数値型のリテラルを代入
console.log(typeof myFunc);     // 出力:number
```
herokuでProximoを使って固定IPを取得する方法

# TL;DR

IP制限がかかっている環境にherokuからリクエストを送りたい場合に、
固定IPが必要になるケースにて、proximoが役に立つという話

# 環境

- rails '5.2.3'
- ruby '2.5.2'

# Setupドキュメント

本家を参考にすすめる、以下必要な手順をピックアップして記載する
https://devcenter.heroku.com/articles/proximo

## Addonをとりこむ

`$ heroku addons:create proximo:development`

planは5ドルからスタートする

登録後に、herokuの環境変数PROXIMO_URLが追加されており、PROXYにつづく数字が固定IPとなっている

PROXYのURLは コンソールからも確認できる

`$ heroku config | grep PROXIMO_URL`

```
http://proxy:d898e01dc292431cbbbf3c79993de7d9@proxy-54-83-47-xx.proximo.io
```

この場合は、`54.83.47.xx`が固定IPとなる

## ProximoWrapperをRailsにとりこむ

Railsで使えるように、以下のようにcurlでファイルを取得する

```
$ cd ~/myapp
$ curl http://downloads.proximo.io/proximo-stacklet.tgz | tar xz
```

ここでCommitしろとマニュアルにはかいているのだが、

`vendor/dante`が、herokuにpushするとき、

私の環境だけかもしれないが、以下のようなエラーがでたので、vendor配下を使わないようにする。

```
unexpected token at 'ERROR: ld.so: object 'libdl.so' from LD_PRELOAD
```

`$ mv vendor/dante proximo/dante`

としてpathを変更した。
それに伴い、bin/proximo内のvendorパスを上記で変更したパスに変更してCommitした

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73202/3e9fa0a0-711d-722b-c006-443a518538b9.png)

## Procfileを作成

bin/proximoを頭につける。

```:Procfile
web: bin/proximo bin/rails server -p $PORT -e $RAILS_ENV
```

別途workerが必要な場合は同じように対応する


# 固定IP確認

検証方法はなんでもよいのだが、簡易的にダミー環境を作成してそこにhttpリクエストをとばすことで確認する


```:lib/tasks/ip_debug.rake 
require "rest-client" # gemで追加する

desc "Test static ip"
task :dummy_request, :environment do
  RestClient.proxy = ENV["PROXIMO_URL"] if ENV["PROXIMO_URL"]
  RestClient.get(ENV["PROXIMO_REQUEST_TEST_URL"])
end
```

`PROXIMO_REQUEST_TEST_URL`には、例えば、ngrokなどをつかって外部エンドポイントをローカルにとりこむのが
はやいだろう。さらにそのエンドポイントにbinding.pryを仕込めば、requestをデバッグできる。

- ダミーリクエスト実行

`$ heroku console rake dummy_request`


- リクエスト受け先のRails

homeコントローラのtopをルートにしている


```:app/controllers/home_controller.rb
class HomeController < ApplicationController
  def top
    binding.pry
  end
end
```

- 無事固定IPにてリクエストしていることを確認

```
$ request.remote_ip
=> "54.83.47.xx"
```
netlifyのキャッシュ削除方法


まずプロジェクト管理画面に行きます

![スクリーンショット_2019-07-08_09_42_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115687/4627fb36-72e1-eb06-1c92-139560f58d44.png)

`Deploys` を選択

![スクリーンショット_2019-07-08_09_43_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115687/21775d60-1644-f0e0-5cc7-eabf7ac22c36.png)

`Trigger deploy > Clear cache and deploy site`を選択すればキャッシュを削除できます。
記事の新着情報をSlackに通知するフローを考えてみた（サーバーレス）

# 概要
Slackを盛り上げようと思って、定期的に記事の新着情報をSlackに流したい。
ただサーバは持ちたくない。コストかかるし。
サーバレスでコスト安くうまくできないかなーと思って考えた。

# 利用ツール

- AWS CloudWatch
  - 定期的にlambdaのスクリプトを呼び出す
- AWS Lambda
  - CloudWatchで呼び出される
  - 主な処理部
  - pythonで実装
- AWS DynamoDB
  - 過去のスクレイピング情報の保管
  - PynamoDBを利用
- lambda_uploader
  - ワンクリックデプロイを実現！

## 処理フロー
1. AWS CloudWatch
    1. Lambdaの処理を呼び出す
1. AWS Lambda
    1. 過去のスクレイピングデータをDynamoDBから取得
    1. 現ページに記載されている情報をスクレイピング
    1. 過去登録されているかどうかを比較
    1. 登録されていないデータをDynamoDBへ登録
    1. 登録されたデータをSlackへ通知


# まとめ
詳しくはリポジトリ参照ください。
https://github.com/tashua314/fun_slack_lambda

# TODO
- モデル周りがこれだけだとわかりにくいかも。もうちょっとドキュメント周り調整する。

# 所管
ありがちなフローな気がするけど同じ構成で全て通して作ってる人の記事があまりなかった。

NoSQLをまだあまり使ってないので使用方法がこなれてない感にやきもきで思ったより時間かかってしまった。
hash_keyとかrange_keyとかの概念をようやく掴めてきた。

複数のサイトのスクレイピングにも対応できるよう作ったつもりだが、いけそうかな・・？

CloudWatchを今までログ確認用としか使ってなかったけど、cronのようなスケジューラとしても使えるんじゃん。
活用の幅が広がりそう。

コストを考えたらDynamoさんじゃなくてスプレッドシートをDB代わりにしてもまぁできたっちゃできたが、後悔はしていない。

今回のDynamoDBの使い方としては微妙な気もする。
一応記事データ溜め込んでるけど、そういうのじゃなくて、
「状態管理」的な方が使い方としては的確な気がする。

クエリの作成がRDBMSより自由度が無いし。

今回でいうと、溜め込んでる分ってあまり意味がなくて、
「最後に取り込んだデータ」が何かさえわかれば正常に稼働する。
GitLab CIで指定ブランチのマージリクエスト作成時（マージ前）にパイプラインを動かす方法

共用開発／ステージング／本番と環境を使い分けているのですが、共用開発まではデバッグビルドのためスルーされていたエラーがステージングへのデプロイ時の本番ビルドでエラーとなってデプロイに失敗するということが多々ありまして。（使ってない変数が存在する等。。。）

そんなしょうもないエラーを解決するためにまたローカル環境からやり直すのは時間の無駄だな～。もっと早い段階で潰したいな～。と思って調べてみたら、指定ブランチのマージリクエスト作成時にパイプラインを動かす方法があったので試してみました。




# 〇環境
- ローカル環境（feature/～ブランチ）
- 共用開発環境（developブランチ）
- ステージング環境（stagingブランチ）　※HEROKU
- 本番環境（masterブランチ）　　　　　 ※HEROKU

## プロジェクト構成
Node.js＋Angular＋Express.js




# 〇マージリクエスト作成時にパイプラインを実行する方法

[GitLab Docs](https://docs.gitlab.com/ee/ci/merge_request_pipelines/)に載ってました。

```.gitlab-ci.yml
test:
  stage: test
  script: ./test
  only:
  - merge_requests
```
これでマージリクエスト作成時にパイプラインが走るようになります！

が。。。
今回はdevelopブランチへのマージリクエスト作成時のみ実行したいのですが、上記の指定だと全ブランチへのマージリクエスト作成時にパイプラインが実行されてしまいます:sob:


## ◆ブランチ指定

色々探していたら、[Stack Overflowの記事](https://stackoverflow.com/questions/52746338/in-gitlab-ci-is-there-a-variable-for-a-merge-requests-target-branch)に書いてありました。

`$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"`のように指定できるみたいです！

```.gitlab-ci.yml
test:
  stage: test
  script: ./test
  only:
    refs:
        - merge_requests
    variables:
        - $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"
```

これで、developブランチへのマージリクエスト作成時のみパイプラインが動くようになります:laughing:


# 〇まとめ

こんな感じでマージリクエスト作成時にパイプラインを動かすことが出来ました。
これで、マージリクエスト作成時（マージ前）にビルド確認ができるので、手戻りが少なくなりました:relaxed:
また、テストの実施もできるため、ちゃんとテストが通ってからレビュー依頼を出すという運用にでき、レビュー工数の削減やデグレの早期発見にもつながるかと思います。



# 参考
[Pipelines for Merge Requests](https://docs.gitlab.com/ee/ci/merge_request_pipelines/)
[In GitLab CI, is there a variable for a Merge Request's target branch?
](https://stackoverflow.com/questions/52746338/in-gitlab-ci-is-there-a-variable-for-a-merge-requests-target-branch)
PHP リフレクション　メモ

# 概要

> 情報工学においてリフレクション (reflection) とは、プログラムの実行過程でプログラム自身の構造を読み取ったり書き換えたりする技術のことである。　

# 目的
> 自由にコンストラクタ等を扱えること

# PHPメモ
>  (PHP 5, PHP 7)
ReflectionClass::newInstance — 指定した引数でクラスの新しいインスタンスを作成する

[https://www.php.net/manual/ja/reflectionclass.newinstance.php]
(https://www.php.net/manual/ja/reflectionclass.newinstance.php)

> (PHP 5, PHP 7)
ReflectionClass::getConstructor — クラスのコンストラクタを取得する

[https://www.php.net/manual/ja/reflectionclass.getconstructor.php](https://www.php.net/manual/ja/reflectionclass.getconstructor.php)

# 参考
> オブジェクト指向的には以下のjavaの例があるため、上記PHPメモの関数に置き換えて考えれば実現可能

[https://qiita.com/manahirosan/items/32da2cc9f5f03dc454ca](
https://qiita.com/manahirosan/items/32da2cc9f5f03dc454ca)

> PHP リフレクションについて（公式）

[https://php.net/manual/ja/book.reflection.php](https://php.net/manual/ja/book.reflection.php)
php-master-changes 2019-07-07

今日は Azure Pipelines の設定修正、ドキュメントの更新、ビルドシステムのリファクタリングがあった！

# 2019-07-07
## nikic: Disable jit on msan job
- https://github.com/php/php-src/commit/8e948204f971c5bf6b8eea4dfb1c8ba7a80b30a2
- Azure Pipelines の設定で、msan 有効のジョブでは JIT を無効化するよう修正
- こけ始めたので無効化することにしたけど、instrumentation 効かないので逆に何でこれまで動いてたんだみたいなのがあるみたい

## nikic: Mention that zend_parse_parameters should not be tested
- https://github.com/php/php-src/commit/7514b5d91c01eee72837727e853183869a156a7f
- [7.4~]
- CONTRIBUTING.md で、ZPP のテストはもうこれ以上要らないよと追記し、`--CREDITS--` セクションも git で書いた人取るので要らないよというむね追記

## petk: Remove some more Apache 1 left overs
- https://github.com/php/php-src/commit/49cc2a63b31f9b749f1fb3b26f568ad87c3ff17d
- [7.4~]
- ビルドシステムで、apache 1 だの 2.0 だのへ言及している古い記述を修正

## petk: Remove PHP_DEBUG_MACRO
- https://github.com/php/php-src/commit/3bde4838f47c4800ac4b9efb23e320d9fdcec638
- [7.4~]
- ビルドシステムで、使われていないマクロ PHP_DEBUG_MACRO を削除
[Vue.js]input fileで選択した画像のプレビューを表示する

# Vue.jsでinput type="file"で選択した画像プレビューを表示

## Example1
サンプル

```vuejs
<template>
  <div>
     <input type="file" ref="file" @change="setImage"/>
     <img :src="data.image">
  </div>
</template>
<script>
export default {
  data() {
    return {
      data: {
        image: "",
        name: "",
      }
    };
  },
  methods: {
    setImage(e) {
      const files = this.$refs.file;
      const fileImg = files.files[0];
      if (fileImg.type.startsWith("image/")) {
        this.data.image = window.URL.createObjectURL(fileImg);
        this.data.name = fileImg.name;
        this.data.type = fileImg.type;
      }
    },
    
  }
};
</script>

```

初めに、`` <input type="file" ref="file" />``でref=で適当に名前をつけてあげます。
そして``@change``で画像の選択時に``setImage``を発火させています。
``this.$refs.file``で画像のようなdomが参照できるのでそこから画像dataをひっぱって来るようにしています。
![スクリーンショット 2019-07-08 7.27.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261676/a3bb5f7f-e1bd-46d0-0726-319dc4d7f305.png)

最後に、``window.URL.createObjectURL(file)``でsrcに指定するURLを生成しています。![スクリーンショット 2019-07-08 7.33.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261676/b11b1ee2-d607-bc7d-c1fe-31aba4d2c82d.png)
こんな感じでプレビューを表示させてあげれます。

## Example2

先ほどは``this.$refs.``を使った方法になりますが、eventをとってきてやる方法でもいいかな？

```vuejs
<template>
  <div>
     <input type="file" @change="setImage($event)"/>
     <img :src="data.image">
  </div>
</template>
<script>
export default {
  data() {
    return {
      data: {
        text: "",
        image: "",
        name: "",
      }
    };
  },
  methods: {
    setImage(event) {
      const file = (e.target.files || e.dataTransfer)[0]
      if (file.type.startsWith("image/")) {
        this.data.image = window.URL.createObjectURL(file);
        this.data.name = file.name;
        this.data.type = file.type;
      }
    },
    
  }
};
</script>

```

## 最後に
もっと簡単な方法があればご教授ください。
ありがとうございました。
GitHubをMACのターミナルから操作する方法

## MACでGitを使用するための準備作業
```
// 自分がいるディレクトリを確認する
pwd


// フォルダを作成する
mkdir フォルダ名


// ディレクトリのリストを表示してフォルダがつくれているかを確認する
ls


// つくったフォルダに入る
cd フォルダ名


// 自分がいるディレクトリを確認する
pwd
```

## gitの設定
```
// Gitを初期化する
git init

// 今いるディレクトリを確認する
ls -la

// GitHubで設定したユーザー名とメールアドレスを設定する
git config user.name ユーザー名
git config user.email メールアドレス

// ユーザー名とメールアドレスの設定ができているかを確認する
cat .git/config

// ファイルを作成
touch ファイル名

// ファイルにテキストを打つ

// テキストが表示されているか確認する
cat ファイル名

// ファイルを確認する
git status

// gitにファイルを追加する
git add ファイル名

// ファイルが追加されているか確認する
git status

// コミットする
git commit ファイル名 -m "コミットメッセージ"

// コミットされているか確認する
git log
```

## ブランチを作成する
```
// 自分がmasterにいるか確認する
git branch

// 新しいブランチを作成する
git checkout -b ブランチ名

// ブランチが作成されているか確認する
git branch

// ブランチの作業をmasterに反映させる(マージする)
git marge branch

// GitHubをブラウザから開き、『New repositly』をクリックし作成する

// 作成後出てくる画面の1つ目のブロックにある『git remote add~』以下をコピーする

// コマンドに戻り、GitHubの設定を反映させる
git remote add origin 『git remote add~』以下のコピー

// 
git remote -v

// ターミナルからpushする
git push -u origin master
```

## 新しいプロジェクト等でGitHubからコードを取得するとき
```
// GitHubの『clone』or『download』のURLをコピーする

// ターミナルでクローンを作成する
git clone 『clone』or『download』のURL

// フォルダができているか確認する
ls

// フォルダに移動する
cd フォルダ名

// ファイルがあるか確認する
ls -la
```

## その他よく使うコマンド一覧
```
// ファイルの削除
rm -rf ファイル名

// ファイル名を変更
mv 今のファイル名 / 変更後のファイル名

// Gitのブランチ削除(どちらでも可能)
git branch --delete 削除したいブランチ名
git branch --d 削除したいブランチ名
```
Node.jsのバージョンを管理・変更する

筆者的にはnやnodebrewよりasdfがおすすめです。（nodeに限らず多くの言語をサポートしているため）

## [下準備] Homebrewでインストール済みのnodeがある場合
homebrewで管理されていたnodeを抜きます。
nodeが存在しないなどとエラーが出る場合はそのまま進んでください。
npmで管理されている場合はnpmで抜いてください。

```
$ brew uninstall --force node
```

# asdfを利用するパターン

```sh
# asdfのインストール
$ brew install asdf
$ echo -e "\n. $(brew --prefix asdf)/asdf.sh" >> ~/.bash_profile
$ echo -e "\n. $(brew --prefix asdf)/etc/bash_completion.d/asdf.bash" >> ~/.bash_profile

# nodejs pluginのインストール
$ asdf plugin add nodejs
$ asdf plugin list
nodejs

# nodejsのインストール可能なバージョンを表示
$ asdf list all nodejs
0.1.14
0.1.15
0.1.16
0.1.17
...

# 特定のバージョンをインストール
$ asdf install nodejs 18.16.0

# ディレクトリ内にnodeのバージョンを適用
$ cd ./directry/path/here
$ asdf local nodejs 18.16.0

# グローバルにnodeのバージョンを適用
$ asdf global nodejs 18.16.0
```

### 🚨 注意
yarn等のグローバルなパッケージはnodejsのバージョンごとにインストールする必要があります。

```sh
# 19.9.0でyarnを使えるようにする場合
$ adsf global nodejs 19.9.0
$ npm i -g yarn
```

### インストールしたプラグインがうまく反映されない場合

```sh
$ asdf reshim
```



# nodebrewを利用するパターン

```
// 利用可能なバージョン一覧
$ nodebrew ls-remote

v8.0.0    v8.1.0    v8.1.1    v8.1.2    v8.1.3    v8.1.4    v8.2.0    v8.2.1
v8.3.0    v8.4.0    v8.5.0    v8.6.0    v8.7.0    v8.8.0    v8.8.1    v8.9.0
v8.9.1    v8.9.2    v8.9.3    v8.9.4    v8.10.0   v8.11.0   v8.11.1   v8.11.2
v8.11.3   v8.11.4   v8.12.0   v8.13.0   v8.14.0   v8.14.1   v8.15.0   v8.15.1
v8.16.0   v8.16.1   v8.16.2   v8.17.0
[...]
v13.7.0   v13.8.0   v13.9.0   v13.10.0  v13.10.1  v13.11.0  v13.12.0  v13.13.0
v13.14.0

v14.0.0   v14.1.0   v14.2.0   v14.3.0   v14.4.0
```

```
// 特定のバージョンのインストール
$ nodebrew install-binary v8.16.0
```

[Warning: No such file or directory](#warning-no-such-file-or-directory) が出てしまったら

```
// 利用可能なバージョン
$ nodebrew ls
v8.16.0
v10.11.0

current: v10.11.0
```

```
// バージョンの切り替え
$ nodebrew use v8.16.0
```

```
// 最終確認
$ node -v
v8.16.0
```

[切り替わらない場合](#切り替わらない場合)

### Warning: No such file or directory が出る場合
```
$ nodebrew install-binary v10.21.0
Fetching: https://nodejs.org/dist/v10.21.0/node-v10.21.0-darwin-x64.tar.gz
Warning: Failed to create the file
Warning: /Users/k3ntar0/.nodebrew/src/v10.21.0/node-v10.21.0-darwin-x64.tar.gz:
Warning:  No such file or directory
```

ディレクトリが無いと言われているので以下のコマンドで作成してから再度 `nodebrew install-binary` してみてください。

```
$ mkdir -p ~/.nodebrew/src
```

### 切り替わらない場合
ここまでやってバージョンが切り替わらない場合などはPATHが通っているかを疑ってください。
パッケージマネージャーを変更した場合などにnodebrewのPATHを追記する必要があるので注意してください。
[macでPATHを通す方法 - zsh/bash](https://qiita.com/k3ntar0/items/eb8cdbd8eba9da388def)

```
// .bash_profile, .zshrc 等に下記を追記して
export PATH=$HOME/.nodebrew/current/bin:$PATH

// sourceする
$ source ~/.bash_profile または ~/.zshrc
```

## 番外編 homebrewを使用したダウングレード例
```
// 利用可能なバージョン一覧
$ brew search node@
==> Formulae
libbitcoin-node  node ✔           node-sass        node@12          nodebrew ✔       nodenv
llnode           node-build       node@10          node_exporter    nodeenv
```

```
// node10をインストール
$ brew install node@10
```

```
// 現在のバージョン
$ node -v
v12.16.1
```

```
// node8にリンクしなおす
$ brew unlink node
$ brew link node@10
```

asdfを使用することをおすすめします。
Dockerでよく使用するコマンドをまとめ

## 何かを表示させる系のコマンド

```
//Dockerのバージョン表示
docker version

//ダウンロードされているイメージ表示
docker images

//起動しているコンテナを表示
docker ps

//これまでに起動した(起動している)コンテナ表示 ※exited=過去　up=今
docker ps -a　　

//コンテナの中身表示
docker exec -it コンテナ名 ls

//今までの動かした軌跡が全て表示
history

//今までの動かした軌跡の単語検索結果表示
history|grep "見たい単語"　　
```

## イメージを扱うときのコマンド

```
//DockerHubからイメージをダウンロード
docker pull イメージ名:タグ

//イメージからコンテナを作成・起動
docker run -it -d --name コンテナ名 イメージ名:タグ
```


##コンテナを扱うときのコマンド

```
//コンテナの操作許可
docker exec -it コンテナ名 pwd

//コンテナ内に入場
docker exec -it コンテナ名 /bin/bash

//コンテナの起動開始
docker start コンテナ名

//コンテナの起動終了
docker stop コンテナ名

//コンテナの削除
docker rm コンテナ名

//フォルダの頂点
/(ルート)
```

## (新規)開発作業時に使うコマンド

```
//今いるディレクトリの参照(Dockerfileのみで使用可能)
./

//コンテナを作成
docker build ./ -t コンテナ名:タグ

//マウント
docker run -d -p 8080:80 -v $PWD/PCのマウントしたいフォルダ名:コンテナのマウントしたいフォルダ名までのツリー　--name サーバー名 コンテナ名:タグ
```

## Dockerfile 関連

```Dockerfile
# build するときに基にするイメージの指定
FROM イメージ名
```
Microsoft Flow：「式」（関数）の引数に使う操作対象のコードを調べる

# 開発テクニック

Flowは、基本的にGUIで操作していきます。
けれど、「式」ではコードを書く必要があり、操作対象をコードでどのように表現するのかわからないときがあります。

この場合、アクションやトリガーのプロパティから「コードのプレビュー」を選択すればGUIで表されているもののコードが分かります。
これを利用して、テンプレートなどサンプルのコードを確認して、操作対象のコードを調べます。

![d1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/e8c84c7b-22b8-59a6-0863-4f134096d298.png)


![d2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/5fa3222a-c9e2-65c2-7641-4960f3c07b95.png)
これは、GUI上の「出力」の内容をコードで確認しています。
Microsoft Flow：オブジェクト(JSON）の値を更新

# 仕様
　1. オブジェクト変数を初期化。

![pr1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/edf5039e-58cf-d4a4-f029-80d6a67fb0fb.png)

　2. アクションの「データ操作」＞「作成」を選択
　
![pr201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/570df328-4b78-194d-e1f7-1cfd7e24355a.png)

![pr202.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/1b9a8748-55b1-caa3-92f5-2d2265cdca38.png)

　3. オブジェクト変数のプロパティを「式」の「setProperty」で更新。
　　ここで、デフォルトのアクション名「作成」を変更して、分かりやすい名前にしておく。

```javascript:update
setProperty(variables('theVar'), 'name', 'taro')
```

![pr21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/82353a4e-208e-c233-33b5-eaaaa7124f77.png)

　4. 続けて別のプロパティを更新。このときは、前の処理の結果を「outputs」で取得。これは、GUI上では、「出力」と表示されるものに相当。
　   「outputs」の引数は、アクション名。ここでアクション名を使用するので、分かりやすい名前にしておくのがよい。

```javascript:update2
setProperty(outputs('setName'), 'age', 100)
```

![pr3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/499541f1-1c6a-7c68-f429-3308a2f93ce0.png)

　5. アクションで「変数の設定」を選択肢、オブジェクト変数を指定し、値は更新アクションの最後の戻り値（出力：outputs）にする。

![pr4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/051bf6f4-a66e-4587-2901-658a662d8921.png)

　6. OneDriveに変数を出力。

![pr5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/c6685609-1feb-584f-9f1f-d4f8a9e991fe.png)

　7. 出力結果。

![pr6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/ef11ef50-6225-5d6e-bd35-58bd0dfb7ed3.png)
firebase init で遭遇したエラー

```
$ firebase init
```

エラーメッセージ抜粋

> Error: Cloud resource location is not set for this project but the operation you are attempting to perform in Cloud Firestore requires it. Please see this documentation for more details: https://firebase.google.com/docs/projects/locations .

## 原因
エラー： **Cloud Firesotreを利用するにはクラウドのリソースロケーションを設定する必要があります。** 

## 解決方法
1. Firebase Console にログイン
2. 当該プロジェクトのSettingsを開く
3. [全般] 中程の リソース ロケーション を任意のロケーションに指定

※特に希望がなければus-centralで間違いないかと
Serverless FrameworkでLambda + ALBを使う


## はじめに

API Gatewayを利用するのであれば`functions`に記載するだけであったが
ALBをLambdaのトリガーとする場合別途ALBを作成する必要がありそうだったのでやってみた

### サービス構成

ALB -> Lambda

Lambdaは引数をそのままレスポンスとして返すだけのものを作成。
ALBは2つのパスでのルーティングをそれぞれ同じLambdaへ、それ以外を404とするものを作成。

※事前に用意したもの
- LambdaにつけるIAMロール
- ALBにつけるVPC(のサブネットID2つとセキュリティグループID)


### フォルダ構成
```
.
├── handler.js
└── serverless.yml
```


## Lambdaソースコード

コードは内容には特に関係ないので別になんでもよい

```handler.js
module.exports.main = async (event) => {
    return response = {
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(event),
        statusCode: 200
    }
}

```

## serverless.yml

API Gatewayと若干書き方は変わるが
単純にALBをLambdaのAPIとしての口としたいだけなら
ALBとリスナーをresourcesで作成して
functionsでそれに紐づけるだけでよさそう。

```serverless.yml
service: alb-lambda-example

provider:
  name: aws
  runtime: nodejs10.x
  region: ap-northeast-1

functions:
  echo:
    handler: handler.main
    role: arn:aws:iam::00000000000:role/iam_role # IAMロールのARN
    events:
      - alb:
          listenerArn: 
            Ref: exampleLoadBalancerListener
          priority: 2
          conditions:
            path: /hello
      - alb:
          listenerArn: 
            Ref: exampleLoadBalancerListener
          priority: 1
          conditions:
            path: /world

resources:
  Resources:
    exampleLoadBalancer:
      Type: AWS::ElasticLoadBalancingV2::LoadBalancer
      Properties:
        Name: alb-lambda-example-alb
        Scheme: internet-facing
        Subnets:
          - subnet-XXXXXXXXXXXXX # サブネットID
          - subnet-YYYYYYYYYYYYY # サブネットID
        SecurityGroups:
          - sg-ZZZZZZZZZZZZZZ # セキュリティグループID
    exampleLoadBalancerListener:
      Type: "AWS::ElasticLoadBalancingV2::Listener"
      Properties:
        DefaultActions:
          - Type: fixed-response
            FixedResponseConfig: 
              ContentType: text/html
              MessageBody: <h1>Not Found</h1>
              StatusCode: 404
        LoadBalancerArn: 
          Ref: exampleLoadBalancer
        Port: 80
        Protocol: HTTP
```

## 結果

### AWSコンソール上のALBの振り分けルール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75588/3c8d3497-8195-018d-7b1c-02374a6dedff.png)

作成されたALBのDNSにブラウザでアクセスすると`/hello`と`/world`ではJSONがレスポンスされそれ以外では`Not Found`ページが表示された。


## トラブルシュート

### `sls deploy`に成功するがLambdaがALBと関連付けられてない

`serverless` をアップデートすると治るかも
グラフ表示とともにファイル名に時間を付けて保存するデコレータ

## 目的
* デコレータの使い方を初めて勉強したので記録する。
* 練習のために、グラフを書くときに便利になる機能を考えて実装してみた
* グラフ表示と同時にファイル名に接頭字と時間を付けて保存する

## ポイント
* デコレータの使いどころとしては、hogehogeってよくやるけど、ついでにXXXの処理もいつもやってるなぁって時
* 自作モジュール(decorator_utility.py)にデコレータを作成し、いつでも呼び出せるようにしておけば＠XXXXでお手軽に使える。ベンリー！

## コード

デコレータの実装

```decorator_utility.py

import datetime

def save_deco(name):　#デコレータの引数でファイル名の接頭字を定義する
    def __save_deco(func): # 描画関数を持ってくる
        def wrapper(*arg, **kwargs):
            now = datetime.datetime.now() #保存時間の設定
            fig_img = func(*arg, **kwargs) #描画関数の実行
            return fig_img.savefig('{0}_{1:%Y%m%d%H%M%S}'.format(name, now)) #メインの処理
        return wrapper # 関数名が返り値
    return __save_deco # 関数名が返り値
```


処理系

```main.py

import numpy as np
import random
import matplotlib.pyplot as plt
from decorator_utility import save_deco

# プロットする値を適当に
x = np.array([random.randint(0, 10) for i in range(10)])
y = np.array([random.randint(8, 12) for i in range(10)])


@save_deco('new_graph')
def drow_graph(x_data,y_data):
    fig, ax = plt.subplots()
    ax.plot(x_data, y_data, 'o')
    return fig


drow_graph(x, y)
```

CWDにファイルが出来ている。迷子になったら```os.getcwd()```。

## 参考にさせていただきました
* [Pythonのデコレータについて](https://qiita.com/mtb_beta/items/d257519b018b8cd0cc2e#fn1)
    * デコレータについて、非常に分かりやすく解説してくださっています。
NetlifyのCIでNode.jsのバージョンを最新に指定


Nuxt.jsをSSRしてNetlifyに上げて運用しています。

> http://protoout.studio

ローカル環境はNode.js v12を利用していますが、なかなかサンプルコードなども見当たらなかったのでメモ

[[途中] Netlify ドキュメント 日本語翻訳](https://qiita.com/superyusuke/items/0d222732df8b9b82b051)が参考になりました。

## .nvmrcを追加するだけ

```bash
node -v  > .nvmrc
```

という記述がありますが。

プロジェクトルートに`.nvmrc`というファイルを作成し、中にバージョンを記述すればおkです。

```.nvrmrc
v12.6.0
```

これでNetlifyにデプロイすればimageにインストールされて使えます。

## 対応バージョンは?

ログを見る限りだとnvmで利用できるバージョンがそのまま利用できそうなので、最新を常に使うことができそうです。ありがたいですね。

![](https://i.gyazo.com/1d16a131ddd21ba9e242895a02ad2e04.png)

こんな感じで裏側でインストールされてました。なので初回は少し時間がかかる印象ですが、2回目以降はこんな感じで既にインストールされた状態になっているのでビルド時間も特段気にしなくて良さそうです。
![](https://i.gyazo.com/e66810771388057daf208abe8de8c164.png)
Selenium for Python 画像が読み込まれるまで待機する

# はじめに

Seleniumで処理を自動化しました。
しばしば画像の読み込みが完了する前に、処理を始めてしまい例外が発生していました。
そこで画像の読み込みが完了するまで待機する処理を考えてみました。

# 環境

Python 3.7.3
selenium 3.141.0
Firefox: 67.0.4 (64 ビット)
geckodriver 0.24.0 ( 2019-01-28)

# ソース01

## JavaScript

画像の読み込みが完了したかどうかを判定する処理は、JavaScriptで実装しました。
以下のようになります。
ここでは、Document配下の全ての画像を対象にしています。
適宜、修正してください。

```javascript:JavaScript
const isLoadedAllImages = () => {
  const images = document.getElementsByTagName("img");
  let completed = true;
  for (const image of images) {
    if (image.complete === false) {
      completed = false;
      break;
    }
  }
  return completed;
}
return isLoadedAllImages()
```

## Python

上で定義したJavaScriptをSelenium(Python)側から呼び出します。
単純な事ですが、重要なのは、画像が読み込まれるまでSelenium側でsleepをしてやることです。
理由は、

- JavaScriptには、単純なSleepがない
- JavaScript側がビジー状態になっていると画像の読み込みが完了しない

からです。
Sleepをしてくれるライブラリ等あればそれを使えば良いのでしょうが、それの設定をするのも面倒なのでこのような実装にしました。

```python:Python
JavaScriptIsLoadedAllImages = '''
const isLoadedAllImages = () => {
  const images = document.getElementsByTagName("img");
  let completed = true;
  for (const image of images) {
    if (image.complete === false) {
      completed = false;
      break;
    }
  }
  return completed;
}
return isLoadedAllImages()
'''

def isLoadedAllImages(timeOut=300, interval=1):
  completed = False
  start = time.time()
  while time.time() - start < timeOut and completed == False:
    completed = driver.execute_script(JavaScriptIsLoadedAllImages)
    time.sleep(interval)
  return completed
```

# ソース02

## JavaScript

同じ関数を繰り返し定義しているためか挙動が不安定な事もあったので修正案です。
こちらはグローバル変数を変更するので注意が必要です。
関数定義

```javascript:JavaScript
window.isLoadedAllImages = () => {
  const images = document.getElementsByTagName("img");
  let completed = true;
  for (const image of images) {
    if (image.complete === false) {
      completed = false;
      break;
    }
  }
  return completed;
}
```

関数呼び出し

```javascript:JavaScript
return isLoadedAllImages();
```

## Python

```python:Python
JavaScriptIsLoadedAllImagesDefine = '''
window.isLoadedAllImages = () => {
  const images = document.getElementsByTagName("img");
  let completed = true;
  for (const image of images) {
    if (image.complete === false) {
      completed = false;
      break;
    }
  }
  return completed;
}
'''
JavaScriptIsLoadedAllImagesCall = "return isLoadedAllImages();"
driver.execute_script(JavaScriptIsLoadedAllImagesDefine)

def isLoadedAllImages(timeOut=300, interval=1):
  completed = False
  start = time.time()
  while time.time() - start < timeOut and completed == False:
    completed = driver.execute_script(JavaScriptIsLoadedAllImagesCall)
    time.sleep(interval)
  return completed
```

# 最後に

単純なサイトではこれでうまく行くと思います。
実際には、アクセスしているサイトの挙動によってはうまく行かないことも出てくるかと思います。

余談ですが、Selenium等での自動化にはまると楽しいですね。
これを仕事や収入に結び付ければ良いのでしょうが。
railsのcredentials.yml.encとRAILS_MASTER_KEY

## RAILS_MASTER_KEYってなんだ？
credentials.yml.encをつかう際に、デコードするためのキー

## credentials.yml.encってなんだ？
rails5.2より前のバージョンでは、secrets.ymlにて平文で情報を扱っていた。（secretsなのに。）
環境変数を暗号化して入れられるということですね。

これまでsecrets.ymlは環境ごとに分割して使われていましたが
credentials.yml.encは本番環境のみで使われる想定のものだそうです。


## 使い方

```
Rails.application.credentials.hogehoge
```
で情報を取得する事ができます。


参照
[Rails5.2からsecrets.yml*が廃止されcredentials.yml.encに統合されるよ
](https://qiita.com/daichirata/items/da40e205d273ae69fcfc)
数検１級 (9) 実解析

# 問題

実数全体を定義域とする関数

```math
f(x) = \begin{cases}
\frac{\sin x}{x} && (x\not=0) \\
1 && (x=0)
\end{cases}
```

について、次の問いに答えなさい。

（１）$f(x)$ はすべての実数 $x$ において微分可能であり、 $f(x)$ の導関数 $f'(x)$ は連続であることを証明しなさい。

（２）（１）での $f'(x)$ において、$a_n=f'(n\pi)$ （$n$ は正の整数）で定めるとき、級数 $\sum_{n=1}^{\infty} a_n$ の和を求めなさい。

<details><summary></summary><div>
# 知識

## ロピタルの定理

$\lim_{x \to a} \frac{f(x)}{g(x)}$ が不定形で、
$\lim_{x \to a} \frac{f'(x)}{g'(x)}$ が存在するなら、

```math
\lim_{x \to a} \frac{f(x)}{g(x)} = \lim_{x \to a} \frac{f'(x)}{g'(x)}
```

* ここで不定形とは、分母子の極限をそれぞれ求めた結果が $\frac{0}{0}$, $\frac{\pm\infty}{\pm\infty}$ になることを指す
* $a$ は 無限大でも良い
* 片側極限にも適用できる


## 関数の連続性

次が成り立つとき、関数 $f$ は $x=t$ において連続。

```math
\lim_{x\to t}\,f(x) = f(t)
```


# 解答

（１）

$x\not=0$ においては、商の微分を適用して

```math
f'(x) = \frac{x\cos x -\sin x}{x^2}
```

$x=0$ のおいては、導関数の定義から

```math
\begin{align}
f'(0) 
&= \lim_{h\to 0} \frac{f(h) - f(0)}{h} \\
&= \lim_{h\to 0} \frac{\frac{\sin h}{h} - 1}{h} \\
&= \lim_{h\to 0} \frac{\sin h - h}{h^2} \\
&= \lim_{h\to 0} \frac{\cos h}{2h} &&\text{（ロピタルの定理）} \\
&= \lim_{h\to 0} \frac{-\sin h}{2} &&\text{（ロピタルの定理）} \\
&= 0
\end{align}
```

したがって、

```math
f'(x) = \begin{cases}
\frac{x\cos x -\sin x}{x^2} && (x\not=0) \\
0 && (x=0)
\end{cases}
```

$x\not=0$ における $f'$ の連続性は明らか。
$x=0$ においては、次の極限を考える。

```math
\begin{align}
\lim_{x\to 0}\frac{x\cos x -\sin x}{x^2} 
&= \lim_{x\to 0}\frac{\cos x -x\sin x -\cos x}{2x}  &&\text{（ロピタルの定理）} \\
&= \lim_{x\to 0} \frac{-x\sin x}{2x}   \\
&= \lim_{x\to 0} \frac{-\sin x}{2}   \\
&= 0 \\
&= f'(0).
\end{align}
```

したがって、$f'$ は $x=0$ においても連続である。


（２）

```math
\begin{align}
a_n &= f'(n\pi) \\
&= \frac{n\pi\cos (n\pi) -\sin (n\pi)}{(n\pi)^2} \\
&= \frac{n\pi\cos (n\pi)}{(n\pi)^2} && \text{($\sin \pi, \sin 2\pi, \dots = 0$)} \\
&= \frac{\cos (n\pi)}{n\pi}  
\end{align}
```

したがって

```math
\sum_{n=1}^{\infty} a_n 
= \frac{1}{\pi} \left( -1 + \frac{1}{2}  - \frac{1}{3} + \frac{1}{4} - \cdots  \right)
```

ここで、$g(x) = \log(x)$ の $x=1$ におけるテイラー展開を考える。
$g'(x) = x^{-1}, g''(x) = -x^{-2}, g'''(x) = 2x^{-3}, g^{(4)} = -3\cdot 2x^{-4}, \dots$ だから、

```math
\begin{align}
\log(x) &= 0 + (x-1) - \frac{1}{2!} (x-1)^2 + \frac{2}{3!}(x-1)^3 - \frac{3\cdot 2}{4!}(x-1)^4 + \cdots \\
&= (x-1) - \frac{1}{2} (x-1)^2 + \frac{1}{3}(x-1)^3 - \frac{1}{4}(x-1)^4 + \cdots
\end{align}
```

$x=2$ を代入すると

$$
\log(2) = 1 - \frac{1}{2} + \frac{1}{3} - \frac{1}{4} + \cdots
$$

したがって、求める級数は、

```math
\begin{align}
\sum_{n=1}^{\infty} a_n 
&= \frac{1}{\pi} \left( -1 + \frac{1}{2}  - \frac{1}{3} + \frac{1}{4} - \cdots  \right) \\
&= \frac{-\log(2)}{\pi}.
\end{align}
```

# 感想

* ロピタルの定理が使えると、極限計算が閃きに依存しなくなって嬉しい。
* この無限級数は、ひと目テイラー展開だったらいいなと思ったが、$\log x$ を思いつくかどうか。テイラー展開の分母にある階乗を約分するために、導関数が階乗になってほしい。そんな関数あったかなと思ったら、べき乗がまさにそれだった。
* ゼロ以外の点でテイラー展開する問題は初めてだった。

</div></details>
Redmineで入力フィールドをグルーピングして見出しを入れる

# はじめに
先日書いた[Redmineで要否プルダウンが要のときのみ入力できる項目を表示する（否のときは表示しない）](https://qiita.com/drafts/d062a85f04fd0f086974)からの発展で、いくつかのカスタムフィールドをグルーピングして見出しを入れる方法をご紹介します。

# 前提条件
### 環境
* Redmine 3.4.10.stable.18167
* view_customize プラグイン 2.2.0

極端なバージョン依存のコードではないので、その他のバージョンでもたぶん動作します。
### カスタムフィールドの設定
| ＩＤ| 名称 | 形式 | 備考 |
|:-----:|:---------:|:----------------:|:----------------|
|2|コメント|長いテキスト||
|3|起票者|ユーザー||
|4|コメント回答|長いテキスト||
|5|回答者|ユーザー||
これらのカスタムフィールドは、以下のサンプルコードで使う用に定義していますが、標準フィールドや任意のカスタムフィールドをグルーピングすることが可能です。

# サンプルコード
```javascript
/*
サンプルチケット編集画面
Path pattern: .*
挿入位置：チケット入力欄の下
Type: JavaScript
*/

if (!$('div#my_div1').length){								// 自分で定義する'my_div1'ブロックない場合
  $('div#attributes').after(								// 'div#attributes'の後ろに、'my_div1'ブロックを作成、その中身は以下のとおり
    $('<div id="my_div1">').append(							//   'my_div1'ブロックを作成
      $('<fieldset id="my_fieldset1">').append(				//     'fieldset#my_fieldset1'を作成
        $('<legend>').text('起票者入力欄'),					//       見出し「起票者入力欄」
        $(':input#issue_custom_field_values_3').parent(),	//       カスタムフィールド3「起票者」
        $(':input#issue_custom_field_values_2').parent()	//       カスタムフィールド2「コメント」
      )
    ),
    $('<div id="my_div2">').append(							//   'my_div2'ブロックを作成
      $('<fieldset id="my_fieldset2">').append(				//     'fieldset#my_fieldset2'を作成
        $('<legend>').text('回答者入力欄'),					//       見出し「回答票者入力欄」
        $(':input#issue_custom_field_values_5').parent(),	//       カスタムフィールド5「回答者」
        $(':input#issue_custom_field_values_4').parent()	//       カスタムフィールド4「コメント回答」
      )
    )
  );
}

```

# 結果
Redmineのチケット編集画面はこんな感じになりました。起票者入力欄、回答者入力欄が、本スクリプトでグルーピングしているところです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138759/5d676add-512f-0769-4d59-b9d7683e613c.png)

# 解説
* `$('div#attributes').after()`を使って、自分が作成したいブロックを挿入しています。ちなみに、`$('div#all_attributes').after()`としてもできそうな気がするのですが、画面が崩れてしまいうまくいきません。この記事を書くためにいろいろ実験をしたのですが、ここが一番ハマりました（汗）
* グルーピングしたいフィールドを`$('<fieldset id="my_fieldset1">')`のように作成して、そこに`$('<legend>').text('起票者入力欄')`のようにして見出しを入れます。ここでは、my_fieldset1に起票者入力欄、my_fieldset2に回答者入力欄の見出しをつけています。
* さらなる発展として、先日書いた[Redmineで要否プルダウンが要のときのみ入力できる項目を表示する（否のときは表示しない）](https://qiita.com/drafts/d062a85f04fd0f086974)と組み合わせれば、グルーピングした領域をステータスや任意のプルダウンと連動させて表示／非表示を制御することも可能になります。
tmux最新版のビルド備忘録

# 前提

ビルドに必要なパッケージをインストールする

```bash
sudo apt install make automake autogen libevent-dev libncurses5-dev bison gcc autoconf pkg-config zlib1g-dev curl libbison-dev
```

# 最新版のビルド

```bash:/tmp
git clone https://github.com/tmux/tmux
cd tmux
sh autogen.sh
./configure
make
sudo make install
tmux -V
# tmux next-3.1
```

終わり！

# 引用

[最新のTmuxを入れる方法](https://qiita.com/egoa56/items/650dcb3dcbf324160b5e)
Hackerrankで使える、listの要素を横並びで抽出する方法

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている<小栗>です。
「プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

はじめに
===
Hackerrank（Algorithm,Data structures)に取り組むにあたり、初心者の僕にはデフォルトのコードが理解できないということに苦しみました。

関数をつくってreturnで返せばいいだけならいいですが、listの要素だけをprintするときに役立った方法を紹介します。


listをそのまま出力
===
以下はコードの一部なのでわかりにくいかもしれませんが、leftRotationという変数にはlistが返された関数を代入しています。

これをこのまま
```
print(leftRotation)
```
とすると、

[5, 1, 2, 3, 4]

このように出力されてしまいます。


しかしここで、

```py

for ans in leftRotation:
        print(str(ans),end=' ')

```
こうするだけで、

5 1 2 3 4

このように要素のみの出力に成功します。


もととなる考え
===
・print関数のエンドオプション
https://qiita.com/tortuepin/items/4fbf29e42f05cb4b02a5

・イテレーターの考え

以上を勉強すると理解できました。
iterは奥が深いみたいなので　、まだ学んでいきます。
[WIP]RedisとSidekiqの説明

SidekiqとRedisを知るために、情報をまとめた記事です。





## sidekiqとは
sidekiqとは、非同期処理を行いたい時に使うライブラリである。
Railsが必須というわけではないようですが、基本的にはRailsで使います。


### sidekiqの使い方

1.まず、sidekiqを追加します。

```
gem 'sidekiq'
```

2.app/workersにワーカーファイルを作成します。

```
rails g sidekiq:worker Hard #このコマンドがapp/workers/hard_worker.rbファイルを作成します
```

```
class HardWorker
  include Sidekiq::Worker
  def perfome(name, count)
    # do something
  end
end
```

3.非同期処理が行われるように、ジョブを作成します

```
HardWorker.perform_async('bob', 5)
```

"perform"はインスタンスメソッドです。
他にも下記のようなインスタンスメソッドがあります。

```
HardWorker.perfome_in(5.minutes, 'bob', 5)
HardWorker.perfome_at(5.minutes.from_now, 'bob', 5)
```

メモ：もしsidekiqと使うときにrails consoleで使う場合は、springを止める事で新しいワーカーを使う事ができます。ワーカーの初期化かな？

4.sidekiqを動かすには下記コマンドを打ちましょう

```
bundle exec sidekiq
```


### sidekiqにはpro版とかがある
Pro版とEnterprise版とで機能などが変わってくるそうです。
[https://sidekiq.org/](https://sidekiq.org/)



## Redisとは
Key-Valueストアデータベースです。
オープンソースのインメモリ型です。

### データ保存方法の特徴
コンピュータの記憶領域として、
- CPUから直接アクセスできるメインメモリ
- ハードディスクなどのディスクストレージ
の2つがあります。
インメモリ・データベースとは、メインメモリ上だけでデータを管理する仕組みです。
メモリは「揮発性」という性質により、コンピューターが停止すると、メモリに載っている情報も全て消えてしまいます。しかしRedisではデータ永続化機能のオプションがあり、メインメモリ上のデータをディスクストレージに記憶させる事ができます。

### Redisで保存できるデータ
Redisでは
- リスト型
- セット型
- ハッシュ型
のデータも扱う事ができます。


### Redisの用途

#### キャッシュ
- DBクエリ結果のキャッシュ
- 永続的なセッションのキャッシュ
- Webページのキャッシュ
  - 画像
  - ファイル
  - メタデータ

#### チャット
リアルタイムでのコメントストリーム
ソーシャルメディアフィード

#### ゲームのリーダーボード
リアルタイムでのランキングリストを作成する

#### セッションストア
セッション状態のなどを管理する時

#### リッチメディアストリーミング
（とにかく認証系を素早く大量に処理できる、という事でしょうか・・・）

#### 地理空間
(地理空間データを簡単・高速に処理する事ができるそうです。位置情報などをリアルタイムに更新する際などには良さそうですね。)

#### Machine Learning
作成されたデータに対して、並行して機械学習・データ処理を行う訳ですが、その処理を行う際に、迅速に処理する事ができるという点ではRedisは有用なようです。

#### リアルタイム分析
断続的に更新されるデータを素早く処理するという意味で、Redisは有用そうです。

こうして見ると、Redisは、メモリの特徴を踏まえればわかるように、リアルタイム処理などに有効に働くようです。


### 競合ライブラリ
MemcachedもインメモリのOSSデータストアです。


参照
[https://github.com/mperham/sidekiq/wiki/Getting-Started]
(https://github.com/mperham/sidekiq/wiki/Getting-Started)
[https://aws.amazon.com/jp/redis/](https://aws.amazon.com/jp/redis/)
Androidビルド in Unity2019.1.2f1

Oculus Quest開発用にAndroidビルド環境を作成しようとしたところ、`UnityEditor.BuildPlayerWindow+BuildMethodException`に詰まりました。今回は、解決しなかったが試した方法をメインに公開します。解決した方法については[解決方法](#解決方法)までスキップしてください。

#試行一覧
Unity - 2019.1.2f.1
Android Studio
・SDK Platforms - 8.0, 8.1
・SDK Tools - 26.1.1
・SDK Build Tools - 29
jdk - 1.8.0.211

##ビルド場所を変更した
[Assets配下にビルドするとエラーになるという記事](https://blog.narumium.net/2017/09/16/unity2017%E3%81%A7%E3%83%93%E3%83%AB%E3%83%89%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E7%8A%B6%E6%85%8B%E3%81%AE%E8%A7%A3%E6%B1%BA%E6%B3%95/)を見たため。
**結果：効果なし**

##UnityHubのデフォルトのSDK/NDKを使った
Unityのバージョンが2019以上だと、UnityHub>インストール>モジュールを加える>AndroidBuildSupport>Android SDK&NDK Toolsで追加インポートが可能。Preferenceではそちらを推奨されたため。
**結果：効果なし**

##SDK Platformsのバージョンを増やした
4.4 ~ 8.1までのバージョンを追加インストールしました。
**結果：効果なし**

##Build SystemをInternalにしようとした
[こちらの記事](http://nn-hokuson.hatenablog.com/entry/2017/09/05/202327)よりInternalに変更しようとしたが、2019.1.2f1では見当たらなかったです。
**結果：不明**

##SDK Toolsのバージョンを変更した
[Unity Answers](https://answers.unity.com/questions/1323731/unable-to-list-target-platforms-please-make-sure-t.html?childToView=1326427#answer-1326427)から推奨されていた。SDK Toolsのバージョンを26.1.1から25.2.5に変更しました。
この際、WindowsとMacでアクセスすべきURLが異なるので注意。Windowsは`http://dl-ssl.google.com/android/repository/tools_r25.2.5-windows.zip`ですが、Macは`http://dl-ssl.google.com/android/repository/tools_r25.2.5-macosx.zip`です。
SDKのバージョンは[公式サイト](https://developer.android.com/studio/releases/sdk-tools)から確認できます。
**結果：おそらく効果あり**(要検証)

##SDK Build Toolsのバージョンを下げた
SDK Build Toolsのバージョンを29から28に変更しました。
**結果：効果あり**(エラーが7カ所減少した)

##Scripting Backendを変更した
PlayerSettings>OtherSettings>ConfigrationのScripting BackendをMonoからIL2CPPに変更しました。
**結果：効果なし**

##Visual Studio関連のファイルを消去した
[こちらの記事](https://teratail.com/questions/139998)より。`.sln`と`.vs`のファイルを消去しました。
**結果：効果なし**

##PC, Unity再起動
最後の手段、治ればいいなという願望。
**結果：効果なし**

***

#解決方法
AndroidStudioをアンインストールしたのち、[こちらの記事](https://qiita.com/relzx/items/7f8e7817c9edd11c5023)を行い解決しました。SDKのセットアップは記事内の(B)の方法で行ってください。
注意点として、Unity2018.4ですとNDKのバージョンが`r13b`でなく、`r16b`以上である必要があります。

####補足
ビルド時にSuccessと出たのに、apkファイルが出力されない事態がありました。
その際、ProjectSettings/PublishSettingsのUse legacy SDK toolsを選択したところ、apkファイルが出力されました
VSCodeのRemote SSHでVM環境で開発するまでの手順

毎度メモ程度ですが、VSCodeのremote sshという拡張機能を使ってVMにSSHする方法を書きます。
MSの公式拡張機能です。

# メリット
リモート環境を使い開発する際に、ローカルにほとんど何もいれなくて済みます。

**例**
- Pythonで開発していた人の場合
Remote上のPythonのpathを指定して、remote上でデバグができる。
- 今まで**Remote FS**を使ってremote上のファイルを管理していた人も、それを使うことなく同様のことができる。ファイルをremoteで変更した時**Remote FS**にくらべ、にファイルの更新が早い。

# 前提条件
- VMにファイルを転送できる状態
- Ubuntu LTS 18.04

# 方法
※GCPのインスタンスを使用する場合は、簡略化した方法で**Remote SSH**を使うことができる。GCPがAuthorized_keyの設定などをしてくれるため。
その場合、以下の記事の内容をフォローした後に、本記事の**ローカルのpcからコマンドライン経由でsshしてみる**から実行すればできる。

https://sleepless-se.net/2018/09/15/gcp-ssh/

#### 1. 公開鍵と秘密鍵の作成

```shell:Local terminal
$ ssh-keygen -t rsa -b 4096
```

#### 2. リモートサーバーに公開鍵を転送（.pubファイル）
リモートVMにSCPやSFTPなどで鍵を転送する。もちろん、さっき作ったユーザでは転送できないので、VMにすでにアクセスできるユーザで転送する。
※GCPやAWSでは、GUIコンソールから鍵を追加することもできる。以下を参照。

https://sleepless-se.net/2018/09/15/gcp-ssh/



#### 3. リモートサーバーの"~/.ssh/"ディレクトリのパーミッションを変更（読み取り、書き込み、実行）

```shell:Remote terminal
$ chmod 700 .ssh
```

.sshがないときは自分で作る

#### 4. ファイル"authorized_key"のパーミッションを変更（読み取り、書き込み）
リモートサーバーの"~/.ssh/"ディレクトリにある、なかったらつくる

```shell:Remote terminal
$ chmod 600 authorized_key
```

#### 5. 公開鍵を"authorized_key"に登録
ここではid_rsa.pubファイルを例に

```shell:Remote terminal
$ mv id_rsa.pub ./.ssh/id_rsa.pub
$ cat id_rsa.pub >> authorized_key
```

#### 6. sshdの設定を変更

```shell:Remote terminal
$ sudo vi /etc/ssh/sshd_config
```

以下の設定をオンにする

```shell:/etc/ssh/sshd_config(変更前)
#PubkeyAuthentication yes
#AuthorizedKeysFile      .ssh/authorized_keys
```

```shell:/etc/ssh/sshd_config(変更後)
PubkeyAuthentication yes
AuthorizedKeysFile      .ssh/authorized_keys
```

#### 7. sshdのサービスを再起動する

```shell:Remote terminal
$ sudo service sshd restart
```

#### 8. ローカルのpcからコマンドライン経由でsshしてみる

#### 9. VScodeのremote developmentの拡張機能をインストール
以前は、**Vscode Insiders**でのみ使用可能だったが、2019年のGWあたりのVScodeの更新でVSCodeでも使用できるようになった。

#### 10. VScodeのデスクトップマークが現れるのでそこを押すと、歯車マークそこを押して、設定ファイルを作る

```xml:VScodeの設定ファイル
Host [host-alias]
    HostName [XX.XX.XX.XXX]
    User [your-username]
    IdentityFile [C:/Users/user/.ssh/id_rsa]
```

host-aliasを

```xml:VScodeの設定ファイル
Host [your-username@XX.XX.XX.XX]
```

のようにすると、怒られました。なんでだろう。(2019.07.10追記)


#### 11. SSH開始

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306295/8709decf-68a1-cfa1-36df-b22a5264708c.png)

スクショのようなHostが現れるので、ここを右クリックするとSSHができる


以上です。
ありがとうございました。
何かご指摘があれば、ぜひお願いします。
多重継承でのSuper ClassとSub Class

## 目的
Super ClassとSub Classを初めて学んだので、関係性と使い方をまとめる。
多重継承した時の引数の設定の方法に悩んだので、本人の備忘録として記載する。

## ポイント
*  コンストラクタでsuper().\_\_init\_\_()を定義する際には、明示的にSuperクラスの引数をを定義する。
その際にselfは入れない。

* 多重継承の場合はsuper()使わずに直接クラス名を指定する
* クラス名を指定する場合は、\_\_init\_\_(ここにselfが必要！)
* 多重継承を定義したサブクラス中のsuper()は第一引数のSuperclassを参照する

## コード
super class1

```python

class Student:
    def __init__(self, std_name, std_id):
        self.std_name = std_name
        self.std_id = std_id

    def work(self):
        print('勉強します')
```



super class2

```python

class Field:
    def __init__(self, place):
        self.place = place
```

sub class1

```python

class Economics(Student):
    def __init__(self, std_name, std_id, campus):
        #明示的にSuperクラスに渡す値を定義する。selfは入れない
        super().__init__(std_name, std_id)
        self.campus = campus
```

sub class2

```python

class Engineering(Student, Field):
    def __init__(self, std_name, std_id, place, campus):
        #多重継承の場合はsuper()使わずに直接クラス名を指定する
        #クラス名を指定する場合は、__init__(ここにselfが必要！)
        #super()は第一引数のSuperclassを参照する

        Student.__init__(self, std_name, std_id)
        Field.__init__(self, place)
        self.campus = campus
```

実行コード

```python
student1 = Economics('jiro', 1, 'Yokohama')
student1.work()
print('super_class', student1.std_name, student1.std_id)
print('sub_class-campus', student1.campus)
print() #出力の改行


student2 = Engineering('Taro', 2, 'Kawasaki', 'Kamakura')
student2.work()
print('first_super_class', student2.std_name, student2.std_id)
print('second_super_class-Field', student2.place)
print('sub_class-campus', student2.campus)
```


出力

```
勉強します
super_class jiro 1
sub_class-campus Yokohama

勉強します
first_super_class Taro 2
second_super_class-Field Kawasaki
sub_class-campus Kamakura
```
AutoML Tablesチュートリアル 〜概要編〜

#目次
**1. AutoML Tablesチュートリアル 〜概要編〜**
2. AutoML Tablesチュートリアル 〜セットアップ編〜(近日公開)

#AutoMLとは
![スクリーンショット 2019-07-08 1.09.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296645/91c8345d-e849-63a3-2768-0970fcf90ba7.png)

・**最小限の労力と機械学習の専門知識**で、高品質のカスタム機械学習モデルをクラウド上で作成できるGUIのツールです

・Google Cloud Platform(GCP)の無料枠（12ヶ月, ＄300まで）の範囲内なら使用は**無料**です。

・**学習用/予測用データセット**さえ用意すれば、あとは画面の指示に従ってボタンを押すだけである程度の精度のモデルが組め、予測できます。
#AutoMLのバリエーション
|| **データの種類**|**名称**|
|-----------:|-----------:|------------:|
|**1**|構造化データ|**AutoML Tables**|
|**2**|テキスト|AutoML Natural Language|
|**3**|テキスト|AutoML Translation|
|**4**|画像|AutoML Vision|
|**5**|画像|AutoML Video Intelligence|
AutoMLには分析するデータの種類や目的に応じて、様々なバリエーションがあります。
今回は、**構造化データ(表データ)**に基づいて、機械学習モデルを作成するAutoML Tablesについて説明します。
#AutoML Tablesとは
・複数の説明変数（特徴量）と1つの目的変数（ターゲット）を含んだ表データをもとに機械学習モデルを作成し、予測を行うことができます。以下は表データの例です。

![スクリーンショット 2019-07-07 18.10.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296645/2f7b9598-afdb-5fdf-14bd-4e8c0412e293.png)  

・学習データをインポートし、説明変数と目的変数を指定すれば、**クラウド上**で学習のための計算を自動で行います。

・学習が終わればメールで通知してくれるので、モデル作成中は待つだけでよく非常に便利です。

#AutoML Tablesの仕組み
![スクリーンショット 2019-07-07 23.00.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296645/2dcbf0d3-a2cf-4ccb-4408-ee8a91a77ac9.png)
1.学習用の構造化データ（**表形式データ**）をインプットします。

2.データのスキーマを定義（**各変数は数値かカテゴリかなど**）します。

3.**目的変数**（ターゲット）と**説明変数**（特徴量）を選択します。

4.学習データに基づき、機械学習モデルのトレーニングを行います。
ー特徴量エンジニアリング
ー適切なモデルの選択＆アンサンブルモデルの作成
ーハイパーパラメータチューニング

5.作成したモデルの評価を、各評価指標を用いて実施します。

6.作成したモデルをデプロイします。

7.モデルに予測データを入れて、予測を行います。

8.予測結果を表示します。

#AutoML Tablesの料金
・**初回に限り、6時間分**無償でモデルをトレーニング可能です。
・モデルトレーニング**1時間あたり＄19.36** 請求されます。

・作成したモデルで予測を行う際は**1時間あたり＄1.16** 請求されます。

・請求は秒単位まで計算して行われます。

・Google Cloud Platform(GCP)の無料枠**（12ヶ月, ＄300まで）**の範囲内なら使用は無料です。


#AutoML Tablesの実績
・Fox Sports社のマーケティングチームはAutoML Tablesで作成した機械学習モデルを用いて、クリケットにおいて、**各プレーが起こるタイミングを事前に予測する**ことを可能にしました。この予測結果を用いて、クリケット中継のカメラアングルなどを変更することで、**1ドルの支出に対する契約者数が150%もUP**しました。

・Jam City社のリードデータサイエンティストは、AutoML Tablesを用いて、**ハリーポッターのゲームでのプレーヤーの動きを予想**できるようになりました。予測結果を用いることで、課金をするプレーヤーの行動が明らかになり、**効果的な広告費の運用につながりました。**

・Kaggleが主催するハッカソンイベントの、KaggleDays SF Hackathonにおいて、自動車部品についての素材の特性とテスト結果の情報を与えて、製造における欠陥を予測する課題にAutoML Tablesを用いたGoogleのチームが参加しました。結果は**74組中、僅差の2位**を獲得しました。他のチームが手動で懸命に特徴量エンジニアリング、ハイパーパラメータチューニングを行う中、GoogleのAutoMLを用いたチームは**モデルが自動的に作成されるのを監視していただけ**でした

#参考文献
[AutoML テーブル Google Cloud](https://cloud.google.com/automl-tables/?hl=ja)
[開発者のための機械学習入門]
(https://www.slideshare.net/uesaka/azure-machine-learning-studio-148264288)
[Google Developers Japan: GoogleのAutoMLがKaggleDaysでの表形式データのコンペで2位に](https://developers-jp.googleblog.com/2019/06/google-automl-kaggledays-2.html)