OmniAICreator/Qiita-1.07M huggingface dataset:
LaravelのModelに補完が効かなくて辛い人たちに贈る「Laravel IDE Helper Generator」の紹介

Eloquent Model でプロパティや scope を扱うときに補完が効いて欲しい。しかし、例えば下記のようにコードを書いても補完が効かなくて辛いですよね。

```php:SampleRepository.php
    $sample = new Sample();
    dd($sample->id); // ここでidに補完が効いて欲しい！できればタイプヒンティングもしてほしい！
```

このように Model からカラム名にアクセスした際に補完が効かないのに加え、クエリをカプセル化してくれる scope を利用したときも補完は効きません。

```php:App\Models\Sample.php
    public function scopeIsPublic($query)
    {
        return $query->where('is_public', true);
    }
```

```php:SampleRepository.php
    $sample = new Sample();
    dd($sample->isPublic()->get()); // ここでisPublic()に補完が効いて欲しい！
```

補完が効かないから、カラム名は typo や型を間違えて代入してしまうリスクもあるし、scope も大文字や小文字を間違えてしまうこともあるでしょう。

本記事では Laravel の Model に補完・型情報を付与してくれるライブラリ【[Laravel IDE Helper Generator](https://github.com/barryvdh/laravel-ide-helper)】について解説します。

# 本記事でできるようになること

このように scope を hover すると型定義が出ますし、補完も効きます。

![スクリーンショット 2020-02-18 13.21.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156567/d6971175-87c9-b7e0-eee5-63534217a18d.png)

また、カラム名へのアクセスに対しては型補完が効いています（業務ソースなので隠しまくりなのですがご容赦ください）。

![スクリーンショット 2020-02-18 17.21.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156567/635e5cb4-4686-d031-debb-af8abe968eb4.png)

この例ですと、とあるテーブルの transferred_at カラムへ日付を保存しているわけですが、日付保存可能かつ、振り込みされていない場合は null が格納されている、といったことがある程度型情報から読み取ることができます（null が良いのかはさておき）。

# セットアップ

https://github.com/barryvdh/laravel-ide-helper

に概ね書いてあるとおりです。

まずは composer でインストールします。

```
composer require --dev barryvdh/laravel-ide-helper
```

Laravel5.5 以上を利用している方はこれでセットアップはもう終わりです。

# Model の phpDocs を自動生成

続いて Model の scope やカラム名に対応した phpDocs を自動生成します。

下記コマンドを実行します。

```
php artisan ide-helper:model --nowrite
```

`ide-helper:model`コマンドで実行できるわけですが、型定義ファイルをつくるオプションと、各 Model に直接上書きするオプションがあります。

個人的には、自動生成されたコメントがプロダクトコードに入り込むのは、運用ルールが増えてしまってあまり好きではないので`--nowrite`オプションをつけて実行するのがおすすめです。

さて、コマンド実行後に、root ディレクトリに`_ide_helper_models.php`が生成されています。

一部抜粋するとこのような内容です。

```php:_ide_helper_models.php
/**
 * App\Models\User
 *
 * @property int $id
 * @property string|null $email
 * ...
```

以上でやることはもう終わりました。さっそく自身の Repository や Model ファイルを開き、hover してみましょう。

# 補足

運用面では`_ide_helper_models.php`を git 管理してしまうと、複数メンバー間で Conflict が多発すると思うので、gitignore 扱いにして、各自で生成しましょうという運用にしたほうが望ましいと思います。
【MS ACCESS】Accessファイルを開いたときに最初に自動実行する方法

メモとして残します。


#■やり方
##1.`AutoExec`という名前のマクロを作成する。

![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213462/b166221c-dd9e-cf22-5bec-809efdf96687.gif)

##2.標準モジュールにFunctionでプロシージャを作成
```vb
Function MyAutoOpen()
    '起動後、始めに処理したい内容
End Function

```

以上。

#■さいごに
自動実行をスキップする場合はACCESSファイルを一旦閉じて、
SHIFTを押した状態でACCESSファイルを起動すると自動実行されません。
テキストからコード譜を作成するWebアプリ「ChordType」を作ってみた

### あらまし

作曲した曲が溜まってきました！

ですが整理するのが大変です。

現在はルーズリーフにメモっていますがあとで見返せる代物ではないです。

清書には楽譜作成ソフトのNotionを持っているのですが、楽譜とまでは行かないレベルの気軽さが欲しい場合もあります（あった）。

そこで「コード譜（歌詞とコードが並べて書いてある譜面）」を作るアプリを作ってみました。

### できたもの

[ChordType](https://mi-ki-ri.github.io/chordtype/)

<img width="1433" alt="testsong.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92027/da6afc78-93c2-555c-956b-49df51045491.png">


### 使用法

画面左のテキストボックスに歌詞とコードを記述します。

その際、改行コード2つ区切りでひとかたまりと認識します。

ひとかたまりの中で、最初の行をコード、次の行を歌詞と認識します（コード以外も入れられるけど・・・）

さらに行の中で、`|`区切りで小節と認識します。

さらに小節の中で、`,`区切りで区切れます。

`|`と`,`をうまく駆使してコード譜を作っていきます。

画面右にプレビューが表示され、「DL」をクリックするとPNG形式でダウンロードできます。

`\[[a-zA-Z0-9]+\]`こんな感じの部分は見出し、`---`は区切り線になります。

[Github](https://github.com/mi-ki-ri/chordtype)も参照。

### 使用した技術

#### Nuxt

ページ自体はNuxtで作りました。

左ペインのテキストを **いい感じに** パースして配列を作り、

右ペインではその配列をv-forで回してHTMLにしています。

（BootstrapVue使用）

#### html2canvas

ダウンロード時に一瞬html2canvasを使用しています。

右ペインのDOMをhtml2canvasに渡し、帰ってきたcanvasをAタグのリンク先に指定しました。

```js
download() {
  html2canvas(document.querySelector("#visual")).then(canvas => {
    let link = document.createElement("a");
        
    link.href = canvas.toDataURL("image/png");
    link.download = this.editorTitle + ".png";
    link.click();
  });
}
```

こんな感じです。

本当はPDFで吐き出したかったけど挫折しました。

#### Github Pages

Github Pagesにデプロイしています。

それに伴い、`nuxt.config.js`をちょっといじりました。

```js
generate: {dir:"docs"},
  router: {
    base: '/chordtype/'
  },
```

### 欠点

歌詞中にカンマを使うことができません（区切り文字として認識されるため）…

### 今後

スタイルシート部分がまだ弱いと思うので改良していきたいです。

並行して作曲もしたいです。作曲楽しい。
DjangoのMarkdownx をサイトルート以外で使う

DjangoではMarkdownx というパッケージを使って、プレビューを出しながらマークダウン記法で書かれたソースのデバッグができる。
これはかなり便利なのだけど、Markdownx は、Djangoプロジェクトがサイトルート以外にデプロイされていると対応してくれない。

たとえば、

```apache:apache2.conf
WSGIScriptAlias /prefix /django/project/project/wsgi.py
```
のようになっている場合、Markdownx のURLとしては
`/prefix/markdownx/markdownify` のようになってくれないと困るが、Markdownxのコードでは、`markdownx/settings.py`の中で固定値で書かれたものを使っているため、`/markdownx/markdownify`にアクセスしようとして`404`になる。

これを回避するには、以下のようにすればよい。

1. プロジェクトの`urls.py` でmarkdownxのincludeにnamespaceを指定しておく(markdownxとする)
2. `markdownx/widgets.py` 内の`attrs.updateのうち、URL部分をreverse()で書き換える

検索で引っかかってくるMarkdownxの解説では、`urlpatterns`にnamespaceを指定してしないものもあるので、以下のようにnamespaceを指定しておく。

```python:settings.py
urlpatterns = [
    path('markdownx/', include(('markdownx.urls','markdownx'))), 
      :
```

続いて、`markdownx/widgets.py`(各環境の site-packages内にある)だが、元は以下のようになっている。(どこにあるんだよ、って時は、定番のfindで、
`sudo find / -name 'widgets.py' | grep markdownx`
で探しましょう。settings.pyもそこ。)

```python:widgets.py(オリジナル)
attrs.update({
    'data-markdownx-editor-resizable': MARKDOWNX_EDITOR_RESIZABLE,
    'data-markdownx-urls-path': MARKDOWNX_URLS_PATH,                  
    'data-markdownx-upload-urls-path': MARKDOWNX_UPLOAD_URLS_PATH,             
    'data-markdownx-latency': MARKDOWNX_SERVER_CALL_LATENCY
})
```

大文字の変数は、markdownx/settings.py の中で定数として定義されていて、`widgets.py`の頭のところでimportされている。これらのうち、`_URLS_PATH`で終わる2つを以下のように書き換える。

```python:widgets.py(改変後)
from django.urls import reverse
       :
attrs.update({
    'data-markdownx-editor-resizable': MARKDOWNX_EDITOR_RESIZABLE,
    'data-markdownx-urls-path': reverse('markdownx:markdownx_markdownify'),
    'data-markdownx-upload-urls-path': reverse('markdownx:markdownx_upload'),
    'data-markdownx-latency': MARKDOWNX_SERVER_CALL_LATENCY
})
```

これで、サイトルート以外にDjangoをデプロイしている場合にもMarkdownxを使うことができた。

まぁ、サイトルート以外で使う例はそれほどないのかもしれないけど、今回は既にあるPHPサイト(こいつがサイトルート)に追加でデプロイという関係からちょっとハマってしまった。
まだ引数に順番指定してんの？

#はじめに
vueとnuxtの記事も書こうかなあ、、、

#プロジェクトが壊れる可能性あり、、、
先日、仕事中に学んだこと。
インスタンス変数を作成するためにinistializeメソッドを活用していた際に今までの自分は引数の順番に依存していました。


```Human.rb
class Human
  attr_render :name, :age, :sex
  def initialize(name, age, sex)
     @name = name
     @age = age
     @sex = sex
  end

〜省略〜

end

Human.new('Taro',20,'male')
```

この例では、Humanのinitializeメソッドは次の3つの引数を取ります。name, age, sexの３つですね。
つまりHuman.newでインスタンスを作成するところでは引数を３つ渡しています。
まあ教科書通りのinistializeメソッド及び引数の使い方ですね。
**しかしこの方法には大きな欠点があります。**

1. 引数を順番に渡さなければならない
2. ３つの引数をもれなく、だぶりなく渡さなければならない

この引数の使い方は小規模かつ個人での開発なら何ら問題有りません。
自分が作成したインスタンスなので勝手はわかっているし、他のクラスとの依存関係も頭に入っているはずです。
小規模の開発なら変更も少ないですし、この仕様が変わることはないかもしれません。

**しかし、大規模な開発かつチームでの開発だったらどうでしょう？**
チームでの開発/実務レベルでの大規模な開発では常に変更を考えて実装しなければなりません。
プログラムに機能が追加されたり、改修要望が入った際には、インスタンスの引数の数が変わるかもしれないし、
そもそも既存のインスタンス変数が削除されるかもしれません。
また、この一つのインスタンスだけなら良いですが、別のクラスでHumanクラスのインスタンスを作成していた場合その箇所をすべて直さなければなりません。（１０箇所の変更とか普通にあります、、、）
この書き方ではまずそうですね、、、。

ではどのように書きましょう？

#引数にハッシュを使う
先程述べた「引数の順番固定」を簡単に回避する方法があります。
**ハッシュです！！！**

```Human.rb
class Human
  attr_render :name, :age, :sex
  def initialize(args)
     @name = args[:name]
     @age = args[:age]
     @sex = args[:sex]
  end

〜省略〜

end

Human.new(name: 'Taro', age: 20, sex: 'male')
```

このテクニックにはいくつかの利点があります。

1. 引数の順番依存を取り除ける
2. 変更に強い
3. key名が明示的なドキュメントになってくれている

この方法のおかげでどんなに引数を変更しても他のコードに対する副作用がなくなりました。
よって、仕様変更の際になんの気兼ねもなく引数の追加や除去ができます。
安心感がすごいです。
またkey名がなんの情報を渡しているのかを示してくれているため、
インスタンスを生成する際にとてもわかりやすいですね。

#その他のテクニック①

```Human.rb
class Human
  attr_render :name, :age, :sex
  def initialize(args)
     @name = args[:name] || 'Jiro'
     @age = args[:age]   || '10'
     @sex = args[:sex]   || 'male'
  end

〜省略〜

end

Human.new(name: 'Taro', age: 20, sex: 'male')
```

**||メソッドを使用することでデフォルト値を設定することができます。**
||メソッドはor演算子と同様に作用します。
左辺を評価し、その結果がfalseまたはnilであれば右辺の評価に移ります。
こうすることで引数に値を入れ忘れたとき（意図的に入れないとき）でもインスタンス変数を生成することができるでしょう。
例えば「sexの値はほとんどの人がmaleだな」と思えば

```
@sex = args[:sex]   || 'male'
```
と設定しておくだけでインスタンス生成時に引数を渡さなくても良くなります。


#その他のテクニック②

```Human.rb
class Human
  attr_render :name, :age, :sex
  def initialize(args)
     args = defaults.merge(args)
     @name = args[:name]
     @age = args[:age]
     @sex = args[:sex]
  end

〜省略〜

  def defaults
    {name: 'Jiro', age: 10, sex: 'male'}
  end

end
```

この方法もデフォルト値を設定するのに大変役立ちます。
隔離テクニックとでも名付けましょうか。
defaultsメソッドを設定し、initializeメソッド内で呼び出しています。
この方法は特にデフォルト値が長いときや複雑な時に活用すべきです。
コードの可視性が高まりますね。


#終わりに

プログラムは普遍的なものではありません。
常に変更と改善の繰り返しです。
変化に強いコードを書けるスキルは今の時代（アジャイルでの開発が主流になってきた時代）、必須のスキルと言っても過言ではありません。
あなたのコードがチームメンバーに多くの手間と工数をかけさせるかもしれません。
ひどいときにはプログラム自体を破壊してしまう可能性もあるのです。
ただ動くだけではなく、本当に"良いコード"を書けるように一緒に邁進しましょう！！！


（今回はちょっと真面目に書きすぎたな、、、:robot::robot:）


#参考
オブジェクト指向設計実践ガイド　～Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方 
Sandi Metz (著), 髙山泰基  (翻訳)
[python] コールバック関数（引数に関数を渡す)

#javascriptとpython
```javascript:javascript
const sayHello = word => console.log(word);
const func = callback => {
  console.log('ここはsayHelloが呼ばれたあとに実行される');
  return callback;
 }

func(sayHello('hello'));
```

```terminal:実行結果
hello
ここはsay_somethingが呼ばれたあとに実行される
```

```python:python
def say_something(word):
    print(word)
    
def func(callback):
    print('ここはsay_somethingが呼ばれたあとに実行される')
    return callback 

func(say_something('hello'))
```

```terminal:実行結果
hello
ここはsay_somethingが呼ばれたあとに実行される
```
vueで動的に生成したフォームのバインディング

# 構成
 * vue2.61
 * vuetify2.26

# 実現したこと
v-forを使って動的に生成したそれぞれのインプット項目をリアクティブに扱う

# 無駄にはまったところ
余計なv-modelをつけるとインプットイベントでv-forで展開したインプット項目が初期化されてしまう。

# 実装したもの

```vue:sample.vue
<template>
  <v-container v-for="item in list" :key="item.id"><!-- リアクティブだからといってここに v-model="list"としてはいけない-->
      <v-row>
          <v-col>
              <v-textfield
                  label="ユーザーアドレス"
                  v-model="item.email"
              ></v-textfield>
          </v-col>
          <v-col>
              <v-textfield
                  label="ユーザー名"
                  v-model="item.name"
              ></v-textfield>
          </v-col>
      <v-row>
  </v-container>
</template>

<script>
  export default {
    name: 'sample',
    data: () => ({
      list: [
        {id: 1, email: 'sample1@eamil.com', name: 'sample1'},
        {id: 2, email: 'sample2@eamil.com', name: 'sample2'}
      ],
    }),
  }
</script>
```

なんでこんなことでハマったのかと思うところではまった。
バインド対象のオブジェクトを削除したり、バインド対象のオブジェクトをユーザーアクションに紐付けて追加したりし、かつ、インプットイベントに対しては対象オブジェクトの中身をリアクティブに変更できるようにする的な箇所だったので、あれこれ元のリストの更新をリアクティブにやるにはモデルで紐づけてあげなければいけないのでは？と考えたところがハマりポイントだった。
二度同じミスをしないように備忘録として残す。
[WIP]FirebaseでiOSアプリ開発をする時にやること備忘録

今のところ公開自分メモです。失礼いたします :bow: 

##Prod/Staging/Devなどの環境別にプロジェクト作成
さすがにProdしかないと本番稼動中の環境を開発でガリガリ触るのはまずいので、最低でも2環境は必要そう。

3環境用意はちゃんとした企業のプロジェクトではやった方が良いと思うが、スモールスタートや個人開発なら2環境で十分事足りそう。Xcodeの初期設定が1Schemeと2Configuration(Debug, Release)なので、設定をいじらないまま進めることもできる。

## ライブラリのインストール
CocoaPodsとCarthageがある。SPMは対応予定っぽい。

Firebaseは依存ライブラリが多く、ビルドにすごく時間がかかる。なのでCocoaPodsを素で使うのは好まれない傾向がある。以下のような対策が考えられる。

### 1.Carthageを頑張って導入する
導入は面倒だが、設定さえ終わってしまえばビルド時間を気にせず開発できる。方法は[公式](https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md)でも記述されている。

### 2. cocopPods-binaryを使う
CocoaPodsをpod install時にバイナリにして使えるplugin。公式でも紹介されているが、スターが少なくて微妙に心配がある。あとwatchOSには使えないと書いてある。

### 3. そのまま使う
ビルド時間はかかるが、CocoaPodsをそのまま使っている分に関しては問題は起きない。ただエンジニア三代美徳の短気に反する選択ではありそう。

## デフォルトリージョンの選択
デフォルトリージョンは一度設定したら変えられないので慎重に進める必要がある。

とはいえ、アプリをリリースしていない状況でどこからのアクセスが多いかなんて把握できないので、とりあえず東京で良さそう。
https://qiita.com/qrusadorz/items/99432fac6cbc93ebaff2

## plistを適切に使うように設定

[公式ドキュメント](https://firebase.google.com/docs/projects/multiprojects?hl=ja)でランタイムでのplistの切り替えをやると、Analyticsの収集がFirebaseApp.config()より前に行われることもあって、挙動が壊れそうな旨が説明されているので、ビルドスクリプトで切り替えておく方が安全そう。

そのやり方は[こちら](https://qiita.com/KazaKago/items/aacf6eaec65b6d4244d0)に書かれている。

## [dsymを人が読める形式でアップロードする設定](https://firebase.google.com/docs/crash/ios#upload_symbol_files)

crashlyticsが読めると、かなりデバッグが捗る。

## slackに連携つなげておくと便利
外部連携が出来て、Slackにつなげておくと重要な情報とか通知送ってくれるので便利っぽい。

## Firebase Authを使うなら、必要なOAuthプロバイダーの設定をする

FirebaseAuthは便利だが、Facebook/Twitterなどの開発者向けサイトでApplicationID/Secretを取得しないと認証機能が使えないため、**各種サイトで認証用のアプリケーション作成をする必要がある。**

https://firebase.google.com/docs/auth/ios/firebaseui?authuser=1

複数デバイスでのデータ同期などをしようと思うと、基本的にはユーザー認証しておかないとダメなので、基本的にアプリケーションごとに用意することになると思う。

Google認証は比較的に簡単だったので、Google認証のみの場合は必要ないかもしれない。
[java] staticを使う理由

javaを使っていてstaticとかどうやって使い分けるのかあいまいだったので、それを調査した。

##static

>
メソッドやメンバ変数にstatic修飾子を付けると、staticメソッド、static変数になります。
static修飾子を付けると何が変わるかというと、newしなくてもそのメソッドやメンバ変数にアクセスできるようになります。

http://www.366service.com/jp/qa/75864cfae2ee945a362e5a9818cabb58

つまり共通のメソッドや変数をクラス間で共有したい場合に使うということ。以前Applicationクラスを通してデータをやり取りするという記事を書いたが、それと同じである。
https://qiita.com/QiitaD/items/549fb2143b2774c30d72

（それにしてもstaticおじさんはさすがに笑った…）

ほかにも「インスタンス化しなくても利用できるから」というものがある。Utilityクラスなどは、メソッド単体で処理が完結している、つまりクラスを定義した時点で用途が確定しているので、インスタンス化が必要ないということらしい。その場合はstaticもする。
https://teratail.com/questions/13203

##感想
staticについてはわかったが、publicやfinal等まだわかっていない。
publicとprivateは言わずもがなオブジェクト指向設計の観点から使い分けるのだろう。
しかしprotectedやデフォルトがなぜ存在しているのかわからない（アクセスに違いがあるのはわかるが）ので、それも調べてみたい。
KornShell（ksh）に関する覚え書き

# KornShell（ksh）とは何か
UNIX系OSを利用するのに避けて通れないのがシェルです。Linuxなどではbash（Bourne-Again Shell）が標準で使われていますが、これは様々なシェルの祖先となるsh（Bourne Shell）の機能強化版と考えていいかと思います。

KornShellも、そのようなUNIX系OSで利用できるシェルのひとつですが、近年標準で採用されていることは多くない模様です。今回は、そんなKornShellを使ってみよう、という記事です。

## きっかけ
個人的な動機に簡単に触れておきます。某中古書店でオライリーのKornShell解説本が格安で売られており、これを手に取ったのが直接のきっかけです。オライリーからはbashやtcsh/cshの解説本も出ていますが、KornShell解説本も出ていたのは知らなかったので購入して通読しました。

# shやbashとの関係
非常にざっくりした認識ですが、昨日の豊富さという意味では、下のような感じの認識でよいのではないでしょうか。

sh < ksh < bash

bashほど高機能ではないにせよ、普通に対話的に利用できる程度の機能は備わっている感じがします。また、csh/tcshのようにbash系（？）と大幅に流儀が違うような感じもないので、その点もとっつきやすいです。

# kshのバリエーション
ややこしいことに、kshは当初プロプライエタリなライセンスであったことなどから、複数の実装が存在します。

## ksh
元祖版です。David Kornが開発しています。当初プロプライエタリでしたが、2000年代に入ってからオープンソースになりました。

## pdksh
パブリックドメインのKornShell実装です。

## mksh
MirOS BSDなるBSD系のOSのために開発された実装です。DebianやUbuntuなどではaptを用いて導入することができます。

# とりあえず試してみる
現在のLinuxディストリビューションでデフォルトのシェルになっていることはほとんどないのではないかと思いますが、公式レポジトリに含まれていることが多いため、パッケージ管理で導入し、とりあえず試してみることができます。常用するのはともかく、歴史的な観点などからも興味深いかと思います。
【Salesforce】選択リストの値を取得したい

Salesforceでは選択リストが[値]と[API参照名]を別で設定できます。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/ea135793-93a0-0146-21ac-ef48e90478ff.png)

そのため、以下のようなSOQLでレコードを取得すると

```
List<Case> caseList = [SELECT id, Status__c FROM Case];
System.Debug('★★ 変数 caseList ： ' + caseList);
```

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/e5c5ca54-3f03-91e7-251d-0c960d77442c.png)

上記のように「Status__c=0」とAPI参照名が表示されます。
そのため、レコードを取得し、Visualforce などで値を表示したい場合は「tolabel()」を設定することで値を取得できます。

```
List<Case> caseList = [SELECT id, tolabel(Status__c) FROM Case];
System.Debug('★★ 変数 caseList ： ' + caseList);
```

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/a3b43976-e0b4-3592-cad6-30dc502f2cf0.png)

~~今までCommonUtilとかにいかついDescribe置いて処理してました。すみません。~~
ElectronでWindows固有のファイルパスを得る


[progreさんのqiita](https://qiita.com/progre/items/2718f4ad20eecf27d599)でまとめて頂いていたが、最新のElectronで試したらエラーなく表示できる範囲が替わっていた。
windowsの範囲を改めて調べてみました。

# Electronで固有パスを得るには

メインプロセスを実行しているファイルで、`app.getPath()`に取得したいフォルダの固定名を引数を入れて実行する。

詳しくは、以下参照
https://github.com/electron/electron/blob/master/docs/api/app.md#appgetpathname

```js:固有パスを取得
const { app } = require('electron')
app.getPath(/*ここに取得したい固定名を入れる*/);

//実行例
console.log(app.getPath('home'));// C:\Users\【ユーザー名】
```

|固定名  |フォルダ |パスの例 |
|---|---|---|
|home| ユーザホーム| C:\Users\【ユーザー名】|
|appData| ユーザーごとのアプリケーションデータディレクトリ(%APPDATA%のパス)| C:\Users\【ユーザー名】AppData\Roaming |
|userData| 起動アプリのアプリケーションディレクトリ| C:\Users\【ユーザー名】\AppData\Roaming\【パッケージ名】】|
|cache| (謎) | C:\Users\【ユーザー名】\AppData\Roaming|
|temp | 一時フォルダ | C:\Users\【ユーザー名】\AppData\Local\Temp |
|exe| 実行している.exeのパス | 実行している.exeのパス |
|module| 実行している.exeのパス | 実行している.exeのパス |
|desktop |デスクトップ| C:\Users\【ユーザー名】\Desktop |
|documents |ドキュメント| C:\Users\【ユーザー名】\Documents |
|downloads |ダウンロード| C:\Users\【ユーザー名】\Downloads |
|music |ミュージック| C:\Users\【ユーザー名】\Music |
|pictures |ピクチャ| C:\Users\【ユーザー名】\Pictures |
|videos |ビデオ| C:\Users\【ユーザー名】\Videos |
|logs| setAppLogsPathの設定値。デフォルト空文字 | (エラー:electron6) |
|pepperFlashSystemPlugin| Pepper Flash pluginのフルパス | (エラー:electron6)
Discordで動く「ぴえんBot」を作る

# やる事
1. Discordのテキストチャットでちくちく言葉（例：バカ、アホ など）が含まれるメッセージを検知する。
2. 「ぴえん🥺」と泣く。
3. ちくちく言葉の多様を防ぐ。
4. みんな幸せ。

#Botの作り方
Bot作成全般は、以下の記事を参考にしました。
[Pythonで簡単なDiscord Botの作り方](https://qiita.com/PinappleHunter/items/af4ccdbb04727437477f)
[Pythonで実用Discord Bot(discordpy解説)](https://qiita.com/1ntegrale9/items/9d570ef8175cf178468f)

# 実装内容
コードは以下の通りです。

``` pien.py
import discord

client = discord.Client()

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

#ちくちく言葉のリスト
ngwords = ["バカ", "ばか", "馬鹿", "アホ", "あほ", "死ね", "しね"]

@client.event
async def on_message(message):
    #ちくちく言葉を検知する
    for ngword in ngwords:
        if ngword in message.content:
            # Botを除外
            if client.user != message.author:
                # ぴえん
                m = "ぴえん:pleading_face:"
                # 該当チャンネルに送信
                await message.channel.send(m)

client.run("Botのトークン")
```
やっていることは次の通りです。
1. テキストチャットにメッセージが送信される度に、メッセージの中にちくちく言葉のリストに該当する文字列が含まれているかどうかを調べる。
2. ちくちく言葉が含まれていた場合、送信者がBotでなければメッセージが送られたチャンネルに「ぴえん🥺」とメッセージを送信する。

#動作の様子
画像よりYoutubeに飛びます。
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/_YUzP7IMm-I/0.jpg)](http://www.youtube.com/watch?v=_YUzP7IMm-I)

#リンク
自身が管理しているDiscordのサーバがある方は以下のリンクよりBotを追加できます。
[PienBot](https://discordapp.com/api/oauth2/authorize?client_id=679204200030404629&permissions=0&scope=bot)

#終わりに
お遊び程度で簡単に作ってみました。
ちくちく言葉はコード内にリストを作るのではなく、外部ファイルから読み込む等するべきなのでしょうが、面倒なので今回はやりませんでした。

天の声「できるならやれ馬鹿野郎」

ぴえん🥺


# 追記
Qiitaで使える顔文字の中になぜか「🥺」だけがありませんでした。（🥺は他のサイトのテキストからコピーしたもの）
ぴえん🥺
[Angular] ERROR in Cannot assign to a reference or variable!  を解決する

# 環境

- Angular CLI: 8.3.25
- Node: 10.16.3
- OS: win32 x64
- Angular: 8.2.14

# 原因

双方向バインディング（2方向バインディング, Two way binding）の機能を提供していないプロパティに対して双方向バインディングのシンタックス *[()]* を適用していた

# 解決策

そもそも双方向バインディングの必要性がなかったため単方向バインディングのシンタックスに修正

# 状況

```ng build --prod``` を実行したときに発生
```ng serve``` やプロダクションモードでないビルドではエラーが出ないので発見が遅れた

> ERROR in Cannot assign to a reference or variable!

そしてこのエラー、情報量少なすぎる！

# 具体例（私の場合）

## 修正前

``` html
<mat-form-field>
    <mat-label>ラベル</mat-label>
    <mat-select [value]="selected">
        <mat-option [(value)]="role" *ngFor="let role of roles"> {{role}} </mat-option>
    </mat-select>
</mat-form-field>
```

```<mat-option [(value)]="role" *ngFor="let role of roles">``` の **role** が双方向バインディングされているが、1行上の **selected** に指定したかった

## 修正後

``` html
<mat-form-field>
    <mat-label>ラベル</mat-label>
    <mat-select [(value)]="selected">
        <mat-option [value]="role" *ngFor="let role of roles"> {{role}} </mat-option>
    </mat-select>
</mat-form-field>
```

# おわりに

このエラーでぱっと検索してみると他の原因で出ている方もいるようなので、あくまで原因の1例って感じですね

「抽象的な良くわからないエラーメッセージ」 → 「検索してもぱっと解決策がない」 のコンボくらうと調査が大変になりますよね

すごい初歩的な間違いだったんですが、```ng serve``` 時にはエラーが出ないこともあって、バグ発見前に開発が進み調査対象が大きくなったので原因のわりに特定が大変でした

いつもエラー解決系の記事にはお世話になっているので書いてみました
みなさんいつもありがとうございます！
デメテルの法則

PMDで解析していたところ、デメテルの法則を守れていないという警告を出されたが、聞いたことなかったので調べてみた。

##デメテルの法則とは
別名で「最小知識の法則」と言われているらしい。

>
ソフトウェアの設計、特にオブジェクト指向プログラムの設計におけるガイドラインである。 このガイドラインは1987年の末にかけてノースイースタン大学で作成された。簡潔に言うと「直接の友達とだけ話すこと」と要約できる。基本的な考え方は、任意のオブジェクトが自分以外（サブコンポーネント含む）の構造やプロパティに対して持っている仮定を最小限にすべきであるという点にある。 

https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%A1%E3%83%86%E3%83%AB%E3%81%AE%E6%B3%95%E5%89%87

つまり「いろんなこと知ってるオブジェクトを作るな」ということらしい。

##デメテルの法則に反したら
結合度が高くなるので、テストや修正がきつい…　オブジェクト指向に反するということですね。

##解決するには
参考URLに乗せたサイトには
>
・ドットを無くす（importとか他クラスのインスタンスメソッド使うなってことかな？）
・設計を見直す

といったことが挙げられていた。

##感想
調査後、自分のAndroidプログラムを振り返ってみると　、メインアクテビティとか結構ドットが入っている…
アクティビティは膨らみやすいというのもあるので、適切な書き方を考えないと悪いプログラムになりそうだ。とりあえずドットを減らすところから始めたい。

##参考URL
・デメテルの法則を厳密に守るにはどうすればいいの？
https://qiita.com/br_branch/items/37cf71dd5865cae21401
[Google Apps Script] ブラウザからの入力値をもとにGmailの下書きを作成する

# 概要
以下の記事の続編として、ブラウザからメールのタイトル、To、Cc、本文を入力して、その値をmailの下書きに反映させるプログラムを作成しました。

[[Google Apps Script] エクセルをGmailの下書きに圧縮して添付する](https://qiita.com/kihachi_takayama/private/8568222c271264429b09)

# 動作結果
1. ブラウザから、メールのタイトル、To、Cc、本文を入力し、実行をクリックします。

![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533728/d22ee031-49b1-1e7f-a296-adb48f658b6d.png)

2. すると、gmailの下書きに入力した値が反映された下書きが作成されます。
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533728/f3ae4ac3-97e0-b525-bb3b-6deaf2ab808a.png)

# ソースコード
Standalone ScriptのGASプロジェクトで、以下の2つのプログラムを作ります。

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <h1>メール下書き作成</h1>
    <form id='myForm' onsubmit="javascript:return false;">
      タイトル：<input type="text" name="title"> <br>
      To：<input type="text" name="To"> <br>
      Cc：<input type="text" name="Cc"> <br>
      mailBody: <br>
      <textarea name="mailbody"></textarea>
    
      <input type='button' value='実行' onclick="runGAS()">
    </form>
  </body>
  
  <script>
  function onSuccess(res){
    console.log("success")
  }
  
  function runGAS(){
    //各入力をdocument.querySlector()で取得します。
    var title = document.querySelector('input[name="title"]').value;
    var to = document.querySelector('input[name="To"]').value;
    var cc = document.querySelector('input[name="Cc"]').value;
    var body = document.querySelector('textarea[name="mailbody"]').value;
    
    // onSuccess()が成功した場合、draft2.jsのmyFunction()を実行します。
    google.script.run.withSuccessHandler(onSuccess).myFunction(title, to, cc, body);
    
  }
  </script>
</html>
```
```javascript:make_draft2.js
function myFunction (title, to, cc, body) {
  var mailTo = to;
  var mailCc = cc;
  
  var mailBody = body;
  var mailTitle = title;
  
  //受け取った引数をもとにgmailの下書きを作成します。
  GmailApp.createDraft(mailTo, mailTitle, mailBody,  {cc: mailCc});
}
```
なぜかpip3がpython2.7でのインストールになってしまった時用のメモ

python3にpip3を使ってパッケージをインストールしたいのになぜかpip3のpythonのバージョンがpython2.7でpython3でそのパッケージがインストールできないというエラーが起きてしまいました.


```terminal
~: python3 -V
Python 3.7.4
~/program/scrape: pip3 -V
pip 20.0.2 from /Users/eijikudo/Library/Python/2.7/lib/python/site-packages/pip (python 2.7)
```

```terminal
python3.7 -m pip install パッケージ名
```

というようにpythonのバージョンを指定してinstallしたらできました。
こんな事ができるんですね。。。
sshfsで別サーバのディレクトリをマウントする

サーバーのFileを使いたい時に、どうすればいいの？
ftp?

sshfsでsshを経由してサーバのディレクトリをマウントできます。

# 恒例
https://github.com/libfuse/sshfs

# インストールする
```bash
apt-get install sshfs
```
# 使う
```bash
sshfs username@192.168.1.101:/tmp/ /mnt/ -p 22


#ペラメタ：
#-p PORT　equivalent to '-o port=PORT'
#-C　equivalent to '-o compression=yes' 
#-F ssh_configfile　specifies alternative ssh configuration file 
#-o reconnect　reconnect to server 
#-o no_readahead　synchronous reads (no speculative readahead) 
#-o sshfs_debug　print some debugging information 
#-o cache=BOOL　enable caching {yes,no} (default: yes) 
```
Pythonを使い、iOSアプリのレビューを取得して、Lineで知る

自身の出したアプリのレビュー件数を取って毎日Lineで知りたい時ないですか？
自分にはありました。
そこで、作成。

今回はiOS用に作成したものになります。


### 使用ライブラリ

 - requests
  - APIを叩くのに
 - urllib3
  - レスポンスをJSONに分解
 - line-bot-sdk
  - LineBOT

### コマンド

```
pip install line-bot-sdk
pip install requests
pip install urllib3
```

### 実際のコード

```GetReview.py

from linebot import LineBotApi
from linebot.models import TextSendMessage
from linebot.exceptions import LineBotApiError
import requests
import json
import urllib.request
import urllib.parse

#LINEでメッセージを送るためのキー
LINE_ACSESS_KEY = "LINE_ACSESS_KEY"
#送信先のLINEのID
LINE_USER_KEY = "LINE_USER_KEY"

def push_info(json_input, context):
    line_bot_api = LineBotApi(LINE_ACSESS_KEY)
    text_message = get_text_message()
    try:
        line_bot_api.push_message(LINE_USER_KEY, TextSendMessage(text=text_message))
    except LineBotApiError as e:
        print(e)

def get_text_message():
    review_url = "https://itunes.apple.com/jp/rss/customerreviews/id=アプリID/json"
    headers = {
        "Content-Type":"application/json",
    }
    response_obj = urllib.request.Request(review_url, headers=headers)
    #tryでエラーハンドリング
    try:
       with urllib.request.urlopen(response_obj) as response:
        response_body = response.read().decode("utf-8")
        result_objs = json.loads(response_body)
        result_obj = result_objs["feed"]
        review_count = len(result_obj["entry"])
        messages = "レビュー数は" + str(review_count) + "件です"
        return messages
    except urllib.error.HTTPError as e:
        if e.code >= 400:
            messages = e.reason
            return messages
        else:
            return e

```


これを圧縮して、AWSLambdaなどに設置してCloudWatchで定期実行すれば、レビューが全件取れます。
Lambdaにあげる時は、作業ディレクトリに移動（コマンド「cd」で）後、ライブラリのインストール時にオプションで「-t」 をつけてください。

#### 注意
その時の全件（コメントのついたレビュー）しか取れないので、差分だけ欲しいなどの時は、取得したデータをDBなどに保存して差分を出す必要があります。


#### github
https://github.com/isamiodagiri/LineGetReview
Routing Error : uninitialized constant ◯◯Controller解決出来ない。

##コントローラちゃんと作ってルーティングしたのに！？
今日のメモは、きちんと設定できてるはずなのに、何故かルーティングエラーが出て、検索しまくるハメになってしまった話です。

##解決までの流れ

まずは、**テーブル**　からご紹介。

```
novel_listsテーブル
novel_postsテーブル
```

この二つを使って、作成画面である、new.html.erbを作っていた訳ですが。
```resources novel_lists only: ・・・・略  do
　resources novel_posts only: ・・・・・略
end```

novel_listsのnewアクションのnew.html.erbファイルにてformを作り。
createアクションでsaveされ、novel_postsのnewアクションのnew.html.erbに飛ぶ。

こんな流れで

```
 @novel_list = current_user.novel_lists.build(novel_list_params)
    
    if @novel_list.save
      flash[:success] = 'タイトルを作成しました'
      redirect_to new_novel_list_novel_post_path(@novel_list)
    else
      flash[:danger] = '作成に失敗しました。'
      render :new
    end
  end
```
作っていました。

##飛んだ直後にエラーが。

Routing Error : uninitialized constant NovelPostsController

！！？？ちゃんとルーティング設定したはず・・・
rails routesで確認してもルーティングはしっかりと出来ています。


```new_novel_list_novel_post GET    /novel_lists/:novel_list_id/novel_posts/new(.:format)                                    novel_posts#new```

何故だ・・・と色々な所をチェックしていくが、治らない。
仕方なくネット検索をかけ、同じようなエラー記事をみて行く。
しかし、中々、解決に至る記事を見つけられない。

その中で、見つけたのが
http://blog.livedoor.jp/tokyo_kinako/archives/21045311.html
このブログ記事。コントローラを作った際に
rails g controller NovelPost  (s)　　複数形にしていない事で起きた。と書かれていた。
複数形にしたつもりではいたが、まさか。と思って・・・・コントローラをチェックすると。

##novelposts.controller←ファイル名が違ってる！？

はい、その通りです。
novelposts→正しくは、novel_posts.controllerにならなければいけません。

_　ただの棒線１本の違い。違いが細かすぎて出来てると思っている自分には、見えていませんでした。

という事で、今後は気をつけようとメモでした。

同じようなエラーが出た方はまず。

コントローラのファイル名を確認してみてください。

名前が違ったり、単数形になっていたりしているかもしれません。

気をつけて欲しいのは、作り直した場合、viewsファイルと、コントローラの中身は消えますので、
どこかにコピーなどしておくかしないと、書き直しです。

では以上となります。！！
phppgadminをWebで開きたい

どうもしゅうです。
Laravelを使ってToDOリストを作ろうと思っています。
LaravelでTODOリストを作るにあたってデータベースが必要です。
僕が今回参考にしている学習教材によるとPostgreSQLを使っています。

前にPHPを学習していたときにはPhpmyadminという便利なものを使ってデータベースを管理していました。今回もPostgreSQL版のphpmyadminはないかなと探していたところphpPgAdminというのも見つけたので、それを使っていこうと思います。

今回はphpPgAdminをWebで開く方法をまとめておこうかなと思います。

###まず最初にやること
①MAMPをインストールしておく。
②[phppgadmin](http://phppgadmin.sourceforge.net/doku.php?id=download)をインストールしておく。(三種類くらいインストールできるファイルがあるけど、僕は.zipで終わるものをインストールしました。)
③HomebrewでPostgreSQLをインストールしておく。


###  いろいろやっていくよ
phppgadminをインストールしたあとに、便宜上ファイル名を変えておきます。
右矢印で示した名前に変えておく。
下矢印はフォルダの階層を表しています。

```
phppgadmin-REL_5-6-0 → phppgadmin
↓
conf
↓
config.inc.php-dlist（みたいな感じ） →　config.inc.php 
```

phppgadminフォルダをMAMPの中の```htdocs```の中にコピーします。
そして、MAMPを起動します。
最後に```http://localhost:8888（人によって違うかも）/phppgadmin/```のURLで無事開くと思います。

##### MAMPのドキュメントルート
このドキュメントルートの設定によって開ける人開けない人が出てくるかもしれません。
細かいことはわからないので説明はできませんが、このキーワードを元に調べると解決の糸口が見えるかもしれません。

### まとめ
見ていただきありがとうございました。
間違っている点やわからない点などがありましたら、指摘していただけると助かります。
32bit UEFIなPCにLinuxをインストールする方法

現在の個人向けPCは基本的に64ビット対応なので、Linuxディストリビューションをインストールする際には、amd64（x86-64）イメージを用います。

しかし、一部のマシンでは、UEFIが32ビット版のため、そのままamd64向けイメージを用いてもインストールできません。特に、数年前に盛んに発売されたIntel Atom（Bay Trail）を搭載した8-10インチタブレットや、同様のアーキテクチャを使用したノートPCなどにはこのような問題があります。

さらに、Linuxディストリビューションの配布しているISOイメージで、32ビットUEFIに対応しているものは限られているため、該当マシンへのLinux導入はさらに困難を増します。

本記事では、実機での経験をもとに、このような困難にどのように対処するか簡単にまとめます。

# Debian 最新版（Buster）の32ビットイメージを使う
現時点で（少なくとも実機にLinuxをインストールするだけであれば）この方法が簡単かと思われます。公式サイトやミラーサイトから32ビット版ISOイメージをダウンロードし、ddや各種ツールを使ってUSBメモリなどに焼けば、問題なくインストーラーが立ち上がり、システムのインストール、およびその後の起動も問題なく行えるかと思います。

## しかし、下記のような問題がある
この方法だと、比較的楽にDebianの最新版を導入できるのですが、以下のような問題があります。
- Debianのポリシー上、プロプライエタリなドライバなどがインストールイメージに含まれていない
- 64ビット版でしか動作しないソフトウェアは（当然ながら）動かない

# Debian Busterのmulti-archイメージを使う
そこで使いたいのが、multi-archイメージと呼ばれるものです。このイメージを用いると、32ビットUEFIを認識しつつ、amd64アーキテクチャ版のDebianを導入することが可能です。

## 使い方
基本的には、通常と同じです。ただし、用意するイメージが"debian-10.x.x-amd64-i386-netinst.iso"となります。有線LANが利用できない場合など、プロプライエタリなドライバが必要な場合は、非公式のイメージとなりますが"firmware-10.3.0-amd64-i386-netinst.iso"を用いましょう。

イメージをUSBメモリなどに焼き、ブートすれば画面に従ってDebianを導入できるかと思います。

## 64ビット版を導入する利点と欠点
Linux向けには64ビット版しか用意されていないソフトウェアが利用可能になります。Google Chrome（Chromiumはi386版でも利用可能）や、Electronを用いたソフトウェア（AtomやVisual Studio Code）を利用することができます。

一方、課題となるのがメモリの使用量の問題です。Baytrail世代のAtomを搭載しているマシンの大半は、搭載されているメモリが2GBなど限られています。Electronを使ったエディタなどをフル活用するには、このメモリ量では少し物足りないかもしれません。軽量なデスクトップ環境を利用するなどの対策を講じましょう。

## 終わりに
Debianというと、Linuxディストリビューションの中でも硬派で、Ubuntuなどに比べるととっつきにくいイメージもありますが、インストール作業自体は比較的簡単にGUIで行うことができます。また、ユーザー数が多いため、情報を得ようとする際にも比較的入手しやすいのが特徴です。

32bit UEFIなマシンにLinuxは無理、と諦めてしまう前に、Debianの導入を検討してみてはいかがでしょうか。
レコードレベルセキュリティ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442974/08985065-6c69-dac6-f4ee-6f50223ba65f.png)



From: https://trailhead.salesforce.com/ja/content/learn/modules/data_security/data_security_records
EKSとALBで502を起こさずデプロイする

# TL;DR

ALBのターゲットを`instance`→`ip`に変更する。
ALBの `登録解除の遅延` < `Podの削除遅延(preStop)`に設定する。

# ALB+ローリングアップデートの問題

k8sを使っているとローリングアップデートが手軽にゼロダウンタイムでデプロイする方法です。
しかし、ALB(ingress)を使っているとローリングアップデート中の一部のアクセスが`502`になってしまいます。

いくつかissueが上がってますが、まだopen状態です。
https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues/1065
https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues/1131

色々試してみた結果、502を回避してデプロイする方法が見つかったので共有します。

# ダウンタイムなしでデプロイする方法

- ターゲットの種類(target-type)を`ip`にする
    - Pod毎にIPが設定される(セカンダリプライベートIP)
    - ALBのターゲットがNodeのIPとポート(NodePort)からPod毎のIPとポートになる
- ALBの `登録解除の遅延` < `Podの削除遅延(preStop)`に設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63462/efe07204-77ee-8025-a515-b1c8bb7fc9d0.png)

```example.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: "example-ingress"
  annotations:
    kubernetes.io/ingress.class: alb
    # annotations: https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/ingress/annotation/
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/healthcheck-path: /
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: "5"
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: "3"
    alb.ingress.kubernetes.io/healthy-threshold-count: "2"
    alb.ingress.kubernetes.io/unhealthy-threshold-count: "2"
    alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=10
    alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=10
  labels:
    app: "example-ingress"
spec:
  rules:
    - http:
        paths:
          - path: /*
            backend:
              serviceName: "example-service"
              servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  type: NodePort
  selector:
    app: example
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
        - name: example
          image: nginx:alpine
          resources:
            limits:
              memory: "128Mi"
              cpu: "128m"
          ports:
            - containerPort: 80
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 1
            periodSeconds: 10
            timeoutSeconds: 3
            successThreshold: 2
            failureThreshold: 2
          lifecycle:
            preStop:
              exec:
                command: ["sh", "-c", "sleep 20"]

```

# 最後に

まだまだk8s周りのツールはバグ等が多いので、頑張って追っていく必要がありそう
容器技术


容器技术及其应用白皮书（上）-- 容器技术
https://blog.csdn.net/wh211212/article/details/53535881

容器技术及其应用白皮书（下）-- 容器应用
https://blog.csdn.net/wh211212/article/details/53540342

现实中的容器技术运用案例
https://blog.csdn.net/horsefoot/article/details/52372602


《2019容器技术及其应用发展白皮书》发布，拥抱容器正当时
https://blog.csdn.net/ZPWhPdjl/article/details/102674585

容器（Container）和虚拟化技术的区别
https://blog.csdn.net/weixin_38885808/article/details/81130153

Docker 教程
https://www.runoob.com/docker/docker-tutorial.html
Firebase FunctionsでRealtime databaseにdataを送信する

# 恒例
https://firebase.google.com/docs/functions ドキュメントを読んでください

# Firebase CLI をインストールする
```npm install -g firebase-tools```

# Coding

```bash
mkdir test
cd test
mkdir functions
cd functions
vi package.json
```

```json
{
  "name": "mytest",
  "description": "mytest",
  "dependencies": {
    "firebase-admin": "~7.1.1",
    "firebase-functions": "^2.2.1"
  },
  "devDependencies": {
    "chai": "^3.5.0",
    "chai-as-promised": "^6.0.0",
    "firebase-functions-test": "0.1.6",
    "mocha": "^5.0.5",
    "sinon": "^4.1.3"
  },
  "scripts": {
    "ci-test": "npm install && npm run test",
    "serve": "firebase serve --only functions",
    "shell": "firebase experimental:functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "8"
  },
  "private": true
}
```

```bash
vi index.js
```

```js
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.send_data = functions.https.onRequest(async (req, res) => {

  const time = req.query.time;
  const text = req.query.temp;

  const snapshot = await admin.database().ref('/test').push({time:time,text:text});

  res.redirect(303, snapshot.ref.toString());
});

exports.read_data = functions.https.onRequest((req, res) => {

    var ref = admin.database().ref("test");
    return ref.orderByChild("time").limitToLast(10).once('value').then(function(snapshot) {
      res.send(snapshot.val());
    });

});
```

# Deploy

```bash
cd functions && npm install && cd ..
firebase deploy
```

# 送信方法
https://us-central1-[MY_PROJECT].cloudfunctions.net/send_data?time=20200218&text=uppercaseme をアクセスする

# DATAを読み取る方法
https://us-central1-[MY_PROJECT].cloudfunctions.net/read_data をアクセスする
VS Code ショートカット一覧(一部)

Visual Studio Codeを自分が使用する際に便利なショートカットキーを、忘れないようにまとめておく。Macで使用確認。

## 編集系
1.`Alt` + `↑/↓`　カーソル行／選択行をそのまま移動(複数行対応)
2.`Alt` + `Shift` + `↑/↓`　カーソル行／選択行をそのままコピー(複数行対応)
3.`⌘`+`←/→`　行の頭、末尾に移動
4.単語選択後`⌘`+`D` 同じ単語にのみカーソルがあたり同時に編集出来る(10個あれば10回Dを押す＝編集する数調整可)
5.`⌘`+`Shift`+`V`でプレビューを出す

2.は移動距離が近ければいちいちコピペしなくていいので便利。
4.はclass名など同時に編集したい時に便利
5.README作成時にマークダウン記法確認のために出していると便利

## 検索系
1.`⌘`+`F` ファイル内のキーワード検索
2.`⌘`+`P` ファイル検索 

1.はいちいち探す手間が省ける
2.はファイルの置き場を探さなくても大丈夫




自分が普段本当に使っているものです
まだ、駆け出しなのでこんなのも便利だ！などあれば是非教えて頂きたいです。
WordPressのソースをいじってみる（Docker調整編）

[PHP出来るけど全然WordPressわからないので使ってみる（環境準備編）](https://qiita.com/gungungggun/items/73b9053390a313df5157)でサクッとDockerで環境を用意しました。
ただ、この方法だとWordPressのソースコードをいじることが難しいので少し修正します。

# コンテナの停止

```
$ docker-compose down
```

これで今動いているコンテナを停止します。

# docker-compose.yamlの書き換え
```yaml:docker-compose.yaml
version: '2'

services:
   db:
     image: mysql:5.7
     container_name: test-wp-db
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: wordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     image: wordpress:latest
     container_name: test-wp
     depends_on:
       - db
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_PASSWORD: wordpress
     volumes:
       - ./html:/var/www/html
volumes:
    db_data:
```

`wordpress`部分に`volumes`を追加しています。
これによりローカルの`./html`にwordpressのソースがマウントされます。

# コンテナの起動
```
$ docker-compose up -d
```

# 書き換えてみる
`./html/index.php`の頭に`exit;`と書いてみます。
これで`http://localhost:8000`にアクセスするとワードプレスの画面でなく、真っ白画面になることが確認できたらOKです。

# まとめ
DockerのWordPress環境で、WordPressのソースコードをいじれるようにしました。
これでさらにいろいろ試せますね。
[python]画像の表示と保存について

#はじめに
こちらの記事https://qiita.com/Daiki_P/items/e2a67be67992783ef2e2 で画像表示について簡単にまとめました. 次はこの画像の保存についてまとめたいと思います. 個人的には意外と面倒だと感じます.

```python
import cv2
from matplotlib import pyplot as plt
img = cv2.imread("Pasta.jpg") #BGRで取得.
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #BGRをRGBに変換.
plt.imshow(img)
plt.show()
```

![Qita用.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285948/4a904844-301d-66e9-0adc-6925db9c42d7.jpeg)

#OpenCVの関数で保存
素直に書くと以下のようにcv2.imwriteを書いてしまうこともあると思います. しかし, OpenCVのcv2.imwriteはBGRの順で書き込むので, RGB変換をしたことが原因で変な画像となってしまいます.

```python:失敗例
#imreadで読み込んだ画像をRGBに変換したのがimg.
#このimgをそのままimwriteに渡すと保存結果が不自然になる.

import cv2
from matplotlib import pyplot as plt
img = cv2.imread("Pasta.jpg") #BGRで取得.
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #BGRをRGBに変換.
cv2.imwrite("Past_write.jpg",img)
plt.imshow(img)
plt.show()
```
[保存結果]
![h.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285948/9f687f48-07e3-c8ae-4d4f-01ed0b6def5d.jpeg)

なので, こうするのが一つの対策です. 変数名を変えて, imgを避難させただけです.

```python:成功例
#matplotlibでの表示はRGBのimg_RGBで行う.
#opencvでの保存はBGRのimgで行う.

import cv2
from matplotlib import pyplot as plt
img = cv2.imread("Pasta.jpg") #BGRで取得.
img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #BGRをRGBに変換.
cv2.imwrite("Past_write.jpg",img) 
plt.imshow(img_RGB)
plt.show()
```
[保存結果]
![Qita用.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285948/4a904844-301d-66e9-0adc-6925db9c42d7.jpeg)

#最後に
今回は, OpenCVの関数での画像保存について書きました. matplotlibのsavefigでも画像保存が可能ですが, 軸や余白の設定がやや煩雑となり, OpenCVのimwriteの方がスッキリと書けると個人的には思うので, そのようにしました.
【Ruby】大文字→小文字変換（アッパーケース→キャメルケース）

# 用意されているメソッド
大文字・小文字変換に使えるもの

## upcase
全部大文字に変換

```ruby
'abc'.upcase # => ABC
```

## downcase
全部小文字に変換

```ruby
'ABC'.downcase # => abc
```

## capitalize
最初の文字を大文字に、他を小文字にする

```ruby
'abc'.capitalize # => Abc
```

## swapcase
小文字と大文字の入れ替え

```ruby
'AbCd'.swapcase # => aBcD
```

## camelize
キャメルケースに変換する。通常はアッパーキャメルケース。

```ruby
'john_do'.camelize # => JohnDo
```

引数に`:lower`を指定するとローワーキャメルケースになる

```ruby
'john_do'.camelize(:lower) # => johnDo
```

## underscore
スネークケースにする

```ruby
'JohnDo'.underscore # => john_do
```

# アッパーケース → ローワーキャメルケースへの変換
メソッドを組み合わせれば可能

```ruby
"UPPER_CASE".downcase.camelize(:lower)
# -> upperCase
```


# 参考

- [Rubyでハッシュのキーを全てローワーキャメルに変換する](https://shinkufencer.hateblo.jp/entry/2018/05/09/175257)
- [Rails キャメルケースとスネークケースを変換する](https://qiita.com/hmuronaka/items/79208f54bb88397517a4)
[python]matplotlibを用いた画像表示の基礎

#画像表示
OpenCVで読み込んで, それをmatplotlibで表示したいときのメモとなります.
まずは, 失敗例から.

```python
import cv2
from matplotlib import pyplot as plt
img = cv2.imread("Pasta.jpg") #BGRで取得.
plt.imshow(img)
plt.show()
```
[原因]：OpenCVのimreadは色情報をBGRで取得するが, それをmatplotllibでRGB表示させているから.
<img width="304" alt="screenshot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285948/e6b39898-cc5a-cf25-edc0-b831614f1336.png">
なので, 一度OpenCVで取得したBGRをRGBに変換し, それをmatplotllibでRGB表示させることで正常に画像表示できる.

```python
import cv2
from matplotlib import pyplot as plt
img = cv2.imread("Pasta.jpg") #BGRで取得.
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #BGRをRGBに変換.
plt.imshow(img)
plt.show()
```

![Qita用.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285948/4a904844-301d-66e9-0adc-6925db9c42d7.jpeg)


余談ですが, 画像のグレースケール表示に関しては自分の下の記事にあります.
https://qiita.com/Daiki_P/items/844bc3a4b271e6ae179b
ZshでFlutter導入してみた（Mac用）

今日Flutterを導入しようとして、手間取ってイライラしたので、この記事が他に同じことしようとしている人の助けになれば幸いです。
ZshでのFlutter導入の日本語のドキュメント、記事などは探したところありませんでした。なので、英語の記事とFlutterの公式ドキュメントを参考にさせていただきました。

最初に、こちらの2つの記事を参考にさせていただきました。(https://qiita.com/tomy0610/items/896dc8ec9ba95c33194f,
https://qiita.com/akatsukaha/items/3b8a5a6d94a3cdb1e047)

<b>ですが、こちらの記事はコマンドシェルにZshを採用している方用ではありません。<b>

#前提
Mac Catalina 10.15.2(Macbook pro 2019年モデル)
Xcode 11.3.1

#環境構築手順
##Flutter SDKのダウンロード
[公式サイト](https://flutter.dev/docs/get-started/install/macos)でSDKをダウンロード。
最初にzipをダウンロードする場所はどこでもいいと思いますが、zipを解凍した後は解凍して出てきた、Flutterというフォルダを安全な場所に保管しましょう。（僕の場合は、userの下にdeveloperというフォルダを作って、そこに保管しました）

##PATHを通す
まずTerminalを開きます。（Terminal見つけられない場合は、Spotlight Searchで検索してみてください）
<img width="901" alt="Screen Shot 2020-02-18 at 8.59.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341253/84a7f9d7-7785-0b84-2d78-b3943e45202f.png">
こういう風に開けたらOKです。Terminalの上に家のロゴ的なものとユーザーネームがあるようにしてください。（Terminalでcdとタイプして、Enterでホームディレクトリに移動できます）

そこでPATHを通すために.zshrcをvimで開きます。

```
vim .zshrc
```
上記のコードをTerminalにコピーペーストしていただければzshrcを開けるかと思います。
そしてこのzshrcの中でflutterへのPATHを通すコードを書いていきます。

vimを開けたら、iを押してエディティングモードにします。

```
export PATH="$PATH:[FlutterフォルダまでのPATHを入力]/bin"
```
僕の場合は、Userの下のDeveloperというフォルダにflutterフォルダがあるので、コードは下のようになります。参考にしていたいただければ幸いです。

```
export PATH="$PATH:/Users/[僕のUSERNAME]/Developer/flutter/bin"
```
ご自分のPATHが入力できたら、escキーを押して、:wq!とタイプ。そしたら、元のホームディレクトリに戻れると思います。
そしたら、Terminalのタブをいったん閉じて、新しいタブを開きましょう。

ちゃんとPATHが通ったか確認しましょう。

```
which flutter

# 以下の様にパスが出ればOKです
/Users/[僕のUSERNAME]/Developer/flutter/bin/flutter
```
##依存性確認
```flutter doctor```とTerminalでタイプし、依存性の確認をしましょう。

```
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.8, on Mac OS X 10.15.2 19C57,
    locale en-JP)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 11.3.1)
[✓] Android Studio (version 3.5)
[✓] VS Code (version 1.42.0)
[!] Connected device
    ! No devices available

! Doctor found issues in 1 category.
```
上記のように表示されれば、大丈夫です。

<b>ここでエラーが出てきても焦らないでください！<b>

エラーが出ても、だいたいの場合は何はダウンロードしていないか、プラグインをインストールできていないだけなので、Terminalに出てくる指示にしたがってゆっくりダウンロードしていきましょう。

[こちらの記事](https://qiita.com/tomy0610/items/896dc8ec9ba95c33194f)の```環境構築手順:おまけ```の章が参考になると思います。

エラーがなくなったら、環境構築完了です。お疲れ様でした！！

#参考にした記事
* https://flutter.dev/docs/get-started/install/macos#update-your-path
* https://stackoverflow.com/questions/58400500/zsh-command-not-found-flutter
* https://qiita.com/akatsukaha/items/3b8a5a6d94a3cdb1e047
* https://qiita.com/tomy0610/items/896dc8ec9ba95c33194f
ClickOnce 実行ボタンが表示されない問題

# 問題
　ClickOnce配信によるアプリケーションを起動しようとしたときに、以下のイメージのように、
　「実行ボタン」が表示されず、起動できない。
![アプリケーションの実行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15241/a3f5ea6a-834e-f141-4287-8798b37069f3.png)


# 解決策
　レジストリに問題がある。
　以下のようにDisabledになっていると思われるので、Enabledに変更することで改善する。

```csharp
[HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\.NETFramework\Security\TrustManager\PromptingLevel]
"MyComputer"="Disabled"
"LocalIntranet"="Disabled"
"Internet"="Disabled"
"TrustedSites"="Disabled"
"UntrustedSites"="Disabled"
```

# 参考
　詳細は以下のサイトを確認してください。
　https://docs.microsoft.com/ja-jp/visualstudio/deployment/how-to-configure-the-clickonce-trust-prompt-behavior?view=vs-2015&redirectedfrom=MSDN
glTF 2.0 PBR アルファテクスチャのメモ

https://github.com/WonderMediaProductions/Maya2glTF/issues/44

https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#alpha-coverage

PBR material では, alpha texture は baseColor の alpha channel で扱う.
仕様では, alpha texture だけを指定はできないため, baseColor のテクスチャにアルファチャネルを含める必要がある.
technique を transparent にする. alphaMode = BLEND にする.

## Alpha cutoff

デカールテクスチャなど, アルファで抜く場合は, alpha cutoff を使う. alphaMode = MASK.
Reactコンポーネントとは

# この記事の目的
公式チュートリアルで三目並べを作ってもらうのが一番理解できるが、その中でも特に日本語で説明しておいたほうがよさそうなポイントを纏めている。
本資料を読んだ後に、チュートリアルを両方やってもらったほうがより理解が深まる。

## 関連するQiita記事
[Reactのざっくり概要](https://qiita.com/drafts/82f4d800030f40afda51/edit)

## 参考資料
### ドキュメント
[公式ドキュメント](https://ja.reactjs.org/docs/getting-started.html)

### チュートリアル
[公式チュートリアル](https://ja.reactjs.org/tutorial/tutorial.html)

※余力があれば、以下のチュートリアルも行うことを推奨する
[Getting Started with React - An Overview and Walkthrough Tutorial](https://www.taniarascia.com/getting-started-with-react/)

# Reactコンポーネントとは
ReactはUIを「コンポーネント」という部品単位で構築する。

## 1つのコンポーネントを描画する例
例えば、以下のような四角形のボタンを描画する場合を考える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329353/ad7bda96-0fc8-3899-0fc3-d9a7a6bdf31b.png)

これをReactコンポーネントで定義すると、以下のようになる。（スタイルは省略している）

```jsx:square.js
class Square extends React.Component {
  render() {
    return (
      <button className="square"></button>
    );
  }
}
```

SquareというReactコンポーネントを定義しており、render関数で描画内容をreturnしている。

このとき<button className="square"></button>というHTMLタグをreturnしているように見えるが、これはJSX記法であり、以下のようにJSXを使わずにReact.createElementで記述した場合と等価である。

```jsx:square.js
class Square extends React.Component {
  render() {
    return (
      React.createElement(
      'button',
      {className: 'square'}
      );
    );
  }
}
```

## 複数のコンポーネントを描画する例
上記のSquareを更に3×3のマス目でボタンを並べて描画する場合を考える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329353/f1c69d2e-6d18-cac3-0315-c06ab67ea68c.png)

これをReactコンポーネントで定義すると、以下のようになる。（スタイルは省略している）

```jsx:board.js
class Square extends React.Component {
  render() {
    return (
      <button className="square"></button>
    );
  }
}

class Board extends React.Component {
  renderSquare(i) {
    return <Square />;
  }

  render() {
    return (
      <div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}
```

新たに加わったBoardというReactコンポーネントは、Squareコンポーネントを9つ組み合わせて3×3のマス目を実現している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329353/1ead0e92-f6a5-bf32-5952-ae9b9d5b0fdd.png)
dockerで環境構築する際にrails5.2.0環境以降でcredential.ymlを編集する方法

# はじめに

初投稿です。よろしくお願いします。
忘備録として投稿します。

# 内容
docker-compose.ymlにvimを入れてインストールしたはずなのにcredential.ymlを編集しようとしても暗号化されたまま編集できませんでした。
他にも方法があるかもしれませんが、全くの初心者レベルの人が解決できると仮定してその道筋を投稿します。

# 開発環境

docker 19.03.5
docker-compose 1.25.4
rails  5.2.4.1
ruby   2.5.1
nginx 1.15.8
Mysql 5.7



# docker-compose.yml
```docker-compose.yml
version: '3'
services:
  app: &app_base
    build:
      context: .
    env_file:
      - ./environments/db.env
    command: bundle exec puma -C config/puma.rb
    volumes:
      - .:/webapp
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
      - log-data:/webapp/log
    depends_on:
      - db
    tty: true
    stdin_open: true

  db:
    image: mysql:5.7
    env_file:
      - ./environments/db.env
    volumes:
      - db-data:/var/lib/mysql
    ports:
      - "4306:3306"

  web:
    build:
      context: containers/nginx
    volumes:
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
    ports:
      - 80:80
    depends_on:
      - app
volumes:
  public-data:
  tmp-data:
  log-data:
  db-data:

```

#Dockerfile
```Dockerfile

FROM ruby:2.5.1

# リポジトリを更新し依存モジュールをインストール
RUN apt-get update -qq && \
    apt-get install -y build-essential \
                       nodejs \
                       vim    

# ルート直下にwebappという名前で作業ディレクトリを作成（コンテナ内のアプリケーションディレクトリ）
RUN mkdir /webapp
WORKDIR /webapp

# ホストのGemfileとGemfile.lockをコンテナにコピー
ADD Gemfile /webapp/Gemfile
ADD Gemfile.lock /webapp/Gemfile.lock

# bundle installの実行
RUN bundle install

# ホストのアプリケーションディレクトリ内をすべてコンテナにコピー
ADD . /webapp

# puma.sockを配置するディレクトリを作成
RUN mkdir -p tmp/sockets
```

#docker-compose build→up -d
コンテナをbuildしてvimインストールして起動したが、あれ？ credential.yml編集できない...

#なぜだ....
vimインストール出来ているか見てみよう！

作業ディレクトリでwhich vimコマンド

```
which vim
/usr/bin/vim
```

インストールはされているな.....どうやって起動すれば良いんだ

#コンテナの中に入ってみよう
コンテナの中に入ればできるかも....

```
docker-compose exec app bash
                    ⬆️docker-composeのrails名
                      
```

そうするとroot@というところに入るので以下のコマンドを打ちましょう

```
EDITOR=vim bin/rails credentials:edit
```

credentialに入れた！

```credentials.yml.enc

#   aws:
#   access_key_id: 123
#   secret_access_key: 345

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 8be8e637d755f79c799048bed8be0c...
```

#最後に
手順を書いてある記事が少なかったので少しでも参考になればと思います。
何かあればご意見ください！