OmniAICreator/Qiita-1.07M huggingface dataset:
MySQLdbでレコードを保存できない対処法（autocommitを使う）

MySQLdb.connectの引数全解説は[MySQLdb.connectの引数全解説](https://qiita.com/momomo_rimoto/items/9da8b3f76d9542defd9a)もぜひお願いします！

また，結論だけ見たい方は[autocommitを使う](autocommitを使う)の章へどうぞ．
本ページの目的は，いっぱいINSERTしたいときとかUPDATEしたいときとかです．try-except使ってINSERTに失敗したときの処理とかは書いていません．

# Insertができないときの普通の対処法
Pythonを使ってMySQLを操作する際にSELECT文はうまくいくのにINSERT文がうまくいかない，ということの説明をしているサイトはいくつもあると思います．この原因はcommitをしていないからで，Qiitaを始めとして，commitをいちいち書く方法や，PythonらしくWith文を使えるようにしよう！というものが色々見つかります．

（参考）
[Python で MySQLのテーブルに INSERT しても反映されない(丸２日無駄に!!)](https://qiita.com/mighty-n/items/19c737a4a140468409c1)
[MySQLdbの優雅な使い方](https://qiita.com/fukkyy/items/759b25d72eb20ac2ccbe)
[PythonでMySQLのデータ操作をやろう](https://qiita.com/ta_ta_ta_miya/items/b95c7a2e5e32545c8adc)

最後のページの筆者の方はautocommit反対派のようですが…．

# 簡単にMySQLdbの使い方
一般的にはこのように使います．

```python:basic.py
import MySQLdb

# データベースに接続
con = MySQLdb.connect(
        user='MySQLのユーザー名',
        password='MySQLのパスワード',
        host='MySQLのホスト名',
        database='データベースの名前',
    )

# カーソルの生成
cur = con.cursor()

# SQL文を作る
# 入力したい数だけ%sは必要
# テーブルの全てのカラムに値を入れる（NULLがなかったりデフォルト値を使わなかったり）なら `(カラム名1, カラム名2, ...)` は不要
sql = "INSERT into テーブル名 (カラム名1, カラム名2, ...) values (%s, %s, ...)"
# 実際の値はここに書く．タプルを書くとき，1つしか中身がないときもカンマが必要なことに注意
cur.execute(sql, (カラム1の値, カラム2の値, ...))
# 保存するためにはコミットが必要
con.commit()
# 必要なだけこのブロックを繰り返す

# 終わるとき
cur.close()
con.close()
```

MySQLdb.connect()関数の引数の説明は[MySQLdb.connectの引数全解説](https://qiita.com/momomo_rimoto/items/9da8b3f76d9542defd9a)を参考にしてください．

# Commit忘れがだるい，そもそもコードが煩雑になる
みんなが抱えている煩わしさのようです．これを回避するために，With文を使う方法がよく取り上げられています．けど個人的に，毎回connectからやるのよくないと思うんですよね．（それが良いのだとしたら2回もcloseしないはず）

# autocommitを使う
ここでGitHubのソースをちゃんと見てみましょう．
（GitHub）https://github.com/PyMySQL/mysqlclient-python/blob/master/MySQLdb/connections.py 
（日本語訳）[MySQLdb.connectの引数全解説](https://qiita.com/momomo_rimoto/items/9da8b3f76d9542defd9a)

`MySQLdb.connect`という関数には引数があり，userやpassword，hostやdatabaseは書くことが多いと思います．他にもcharsetなどは少なくとも使うでしょうか（日本語の場合は`utf8`か`utf8mb4`ですよねきっと）．
これ以外にも，`autocommit`という引数があります．というわけで，以下が本ページの最後のコードです．

```python:advance.py
import MySQLdb

# データベースに接続
con = MySQLdb.connect(
        user='MySQLのユーザー名',
        password='MySQLのパスワード',
        host='MySQLのホスト名',
        database='データベースの名前',
        autocommit=True, # ポイント
    )

# カーソルの生成
cur = con.cursor()

# クエリの実行
sql = "INSERT into テーブル名 (カラム名1, カラム名2, ...) values (%s, %s, ...)"
cur.execute(sql, (カラム1の値, カラム2の値, ...))
# これで保存されている（コミット済み）なので，con.commit()は不要
# 必要なだけこのブロックを繰り返す

# 終わるとき
cur.close()
con.close()
```

commit関数がいらないのでいいですね．connectも一回ですし，with文使うよりも個人的にはスマートです．いっぱいINSERTとかUPDATEしたいときは便利です．
Google App Engine の応答パフォーマンスを改善する

Google App Engine は、 Google の提供する PaaS (Platform as a Service) です。

[App Engine - 任意の言語でスケーラブルなウェブ バックエンドやモバイル バックエンドを構築  |  App Engine  |  Google Cloud](https://cloud.google.com/appengine/?hl=ja)

# App Engine の環境

App Engine にはインフラも含めてGoogleが管理する Standard Environment と、Compute Engine上で実行する Flexible Environment があります。本稿では、 Standard Environment を利用している場合について述べます。

# App Engine Standard Environment のスケーリング設定

App Engine のスケーリング設定は app.yaml に記述します。詳細は公式ドキュメントを参照してください。

[app.yaml リファレンス  |  Python 2 の App Engine スタンダード環境  |  Google Cloud](https://cloud.google.com/appengine/docs/standard/python/config/appref#scaling_elements)

本稿では、 automatic_scaling を利用している場合のチューニング観点について述べます。

## 初回リクエストに対する反応が遅い

`min_idle_instances` の値を 1 以上に設定しましょう。

アクセスが間欠的なサービスの場合には、インスタンスが存在しない状態になっている場合があります。インスタンスが存在しない状態での初回リクエストでは、インスタンス作成されてリクエストが処理されるまで、応答が遅延することになります。

そのような間欠的なリクエストを受けているサービスの場合には、この設定をすることによって、常に待機インスタンスが存在している状態になるので、「初回リクエストでのインスタンス起動待ち」に遭遇する可能性を減らすことができます。

> App Engine では一定数のアイドル インスタンスが常に確保されるため、異常なほど負荷が急増した場合を除き、リクエストが保留中のキューに入る可能性は低くなります。

アプリケーションの構成によって、リクエスト処理可能になるまでの時間に幅があると思います。リクエスト処理可能になるまでの時間が長い場合にはある程度多めのインスタンスを用意しておくことが、パフォーマンスの改善に役立つでしょう。

### 料金の見積もり

`min_idle_instances` を 1 以上に設定した場合、常時稼働分のインスタンス料金が課金されます。

[App Engine の料金  |  App Engine ドキュメント  |  Google Cloud](https://cloud.google.com/appengine/pricing)

例えば、 us-central1 リージョンにおいて、 F2 インスタンス利用しているときに、 `min_idle_instances=2` を設定した場合を考えてみましょう。
2台のF2インスタンスが24時間起動しているので、 F1 インスタンスに換算すると `2(台) * 2 (F2のF1換算) * 24(時間) = 96インスタンス時間` となります。ここから、1日あたり 28インスタンス時間 は無料の割り当てがあるので差し引くと課金対象となるのは `68インスタンス時間` となります。

[割り当て  |  App Engine ドキュメント  |  Google Cloud](https://cloud.google.com/appengine/quotas#Instances)

月あたりの課金額目安は `68インスタンス時間 * $0.05/インスタンス時間 * 30日 = $102/月` となります。

## サービス利用中の途中でリクエストに対する反応が遅い

`max_idle_instances` に大きめの値を設定しましょう。

SPA (Single Page Application) を利用しているような構成では、操作時に多数のリクエストが断続的に発生することがあります。
これは、多数のリクエストによってスケールアウトして作成されたインスタンスが、速やかにスケールインすることによって、インスタンスの不足が発生していることに由来します。

サービスの利用途中でリクエストが詰まるような現象が発生する場合には、 `max_idle_instances` を明示的に大きめの数値に設定することで回避できる可能性があります。

> 最大数を大きく設定すると、負荷レベルの急増後に通常のレベルに戻る際に、アイドル インスタンスの数がより緩やかに減っていきます。その結果、アプリケーションがリクエスト負荷変動の前後を通じて安定したパフォーマンスを維持しやすくなる一方で、そのような負荷の高い期間のアイドル インスタンスの数（その結果としてランニング コスト）も増えます。

### 料金の見積もり

`max_idle_instances` に設定した値は、エンドユーザからのリクエスト等によってインスタンスがスケールアウトした際にのみ意味を持ちます。
逆に、全くリクエストがない場合に `max_idle_instances` を 1000 に設定したとしても課金は発生しません。

`max_idle_instances` に大きな値を設定した場合、その台数までインスタンスがスケールアウトしたときにそのインスタンス台数が継続する期間が長くなります。

 1. リクエストが全くない状態で、 `min_idle_instances` の台数だけインスタンスが存在する
 2. 多数のリクエストによってスケールアウトが行われる
 3. スケールアウトの結果 `max_idle_instances` を超える台数までインスタンスが作成される
 4. リクエストが落ち着くと、速やかに `max_idle_instances` の台数までスケールインが行われる
 5. リクエストが落ち着いている期間が継続すると、緩やかに `min_idle_instances` の台数までスケールインが行われる
 6. インスタンスの台数は `min_idle_instances` に収束する (1. に戻る)

このパラメータによって増加する課金額は、上記の流れの 4. から 5. にかけて、緩やかにスケールインする期間のインスタンス稼働時間に対応します。

# まとめ

パフォーマンス・チューニングは対象のアプリケーション特定によっても異なる部分が多いですが、少しでも参考になれば幸いです。
Vue.js 1.1 インストールとデータバインディング

#インストール
Vue.jsの公式サイトからvueのリンクをHTML中のbodyの上で入れて、そして自分作るVueオブジェクトリンクを一番下で書き置いて、こられは最初のステップです。

```vue_install.html

<body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
                      .
                      .
   　　　　　           .
    <script src="js/main.js"></script>
</body>
```

#データバインディング
先ずはVueオブジェクトを作る、その中はelはHTMLタグを指定されたidまたはclass名（#id,.class)、dataは画面に表示したいの内容です。

```vue_object.js
    var test=new Vue({
         el:'#app',
         data:{
             name:'larry'
         }
    });
```
それから、HTMLを示す書き方です。{{}}とv-textはどちらができます。

```data_view.html
<p> {{ name }}</p>
<div v-text="name"></div>

```
ちなみに、Vueオブジェクトのdata中にHTMLのタグを入れる方法もあります。

```data_view.js
 var test=new Vue({
        el:'.nickname',
        data:{
            nickname:'<span>sam</span>'
        }
```
v-modelはデータバインディングの機能です。データバインディングはビュー（ここはHTML）とモデル(vueオブジェクト)を繋いで、データ画面から入力同時にvueオブジェクトのデータ内容を変更でき、vueオブジェクトのデータ内容すると、画面が同時に変更できることです。

```vue_v-model.html
<body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
    
    <div class="app">
        <p> {{ name }}</p>
        <p><input type="text" v-model="name"></p>
    </div>
    <script src="js/main.js"></script>
</body>
```

```vue_v-model.js
    var test=new Vue({
         el:'.app',
         data:{
             name:'larry',
             nickname:'<span>sam</span>'
         }
    });
```

#注意点

データバインディングをコントロール一できるDOMの組数は一つしかない。

```error_01.html
<body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
    
    <div class="app">
        <p> {{ name }}</p>
        <p> {{ name }}</p>
        <p><input type="text" v-model="name"></p>
    </div>
    <div class="app"> <!--第二組は無効です-->
            <p> {{ name }}</p>
            <p><input type="text" v-model="name"></p>
        </div>
    <script src="js/main.js"></script>
</body>
````

二重結構も無効になる。

```double_struct.html
 <div class="app">
        <p> {{ name }}</p>
        <div v-text="name"></div>
        <div class="app"> <!--無効です-->
                <p> {{ name }}</p>
                <p><input type="text" v-model="name"></p>
        </div>
        <p><input type="text" v-model="name"></p>
 </div>


```
Kotlinで配列のJson文字列をGsonでparseする

### Json文字列(単独) -> 　任意クラス

`"{a=A, b=B}"`みたいなJson文字列を下記`HogeData`に変換したい場合

```HogeData.kt
data class HogeData(
    var a: String,
    var b: String
)
```

```Hoge.kt
val strJson = "{a=A, b=B}"
val hogeData = Gson().fromJson(strJson, HogeData::class.java)
val a = hogeData.a
```

### Json文字列(配列) -> 任意のクラスのList

`"[{a=A, b=B},{a=AAA,b=BBB}]"`みたいなJson配列の文字列を下記`HogeData`のList型に変換したい場合

```HogeData.kt
data class HogeData(
    var a: String,
    var b: String
)
```

```Hoge.kt
val strJson = "[{a=A, b=B},{a=AAA,b=BBB}]"
val listType = object : TypeToken<List<HogeData>>() {}.type
val hogeData = Gson().fromJson<List<HogeData>>(strJson, listType)
val a = hogeData[0].a
```
Eclipse上でTypescriptの型チェックが動かないときに確認すること

EclipseのTypescriptエディタでは、たまに型チェックがうまく動かず`any`になる事がある。メソッドの候補が表示されないと面倒なので何とかしたいのだが、いくつか原因があるので大抵は試行錯誤になる。いくつか良く嵌まるパターンを以下にまとめる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296170/15524d9b-fda9-0b22-ae07-454b7f770dce.png)

# Typescriptのバージョンが異なる
EclipseのTypescriptプラグインでは、型をチェックするためのトランスパイラを指定できる。デフォルトでは「内蔵」になっており、`Package.json`でインストールしたローカルのトランスパイラとは関係が無い。これにより、「ビルドはできるがエディタ上はエラーになる」という不可解なことが起こる。

Typescriptのバージョンが正しいかを確認するには、EclipseでWindow > Preferences > JavaScript > Typescript > Runtime から以下の設定画面を開く。`Consume Typescript With`でEmbeddedが選択している場合、インストールから時間が経つことで新しい言語仕様に対応できずエラーになる可能性がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296170/2183807a-2714-8800-ace7-7cb1211c5885.png)

以下のような設定があると思う。

| Typescriptの場所 | パス |
|:-----|:-----|
|プロジェクトごと|${workspace_loc:プロジェクト名/node_modules/typescript}|
|グローバル|\<npm config lisで表示されるprefix\>/node_modules/typescript}|

# tsconfigの設定に不備がある
結構落とし穴があるが、Google検索すれば大抵同じ間違いに嵌まった人がいるので、大抵の答えは得られる。以下のようなケースがある。(これらはトランスパイルもエラーになるから特に不可解ではないが…)

## ライブラリを指定していない
`Promise`,`HTMLElement`,`async/await`,`array.map`など、当たり前に使えるべきものが無いというエラーが起きる場合、`compilerOptions`の`lib`が不足しているか、指定はしているが`es*`のバージョンが非対応などの可能性がある。

[TypescriptのCompiler Optionsの一覧](https://www.typescriptlang.org/docs/handbook/compiler-options.html)から選べるものを調べるようにする。

```json:tsconfig.json
{
  "compilerOptions": {
    "lib": [
      "es2015",
      "dom"
    ]
  }
}
```
## JSXを有効にしていない
これはReact限定かもしれない。`react`と`react-native`に分かれているので、間違わないようにする。

```json:tsconfig.json
{
  "compilerOptions": {
    "jsx": "react"
  }
}
```

## デコレータを有効にしていない
デコレータは使おうとすると「この設定を有効にすること」と表示されるのですぐ気づける。(いつまでexperimental?)

```json:tsconfig.json
{
  "compilerOptions": {
    "experimentalDecorators": true
  }
}
```

# @typesをインストールしていない
nodeで`fs`が使えないなど、JavascriptライブラリをTypescriptで使おうとする場合に起きる。`npm install @types/ライブラリ名`で必要な型情報をインストールしておき、`tsconfig.json`の`typeRoots`を設定しておけば解決する。

```json:tsconfig.json
{
    "typeRoots": [
      "node_modules/@types"
    ]
}
```
MySQLdb.connectの引数全解説

MySQLdbの基本的な使い方は[MySQLdbでレコードを保存できない対処法（autocommitを使う）](https://qiita.com/momomo_rimoto/items/a0886fc6b801f97f6dc1)にて簡単に説明しているので，必要に応じてご覧下さい．

詳細
https://github.com/PyMySQL/mysqlclient-python/blob/master/MySQLdb/connections.py 

|パラメタ名 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|型 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|説明 &nbsp;|
|:-:|:-:|---|
|host|str|接続するホスト名|
|user|str|接続するためのMySQLのユーザー名|
|password|str|MySQLのパスワード|
|passwd|str|passwordへのエイリアス．後方互換性のために存在|
|database|str|使用するデータベース名|
|db|str|databaseへのエイリアス．後方互換性のために存在|
|port|int|接続するためのTCP/IPポート|
|unix_socket|str|用いるunix_socketの場所|
|conv|dict|MySQLdb.converters関数のための辞書型引数．割愛|
|connect_timeout|int|接続切れまでの時間（秒）|
|compress|bool|セットするとcompress（圧縮）する|
|named_pipe|str|セットすると名前付きパイプを使う（Windowsのみ）|
|init_command|str|接続が開始されたときに走らせるコマンド|
|read_default_file|str|設定するとこのファイルからデフォルトのクライアントの値が読まれる|
|read_default_group|str|デフォルトファイルから使うグループのconfiguration group|
|cursorclass|type|cursorを作るためのオブジェクトのクラス．（keywordのみ）|
|use_unicode|bool|Trueにすると，テキストlikeなカラムがconnectionの文字コードを使ったunicodeオブジェクトとして返ってくる．Falseなら，テキストlikeなカラムはバイト列として返ってくる．unicodeオブジェクトは常にこの設定に関わらずconnectionの文字コードとしてエンコードされる．デフォルトはPython2でFalse，Python3でTrueなので，デフォルトでPythonの'str'が常に手に入る．|
|charset|str|設定すると，connectionの文字コードが変更される．Python2では，このオプションによって`use_unicode`オプションがFalseからTrueに変更される．|
|sql_mode|str|設定すると，セッションのSQLモードが変更される．詳細はMySQLのドキュメントへ．|
|client_flag|int|使うclient_flagの設定，client_flgについては詳細はMySQLのドキュメントへ．取れる引数は[constants/CLIENTS.py](https://github.com/PyMySQL/mysqlclient-python/blob/master/MySQLdb/constants/CLIENT.py)でも見れる．|
|ssl|dict|SSL接続のパラメータを含む辞書ないしmapping．mysql_ssl_set()も参照．設定され，クライアントがSSLをサポートしていない場合，NotSupportedErrorが発生する．|
|local_infile|bool|`LOAD LOCAL INFILE`を有効にする．0ならば無効．|
|autocommit|bool|False（デフォルト）なら，自動コミットは無効．Trueなら有効．Noneなら自動コミットは設定されず，サーバーのデフォルトが使用される．|
|binary_prefix|bool|Trueに設定すると，`_binary`という接尾語が（Binaryなどの）生のバイトのクエリの引数に使われる．これはデフォルトで無効．|


`charset`では`utf8`や`utf8mb4`を使います．`utf8mb4`は4バイト文字の利用．`autocommit`を`True`にすると，`commit()`をしなくてよくなります．
Rust

# Rust入門

# 公式ドキュメントを見てみる
[Rust Lang](https://www.rust-lang.org/ "Rust Lang")
- Rustってどんな言語？
A language empowering everyone to build reliable and efficent software.
信頼性と効率的なソフトウェアを作りたい人の力になる
- なぜRust?
Performance
Reliability
Productivity
- Rustで何を作る？
Command Line
WebAssembly
Networking
Embedded
- Rustを使っているのは？


## Install
インストール方法
## Learn
学習リソース
## Tools
ツールチェーン
## Governance
コミュニティー運用等ロードマップ
## Community
コミュニティー
## Blog 
ブログ
Swiftの辞書について質問です

つい今月、iPhoneアプリを作りたいと思い、Swifを学びはじめたプログラミング未経験者です。

本を読んだり、ググったりしているのですが、
わからない点がありましてご教授をいただきたいです！

今、配列と辞書の違いを勉強していまして
辞書は結果がオプショナルになる、そしてオプショナルを外さないとそのままの値では使えない、という所までは理解しました。

以下、コードを描いてみたのですが、アンラップをつけて値を取り出そうとするとエラーになってしまいます・・・

何故なのか、調べてもよく理解できず＞＜

ご教授いただけると嬉しいです！

よろしくお願いいたします！！




//辞書
var cameraLens: [String: Int] = ["key1": 24, "key2": 50, "key3": 85,]
cameraLens["key1"] = 2470 //辞書の値を更新
cameraLens["key4"] = 135 //辞書に追加
print(cameraLens["key1"])
print(cameraLens["key5"]) //key5は無いからnilになる

let key2: Int? = cameraLens["key2"] //　?をつけてオプショナル型を指定している。オプショナルが外れる
print(cameraLens)

// ↓エラーになっちゃうその１
if cameraLens["key1"] != nil { //　if文の中で(!)アンラップをつけてnilでないことをチェックしている
    print(cameraLens["key1"]
}

//　↓エラーになっちゃうその２
else if cameraLens["key4"] != nil { //アンラップをつけてオプショナルでない値を取り出す
    let key4: String = cameraLens["key3"]! //アンラップを最後につける
    print(key4)
}
Android で CloudVision API を使って、リモート画像を指定して ラベル検出する

[Android で CloudVision API を使ってラベル検出する](https://qiita.com/ohwada/items/b34718df6a6362e493dc)
の続きです。

前回の記事では、画像をアップロードして、ラベル検出を行った。
今回は、リモート画像のＵＲＬを指定して、ラベル検出を行う。

### 画像の指定

画像を指定するには次の 3 つの方法がある。

(1) 画像をbase64 エンコードの画像文字列として CloudVision にアップロードする。

(2) Gogle Cloud Storage の URI を指定する。

(3) HTTPでアクセス可能な公開 URLを指定する。


[docs Vision API リクエストを作成する](https://cloud.google.com/vision/docs/request)


```
// Convert the bitmap to a JPEG
            byte[] imageBytes = convJpegByteArray(bitmap);

            // create the image
            Image image = new Image();

            // Base64 encode the JPEG
            image.encodeContent(imageBytes);

            annotateImageRequest.setImage(image);

private byte[] convJpegByteArray(Bitmap bitmap) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            // Convert the bitmap to a JPEG
            bitmap.compress(Bitmap.CompressFormat.JPEG, JPEG_QUALITY, byteArrayOutputStream);
            byte[] imageBytes = byteArrayOutputStream.toByteArray();
            return imageBytes;
}
```

画像のＵＲＬを指定する場合は、
下記のように annotateImageRequest を生成する

```
         // create ImageSource
        ImageSource source = new ImageSource();
        source.setImageUri(imageUrl);

        // create the Image
        Image image = new Image();
        image.setSource(source);

    AnnotateImageRequest annotateImageRequest = new AnnotateImageRequest();
    annotateImageRequest.setImage(image);
```

[api AnnotateImageRequest](https://developers.google.com/resources/api-libraries/documentation/vision/v1/java/latest/com/google/api/services/vision/v1/model/AnnotateImageRequest.html)

[api ImageSource](
https://developers.google.com/resources/api-libraries/documentation/vision/v1/java/latest/com/google/api/services/vision/v1/model/ImageSource.html)

[api Image](
https://developers.google.com/resources/api-libraries/documentation/vision/v1/java/latest/com/google/api/services/vision/v1/model/Image.html)


### 実行例
スクリーンショット
![cloud_vision3_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64075/2a5186d9-38b9-ea60-bd1b-adeeafda6825.png)

ラベルとスコア

> Dog (犬): 0.995
> Mamma (l哺乳類): 0.989
> Vertebrate (脊椎動物): 0.985
> Canidae (イヌ科) : 0.981
> Cocker spaniel (コッカースパニエル): 0.901
> Dog breed 9犬の品種): 0.895
> Carnivore (肉食動物): 0.855
> Sporting Group (スポーツ犬): 0.833
> Grass (草): 0.822
> Companion dog (愛玩犬): 0.816

哺乳類の犬で犬種はコッカースパニエルと判定された。

サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/CloudVision3
【Error: Cannot find module 】yarnでグローバルインストールしたモジュールの参照エラーの対処法

## はじめに
`yarn`でグローバルインストールしたモジュールを`Node.js`で参照しようとした際に、`Cannot find module`エラーに出くわしました。

`yarn add`で、開発プロジェクト内にモジュールをローカルインストールすると問題ないのだが、グローバルインストールしたモジュールは参照できませんでした。つまり、`PATH`に問題があるとみて対処しました。

メモよりの投稿です。

## 環境
OS: MacOS
Pakcage Manager: yarn

## エラー

次のように、`require`で`fuga`モジュールをグローバル参照しようとした。

```hoge.js
const fuga = require('fuga');
```

`node`コマンドで`js`ファイルを実行すると、`fuga`モジュールを見つけられないと怒られる。

```zsh
❯ node hoge.js
Error: Cannot find module 'fuga'
```

## 対処法

#### 1. グローバルなインストールディレクトリを確認

[yarn global](https://yarnpkg.com/lang/ja/docs/cli/global/)から引用すると、
> yarn global dir コマンドは、グローバルな node_modules を含むグローバルなインストールディレクトリの出力を表示します。デフォルトでは、~/.config/yarn/global になります。


```zsh
❯ yarn global dir
/Users/takuyanin/.config/yarn/global 
```

#### 2. NODEにグローバルなモジュールパスを設定

```zsh
❯ export NODE_PATH=$HOME/.config/yarn/global/node_modules
```

もしくは、`.zshenv`に記述。

####3. グローバルなモジュールパスを確認
`global.module.paths`に目的パスが含まれていることを、念のために確認。

```zsh
❯ node
> global.module.paths
[ '/Users/takuyanin/.config/yarn/global/repl/node_modules',
  '/Users/takuyanin/.config/yarn/global/node_modules', 👈パスが確認できる
  '/Users/takuyanin/.config/yarn/node_modules',
  '/Users/takuyanin/.config/node_modules',
  '/Users/takuyanin/node_modules',
  '/Users/node_modules',
  '/node_modules',
  '/Users/takuyanin/.node_modules',
  '/Users/takuyanin/.node_libraries',
  '/Users/takuyanin/.nvm/versions/node/v10.15.3/lib/node' ]
>
```

## おわりに

基本的には、プロジェクト内に直接インストールすると思うが、ふとした拍子にグローバルインストールしたモジュールを参照しようとすると、少しハマったので、簡単にまとめました。
Swiftで複数登録可能なdelegateを作る【型安全】

## `weak`なコレクション


Swift では循環参照の回避のために `weak` なオブジェクトを扱う必要がある場合があります。
例えば `delegate` が `weak`でないと循環参照を起こしやすくなってしまいます。

しかし、`delegate` は多くの場合1つのみ用意されていて、
複数のオブジェクトを登録することはできません。とは言っても

```swift
weak var delegate: ADelegate? // これはOK
weak var delegates: [ADelegate]? // これはダメ
```

このように配列として `weak`なオブジェクトを管理することはできません。
また、https://qiita.com/codelynx/items/b5bb9199d01d63d590e0 で紹介されている
`ZWeakObjectSet`には`protocol`を入れることができません。

なので以下のような使い方のできる`Set`を作成しようと思います。

```swift
protocol ADelegate {
    func hoge()
}

class Huga {
    var delegates = RMWeakSet<ADelegate>()

    ...
    
    delegates.forEach{ $0.hoge() }
```

## `実装`
なので、`NSHashTable<AnyObject>.weakObjects()`をラップして型安全に `protocol`
を入れられる`weak`なコレクションを作成しようと思います。

```swift
public class RMWeakSet<T> {

    // =========================================== //
    // MARK: - Properties -
    
    public var all: [T] { objects }
    
    private var _objects = NSHashTable<AnyObject>.weakObjects()
    private var objects: [T] { _objects.allObjects.compactMap{$0 as? T}}
    
    // =========================================== //
    // MARK: - Methods -

    public func contains(object: T) -> Bool {
        return _objects.contains(object as AnyObject)
    }

    public func append(_ object: T) {
        
        self._objects.add(object as AnyObject)
    }

    public func append(objects: [T]) {
        for object in objects {
            _objects.add(object as AnyObject)
        }
    }

    public func remove(_ object: T)  {
        _objects.remove(object as AnyObject)
    }
    
    // =========================================== //
    // MARK: - Constructor -
    public init() {}
    
    public init(_ objects: [T]) {
        for object in objects {
            _objects.add(object as AnyObject)
        }
    }
}
```

`AnyObject`への変換はこのクラス内で行うことで、protocolも内部で保管できるようにしています。
さらに`Sequence`に準拠させておきます。

```swift
extension RMWeakSet : Sequence {
    public typealias Iterator = Array<T>.Iterator
    
    public func makeIterator() -> Iterator {
        return self.objects.makeIterator()
    }
}
```

以上で複数登録可能な `delegate`ができました。



## まとめ
`class-bound`の`protocol`は`AnyObject`として扱えるようにして欲しいです...
RoRでJSONを出力する際にテーブルの列名とキー値が異なる時の対処

#やりたいこと
fullcalendarで以下の様に予定を表示させたい。
![スクリーンショット 2019-09-01 9.37.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468786/1c693391-a320-b314-3eaa-acf9cff44f66.png)

##表示させるために
以下の様なJSONを出力する必要があります。
```json
{"title":"テスト","start":"2019-09-01T09:00:00.000Z","end":"2019-08-29T10:00:00.000Z"}
```

テーブルの列名はname,from_time,to_timeとなっていて、
それぞれ
title ⇔ activity_name 
start ⇔ from_time
end   ⇔ to_time
として紐づいています。

##自分の環境
- Linux Debian 10.0(Docker上)
- ruby 2.6.3p62
- Rails 5.2.3

current_userはログインしているuserを返す自作ヘルパーです。
userとactivity_historysは1:Nの関係です。

#実装したコード（最終形）
```controller.rb
    act_histories = current_user.activity_historys.select(
      "activity_name AS title,
      from_time AS start,
      to_time   AS end"
    ).as_json(only: [:title, :start, :end])

      respond_to do |format|
      format.json {
        render json: act_histories.to_json
      }
```

###没になったコードその１
```controller.rb
   act_histories = current_user.activity_historys

    array = []

    actHistorys.each do |act|
      hash = {}
      hash.store(
        "title", act.activity_name
      )
      hash.store(
        "start", act.from_time
      )
      hash.store(
        "end", act.to_time
      )
      array.push(hash)
    end

    respond_to do |format|
      format.json {
        render json: act_histories.to_json
      }
    end
```
単純にコード量が多い。また、データ量が多いと処理速度が下がるのではと思い、SQLのAS句を使用したくななりました。


###没になったコードその２
```controller.rb
    act_histories = current_user.activity_historys.select(
      "activity_name AS title,
      from_time AS start,
      to_time   AS end"
    )

    respond_to do |format|
      format.json {
        render json: act_histories.to_json
      }
```

```json
{"id":null,"title":"テスト","start":"2019-09-01T09:00:00.000Z","end":"2019-08-29T10:00:00.000Z"}
```

idカラム指定していないのにidがNULLとして出力される...
idいらないんじゃ！

###没になったコードその3
```controller.rb
    act_histories = current_user.activity_historys.select(
      "activity_name AS title,
      from_time AS start,
      to_time   AS end"
    ).pluck(:activity_name, :from_time, :to_time)

    respond_to do |format|
      format.json {
        render json: act_histories.to_json
      }
```

```json
["テスト","2019-09-01T09:00:00.000Z","2019-08-29T10:00:00.000Z"]
```
as句で指定した列別名が消えてしまう。

##まとめ

- テーブルの列名とキー値が異なる時はselectメソッドで列別名をつける
- idがNULLになるのはas_jsonでonオプションを指定する


###参考にさせていただいたページ
https://qiita.com/TakakiSato/items/f4192611a4737323fcb4
https://qiita.com/k-o-u/items/31e4a2f9f5d2a3c7867f
https://railsguides.jp/active_record_querying.html
https://fullcalendar.io/docs/v3/events-json-feed
【iOSDC Japan 2019  事前ブログ】今年はレギュラートーク&スタッフやります

# iOSDC Japan 2019 でレギュラートークします！

9/5(木)-9/7(土)に開催されるiOSDC Japan 2019で
３０分のレギュラートークをさせていただきます。

![スクリーンショット 2019-09-01 5.19.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219965/beb70641-2752-3022-7efa-c8cdd748ab69.png)

https://fortee.jp/iosdc-japan-2019/proposal/0c06aeca-5b6a-4bbe-aeeb-7531740975c5

今回は
**「Swift クリーンコード アドベンチャー ~日々の苦悩を乗り越え、確かな選択をするために~」**
というタイトルです。

内容としては

- クリーンコードって何だろう？
- クリーンコードを書くにはどうすればいいんだろう？
- クリーンコードを書き続けるにはどうすればいいんだろう？

といったことなどを具体例を交えながら話させていただきます。

私が日々の開発の中で悩み続けていることや
様々な資料に触れている中で気がついたことや感じたことを中心に

「良いコードを書くってどういうことだろう？」

などをみなさまと改めて考えるきっかけになれば良いなと思っています。


ちょうどランチ直後のセッションになりますので
食後の休憩ぐらいの感覚でふらっとお越しいただけたら嬉しいです！

# スタッフとしても参加します！

また昨年に引き続きスタッフとして参加させていただきます。

今年はコアスタッフとして
現在本番に向けて着々と準備を進めている段階ですが
一段落したのであとは本番を存分に楽しむだけです。
※個人の感想です


私が担当した〇〇とか当日の〇〇とか
どういう反応があるのかを考えると非常にドキドキしていますが
喜んでいただけたり一緒に楽しんでいただけたら嬉しいです。

# 私にとってのiOSDC

iOSDCの参加は今年が２回目になります。

私にとってiOSDCは

**「学びと出会いと遊びのバラエティパック」**

だと思っており

数多くのセッションから自分の聞きたいセッションを選び
知らない世界に入るきっかけや改めて学び直せる機会がたくさんあるのと

勉強会で会った方に久々に会いに行く機会でもあり
知らなかった方と初めてお話できる機会でもあります。

企画もたくさんあり
参加するもしないも自分で選ぶことができます。

つまり
**人によって自由に参加の仕方も楽しみ方も選べます。**

みんなでワイワイするのも楽しいですが
それ以外にも楽しみ方がたくさんある
そういうところがiOSDC Japanの魅力の一つであると
私は感じています。

今年のテーマは「遊園地・テーマパーク」ですので
まさに色々な乗り物(セッション・企画)があり
乗りたいと思ったものに好きに乗ることができます。

今年も肩肘貼らず自分らしく楽しんでいきたいなーと思います。

# ただただ、楽しみです

このブログを書いている時点(9/1日曜日)から考えると
来週の今頃にはもう終わっているんだなと思い
まだ始まってもいないのに少し寂しく感じてしまいますw

本番中どんなことが起きるかはわかりませんが
何となくどこかで笑って過ごしている光景が目に浮かびます。

私はスタッフで会場をウロウロしていることが多いかと思いますが
もし名札のアイコン見て「見たことがある」と思ったらぜひ気軽に声をかけてやってください。

難しい顔をしているとしたら
自分のトーク前で緊張しているか
予定通りに進行しているか不安に感じているくらいで
そんなに当日忙しい用事はないはずですw

もちろん何か困ったことやわからないことがある時も聞いてください。
私が直接わからなくても最低限知っている人に聞くことはできますので！

それでは
**ぜひぜひ楽しんでいきましょう！！**


# そういえば

最後にふと思い出したのですが
去年のiOSDC Japanで
[BrewDogのパンクIPA](https://whisk-e.co.jp/products/punkipa/)を飲んで
IPAビールという存在を初めて知り
大好きになりました。

iOSDC Japanではクラフトビールが豊富に揃っているので
ビールが好きな方は
もしかしたらがビールとも良い出会いあるかもしれません🍺
900円のアナライザ

中華製の900円のプロトコル・アナライザを試してみました。
あちこちにお試し記事があるので、私も試しに買ってみたのですが噂通りの凄い奴(^^;
特にサンプリング個数がもの凄いので、なにかすら使い途はありそうです。
[**こちら**](https://yokaton.com/mcu-nxp/#i-5)に纏めてみました。
Rで相関行列を作成する際の'x' は数値でなければなりません  

![スクリーンショット 2019-09-01 9.24.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355150/7049f47b-2152-5209-0fe8-554f22d006cf.png)
単に1行目の「野球選手の体力測定」が邪魔だったようです。
これを数値として読み込めないために

```ruby:qiita.rb
> 体力測定 <- read.csv("example_3.csv",header=TRUE)
> 相関行列<- cor(体力測定)
 cor(体力測定) でエラー:  'x' は数値でなければなりません 
```

エラーが出てしまったようです。
元のエクセルファイルをいじって「野球選手の体力測定」を取り除いてやるとうまくいきました。

また1列目は番号がついているのでrow.names=1を入れて、1列目を行名として扱います。

```ruby:qiita.rb
体力 <- read.csv("example_3.csv",header=TRUE, row.names=1)
```


これでやっとできましたが、エクセルファイルをわざわざ変更するのが面倒です。
なんとかしてR上で指定して1行目の文字列を無視してもらうことはできないものでしょうか。。。
そこに空白は要らない｜marginやpaddingなどの空白を確認する方法をご紹介します。

##こんにちは西村です
[未来電子テクノロジー](https://www.miraidenshi-tech.jp/)でインターンをしている西村です。
今回は、webページを作る時に不意に出てくる要らない空白の処理方法を書きます。

##意図しない場所に現れる空白
みなさんHTMLとCSSを勉強し始めた時に経験したことがあるかもしれません。
コイツです。（見やすいように背景をグレーに変えています。）

![スクリーンショット 2019-09-01 9.11.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402724/4f48d862-3fa3-5074-75d2-b80539130f58.png)

この周りのグレーの縁部分が不要なのですが、特に余白はこちらで設定していません。
こういう時に余白をもたらす犯人の見つけ方をご紹介します。

##computedで余白を確認
要素の検証ツールの中に余白を確認できるcomputedというものがあります。

![スクリーンショット 2019-09-01 9.17.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402724/39da8871-a447-2b87-2d97-e978e65094ad.png)


このように、任意の場所をクリックすると、その箇所が含む余白が三つ重なったの四角の図に表されます。
この場合だと、bodyに対して8pxのmarginが有効になっているので、cssで`body{margin:0px;}`とすれば解決します！

##検証ツールを使えるようにすれば効率アップ
不具合を修正する時にコード全体を見ていたらキリがありません。
検証ツールで怪しい箇所を探し出して、デバッグを高速化できるようにしておきましょう！
Windows で新しいドライブを作成する方法

## はじめに

開発サーバーを客先サーバに合わせようと思ったら、開発サーバーに客先環境で使っているドライブがない。そんな時に新しいドライブを作成する方法として以下の４つがあります。

## 外付けHDD

外付けHDDを接続するだけなので最も簡単です。

但し、会社によっては外付けHDDの使用制限があるので注意が必要です。

ちなみに、接続した外付けHDDが意図したドライブに割り当たらない場合、「管理ツール」の「コンピューターの管理」から割り当てを変更することができます。詳細は「ドライブの変更」でGoogle先生に聞いてください。

## パーティション分割

既存のドライブ（パーティション）の容量を小さくして、空いた容量を新しいドライブとして割り当てます。恒久的に新しいドライブが必要な場合の王道だと思います。

但し、「既存のパーティションを変更してPCが動かなくなったらどうするんだ」という謎の抵抗を受けることがあるので、事前に許可をとってから行うのがよいと思います。

「管理ツール」の「コンピューターの管理」から行えます。詳細は「パーティション分割」でGoogle先生に聞いてください。

## VHD

HDのイメージファイルを作成して、新しいドライブとして割り当てます。一時的に新しいドライブが必要な場合は有効かと思います。

「管理ツール」の「コンピューターの管理」から行えます。詳細は「VHD」でGoogle先生に聞いてください。

※ VHDのマウントは、OSを再起動すると外れます。その辺も含めて以下のページが参考になりました。
『仮想ディスクをWindows起動時に自動マウント（アタッチ）するシンプルな方法…バッチファイルもスクリプトファイル不要。』
http://siso-lab.net/yoga-book-vhd-auto-attach/


## ネットワークドライブの割り当て

特定のフォルダを共有フォルダにして、ネットワークドライブとして新しいドライブに割り当てます。とりあえず、ドライブを作って動作させたい場合に使えるかもです。

但し、事前に割り当てたネットワークドライブは、ログインユーザが対話形式で実行した場合しか認識されません。タスクスケジューラ―やJP1といったタスク管理ツールやサービスからバックグランドで起動する場合はドライブが認識されないことがありますので注意が必要です。

## おわりに

補足・他の方法なのど、コメント頂けると嬉しいです。
エンジニアになるためのオリジナルサービス完成！【PHPとYouTube Data APIを使って】

どうも、Hiroyukiです＾＾

####ここ１ヶ月くらい専念して作っていた、オリジナルサービスが
####ついに（ほぼ）完成しました！！！（感涙）

heroku と GitHub にプッシュしましたので、宜しければ是非ご覧いただいて
実際に利用してみてください！


##[YouTubeまとめ × コミュニケーション (オリジナルサービス)](http://youtubematome.herokuapp.com/) ←クリックして閲覧！
####　[ソースコード閲覧はコチラ（GitHub）](https://github.com/shiba920sof/youtubematome)
<img width="1017" alt="スクリーンショット 2019-09-01 8.17.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489124/15c6f6bb-be74-1038-f9fe-c17fae04d4d9.png">

#オリジナルサービスのコンセプト

####●あなたがオススメしたい「YouTube動画」を自由に登録して、他人にオススメできる！
####●Twitterのように、フォローし合ってお互いの動画を共有できる！



######「そんなもん、YouTubeに付いてる普通の機能やんけ（笑）！」

と思ったそこのあなた！！！ ちょっとお待ち下さい（笑）



話は少し変わりますが、今音楽業界で一番稼いでいるのは、[アーティストでもプロデューサーでもなく、「DJ」なのです](https://rutty07.com/entry/information-skill/)。

つまり今は、自分で作品を作ること以上に、他人が作った作品をオススメしたり・サンプリングすること
自体が評価される時代なわけです。

なので今後は、動画の世界も、
######「”この人がオススメするYouTube動画”、マジで全部イケってから、お前も観てみろYO！！」
みたいに言う人が増えて、**動画の評価者自体が評価される時代になるだろう**と思ってます！


少し脱線しましたが、要は
######「YouTube動画のまとめサイトを”超簡単に自分で”作れて
######さらにその動画を共有することで、”みんなとコミュニケーション”できるサービスが
######あったら楽しいやろうなぁ〜！」
と思って、このサービスを作りました。


#悩みまくったところは・・・

僕はオンラインのプログラミングスクールに通いながら、このサービスを作っていたのですが、その先生からも
####「本当にこのサービス、できるのか・・・？」
と疑問視されていました。。。

というのも、先生たちは、PHP/Laravelに関しては専門家なので何でも答えてくれるのですが、
YouTube API に関しては経験がほとんどないのでアドバイスできないのです。。。

しかも、調べてて途中で気づいたのですが、
####「Laravelを利用した”YouTube API”の情報は、日本語の情報がマジでない！！！」
ということでした。

プログラミング上級者の方なら当たり前かも知れませんが、初学者の僕はそもそも英語でググるという習慣も少なく
正直英語情報で調べるというのは、心理的・時間的な負担が大きかったです（汗

ですが、**YouTube/GoogleのclientAPI**と自ら格闘し、
Google翻訳の力も借りながら、何とか**サービスがほぼ初期のイメージ通り**完成しました！
ほんっっっとに嬉しいです。



ただ、「このサービスからYouTubeへ、自分で撮影した動画を投稿できる機能」も実装済みなのですが、
動画を１日に複数アップすると、Googleのクォート制限により、一時的にアップロードができなくなるなど、
いろいろ不備もあると思います。

なので、サービス詳細部分は多めに見てもらいつつ、**不備があれば都度ご連絡・ご指摘**頂けると
とても嬉しいです。

まずは、是非使ってみて下さいね＾＾
ransackの検索パラメータを渡す方法　メモ


##link_to
例えばlink_toで
```book/1``` というルーティングに画面遷移したい場合

```
book = Book.find(1)して

link_to @book.name, book_path(book.id)とか
link_to @book.name, book_path(params[:id])とか
```

すると思う。多分ね。
ransackの場合

```
link_to @book.name, book_path(@q, :'q[book_id_eq' => "#{@book.id}")
```
という風にするとransackのquery parameterを与えることができる。


##indexページでransackで@booksという一覧を表示している場合

ransackで検索するには
[eq, start, cont]とかをうまく使う

今回もBookオブジェクトがあると仮定

```
  def index
    #検索オブジェクト
    @search = Book.ransack(params[:q])

    #検索結果
    @books = @search.result
  end
```
```
<%= search_form_for @search do |f| %>
  <%= f.label :name, "名前" %>
  <%= f.search_field :name_start %>

  <%= f.label :price_gtep, "価格" %>
  <%= f.search_field :price_gteq %>

  <div class="actions">
    <%= f.submit "検索" %>
  </div>
<% end %>

```

```
link_to "一覧に戻る", books_path(@q, :'q[book_name_start' => "#{@book.name}")
```

これで一覧に戻ったときに検索した状態で@book.nameを検索した状態で一覧表示されます。
urlをみるとbooks/%DAsvijkrgsdみたいなransackの検索パラメータが埋め込まれているはず。
pageも引数として受け渡せるかは謎。試してみる。
ReactNativeでアプリがForeground,Backgroundに移行するEventを拾って何かしたい。


アプリがForegound⇔Inactive⇔Backgroundに移行するイベントをトリガーにして何かやりたいとき用に調べました。
AppStateというのを利用すれば取れるみたい。

[この記事](https://reactnativecode.com/detect-app-is-in-background/)を参考（まんまですが）に、動作確認（とりあえずiOS）。

```js:App.js
import React from 'react';
import { StyleSheet, Text, View, AppState } from 'react-native';
import { newTS } from 'uuid-js';

export default class App extends React.Component {

    constructor() {
        super();
        this.state = {
            appState: AppState.currentState,
        }
    }

    componentDidMount() {
        AppState.addEventListener('change', this._handleAppStateChange);
    }

    componentWillUnmount() {
        AppState.removeEventListener('change', this._handleAppStateChange);
    }

    _handleAppStateChange = (nextAppState) => {

        this.setState({ appState: nextAppState });

        if (nextAppState === 'background') {
            console.log("Backgound mode");
        }

        if (nextAppState === 'active') {
            console.log("Foregound mode");
        }

        if (nextAppState === 'inactive') {
            console.log("Inactive mode");
        }
    }

    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignContent: 'center' }}>
                <Text>Current state is : {this.state.appState}</Text>
            </View>
        );
    }
}
```
webarenaでubuntu その39

#概要

webarenaでubuntu18.04やってみた。
plunkerでfavicon作ってみた。

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/1936711a-0e05-9a46-8e80-3cb1b6a8ede7.png)

#成果物

https://embed.plnkr.co/jv00YWjYtaESSOL5Mv5C/

以上。
logrusでナノ秒まで時刻出力を行いたい

golang の構造化ロガーのうち有名なものの一つに [logrus](https://github.com/sirupsen/logrus) があります。構造化ログとして JSON フォーマットを指定するとするとだいたいこんな感じになります

```json
{"level":"info","msg":"hello world","time":"2019-09-01T06:56:59+09:00","user":"kiririmode"}
```

で、このログのタイムスタンプなんですが、できるだけ分解能を細かくしたい。ログにおいてはタイムスタンプって解析の貴重な手がかりなので、秒単位だときつい。せめてミリ秒まで、できればナノ秒まであってほしい。
というわけでプロジェクト内で何とかしてくれって話が上がったのですが、logrus においての出力時刻フォーマット指定は、以下のように `JSONFormatter` の `TimestampFormat` でできる。


```go
func main() {
	log := &logrus.Logger{
		Out: os.Stderr,
		Formatter: &logrus.JSONFormatter{
			TimestampFormat: time.RFC3339Nano,
		},
		Level: logrus.InfoLevel,
	}

	log.WithField("user", "kiririmode").Infoln("hello world")
}
```

logrus においては、デフォルトのフォーマットは time.RFC3339 (`"2006-01-02T15:04:05Z07:00"`) で指定されているので、それを time.RFC3339Nano (`"2006-01-02T15:04:05.999999999Z07:00"`) に変更すれば良い。

- see: https://github.com/sirupsen/logrus/blob/251d6bf71382da18d56ae619e48a8404728b40b0/formatter.go#L7

上記コードを出力すると、出力タイムスタンプの分解能がナノ秒に変わります。

```json
{"level":"info","msg":"hello world","time":"2019-09-01T06:52:23.713652+09:00","user":"kiririmode"}
```
seleniumのセットアップ

Anaconda使用
macOS Mojave バージョン10.14.6
Python 3.7

ターミナルで

    pip install selenium
    # 画像収集用するならこれも
    pip install pillow

Firefox使用のために

    brew install geckodriver

Chrome使用のために

    brew install chromedriver

[brew install chromedriver]を実行したらエラーがでた

    Error: No available formula with the name "chromedriver"
    It was migrated from homebrew/core to homebrew/cask.
    You can access it again by running:
    brew tap homebrew/cask
    And then you can install it by running:
    brew cask install chromedriver

言われた通り

    brew tap homebrew/cask
    brew cask install chromedriver

再度

    brew install chromedriver

ここからは、jupyter notebookで確認

    # 下記の二つ実行してエラーがでなければinstall成功している
    from selenium import webdriver
    from PIL import Image
    
下記を実行するとFirefoxならFirefox
ChremeならChromeが立ち上がります。
注釈）webdriverでブラウザ立ち上げる。
    # インストールできてたら下記実行(１つずつ)
   
    browser = webdriver.Firefox()
    browser = webdriver.Chrome()
【Rails 6.0】Active Storageの画像変換を高速＆省メモリのVipsに換装

個人開発のWebアプリ**「[まちかどルート](https://machiroute.herokuapp.com/)」**を**Rails 6.0**にアップグレードしました。

せっかくなのでRails 6.0の新機能に挑戦したときのメモです。

# 高速＆省メモリのVIPS

Railsの画像アップローダーである**Active Storage**ですが、[公式のドキュメント](https://railsguides.jp/active_storage_overview.html)によると

Rails 6.0では

> デフォルトの画像プロセッサはMiniMagickですが、**Vipsも使えます。**

とあります。

ネットでVipsのことを調べてみると高速かつ省メモリとのこと。

さっそく導入してみようと思いました。

# Railsの設定

公式ドキュメントのとおり、下記のGemを導入します。

```ruby:Gemfile
# gem 'mini_magick' # この行があったらコメントアウトもしくは削除
gem 'image_processing', '~> 1.2' # この行を追加
```
`bundle install`したら、こんどは下記の行を追記します。

```ruby:config/application.rb
config.active_storage.variant_processor = :vips
```

# 開発環境の設定

Railsの設定だけで動くかと思いきや、そうもいかないようです。

じぶんの開発環境のOSはCentOS Linux release 7.6.1810 (Core)つまり**CentOS 7**なのですが、ここにVipsをインストールしなければいけません。

**Vips（libvips）**
https://github.com/libvips/libvips

```
# wget https://github.com/libvips/libvips/releases/download/v8.8.2/vips-8.8.2.tar.gz
# tar zxf vips-8.8.2.tar.gz
# cd vips-8.8.2
# ./configure
# make
# make install
```
このようにひとつずつコマンドを実行していきます。

そして

```
# make check
```
というコマンドでVipsが正常にインストールされたかをしっかり確認します。とくに`no`と表示されたライブラリを

```
# yum install libpng
# yum install libpng-devel
```
というように追加でインストールしていきます。

そして

```
# cd vips-8.8.2
# ./configure
# make
# make install
# make check
```
を行い、`make check`のテスト結果に失敗（FAIL）がなくなればインストール成功です。

# 画像変換のコードを書き換える

従来だと

```ruby
post.image.variant(resize: "240x300", auto_orient: true, strip: true, quality: 60)
```
でしたが、Rails 6.0でVipsを使うには

```ruby
post.image.variant(resize_to_fit: [240,300], autorot: true, saver: { strip: true, quality: 60 })
```
と書き換えたら動きました。

ちなみに`resize_to_fit`は画像の縦横比であるアスペクト比を変えないまま設定値以下に縮小するというもの。`autorot`はスマホでたまにあることですが90度回転して投稿されるのを補正してくれます。`strip`は画像に含まれる位置情報などのメタデータを削除します。`quality`は画像を軽くするための圧縮率です。ほかにもいろいろオプションがあるみたいですね。

# Herokuにデプロイ

以上で、ローカルの開発環境でVipsが動作しました。

ところが、本番環境のHerokuにデプロイすると画像が表示されません。

いろいろ調べたところ、下記の設定が必要でした。

```
heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-apt
heroku buildpacks:add --index 2 https://github.com/brandoncc/heroku-buildpack-vips
```
Herokuユーザーお馴染みのHeroku CIでこれらのコマンドを実行し、Vipsに必要なライブラリをダウンロード＆インストールするためのビルドパックを準備します。

つづいて下記を1行ずつ打ち込んでいきます。

```
$ cat <<EOF >Aptfile
> libglib2.0-0
> libglib2.0-dev
> libpoppler-glib8
> EOF
```

あとはいつものようにHerokuにデプロイします。

```
$ git add -A
$ git commit -m "Add Vips"
$ git push heroku master
```
じぶんのstackはheroku-18です。stackによってはビルドパックの`https://github.com/brandoncc/heroku-buildpack-vips`を別のリポジトリに変えたほうがよさそうでした。

# あとがき

Qiitaでまとめるようになって約8か月。Rubyでプログラミングを学び始めておよそ1年と2か月が経ちました。いつも思うのですが、こうしてまとめると今回の事も簡単に出来るように見えてしまいます。実際は徹夜でしたけど...。精進します。

### **2019年9月2日 追記**

Herokuにデプロイして丸1日、効果を検証してみました。

その結果、本番環境のHerokuではVipsをいったん無効化しました。一部の画像形式の変換がうまく動かなかったり、メモリ消費量の上昇でスワップが増えてしまったためです。VipsがHerokuで正式にサポートされていないせいでしょうか。ローカルの開発環境ではかなり快速に動作するのですが...。
【Rails 6.0】Sidekiqの「待機状態」にactive_storage_analysisのジョブが滞るのを解決

個人開発のWebアプリ**「[まちかどルート](https://machiroute.herokuapp.com/)」**を**Rails 6.0**にアップグレード。

以下、そのときの体験メモです。

# Sidekiqの「待機状態」に

このアプリでは、画像のアップローダーとしてRailsの**Active Storage**を使っています。また、バックグラウンドジョブをさばく**Active Job**のアダプターは**Sidekiq**です。

Rails 6.0にアップグレードしてからというもの、画像をアップロードしたり削除するたびにSidekiqのダッシュボードにある「待機状態」のカウント数が増えていくことに気づきました。その中身を見てみると`active_storage_analysis`と`active_storage_purge`というジョブ群でした。

# 不具合を誘発

以前にまとめた、この機能が動かなくなりました。

**【Rails】Active Storage + S3 + Active JobでGoogle Cloud Visionセーフサーチ**
https://qiita.com/west2538/items/e94db445e22e6151718d

# 解決策

どうやら`sidekiq.yml`にこれらのジョブを追記する必要があったようです。

```ruby:config/sidekiq.yml
:verbose: false
:concurrency: 5
:max_retries: 3

:timeout: 8

:queues:
  - [default, 7]
  - [second, 5]
  - [active_storage_analysis, 3] # 追記
  - [active_storage_purge, 1] # 追記
```

おかげで「待機状態」でジョブが滞ることなく正常にアプリが稼働するようになりました。
HalideとOpenCVとの連携

Halideは画像処理記述用のDSLです。
どういったものかは[公式ページ](https://halide-lang.org/)をご覧いただくか、福嶋先生がある程度の[日本語資料](https://qiita.com/fukushima1981/items/fa3537234e19baffc761)を投稿されていますので、そちらを参照ください。

# HalideとOpenCVとの連携
Halideには画像ファイルの読み込み/書き込み関数がありませんので、別途用意する必要があります。
ここではOpenCVの`imread`/`imwrite`を使ってみましょう。
処理はカラー画像のグレイスケール化にでもしておきましょうか。
![rgb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329142/cc84d847-1c8f-fda5-bdc1-8dbffc16d224.png)

```gray1.cpp
#include <Halide.h>
#include <opencv2/opencv.hpp>

int main()
{
	cv::Mat cv_src = cv::imread("rgb.png");
	cv::Mat cv_dst(cv_src.size(), CV_8UC1);

	Halide::Buffer<uint8_t> hal_src(cv_src.data, cv_src.cols, cv_src.rows, 3);	
	Halide::Buffer<uint8_t> hal_dst(cv_dst.data, cv_dst.cols, cv_dst.rows);    // 1chなのでx,yだけでOK
	
	Halide::Func GrayScale;
	Halide::Var x, y;

	Halide::Expr gray =
		0.114f * hal_src(x, y, 0) +		//B
		0.587f * hal_src(x, y, 1) +		//G
		0.299f * hal_src(x, y, 2);		//R

	GrayScale(x, y) = Halide::cast<uint8_t>(Halide::min(gray, 255));

	GrayScale.realize(hal_dst);		// 出力先をhal_dstにして、グレイスケール化の実行

	cv::imwrite("gray1.png", cv_dst);
}
```

`Buffer<T>`のコンストラクタ先頭の引数にMatの`data`ポインタを渡すことで、直接Mat画像をHalideで扱うことができます。
ポインタを共用しているので、`Buffer`を書き換えれば`Mat`の中身も書き換わります。

# HalideとOpenCVのメモリ配置の違い
さて、実際に生成された画像はというと…
![gray1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329142/36f61edd-c666-e0d8-e658-57a364c4b0ce.png)
なんじゃこりゃ。失敗ですね。

なにが原因かというと、Halideのデフォルトのメモリ配置がプレーナ型を想定しているためです。
プレーナ型とは、以下のようなメモリ配置です。
画像が色チャンネル枚分並んでいる、という形でしょうか。
> BBBBBBBBGGGGGGGGRRRRRRRR


一方、OpenCVの`Mat`はインターリーブ型になっています。
1pixelごとにB,G,Rと並んでいる、素直な形です。
OpenCVを触っている人ならおなじみですね。
> BGRBGRBGRBGRBGRBGRBGRBGR

ということで、上記のプログラムは`hal_src`の作成時に齟齬が生じてしまっています。
直すのは簡単で、Halideの`Buffer`にインターリーブ型であると教えてやれば大丈夫です。

```gray2.cpp
#include <Halide.h>
#include <opencv2/opencv.hpp>

int main()
{
	cv::Mat cv_src = cv::imread("rgb.png");
	cv::Mat cv_dst(cv_src.size(), CV_8UC1);

	Halide::Buffer<uint8_t> hal_src = 
        Halide::Buffer<uint8_t>::make_interleaved(cv_src.data, cv_src.cols, cv_src.rows, 3);   // ここでインターリーブ型だと教えてやる	
	Halide::Buffer<uint8_t> hal_dst(cv_dst.data, cv_dst.cols, cv_dst.rows);
	
	Halide::Func GrayScale;
	Halide::Var x, y;

	Halide::Expr gray =
		0.114f * hal_src(x, y, 0) +		//B
		0.587f * hal_src(x, y, 1) +		//G
		0.299f * hal_src(x, y, 2);		//R

	GrayScale(x, y) = Halide::cast<uint8_t>(Halide::min(gray, 255));

	GrayScale.realize(hal_dst);		// 出力先をhal_dstにして、グレイスケール化の実行

	cv::imwrite("gray2.png", cv_dst);
}
```
こうすると、うまくできます。
![gray2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329142/1774ab01-dad7-6480-d46e-49d5d3bd6878.png)
C#の逐語的文字列と挿入文字列についてまとめる【備忘】

# はじめに
C#の文字列操作で気になった、
逐語的文字列と挿入文字列を(備忘のため)まとめた。

# 逐語的文字列
文字列の最初に`@`を使用することで定義。
文字列を逐語的(原文の通り？)に解釈する。

つまり、特殊文字が通常の文字として解釈され、改行等もそのまま処理される。
ただし、ダブルクォーテーションを文字列として扱う場合は `""`というように連続で記述する。

```c#
Console.WriteLine("記事:\n\"c\\qiita\\qiita.txt\"");
// 記事:
// "c\qiita\qiita.txt"

Console.WriteLine(@"記事:
""c\qiita\qiita.txt""");
// 記事:
// "c\qiita\qiita.txt"

```

# 挿入文字列
文字列の最初に`$`を使用することで定義。
文字列を補完式が含まれている可能性のある文字列として解釈する。

つまり、文字列中に変数や式をいい感じに埋め込める。

※中かっこ`{}`を文字列として扱う際は`{{`,`}}`というように、連続で記述する必要がある。

```c#
Console.WriteLine($"{1+2}");
// 3

string pass = "c\\qiita\\qiita.txt";
Console.WriteLine($"記事:{{{pass}}}");
// 記事: {c\qiita\qiita.txt}

```

# 組み合わせ
逐次的文字列と挿入文字列を組み合わせる際は、`$@`と記述する。

```c#
var item = JsonConvert.DeserializeObject<JObject>($@"{{ ""url"":  ""{url}"" }}");
```

# 参考
[$ - 文字列補間 (C# リファレンス)](https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/tokens/interpolated)
[@ (C# リファレンス)](https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/tokens/verbatim)
start with 　where条件　KSR 

#ORACLE START WITH と WHERE メモ
##start with　文に　where　の位置
```squeak
select  * 
from 
     tableA
where 
     treeID=1
start with 
           parentID = 0
connect by 
           parentID = prior childID 
```
```select * 
from 
     (select * from tableA where treeID=1)
start with 
          parentID = 0
connect by  
          parentID = prior childID 
```

WHERE条件参照：[https://www.cnblogs.com/xcxcxcxc/p/5993835.html]
START WITH参照：[https://blog.csdn.net/weiwenhp/article/details/8218091]
無限ループ参照：[https://codezine.jp/article/detail/2691]
まだ見てない参照：[https://www.cnblogs.com/YuyuanNo1/p/7919332.html]
Vue v-once

#v-once
要素とコンポーネントを一度だけ描画します。

そのあと再描画は、要素 / コンポーネントとすべてのその子は、静的コンテンツとして扱われスキップされます。これは、更新性能を最適化するために使用することができます。

## code
```html
        <!--単一要素-->
        <span v-once>This will never change: {{msg}}</span>

        <script>
            var app = new Vue({
                el: 'span',
                data: {
                    msg: 'Hello Vue!'
                }
            })
         //This will never change: Hello Vue!
        </script>

```
[CS入門] 東工大講義 #5 テーマ１（計算を知る）：Ruby でプログラミング（1）

# やること
[東工大 講義 #5 テーマ１（計算を知る）：Ruby でプログラミング（1）](https://www.youtube.com/watch?v=_g4H868iR7s&list=PLqX1hzBNwl2oMJqjuPylcf8aAQFSGCWQr&index=5)

# 前提
***プログラム = 計算の指示書***

「すべては計算できる。ただし、計算に載せるにはデータとして表わし、
　計算として処理しなければならない」

#  Rubyでプログラミング

# Rubyとは？
* プログラミング言語 = プログラムを書くための言語
* 高水準言語（＝人にわかりやすい言語）の１つ
　⇅
　機械語（＝コンピュータのための言語）

# Rubyのプログラムの例

```ruby:aqrt.rb

# プログラム例）注釈：メモ
# 入力 n,出力 ?)注釈：メモ
n = gets().to_i
a = 1; a2 = a * a
while a2 <= n
   a = a + 1
   a2 = a * a
end
puts(a - 1) 
```

# プログラムで一般的に共通するルール

* プログラムにはプログラム名のファイルに格納
* プログラムは命令の列
* 命令を上から下に順に実行
（例外：繰り返し文、条件分岐分）

### 「変数」 = 計算の途中結果（データ）を入れる箱
### 「命令文」 = コンピュータへの指示文

【計算のため】

* 代 入 文 === 変数に（計算した）値を格納せよ 
* 繰返し文  === 条件の成り立つ間、指定された範囲の命令を繰り返せ

【その他の為】

* 入力文 === gets().to_i
* 出力文 === puts()

# Rubyでプログラミング

```ruby:
a = 8
b = 3
wa = a
while b > 0
     wa = wa + 1
     b = b -1
end
puts(wa)
```
brew cask でインストールされているアプリを全てアップデートする

homebrew-cask で ``upgrade``コマンドがあるが、最新バージョンがアップデートされない。
いちいち``formula名``を指定するとアップデートできる場合もあるが、一つ一つ指定するのは面倒臭い。

そんな時は、`--greedy`を引数にするそうです。
（他の方法で今までやってたんですが、@dotさんの情報で、```--greedy``` すれば良いことがわかりました。）

```bash
% brew cask upgrade --greedy
```

ただし上記コマンドだと、`Warning: Calling brew cask upgrade is deprecated! Use brew upgrade --cask instead.`と警告が出るようになりました。

今後は以下のようにするべきでしょうか。

```bash
% brew upgrade --cask --greedy
```

`man cask upgrade`でも書かれてましたね。

```
--greedy
              Upgrade casks with auto_updates or version :latest
```

因みに、普通に`brew cask upgrade` で最新バージョンにアップデートできないソフトウェアがある理由ですが、ソフトウェア自体でアップデート機能を持つものは、ソフトウェア自体に任せるスタンスらしいです。

まあ、個人的にはバージョン管理もbrew上で合わせたいので、このコマンドで強制的にアップグレードした方がいいかな・・・

ということで、以下の**情報は間違いです！** まあ動くけど・・

<hr>
<br>
<br>
<br>
<br>

~~？？？まてよ**「単純にformula名リストを指定すればいいんじゃね？」**~~


~~## formula名リストを指定して、brew cask upgrade

```bash
$ brew cask upgrade `brew cask list`
```
補足：もちろん`グレイヴ・アクセント`ではなく、`xarg`を利用してもいいと思う。

```bash
$ brew cask list | xargs brew cask upgrade
```

ただし、**この方法だと強制的にアップデートしてしまう**ので、以下のコマンドで事前にチェックした方が良さげ。



## アップデートする前にチェックだけする


```bash
$ brew cask upgrade --dry-run `brew cask list`
```


### 結果: アップデートなしの場合
```bash
==> No Casks to upgrade
```

### 結果: アップデートありの場合

```bash
==> Would upgrade 2 outdated packages:
skype 8.51.0.72 -> 8.51.0.92, thunderbird 60.8.0 -> 68.0
```

~~事前にアップデートをチェックできれば安心。（なぜ``brew cask upgrade``だけではこの情報がピックアップできないのか謎）~~

以上
Homebrewで過去バージョンをインストールしたいぞ

# 背景

OpenAPIを使ったプロジェクトでopenapi-generatorコマンドでコードを自動生成したところ、僕が変更を加えた量より遥かに多い変更がされてしまった。
`.openapi-generator/VERSION`は`4.0.2`になっている。
一方手元で

```
$ openapi-generator version
```

と打つと

```
4.1.1
```

が返ってくる。
要するにマスタとローカルでopenapi-generatorのバージョンが違うのが原因らしいので、openapi4.0.2をインストールしようということになった。

# 確認

openapi-generatorはHomebrewで`brew install openapi-generator`と打って取得したもの。

Homebrewに他のバージョンがあるか確認するには`brew info openapi-generator`と打つ。

ここで例えば以下のように目標のバージョンがあった場合、

```
/usr/local/Cellar/openapi-generator/4.0.2 (4 files, 18.5MB)
  Built from source on 2019-08-31 at 15:50:00
/usr/local/Cellar/openapi-generator/4.1.1 (4 files, 18.8MB) *
  Built from source on 2019-08-31 at 15:35:33
```

`brew switch openapi-generator 4.0.2`などと打てばバージョンをスイッチできる。

# 取得

たぶん上の方法で無いことの方が多いと思うので、そのときはFormulaのバージョンを遡ってインストールする。

Formulaのディレクトリに移動

```
$ cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula
```

ログを確認

```
$ git log openapi-generator.rb
```

ログはj/kで上下移動、qで終了など。
これで目標のcommitを探すのだけど、最近のcommitしか残ってない場合がある。そのときは

```
$ git fetch --depth 10000
```

みたいにdepthを指定してfetchすると昔のcommitが見れる。

するとこんな感じで目標のバージョンのcommit番号が分かるはず。

```
commit 3f66aa275955a9e3c042c48af2462f74cd051f5b
Author: William Cheng <wing328hk@gmail.com>
Date:   Thu Jun 20 14:30:01 2019 +0800

    openapi-generator 4.0.2 (#41145)
```

分かったら以下の感じで良い感じにする。

```
$ git checkout 3f66aa275955a9e3c042c48af2462f74cd051f5b openapi-generator.rb
$ brew unlink openapi-generator #一旦今のリンクを外す
$ HOMEBREW_NO_AUTO_UPDATE=1 brew install openapi-generator #自動更新無しにしてインストール
```

`openapi-generator version`で欲しいバージョンになっていることを確認したら、`git reset --hard`で元に戻しておく。

以降は上の`brew switch`を使ってバージョン行き来もできる。

# 参考リンク

[Homebrewで旧バージョンのパッケージをインストールしたい](https://qiita.com/KyoheiG3/items/912bcc27462871487845)
[homebrew の git logを確認して Python 3.6.5のインストールしてみる。](https://qiita.com/yuyj109/items/4d22ad5614ef4da7895b)