OmniAICreator/Qiita-1.07M huggingface dataset:
【docker】starting container process caused "exec: "bash"エラーがでる場合はshを指定する

alpine-linuxイメージのdockerコンテナで、`docker exec`した場合に`bash`コマンドが使えない時は`sh`を指定するとコンテナに入れる


次のように`docker exec`すると...

```
$ docker exec -it {CONTAINER} bash
```

次のようなエラーが出た

```
OOCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"bash\": executable file not found in $PATH": unknown
```

`bash`ではなく`sh`を指定するとコンテナに入る事が出来る

```
$ docker exec -it {CONTAINER} sh
```
Goのスライスをポインタ渡しした時のindexアクセスの書き方

記述方法でハマったので備忘録として

```sample.go
package main

import "fmt"

type Item struct {
	name string
}

type Items []Item

func main() {
	items := make(Items, 0)
	items = append(items, Item{name: "ペン"})
	items = append(items, Item{name: "ハサミ"})

	fmt.Println(items[0])
	fmt.Println(items[1])

	refItems := &items

	fmt.Println((*refItems)[0])
	fmt.Println((*refItems)[1])
}
```

itemsは[0]とアクセスできるが、refItemsは[0]と記述するとエラーになる。(does not support indexing)
`(*refItems)[0]`と記述する事で配列のindexにアクセスできる。
Assetsを名前完全一致で検索する

`AssetDataBase.FindAssets` のフィルタ式には名前完全一致のオプションがないので以下のようなコードで代替します。

```csharp
var assetName = "c0001";
var assetTypeName = "t:XXXXXX";
var filterString = assetName + " " + assetTypeName;

var path = AssetDatabase
	.FindAssets(filterString)
	.Select(AssetDatabase.GUIDToAssetPath)
	.FirstOrDefault(str => string.Equals(Path.GetFileNameWithoutExtension(str), assetName, StringComparison.CurrentCultureIgnoreCase));
```
WordPressの制作環境をVagrantで

WordPressの制作環境をVagrantで作ります。

## Vagrant起ち上げ

以下の設定で`vagrant up`

```ruby:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "bento/centos-7.4"
  config.vm.network "forwarded_port", guest: 80, host: 8080
end

```

そして`vagrant ssh`

## 必要なモジュールのインストールと設定

```
yum -y install httpd mysql-server php php-mysql
```

```
# サーバーとDBを常に起動させておく
service httpd start
chkconfig httpd on

service mysqld start
chkconfig mysqld on
```

※ 上記でmysqlが起動できないとき

```
yum -y install mariadb-server
service mariadb start
chkconfig mariadb on
```
https://stackoverflow.com/questions/31067135/in-centos7-can-not-start-mysql

したらいけた


## ローカルのディレクトリを公開ディレクトリと同期させる

Vagrantはデフォルトでゲスト(`vagrant ssh`した先のサーバー)の`/vagrant`ディレクトリとホスト(ローカル)のVagrantを起動しているルートディレクトリが同期しています。

その機能をうまく使って`/var/www/html`で公開しているディレクトリとローカルのディレクトリを同期させちゃいましょう

```:ローカル側
mkdir html
```

```:vagrant側
ln -s -d /vagrant/html /var/www
```

詳しい説明は割愛しますが、これでローカルのhtmlディレクトリと公開している`/var/www/html`ディレクトリが同期するようになりました。


## DB作成 

WordPress用に下記のように作ります。

|||    
|:-----------------|------------------:|
| DB名| mywordpress | 
| ユーザー名| myuser | 
|パス|mypass|

#### 実行

```
mysql -u root
```

```
CREATE DATABASE mywordpress;

GRANT ALL PRIVILEGES ON mywordpress.* TO myuser@localhost IDENTIFIED BY 'mypass' WITH GRANT OPTION;
```

## WordPressの設置

公式からとってきて,ローカルのhtmlフォルダに設置

http://localhost:8080/ にアクセスしたらセットアップ画面でてくるはず
[Angular] JavaScriptモジュール vs. NgModule - @NgModuleとは何か (2)

@NgModuleがなんなのかを知るにあたり、いくつか前提知識が必要となります。
前回は[JavaScriptのモジュールについて](https://qiita.com/sengoku/items/a62cb8d75733b0321706)の勝手訳を書きました。
今回は[Angular - JavaScript Modules vs. NgModules](https://angular.io/guide/ngmodule-vs-jsmodule)の勝手訳です。

# 前段

JavaScriptとAngularは、コードを整理するのにそれぞれ異なったやり方でモジュールを使います。Angularはその両方に依っています。


# JavaScriptモジュール

JavaScriptでは、モジュールはコードが書かれた個々のファイルです。

モジュールの中身を使わせたいときは、こんなコードを書きます。

```js:
export class AppComponent { ... }
```

そのモジュールを使いたいときは、こんなコードを書きます。

```js:
import { AppComponent } from './app.component'
```

# NgModule

NgModuleは`@NgModule`によって修飾されたクラスです。`@NgModule`のなかの`imports`配列は、そのモジュールが使いたい他のNgModuleを示します。これはJavaScriptのモジュールとは違います。
`@NgModule`がついたクラスはそれぞれ個別のファイルに保存されていますが、JavaScriptのモジュールのように個別のファイルがNgModuleであることを意味するわけではありません。`@NgModule`とメタデータがあることでNgModuleになります。

Angular CLIコマンドによって生成されたファイルは、JavaScriptモジュールとNgModule両方になっています。

```js:app.module.js
/*
これらはJavaScriptのインポートステートメントです。
Angularはこれらについて関知しません。
*/
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

/*
@NgModule修飾子が、AngularにこのクラスがNgModuleであることを示します。
*/
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [     /* 他のNgModuleをインポートしています。 */
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
```

NgModuleクラスとJavaScriptモジュールの違いを並べるとこんなところです。

* NgModuleは[宣言可能なクラス](https://angular.io/guide/ngmodule-faq#q-declarable)にのみ束縛されます。宣言可能なクラスは、[Angularコンパイラ](https://angular.io/guide/ngmodule-faq#q-angular-compiler)にとって、唯一重要なクラスです。
* JavaScriptモジュールのようにメンバークラスをひとつの巨大なファイルにまとめるのではなく、[@NgModule.declarations](https://angular.io/api/core/NgModule#declarations)リストにNgModuleクラスを列挙します。
* NgModuleは、他からインポートしたか、自分自身である[宣言可能なクラス](https://angular.io/guide/ngmodule-faq#q-declarable)のみをエクスポートします。それ以外のクラスを宣言したりエクスポートしたりはしません。
* JavaScriptモジュールと異なり、NgModuleは[@NgModule.providers](https://angular.io/api/core/NgModule#providers)リストにプロバイダを追加することにより、アプリケーション__全体__を拡張できます。
インターン行ってるだけでは身にならないので気をつけろ


# 諸注意

- 技術的なことを書いていない
- 自戒も込めた記事
- 長期インターンに行ってるからと油断している学生向け

---

# 自分のエンジニア歴

---

## 長期インターン(3社)

---

# 少し長くやってるけど・・・

---

# あんまりエンジニアとして成長できてない

---

# 原因は

---

# 様々なことをなんとなくやってたこと

---

## なんとなくやってたポイント

- なんか実装できちゃったからいいや！
- なんかこれできないけど、ググったらあったわ！
- 動作確認やって見たら動くし、おっけいだ！
- テストより先に実装実装。自分の書きやすさ優先！
- テスト書きやすさの考慮とか知らん！
- まあどうにかなるっしょ！

---

## これらはマジで危険兆候。

---

## 放っておくと

---

## 綺麗な実装があまりわからない

---

## 落ちるコードを書いちゃう(意識してそういうコードにしてるわけではない)

---

## などと行った副作用がある

---

# 意識すべきこと

---

## なんとなくやってたポイント抹殺。

---

## ~~なんとなくやってたポイント~~

- ~~なんか実装できちゃったからいいや！~~
- ~~なんかこれできないけど、ググったらあったわ！~~
- ~~動作確認やって見たら動くし、おっけいだ！~~
- ~~テストより先に実装実装。自分の書きやすさ優先！~~
- ~~テスト書きやすさの考慮とか知らん！~~
- ~~まあどうにかなるっしょ！~~

---

## できる人の真似をする

---

## 例えば

---

#### 公式ドキュメントを読んで理解する
#### わからないところはソースコードを読みにいく
#### フレームワークは綺麗なコード代表格。読む！
#### 汚いコードも読み、何が悪いのかを考える

---

# プロのお仕事を目指すと良いのでは(自分も探してる)

---

## じゃあ、プロってなんだ。

---

## エンジニアでいうと

---

### 考慮の網羅性
### 実装のスピード
### ミスの少なさ
### 作業見積もりの速さ
### 作業見積もりの正確さ
### 配慮のある開発

---

## それに伴い必要だと感じていること

---

### 設計の考慮事項の整理
### 設計のパターンを知ること
### 自分の実装速度の把握
### 言語, ツール仕様の把握
### 調査のやり方の把握
### 自分の作業で短縮できる箇所の断捨離

---

# まとめ

---

結局なんとなくやっているだけではなんでも意味はなくて、何か自分がやらなきゃいけないことを意識していく必要がある。(同期にイキってるとか言われそう笑)
CakePHP2.x で Call to a member function body() on a non-object エラーが出たときの対応

# いきなり解決策

CakePHP2.x系では、Controller のインスタンス生成時に、 `CakeRequest()` オブジェクトと `CakeResponse()` オブジェクトが必要。その設定がされてない場合にこのエラーが出ます。なので、指定すればOK。

```php
// before
new Controller();
// after
new Controller(
    new CakeRequest(),
    new CakeResponse()
);
```

# 背景

僕の場合は、とある事情により、Shellで、`Controller->render()`を実行する必要が出て、その際にこのエラーに遭遇したため、上記対応で解決しました。

コアのソースを見たところ、エラー箇所は以下

```php
// lib/Cake/Controller/Controller.php
 934     public function render($view = null, $layout = null) {
// 省略
 959             }
 960         }
 961
 962         $this->autoRender = false;
 963         $this->response->body($this->View->render($view, $layout)); // ここでエラー
 964         return $this->response;
 965     }
```

ここで、そもそも、`$this->response` が空であることがわかったので、コンストラクタを確認

```php
// lib/Cake/Controller/Controller.php
 319     public function __construct($request = null, $response = null) {
// 省略
 340         if ($response instanceof CakeResponse) {
 341             $this->response = $response; // ここでセット
 342         }
```

なるほど、`CakeResponse` オブジェクトをセットする必要があると分る。
という流れで調査しました。

おそらく、CakePHP1系では、Controller にこういう引数は無いので、1->2の切り替えをするときに遭遇しそうな不具合（ニッチ）ですが、参考になれば幸いです。
自分がよく使う(かもしれない)Excel VBAのコード

空き時間に書いたが、使うか分らない。
でもいつか使うかもしれないものをメモとしてここに記入。
「こんなん作らなくても」ってのもあるかもですけど。
コピペしたり、一部抜き出しで使ったり。

#ファイル一覧表を作る
ダイアログからディレクトリを選んでその中身を一覧で表示させる

まずはこれ

```vb
Sub 表作成()
    ActiveSheet.Range(Cells(1, 1), Cells(cell_number, 5)).Borders.LineStyle = xlContinuous
    ActiveSheet.Range(Cells(1, 1), Cells(cell_number, 5)).BorderAround Weight:=xlMedium
    ActiveSheet.Range(Cells(1, 1), Cells(1, 5)).BorderAround Weight:=xlMedium
    ActiveSheet.Range("A1:E1").HorizontalAlignment = xlCenter

    With Activesheet.Range("A1:E1").Interior
        .Color = RGB(248, 203, 173)
    End With

    ActiveSheet.Range("A1").Value = "ファイル名"
    ActiveSheet.Range("B1").Value = "サイズ"
    ActiveSheet.Range("C1").Value = "種類"
    ActiveSheet.Range("D1").Value = "パス"
    ActiveSheet.Range("E1").Value = "タイムスタンプ"

    Columns("A:E").AutoFit
End Sub
```

次

```vb
Sub ファイル情報取得(path As String)
    Dim file As Object, count As Long
    Dim folder As Object, pathname As String
    
    ActiveSheet.Cells.Clear
    count = 1
    With CreateObject("Scripting.FileSystemObject")
    On Error Resume Next
        For Each folder In .GetFolder(path).SubFolders
            count = count + 1
            ActiveSheet.Cells(count, 1).Value = folder.Name
            ActiveSheet.Cells(count, 2).Value = folder.Size & "B"
            ActiveSheet.Cells(count, 3).Value = .GetFolder(folder).Type
            ActiveSheet.Cells(count, 4).Value = folder & Dir(folder)
            ActiveSheet.Cells(count, 5).Value = FileDateTime(folder)
        Next folder
        
        For Each folder In .GetFolder(path).Files
            count = count + 1
            ActiveSheet.Cells(count, 1).Value = file.Name
            ActiveSheet.Cells(count, 2).Value = FileLen(file) & "B"
            ActiveSheet.Cells(count, 3).Value = .GetFiler(file).Type
            ActiveSheet.Cells(count, 4).Value = file
            ActiveSheet.Cells(count, 5).Value = FileDateTime(file)
        Next folder
    End With
    
    Call 表作成(ActiveSheet.Cells(Rows.count, 1).End(xlUp).Row)
    
End Sub
```

KB,MB表記もしてみたいのですが、自分ではごちゃごちゃになりそうだったので諦めました。

最後

```vb
Sub ダイアログ()
    With Application.FileDialog(msoFileDialogFolderPicker)
    .Title = "フォルダを選択"
        If .Show = True Then
            Call ファイル情報取得(.SelectedItems(1))
        End If
    End With
End Sub
```
マクロ実行時はこのダイアログ()を選択する

#方眼紙マス作成
見出しの通り

```vb
Sub 方眼紙マス作成()
    ActiveSheet.Cells.ColumnWidth = 2
    ActiveSheet.Cells.RowHeight = 15.75
    With ActiveSheet.Cells.Interior
        .Color = RGB(255, 255, 255)
    End With
    ActiveSheet.Cells.Borders.LineStyle = xlDot
    ActiveSheet.Cells.BorderAround Weight:=xlMedium
End Sub
```

もっとうまく綺麗に書けるのかなと思ってはいますが、とりあえず想定通りに実行できるので残しておきます。
WinMergeでThumbs.dbなどを除外する設定

バックアップファイルを作成・比較する際にどうしても邪魔になるThumbs.dbファイルですが、
WinMergeのフィルタファイルに追記すれば比較対象から除外することができます。

WinMergeを起動すると「フィルタ」には初期値で「*.*」が設定されていますが、
右側「選択」ボタンをクリックして適用するフィルタの選択画面に移ります。
![winmerge1.png](https://qiita-image-store.s3.amazonaws.com/0/143784/0efe6859-0278-fea6-2489-5863dcfb0bdd.png)

するとファイルフィルタウィンドウが開くので、
「新規」ボタンでフィルタを新規作成します。
![winmerge2.png](https://qiita-image-store.s3.amazonaws.com/0/143784/47536211-1cd8-4723-501d-8ecc882f348f.png)

デフォルトで'Frontpage.flt'というファイルが開くので、
このファイルに追記していくと早いでしょう。

```
## : コメント
def : 対象の扱い　通常の感覚と逆転しています、注意!!
　def : include でフィルタに記入されたファイル・ディレクトリを比較対象から除く、
　def : excludeでフィルタに記入されたファイル・ディレクトリ以外を比較対象から除く
d : 対象ディレクトリのパターンを指定(正規表現)
f : 対象ファイルのパターンを指定(正規表現)

```
例えば対象ファイル・ディレクトリの除外は下記のように書きます。

``` Frontpage.flt
#####################################################
### Additional Settings

f: Thumbs.db ## Thumbs.dbを除外
f: \.DS_store ## .DS_storeを除外
d: sass ## /sass/ディレクトリを除外

```

ファイルを編集・保存したら先ほどのフィルタ選択画面から
「インストール」で編集したファイルを選択し「OK」をクリック。

あとはWinMergeを再起動し、設定が正しく反映されているか、
ディレクトリ比較をして確かめてみましょう!

### 参考サイト
[WinMerge のファイルフィルタ](http://seesaawiki.jp/aki/d/WinMerge%20%A4%CE%A5%D5%A5%A1%A5%A4%A5%EB%A5%D5%A5%A3%A5%EB%A5%BF)
【メモ】マウスホイールのスクロール方向を横に(JavaScript)

横スクロールのサイトを作るとき、マウスホイールで横方向に移動させるための方法メモ。

```javascript
window.addEventListener("mousewheel", e => {
    if (e.deltaX === 0) {
        e.stopPropagation()
        e.preventDefault()
        // noinspection JSSuspiciousNameCombination
        window.scrollBy(e.deltaY, 0)
    }
})
```

* `mousewheel`イベントを監視。`scroll`だと、そもそもスクロールできない個所ではイベントが発火しない。
* `e.deltaX`及び`e.deltaY`で移動方向と量を取得。
* 横スクロール可能なマウスでの横スクロールを阻止しないため、`preventDefault`するのはX方向への移動が発生していない場合のみ。
* `window.scrollBy`でスクロール実行。ここでは`deltaY`をそのまま使っているが、適度な係数をかけてもいいかもしれない。
* IntelliJは親切にも「Y軸の値をX軸に設定していますよ」という警告を出してくれる。凄い。でも今回はこれで正しいので、`// noinspection`で警告を消す。
Windows で PyTorch 0.4.0 の ImportError の対策

# 1. エラー

PyTorch を利用したいので、オフィシャルサイトの手順で PyTorch をインストールした。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/267887/a7cf15dc-43c9-1fe4-58b3-66c70431bf4a.png)

開発環境の Python のバージョンは 3.6.6 で、CUDA のバージョンは 9.0 です。だから pip で説明通り PyTorch 0.4.0 をインストールした。

しかし、import すると、エラーが出た。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/267887/9557ff7a-ce93-3820-d087-94f0ffc45146.png)

```
Python 3.6.6 (v3.6.6:4cf1f54eb7, Jun 27 2018, 03:37:03) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python36\lib\site-packages\torch\__init__.py", line 78, in <module>
    from torch._C import *
ImportError: DLL load failed: The specified module could not be found.
```

DLL load failed の原因はたぶん DLL の依存関係だから、すぐ Google で検索し始まった。

# 2. ソリューション

「[Windows下通过pip安装PyTorch 0.4.0 import 不成功](https://blog.csdn.net/grllery/article/details/80308122)」を参考にして、問題を解決しました。

# 2.1. ダウンロード
[ここ](https://anaconda.org/anaconda/intel-openmp/files)をアクセスして、 `win-64/intel-openmp-2018.0.3-0.tar.bz2` をダウンロードしてください。

「[Windows下通过pip安装PyTorch 0.4.0 import 不成功](https://blog.csdn.net/grllery/article/details/80308122)」では古いバージョンの `win-64/intel-openmp-2018.0.0-8.tar.bz2` をダウンロードしたのですが、どちらも問題を解決できるみたいです。

# 2.2. 解凍

![image.png](https://qiita-image-store.s3.amazonaws.com/0/267887/c1d531a6-4e9a-ca72-4a62-2499ba7d259f.png)

`win-64/intel-openmp-2018.0.3-0.tar.bz2` から、`Library/bin/` を解凍してください。

# 2.3. パスの設定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/267887/9a3ecdfa-e351-ceb8-a07a-f7e72dfe5876.png)

さっきの解凍先をシステムのパス設定に追加してください。

# 2.4. 再起動

再起動してから、もう一度 PyTorch を import すると：

![image.png](https://qiita-image-store.s3.amazonaws.com/0/267887/4c39d4e3-e060-6542-bdba-ecde10c36c1d.png)

異常なしです。
Swift4.2でBool値の反転をtoggleで行う

##はじめに
Swift4.2からBool値の変更用のメソッドとして`toggle()`が登場しました。
個人用も兼ねてのメモです。

##検証環境
以下の環境を使用しています。

* macOS Version 10.13.4
* Xcode Version 10.0.0 β3

##toggleについて
例えばある項目のチェックのON、OFFを切り替える際に、従来であれば以下のようなコードになっていました。基本的には問題ありませんが、代入時の!をつけ忘れてしまい不具合を発生させる要因になりかねません。

```Swift
var isChecked = false
@IBAction func didTouchUpInsideCheckButton(sender: UIButton) {
    isChecked = !isChecked
}

```

Swift4.2以降では以下のように書くことができるようになります。
!のつけ忘れ等の心配もありません。

```Swift
var isChecked = false
@IBAction func didTouchUpInsideCheckButton(sender: UIButton) {
    isChecked.toggle()
}
```

##Swiftでの実装
Swiftのリポジトリを確認すると、実際の実装は下記のようになっています。

```Swift
public struct Bool {
  // 省略
}

extension Bool {
  @inlinable
  public mutating func toggle() {
      self = !self
  }
}
```
mutatingが付与されているため、自身の値の変更が可能になっています。
当然ですが、以下のようにletで定義したBool値に対して使用するとおこられます。

```Swift
let isHidden = false
isHidden.toggle() 
// Cannot use mutating member on immutable value: 'isHidden' is a 'let' constant

```


##参考
Proposalおよび該当メソッドの箇所を以下のリンクにまとめました。
適宜ご参照ください。

* [/stdlib/public/core/Bool.swif](https://github.com/apple/swift/blob/master/stdlib/public/core/Bool.swift#L344)
* [SE0193-cross-module-inlining-and-specialization](https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md) 
* [SE0199-bool-toggle](https://github.com/apple/swift-evolution/blob/master/proposals/0199-bool-toggle.md)
wordpressよく使う定型文をテンプレートとして登録する

#プラグイン TinyMCE Templateを使用
レフトナビにテンプレートの項目が追加される
新規追加を押して、いつものビジュアルエディターが表示される。
定型文に登録したい箇所を埋め込んで公開。

あとは普通に投稿画面にいって、

テンプレートを挿入ボタンをクリック
![新規投稿を追加 ‹ 【開発】映画『40万分の1』公式サイト — WordPress (1).png](https://qiita-image-store.s3.amazonaws.com/0/187963/c49f7845-1319-b4a5-098b-7fc8957643e0.png)


作ったボックスを選択
テンプレートを挿入

![新規投稿を追加 ‹ 【開発】映画『40万分の1』公式サイト — WordPress (2).png](https://qiita-image-store.s3.amazonaws.com/0/187963/c94ec0ba-fc3f-d939-ffa8-2d3dcf63b625.png)


入力画面に登録した内容が表示される

![新規投稿を追加 ‹ 【開発】映画『40万分の1』公式サイト — WordPress (3).png](https://qiita-image-store.s3.amazonaws.com/0/187963/ebc42f66-2094-525b-56ec-af9f0ee6db49.png)
Javaでnullとの比較をする場合に使える構文と例外の発生条件

# equalsメソッドにnull値が入った場合の挙動
※以下a,bは変数とする

## a.equals(b)
aがnullの場合、例外(NullPointException)が発生する。
bがnullの場合、例外は発生せず、falseが戻り値として返る。

## Object.equals(a,b)
a,bのいずれかがnullの場合例外は発生せず、falseが戻り値として返る。
a,bのいずれもnullの場合はteueが戻り値として返る。


## ポイント
nullとの比較をしたい場合は等価演算子(==)を用いる。

### 空文字("")を比較した場合の挙動
• equals(b)
• Object.equals(a,b)
a,bのいずれが空文字でも比較でき、例外は発生しない。

### equalsメソッドのオーバーロード
同じ型のインスタンスオブジェクトを、フィールドの特定の値で比較できる。

##参考サイト
[Java equalsメソッドで比較する値がnullまたは空文字だった場合のサンプル](https://itsakura.com/equals_null)
[Angular] JavaScriptのモジュール - @NgModuleとは何か (1)

`@NgModule`がなんなのかを知るにあたり、いくつか前提知識が必要となります。
最初はJavaScriptのモジュールです。

[ES6 In Depth:Modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/) の勝手訳です。

# 前段

Googleマップが現れる前は、「典型的なJavaScriptプログラムは1行のみ」というジョークがはやっておった。
`<input onChange=`
というやつじゃ。大抵はそれで事足りた。

現代のJavaScriptプログラムはいくつものファイルやディレクトリにまたがる巨大なものになった。
そんなとき、必要とされるのはモジュールシステムじゃろう。
実際、JavaScriptにはモジュールシステムがある。いくつもな。。。
ここで現れたES6のモジュール文法は、パーティに遅刻してきた輩じゃと感じるかもしれん。


# モジュールの基礎

ES6のモジュールは、JavaScriptプログラムを含んだファイルです。そこには`module`という単語はありません。普通にJavaScriptプログラムとして読めます。普通と違うところは、以下の2つです。

* 自動的にstrictモードになります。
* `export`と`import`が使えます。

## `export`と`import`

既定では、モジュール内で宣言されたすべてのものは、モジュールの中からだけ見えます。モジュールの外に公開したいときはエクスポート(export)します。エクスポートのやり方はいくつかあります。一番簡単なのは`export`キーワードを付けることです。

```js:helloworld.js
export function helloWorld() {
  // 何か楽しいこと
}

export class TheWorld {
  // もっと楽しいこと
}

// この関数はエクスポートされません。
function workHard() {
}
```

トップレベルの`function`、`class`、`var`、`let`、`const`に`export`を付けることができます。

モジュールを書く上で知っていなくちゃいけないことは2つです。全体を即時関数に入れないこととコールバックにしないことです。

エクスポートしたものを他のファイルから使いたいときはインポート(import)します。

```js:demo.js
import { helloWorld } from 'helloworld.js'
```

一度に複数個インポートすることもできます。

```js:demo.js
import { helloWorld, TheWorld } from 'helloworld.js'
```

`import`文は一番最初に実行されます。深さ優先で実行していきます。

# エクスポートリスト

エクスポートする別の書き方もあります。

```js:helloworld.js
export { helloWorld, TheWorld }

function helloWorld() {}
class TheWorld {}
```

エクスポートリストは先頭にある必要はありません。ファイルのどこに書いてもよいです。


# 別名をつける

インポートすると名前が衝突するとき、別名をつけることができます。

```js:demo.js
import { Solaris as SolarisOS } from 'sun.js'
import { Solaris as SolarisMovie } from 'hollywood.js'
```

エクスポートするほうで別名をつけることもできます。

```js:ishihara.js
class Kuniko {}

export { Kuniko as Satomi }
```

# Defaultエクスポート

ES6モジュールはCommonJSやAMDとの相互運用性も考えられています。

人気のlodashを使うとき、ES6では各関数をインポートします。

```js:lodashdemo.js
import { each, map } from 'lodash'

each([3, 2, 1], x => console.log(x));
```

けど、`each`と書かずに`_.each`と書くシーンもあるかもしれません。
あるいは`_`を関数として扱いたいとか。
そんなときは中括弧をつけずにこう書きます。

```js:
import _ from 'lodash'
```
これは、`import { default as _ } from 'lodash'`を省略した書き方です。

CommonJSやAMDのモジュールは、`default`としてエクスポートされます。

# モジュールオブジェクト

長くなりました。もう少し語ってないことがあります。`import *` です。

```js:
import * as cows from 'cows'
```

ここで`cows`が`moo`をエクスポートしていれば、`cows.moo`として参照するようにします。


# モジュールを集約

複数ファイルから構成されるモジュールを、一箇所でエクスポートしたいことがあるかもしれません。

```js:
// yokohamaをインポートして、Shumaiを再エクスポートします。
export { Shumai } from 'yokohama'
// fukushimaをインポートして、MomoとSakuranboを再エクスポートします。
export { Momo, Sakuranbo } from 'fukushima'
// hokkaidoをインポートして、すべてを再エクスポートします。
export * from 'hokkaido'
```

# 実際のところインポートって何してるのさ

何もしてない、、、かもしれません。

大雑把に言うとこんな感じです。

1. パース - ソースを呼んで文法チェックします。
2. ロード - モジュールを再帰的に読み込みます。このあたりはまだ標準化されてないとか。
3. リンク - 読み込んだ各モジュールを適切なスコープに配置したりなんだりします。もしここでエクスポートされていないのにインポートしているものがあれば、エラーになります。
4. 実行 - 読み込み終わったモジュールを実行します。もしここで`import`文があっても何も起きません。
PuTTYgenを使ってGitHubのSSHを設定

# はじめに

GitHubにSSH Keyを設定し、SSHでリポジトリを扱う手順を説明します。

## 環境

* 環境:Windows10
* ツール:TortoiseGit, PuTTYgen

# 作業の流れ

大まかに、以下の流れで進みます。

1. PuTTYgenで公開鍵を生成
2. GitHubに公開鍵を設定

# PuTTYgenで公開鍵を生成

## 鍵の生成

PuTTYgenを起動し鍵を生成します。「Generate」を押し、マウスをぐりぐりすると出来ます。
[ここ](https://qiita.com/amama-nagigi/items/d71a88cd4fcd55508177#%E7%A7%98%E5%AF%86%E9%8D%B5%E5%85%AC%E9%96%8B%E9%8D%B5%E3%81%AE%E4%BD%9C%E6%88%90)でやってることと全く一緒ですね。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/174324/7a25c157-08e1-04b0-bc3d-de32d83847b9.png)

## GitHubに公開鍵を設定

GitHubの公開鍵には、PuTTYgenからテキストをコピペして設定します。
以下の赤枠の部分を全選択してコピーし、テキストエディタとかに貼っておきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/174324/79dbff37-9ac2-dc23-6470-cbff63bed7a5.png)

GitHubにログインし、右上のメニューから「Settings」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/174324/4d85584b-5783-e399-a658-d32848fe81fb.png)

左のメニューから「SSH and GPG keys」を選択。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/174324/0393a0d6-3aa9-1902-390e-9fae14eff370.png)

右上の「New SSH Key」をクリック。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/174324/60ca4ea5-fae2-777e-ab31-50e3a34d0aae.png)

Titleを適当に入力し、Keyには先ほどコピーした内容をペーストします。
で、「Add SSH key」をクリック。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/174324/d632c578-6268-b105-503e-d8164c8f28cf.png)

公開鍵が登録できました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/174324/4d49eebf-db19-2888-1a1b-9b7948475e19.png)

## TortoiseGitでクローン

GitHubのリポジトリのTOPを開き、SSHのURLをコピーします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/174324/c2a22b8c-dae5-3568-21ff-0e0b598a9721.png)

リポジトリをクローンしたいフォルダで右クリックし「Git Clone...」を実施。
クローン時に先ほどの秘密鍵を指定すれば、Pageantが起動し秘密鍵を読み込んでClone出来ます。

# おわりに

正直、何が出来るようになったのかよくわかってません。。。
コマンド履歴から曖昧検索で絞り込んで選択したコマンドを実行できるようにした

## デモ
[![Image from Gyazo](https://i.gyazo.com/e532a6056f90349e561aa576ae6e5ded.gif)](https://gyazo.com/e532a6056f90349e561aa576ae6e5ded)

## 事前準備
### 1. あいまい検索のコマンドfzfを使うのでインストールしてください。

```
$ brew install fzf
```

### 2. これを.bash_profileなどにコピペしてください
自分はfzhってコマンド名つけていますが、 好きな名前を付けてください！

```
alias fzh='history | awk '\''{$1=""; print $0}'\'' | `fzf`'
```

以上です！
RubyでCloudSearchにデータを挿入


AWS Cloudsearch CLIが公式ドキュメントから辿れず、今お騒がせのJavaの環境を作る気にもならなかったので、AWS SDK for Rubyを使ってCloudSearchにドキュメントをアップロードしたいと思います。


環境
---

* ruby(2.3.5)
* aws sdk(2.3.11)


ソースコード
---

```rb
AWS_CONFIG = {
    region: ENV['AWS_REGION'],
    access_key_id: ENV['AWS_ACCESS_KEY'],
    secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
}

csd = Aws::CloudSearchDomain::Client.new(AWS_CONFIG.merge(endpoint: ENV['CS_ENDPOINT']))

upload_documents = [
	  {
        type: 'add',
        id: "一意なID",
        fields: {hoge: 1, fuga: 2}
      },
	  {
        type: 'add',
        id: "一意なID",
        fields: {hoge: 1, fuga: 2}
      }
]

resp = csd.upload_documents(
   documents: upload_documents.to_json,
   content_type: 'application/json'
}
```

用意するデータのフォーマットは以下
https://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/preparing-data.html


気をつけること
---

* 値がnullとなるjsonを送るとエラーが発生した

こういうやつ

```rb
{
	"hoge": null
}
```

* 空配列を送らない
* CloudSearchのアップロード制限

`ドキュメントバッチは 10 秒ごとに 1 つ、バッチあたり 5 MB に制限されます。` 

と[ここ](https://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/uploading-data.html)にかかれています。

できるだけ１回のバッチで多く送りましょう。

* AWS CloudSearch CLIを使ってDynamoDBからCloudSearchに送っていたときは、index field名を気にしていなかった

DynamoDBでfield名はキャメルケースにしていたが、CloudSearchのfield名は小文字で運用していて、AWS CloudSearch CLIを使っていたときはうまく吸収していたっぽい？

Rubyから送るときはちゃんと、field名の大文字・小文字を書かないといけない。

（これは自分だけかも）
【備忘録】Anaconda3をMacOSXから完全に削除してみた

2020-01-04 追記

ちょこちょこ同じ悩みを持っているらしい方に訪問されているので、
細かいですが注意書き。
**この記事はMacOS Catalinaにする前の話です** 
[Catalinaになったときにこう言う事例が発生するのですが、そのあとの追い確認はしていない](https://qiita.com/akinko/items/1909c8d0145d9ba530b9)

それでも良ければ以下の内容をご覧ください。

----[以下原文]--

きっかけは[こちらで紹介されている](https://qiita.com/y__sama/items/f732bb7bec2bff355b69)様に、
**pyenvとcondaがsource activateで干渉してしまう**問題が発生したためです。

Anaconda-Navigator上でも同じ問題が出ており、
上記のリンクの通りにやっても解決しなかったため、
[Condaのchange-log](https://github.com/conda/conda/blob/a4c4feae404b2b378e106bd25f62cc8be15c768f/CHANGELOG.md#440-2017-12-20)で conda activate 導入されている事だし、
一回全部ガラガラポンにしてあげようと思い、
MacOSXの環境設定周りを久しぶりに漁ることになりました。


# 参考サイト
[綺麗にAnacondaをアンイストールする方法 For macOS](https://ai-coordinator.jp/anaconda-uninstall-for-maxos)

[MacのFinderでWindowsみたいにファイルパス指定でディレクトリやファイルにアクセスしたい](https://qiita.com/luccafort/items/7eefe4dcf50cca9d8c02)

[pyenvとanacondaを共存させる時のactivate衝突問題の回避策3種類](https://qiita.com/y__sama/items/f732bb7bec2bff355b69#comment-d00562f16f60826919ce)

# pyenvとcondaの干渉問題
詳細は[pyenvとanacondaを共存させる時のactivate衝突問題の回避策3種類](https://qiita.com/y__sama/items/f732bb7bec2bff355b69#comment-d00562f16f60826919ce)に書いてあるのでざっくり話すと、

「pyenvとcondaのコマンドが被ってて、システムがどっちを選んで実行すればいいのかわからなくなってる」

って事で自分は理解してます。

分析屋さんだと R の dplyr:: とかで回避するべき問題と言えば伝わると思います。

# 解決策
[pyenvとanacondaを共存させる時のactivate衝突問題の回避策3種類](https://qiita.com/y__sama/items/f732bb7bec2bff355b69#comment-d00562f16f60826919ce)
にあるんで読んでください。

自分は何故か解決しなかったので、結局完全削除することになりました。

# 削除手順
[綺麗にAnacondaをアンイストールする方法 For macOS](https://ai-coordinator.jp/anaconda-uninstall-for-maxos)
の内容を箇条書きしますと、

1. "anaconda-clean"と言うツールがダウンロードできるのでそれを落として起動する
2. (pythonを起動するとまだAnacondaが呼び出されるので) Homeフォルダ直下のAnacondaフォルダを完全削除する
3. bash_profile / basic にあるAnaconda関係のPATHを全削除

以上。ただし自分はこの削除手順でできませんでした。

この後ダラダラと書くんですが、
Anacondaがpyenv経由でインストールされていない場合みたいで、

[MacのFinderでWindowsみたいにファイルパス指定でディレクトリやファイルにアクセスしたい](https://qiita.com/luccafort/items/7eefe4dcf50cca9d8c02)

を参考に(Terminal上でのopenコマンドと併用して)Finderを覗いて行ったら、
pyenv経由でAnacondaが落とされていることが分かり、一手間かかりました。

# pyenv経由でAnacondaを入れた時にかかる手間
1. Home直下にAnacondaの物理フォルダがないので別の場所を漁る
2. bash_profile / bashrc のPATHを削除する以外に python-versionファイルも書き換える

この２つです。

１つ目は、
"command+shift+g"で漁ったところ
Home直下の .pyenv/versions に入ってたのでさっさとゴミ箱に突っ込む

２つ目は、
Home直下の .python-version フォルダにAnacondaを呼び出すコマンドが残っていたので削除

上記をやったところ、完全に削除できました。
めでたしめでたし。
~~**これからAnaconda再インストールだぜ**~~

### 余談:
便利だなと思ったコマンド

"command+shift+g"

基本Windows野郎の自分はフォルダパスをて入力することに慣れてたんで、Finderにもこの機能があるのは非常にありがたかった~~さっさとcd/ls/open使いこなせ~~。

以上です。Anaconda再インストール時に死んだら死なない方法追記するかも。
WSLのディストリビューションの切り替えに関するメモ

# 概要
WSLも良い感じに発展してきて、近頃はMicrosoft Storeに様々なディストリビューションが公開されている｡

![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/8558c9b3-443b-8e5c-3cea-dee96a74830f.png)

でも `wsl.exe` コマンドは1つなだけなわけで…
『一体どうやってディストリビューションを切り替えれば良いんだ！？』って思ったので、調べてみた。
そんなメモ。


# `wslconfig.exe` を使いましょうって話
ググればすぐに出てきた。メモる程でもなかったかも。

`wslconfig.exe /list` でインストールされているディストリビューションがリストで出てきた。最高。
ちなみにLegacyってのはWSLを有効にして `lxrun /install` で入る子みたい。
「Storeのやつとおんなじでしょ？」とか思っていたけど、ちょっと挙動が違うかも。

```
> wslconfig.exe /list
Windows Subsystem for Linux ディストリビューション:
Legacy (既定)
Ubuntu
```


`wslconfig.exe /setdefault ディストリビューション名` で変更も良い感じに。

```
> wslconfig.exe /setdefault Ubuntu
```

```
> wslconfig.exe /list
Windows Subsystem for Linux ディストリビューション:
Ubuntu (既定)
Legacy
```

なるほどね。


# 参考文献
他にも色々とまとまっているので良さげ。
https://laboradian.com/installation-and-setting-of-wsl/
Ubuntu16.04.4をインストールしてnvidiaのドライバーを入れる

# ubuntu再インストール失敗と成功の経緯
## 1
TensorFlowの環境構築でcudaなど入れて手間取っている間に，画面がつかなくなった。（ブラックアウト）
一応ライブUSBからは開ける。画面がつく。そこでgrub customizerでgrubのnosetmodeなどいじる（本当にいじれてはいないぽいけど）。
しかし結果は変わらず画面がつかない。

## 2
先ほどのライブUSBは日本語remixのものを入れた。バージョンは16.04無印。（16.04.0?)
https://www.ubuntulinux.jp/News/ubuntu1604-ja-remix
これをUniversal USB InstallerでライブUSBを作成した。
再インストールを行った。
起動すると「ポポン」という起動音はするものの，画面はつかない。

## 3
https://www.glamenv-septzen.net/view/1411
を参考にしてもう一度ライブUSBを作成し直す。
次は日本語リミックスではなく，英語版のものを入れる。バージョンが16.04.4なので多少新しいだろう。
http://releases.ubuntu.com/16.04/
これをインストールすると画面はついた。ちゃんとデュアルディスプレイで4k解像度表示も正しい。

# nvidiaドライバー関係
## 1
次はnvidiaのドライバー関係。
TensorFlowを動くようにしたいので，TensorFlowの公式サイトのいう通りのものを入れていくことにする。

## GRUB_CMDLINE_LINUX_DEFAULT="nomodeset"に変更
デフォルトはquiet splash
これだと問題起こるという記述が多いので，変える

```
sudo add-apt-repository ppa:danielrichter2007/grub-customizer
sudo apt-get update && sudo apt-get install grub-customizer
```
変更したら一応

```
sudo update-grub
```
そこで再起動してみた。
しかしまた画面がつかなくなった。

# インストール時にnomodesetに変更してやる
https://qiita.com/jh3rox/items/20f04527f8084dddd57f
より，

ブート選択画面でinstall ubuntuのラインで「e」を押して以下を変更、その後F10で起動
変更前: quiet splash
変更後: nomodeset

正しく変更できたかわからないけれども，インストールはできた。
起動して/etc/default/grubの文書確認したけどquiet splashだった。

# とりあえず放置してgpu, cuda, cudnn

https://qiita.com/Lirimy/items/a6f051fbfdac333828ed

のお世話になる。
特に

```
sudo apt-get install cuda-9-0
```
とバージョンをつけることが大事。
あとは何度かnvidia-390とcuda-9-0のinstall, purgeを繰り返していたらcudnnのテスト通った。
Windowsでlinuxが使える~!!　WSL(Windows Subsystem for Linux)をインストール

linuxのコマンドを少し(本当に少し)使えるようになってきたかなーぐらいのアラフォー新人:beginner:です。
職場の方に、某コマンド的なことをやりたいんですがlinuxでしかできないってネットに書いてて…なんて
相談をした際に、そういえばWindowsでlinuxが使えるWSLというのがあるよと聞いて早速やってみました。

linux系のOS立ち上げる時はVirtualBoxとかVMwareとかの仮想環境でやっていたのですが
そーゆーの介さずにできるんですって。えー！そんなことできるの:astonished:!! 凄いですね

**WSL は Windows Subsystem for Linux　の略**
ふーん。Linux用Windowsサブシステムかぁ…　まず、やってみます。

---

Windowsのマークを右クリックでアプリと機能を選択
![1.png](https://qiita-image-store.s3.amazonaws.com/0/237418/24d02237-ffdc-d0ca-408c-4941907b8cc7.png)

関連設定のプログラムと機能をクリック
![2.png](https://qiita-image-store.s3.amazonaws.com/0/237418/14e72ed4-ff63-7e0b-e0b0-71f95a03dc25.png)

Windowsの機能の有効化または無効化をクリック
![3.png](https://qiita-image-store.s3.amazonaws.com/0/237418/23364c3b-4578-bb2a-9c49-7a762ce5c2f8.png)

Windows Subsystem for LinuxのチェックをオンにしてOKを押す。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/237418/c8925d00-a322-ef62-1460-3baf73980f53.png)

必要な変更が完了しましたが表示されたら今すぐ再起動をクリックしてPCを再起動します。
![5.png](https://qiita-image-store.s3.amazonaws.com/0/237418/e2a57556-ef5c-1bf0-fc36-803352c381fc.png)

PCが起動したら、アプリの中のMicrosoft Storeを選択、
もし見つからないときは検索窓にストアと入力したら出てきます。
![6.png](https://qiita-image-store.s3.amazonaws.com/0/237418/d0999d00-18e2-97e8-9b93-a3df3f76d18b.png)

Microsoft Storeの検索窓にlinuxと入力すると
WindowsでLinuxを実行するアプリを入手する　が出てくるのでそれを選択
![7.png](https://qiita-image-store.s3.amazonaws.com/0/237418/9a92dfd1-675c-d9bc-97e8-25f6783141a9.png)

ズラッとカラフルなの表示されていますが、どのOSを選んでも大丈夫です。
私は仮想環境で使ったことがあるUbuntuにしました。
![8.png](https://qiita-image-store.s3.amazonaws.com/0/237418/ad1bccc4-8edd-8b78-64ba-68c590e3a71d.png)

入手を押してインストールします。
![9.png](https://qiita-image-store.s3.amazonaws.com/0/237418/a787c78f-3bfe-9a42-09d3-0ef4e545e564.png)

インストール終わりました。起動を押します。
![11.png](https://qiita-image-store.s3.amazonaws.com/0/237418/97772c0d-1509-fc16-1a78-a769f530f27b.png)

すると、Ubuntuのターミナルが立ち上がってきます。ユーザー名を登録します。
![12.png](https://qiita-image-store.s3.amazonaws.com/0/237418/15bcbe5e-58ea-68e2-4342-dbd2ef5fc8b1.png)

続いてパスワードを登録します。Retypeと書いてあるのでもう一回同じのを入力します。
おー！認識されたみたいです。user名が反映されて入力待ちの画面になりました。
![13.png](https://qiita-image-store.s3.amazonaws.com/0/237418/d212fea6-ea33-78a4-1eed-dfd23ee3f2b2.png)

素敵なことにrootの下のmntの中にPC以下の内容がごっそりマウントされてるという話なのです。
このｃとｄはワタシのWindowsのCドライブとDドライブ～!!!!
![7867.png](https://qiita-image-store.s3.amazonaws.com/0/237418/44928e49-0c0d-8926-f686-f9db537abe8e.png)

本当かな～？念のため見てみます。
わー!!!ちゃんとワタシのtedkumaディレクトリの中まで見れてますー！素敵ですね :shamrock:
![90.png](https://qiita-image-store.s3.amazonaws.com/0/237418/e889d344-77c7-d87d-6228-f49eb0acdbbf.png)

気軽にlinuxで色々やってみようーってきっかけになりましたー:smile:
GoogleCroudPlatformのCentOS7にSass入れた時にハマったポイント

# 前提
Linux系は基本的なコマンド知ってる程度の素人です。

# 環境
GCPの無料枠で構築したCentOS環境

```
CentOS Linux release 7.5.1804 (Core) 
```
[環境作ったときの記事](https://qiita.com/KnockoutGT/items/5a74b8561a63f7f0e7de)

# 目指したゴール
SassとCompassのインストール

## 先に結論

Sassをyumるところでエラーが発生したが、先にffiをyumることでエラーを回避できた。
gccが古かったので新しいの入れたが、それもエラー原因だったかは不明。

## 手順

### 事前確認

```
yum list installed|grep ruby
yum list installed|grep gcc
```
いずれもインストールされておらず。

### Rubyのインストールとgemの最新化
```
sudo yum install ruby
sudo yum -y install ruby-devel
sudo yum install rubygems
sudo gem update --system
```

いずれもエラーなし。

### gccのインストール
```
sudo yum install gcc
```
エラーなし。

### Sassのインストール

```
sudo gem install sass
```
ここでエラー発生。

```
# Building native extensions.  This could take a while...
# ERROR:  Error installing sass:
#         ERROR: Failed to build gem native extension.
# 
#     /usr/bin/ruby extconf.rb
# 
# Gem files will remain installed in /usr/local/share/gems/gems/ffi-1.9.25 for inspection.
# Results logged to /usr/local/share/gems/gems/ffi-1.9.25/ext/ffi_c/gem_make.out
```

いろいろ調べてみると、どうもCentOSのgccが古いらしい。

```
# gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)
# Copyright (C) 2015 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions.  There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```
### 新しいgccのインストール
```
sudo yum install centos-release-scl
sudo yum install scl-utils
sudo yum install devtoolset-4-gcc devtoolset-4-gcc-c++ devtoolset-4-binutils
```
いずれもエラーなし。

### 新しいgccの有効化
```
scl enable devtoolset-4 bash
```
```
# gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6)
# Copyright (C) 2015 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions.  There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```

### 再度Sassのインストール
```
# Building native extensions.  This could take a while...
# ERROR:  Error installing sass:
#         ERROR: Failed to build gem native extension.
# 
#     /usr/bin/ruby extconf.rb
# 
# Gem files will remain installed in /usr/local/share/gems/gems/ffi-1.9.25 for inspection.
# Results logged to /usr/local/share/gems/gems/ffi-1.9.25/ext/ffi_c/gem_make.out
```
既視感のあるエラー。

```
# Gem files will remain installed in /usr/local/share/gems/gems/ffi-1.9.25 for inspection.
```
という辺りから、ffi入れてるところでエラー起きてるっぽい気がする。

### ffiのインストール
```
sudo gem install ffi
```
エラーなし。

### 再度Sassのインストール
```
sudo gem install sass
```
エラーなし。

### compassのインストール
```
sudo gem install compass 
```
エラーなし。

### 確認
```
sass -v
```
```
# Ruby Sass 3.5.6
```
```
compass -v
```
```
# Compass 1.0.3 (Polaris)
# Copyright (c) 2008-2018 Chris Eppstein
# Released under the MIT License.
```

# 参考
[Linux環境でSassを利用する](https://rfs.jp/sb/css/sass/sass05_linux_sass.html)
[CentOS6のgccをアップデートする](http://thr3a.hatenablog.com/entry/20180308/1520506543)
Go言語のベンチマーク


```go
package cat

import (
	"bytes"
)

// catは += 演算子をつかって文字列を結合します
func cat(ss ...string) string {
	var r string
	for _, s := range ss {
		r += s
	}
	return r
}

// bufは bytes.Buffer をつかって文字列を結合します
func buf(ss ...string) string {
	var b bytes.Buffer
	for _, s := range ss {
		// NOTICE: エラーは無視しています
		b.WriteString(s)
	}
	return b.String()
}
```

```
package cat

import (
	"testing"
)

func seed(n int) []string {
	s := make([]string, 0, n)
	for i := 0; i < n; i++ {
		s = append(s, "a")
	}
	return s
}

func bench(b *testing.B, n int, f func(...string) string) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		f(seed(n)...)
	}
}

func BenchmarkCat3(b *testing.B)     { bench(b, 3, cat) }
func BenchmarkBuf3(b *testing.B)     { bench(b, 3, buf) }
func BenchmarkCat100(b *testing.B)   { bench(b, 100, cat) }
func BenchmarkBuf100(b *testing.B)   { bench(b, 100, buf) }
func BenchmarkCat10000(b *testing.B) { bench(b, 10000, cat) }
func BenchmarkBuf10000(b *testing.B) { bench(b, 10000, buf) }
```

```bash
go test -bench .
```

```shell-session
goos: darwin
goarch: amd64
BenchmarkCat3-4       	10000000	       207 ns/op	      54 B/op	       3 allocs/op
BenchmarkBuf3-4       	10000000	       227 ns/op	     163 B/op	       3 allocs/op
BenchmarkCat100-4     	  200000	      8057 ns/op	    7520 B/op	     100 allocs/op
BenchmarkBuf100-4     	  500000	      2694 ns/op	    2160 B/op	       4 allocs/op
BenchmarkCat10000-4   	     100	  14908131 ns/op	53327792 B/op	   10000 allocs/op
BenchmarkBuf10000-4   	   10000	    216301 ns/op	  211424 B/op	      11 allocs/op
```

+ ループが実行された回数
+ 1ループごとの所要時間、1ループごとのメモリ
+ アロケーションされたバイト数、1ループごとの
+ アロケーション回数が表示されています。

この結果からわかること

+ +=による文字列結合は、結合する要素数が少ないときはbytes.Bufferと遜色ないパフォーマンスである。しかし、要素数が増えると処理が遅くなり、アロケーションも増える
+ bytes.Bufferによる文字列結合は、+= を使った文字列結合と比べると要素数が増えても性能が出ている。アロケーションも少ない
httpd.conf / php.ini の設定　備忘録

#環境
CentOS7

#httpd.confの設定

アクセスした際、ブラウザ上にディレクトリのファイル一覧を表示させない

```
vim /etc/httpd/conf/httpd.conf
```

```httpd.conf
#Options Indexes FollowSymLinks
Options FollowSymLinks
```

Apacheのデフォルト言語がUTF-8に設定されている為、metaタグが無視されてHTMLやアプリケーションが文字化けしてしまうことを防ぐ

```httpd.conf
#AddDefaultCharset UTF-8
```

Apatchのテストページを表示させない

```
vim /etc/httpd/conf.d/welcome.conf
```

```welcome.conf
#<LocationMatch "^/+$">
#    Options -Indexes
#    ErrorDocument 403 /.noindex.html
#</LocationMatch>
```

設定を反映

```
service httpd restart
```


#php.iniの設定

```
vim /etc/php.ini
```

エラーログの出力先設定

```php.ini
;error_log = php_errors.log
error_log = /var/log/php_errors.log
```

デフォルトで使用する言語を日本語に設定

```php.ini
;mbstring.language = Japanese
mbstring.language = Japanese
```

文字コードをUTF-8に設定

```php.ini
;mbstring.internal_encoding = EUC-JP
mbstring.internal_encoding = UTF-8
```

HTTPヘッダのPHPのバージョンを非表示

```php.ini
;expose_php = On
expose_php = off
```

タイムゾーンの設定

```php.ini
;date.timezone =
date.timezone = Asia/Tokyo
```

設定を反映

```
service httpd restart
```
リプライされた単語でwikipediaの概要をリプライし返すbotを作ってみた


#はじめに
使用言語 python3
使用API  twitterAPI,MediaWiki API
OS windows10
筆者はpython初心者
#プログラムの大体の動き
twitterAPIにアクセス→リプライされたときにif文でwikiが入ってるか確認→`data=wikiapi.getinfo(text)`でWikiapi.pyのgetinfoに行く→mediawikiapiにアクセス→jsonを使って概要を取得→ツイート
まとめると、リプライにwikiという単語が入っていたら、その後ろの単語をmediawikiapiで検索してリプライし返すbot
#ソースコード
```python
#tweet.py

import tweepy
import Wikiapi
import datetime
 
CK="" #Consumer Key
CS="" #Consumer Secret
AT="" #Access Token
AS="" #Access Token Secret
 
# Twitterオブジェクトの生成
auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, AS)
 
api = tweepy.API(auth)
 
class Listener(tweepy.StreamListener):
	def on_status(self, status):
		status.created_at += datetime.timedelta(hours=9)

		if (status.in_reply_to_screen_name) == api.me().screen_name:

			status_id = status.id
			text = status.text.replace("@" + str(api.me().screen_name), "")
			text = text.replace("　", "")
			if "wiki" in text:#リプライにwikiが入ってるか確認
				text=text.replace("wiki","")
				wikiapi=Wikiapi.Wikiapi()
				data=wikiapi.getinfo(text)#Wikiapi.pyのgetinfo呼び出し
				tweet_rep = "@" + str(status.user.screen_name) + " " + str(data.tweet)+"\n"+str(data.url)
				api.update_status(status=tweet_rep,in_reply_to_status_id=status_id)
			
		return True
	
	def on_error(self, status_code):
		print('Got an error with status code: ' + str(status_code))
		return True
	
	def on_timeout(self):
		print('Timeout...')
		return True
 
# Twitterオブジェクトの生成
auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, AS)
 
listener = Listener()
stream = tweepy.Stream(auth, listener)
stream.userstream()
```
```python
#Wikiapi.py

import requests
import json
import urllib
class Wikiapi:
	def getinfo(self,word):
		word=urllib.parse.quote(word)
		api="https://ja.wikipedia.org/w/api.php?action=query&format=json&titles={word}&prop=extracts&redirects=1&exchars=100&explaintext=1"
		api=api.format(word=word)
		r=requests.get(api)#APIにアクセス
		data=json.loads(r.text)
		pages=data["query"]["pages"]
		for page in pages:
			try:
				self.tweet=data["query"]["pages"][page]["extract"]#wikiの説明文を参照
				self.url="https://ja.wikipedia.org/wiki/"+word#urlもツイートに追加
				return self
			except KeyError:#記事なかった場合
				self.tweet="記事がありませんでした"
				return self
```
#解説
読みづらいのは許してください
ちょいちょいコメントで解説していますが要点を紹介
`if "wiki" in text:`リプライにwikiが入ってるか確認
`self.tweet=data["query"]["pages"][page]["extract"]#wikiの説明文を参照`mediawikiapiで取得したjsonから概要があるところにアクセス
#挙動
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/268938/fe7bf810-f221-75fd-6ea5-53d6a2310271.png)
#参考にした記事
忘れたので調べておきます
#まとめ
読みづらいですけど初心者なのでお許しください
まともなbotを作れてよかった
実用性はないと思う
ここわからない とかあったらコメントとかtwitterで言ってもらえれば120%返します
Unity Debug.Log 文字色

```
Debug.Log("<color=#00ff00>あいうえお</color>");
Debug.Log("<color=yellow>あいうえお</color>");
Debug.Log("<color=red>あいうえお</color>");

Debug.Log(String.Format("<color=#00ff00>{0}</color>", "あいうえお"));

Debug.Log(String.Format("<color=#00ff00>{0}</color>", ));
```
werckerを使ってgit pushでファイルをs3へアップロードする

# はじめに

- とあるデータファイルをs3へ自動でアップロードしたい要件がありました。
- githubでファイルを管理してwerckerと連携してgit pushすると自動でs3へファイルアップロードするようにしたので、その備忘録です。


# 手順

- Werckerに公開されている[step-s3sync](https://github.com/wercker/step-s3sync)を利用します。
- 利用方法はREADMEに記載されているとおりですが、以下のようになります。

```yaml

deploy:
    steps:
        - s3sync:
            key-id: $AWS_KEY
            key-secret: $AWS_SECRET
            bucket-url: $BUCKET_URL
            source-dir: $SOURCE_DIR
            opts: --acl-private
```

- wercker.ymlに上記の設定を追加してworkflowsを設定してあげれば`git push`で自動的にs3へファイルがアップロードされます
- アップロードする対象の**ファイルに日本語が含まれていると上記の設定だけだとうまく動作しません**
   - 以下のようにoptsに`--encoding=utf-8`を指定してあげることで動作します

```yaml

deploy:
    steps:
        - s3sync:
            key-id: $AWS_KEY
            key-secret: $AWS_SECRET
            bucket-url: $BUCKET_URL
            source-dir: $SOURCE_DIR
            opts: --acl-private --encoding=utf-8
```

# 参考

- [こちら](https://qiita.com/fantasista_21jp/items/0a269a3d8153a15bd66b)を参考にさせて頂きました
【Django】DjangoでMySQL+ssl通信に設定

# 経緯
DjangoのアプリケーションをSQLiteではなく、MySQLを使いたいと思い、その設定の仕方をまとめました。また、リモートのDBを使う必要があったので、ssl通信する必要があり、それもまとめました。

# セットアップ
Djangoを使うための設定はなされている前提でのセットアップになります。まず、下記をインストールしてください。

~~~
$ pip install PyMySQL
~~~

# settings.pyを修正
ここがメインになります。settings.pyの`DATABASES`を変更します。

~~~python:settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'dbname', # DBの名前
        'USER': 'username', # ユーザーの名前
        'PASSWORD': 'password', # dbのパスワード
        'HOST': 'hostname', # hostの名前
        'PORT': '', # port番号(デフォルトでは3306)
    }
}
~~~

これで一応MySQLにモデルが紐づく形になります。しかし、ssl通信で行うためにはさらに下記のような変更をする必要があります。

~~~python:settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'dbname', # DBの名前
        'USER': 'username', # ユーザーの名前
        'PASSWORD': 'password', # dbのパスワード
        'HOST': 'hostname', # hostの名前
        'PORT': '', # port番号(デフォルトでは3306)
        # それぞれのキーのパスを入れる
        'OPTIONS': {'ssl': {'ca' : 'ca_path',
                            'key' : 'key_path',
                            'cert' : 'cert_path'}}
    }
}
~~~
これでsettings.pyの変更は一応完了です。

## hostにドット(.)がある場合
hostの名前にドット(.)がある場合は上記でもエラーが出るようです。なので、下記のコードをMonkey patchする必要があります。

~~~python:settings.py
import ssl
ssl.match_hostname = lambda cert, hostname: True
~~~

# manage.pyを修正
最後にmanage.pyで、MySQLを使うことを明示します。以下のコードを追加してください。

~~~python:manage.py
import pymysql
pymysql.install_as_MySQLdb()
~~~

# 最後に
DjangoのモデルをMySQLに対応させる方法をまとめました。私の場合、MySQLにすることで、SQLiteで行なっていたモデルのコードをいくつか変更する必要がありました。それらの良い改善方法は分かり次第Qiitaにまとめたいと思います。

## 起きた問題と応急処置
- TextFieldでuniqueキーを使えない→uniqueキー解除 or CharFieldにする
- AutoFieldによってidに0を設定できない→idを自動設定のものではなく、手動で下記のように設定

~~~python
id = models.IntegerField(primary_key=True)
~~~
フォームリクエストバリデーションで複数のフィールドを１つにまとめてバリデーションする方法

# はじめに
２つのフィールドを１つにまとめてバリデーションしたかったけど、
スグにやり方が判らなくてソースを追ってしまったので残しておきます。

# 前提
* 年月日と時分秒を別々に指定しないとイケないFormをお持ちの画面。
* 期間指定したいので、From - Toでフィールド持ってる

こういうヤツ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/56851/020fff2c-62a2-778d-a831-e398ec15938e.png)

postされてくるデータは一応以下みたいな感じで説明

|入力欄|key|値|
|---|---|---|
|開始日|start_date|年月日|
|開始時刻|start_time|時分秒|
|終了日|end_date|年月日|
|終了時刻|end_time|時分秒|

# 愚直にやるとどうなるか

コード書くの怠いので、文字で流れを書いてしまうと・・・

* start_dateのフォーマットチェック
* start_timeのフォーマットチェック
* end_dateのフォーマットチェック
* end_timeのフォーマットチェック

かつ、バリエーション終わった後か、withValidator的なヤツで、

* start_dateとstart_timeをくっつけてCarbonか何かの日付系インスタンス取得
* end_dateとend_timeをくっつけてCarbonか何かの日付系インスタンス取得
* 取得した日付系のインスタンスを比較

怠い＆冗長。
あと多分_dateと_timeをくっつけた後でフォーマットチェックもしないとイケない気がする。
（withValidatorってvalidationがfailすると呼ばれないっけ？なら不要）

# ソリューション
Illuminate\Foundation\Http\FormRequest::validationDataメソッドを上書きする

```php

/**
 * @inheritdoc
 */
protected function validationData()
{
    $this->addStartAt();
    $this->addEndAt();
    return parent::validationData();
}

/**
 * start_dateとstart_timeからstart_atを作ってリクエストパラメータに追加する
 */
private function addStartAt()
{
    $start_date = (string)$this->request->get('start_date');
    if ($start_date === '') {
        return;
    }
    $start_time = (string)$this->request->get('start_time');
    if ($start_time === '') {
        $start_time = '00:00:00';
    }
    $start_at = $start_date . ' ' . $start_time;
    $this->request->add(['start_at' => $start_at]);
}

/**
 * end_dateとend_timeからend_atを作ってリクエストパラメータに追加する
 */
private function addEndAt()
{
    $end_date = (string)$this->request->get('end_date');
    if ($end_date === '') {
        return;
    }
    $end_time = (string)$this->request->get('end_time');
    if ($end_time === '') {
        $end_time = '23:59:59';
    }
    $end_at = $end_date . ' ' . $end_time;
    $this->request->add(['end_at' => $end_at]);
}

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules()
{
    return [
            'start_at' => [
                'nullable',
                'date',
                'before_or_equal:end_at'
            ],
            'end_at' => [
                'nullable',
                'date',
                'after_or_equal:start_at'
            ],
        ];
}

```

validationDataはバリデーションされる前に呼ばれるメソッドなので、
これをオーバーライドして任意のパラメータをrequestパラメータに追加する。

フォームリクエストバリデーションなら、
$this->request->add()で任意のパラメータを増やせるので、バリデーション前に足す・・・ならギリありという判断。

パラメータは文字列で渡すので、dateフォーマットになってるか？とかバリエーション任せにできるし、
from - toの並びが正しいかもLaravel任せにできるのでコードもスッキリ。

これで_date、_timeのチェック不要になる。
ただ、_date、_timeでフォーマットが厳格に決まっている場合は、
それぞれちゃんとチェックして入力エラーがあれば画面上で判るようにしといてあげる、程度の配慮は必要です。

# さいごに
複数フィールドに対するバリデーションの仕方（required_ifとか使う方法）は割とよく出てるけど、
複数フィールドを合体させて１つのフィールドとしてバリデーションする方法は、情報がないので書いてみました。

最近コードが載らない記事は全部はてなに書いてるので久しぶりにQiitaに投稿してみましたが、
何かプレビューモードが見やすくなったような・・・気のせいかも。

また、コードが載るものを書くときはQiitaに書きます（多分）

では～。
Macの移行アシスタントを実行するならThunderboltケーブルとターゲットディスクモードを使おう

会社のMacを、macOS付属の「移行アシスタント」(Migration Assistant)を利用して移行するときは、新旧MacをThunderboltケーブルで繋いで、移行元を「ターゲットディスクモード」にしておくと移行が成功しやすいよ、というお話。

## 環境

- 移行元: [MacBook Pro 15inch Mid 2015](https://support.apple.com/kb/SP719?viewlocale=ja_JP&locale=ja_JP) (以下、旧Mac)
    - 電源端子がMagSafe 2の時代のもの
- 移行先: [MacBook Pro 15inch 2017](https://support.apple.com/kb/SP756?viewlocale=ja_JP&locale=ja_JP) (以下、新Mac)
    - 電源端子がUSB-Cの時代のもの

## 用意するもの

- [Thunderboltケーブル](https://www.apple.com/shop/product/MD861LL/A/apple-thunderbolt-cable-20-m) (手元にあるのは50cm)
    - 注: 新旧Macの端子がUSB-C同士なら [Thunderbolt 3 (USB‑C) Cable](https://www.apple.com/shop/product/MQ4H2AM/A/thunderbolt-3-usb%E2%80%91c-cable-08-m) を使う
    - 単なるUSB-Cケーブルだとうまくいくかはわかりません。USB-Cは規格がいろいろあって難しいですね…
- [USB-C〜FireWire変換アダプタ](https://www.apple.com/shop/product/MMEL2AM/A/thunderbolt-3-usb-c-to-thunderbolt-2-adapter)
    - Thunderbolt 2(Mini DisplayPort形状)のケーブルを使って新Macにつなぐ

## 背景

もともと、双方のMacを通常通り起動して、有線LAN経由で移行しようとしていました。個人で使っていたMacだとそれでうまく行っていたので、会社のもそれでうまくいくと考えいたのですが、そうではなかったのです。

数時間経っても進捗がなく、終わったと思ったら失敗、データが全然移行できませんでした。全てではなく、個別にユーザ情報だけを動かそうとしても、同様に失敗していました。

## やったこと

そこで、旧Mac側を動作させず、ディスクだけマウントすれば移行できるのかと考えて実行したのが以下の手順です。

Macには[ターゲットディスクモード](https://support.apple.com/ja-jp/ht1661)というものがあり、別のMacから直接ディスクをマウントする方法があることがわかりました。これですと、もし旧Mac側のOSが実行中であることが原因で移行できないのなら、解決できるはずです。

### 新Macをとりあえず起動

移行アシスタントが起動する直前まで持っていきます。ケーブルは、電源以外は繋がないでおきます。

### 旧Macをターゲットディスクモードで起動

「T」キーを押しながら電源を押すと、「⚡」マークがディスプレイに表示されてターゲットディスクモードになります。macOSは起動しません。

### 新旧MacをThunderboltケーブルで繋ぐ

実はここが一番難しいことでした。運よく、社内ITの人が1本だけ持っていて、お借りすることができました。これがなかったら詰んでました。無い方は買ってきてください…

### 新Mac側で移行アシスタントを起動

移行アシスタントで、新Macから旧Macのディスクが **直接** マウントできていることが確認できるはずです。ここから移行します。

マウント時、旧Macのログインパスワードを聞かれる場合があります。その場合は入力してください。

あとは、移行を実行して終わるまで待つばかりです。終了したら、旧Macはスイッチを切ります。新Macでは、正しく移行できているかを確認してください。

## おまけ

移行アシスタントをThunderboltケーブル以外で繋いで実行すると、Thunderboltケーブルを使うことをおすすめされますよね。やっぱりそうやって書くには訳があるってことなのでしょう。
Gradle 4.4にした時の "Failed to resolve: 3rd-party Gradle plug-ins may be the cause"エラー

 #概要
Gradleを3.1.3から4.4に上げた時にDaggar2を入れた時に追記したkapt関連で以下のwarningが発生し、ビルドが通らなくなったので対処法メモ

```
Folder /Users/ユーザー名/AndroidStudioProjects/プロジェクト名/app/build/generated/source/kaptKotlin/developmentDebug
　　　・
　　　・
　　　・
3rd-party Gradle plug-ins may be the cause
```

#対処法
Kapt diagnostic locationsを有効にする。
build.gradleにmapDiagnosticLocations = trueを追加することで解決

```build.gradle
kapt {
    generateStubs = true 
    mapDiagnosticLocations = true
}
```
annotation関連のエラーを生成されたJavaスタブではなく、元のKotlinファイルの記述場所へのリンクを表示できるようにする機能らしいです。
なぜ、これを有効にするとエラーが消えるのかは後で調査

#参考
https://github.com/bumptech/glide/issues/2993
レッツノートバッテリー発火

レッツノートをお持ちの皆様
対象製品とかありますので確認してみてください。
心配な方はこちらのURLからパナソニックパソコンサポートにいけます。
http://askpc.panasonic.co.jp/info/141113.html
http://askpc.panasonic.co.jp/info/160128.html

<h1>（1）パソコンの機種の確認</h1>
パソコンの機種は、本体の機種表示をご確認ください（下図参照）。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/249283/e16f966f-ff40-5259-ad90-fe95dbee8455.png)

<h2>（2）バッテリーパックの取り外し</h2>
パソコンの電源をお切りいた+++++++++++だき、バッテリーパックを取り外してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/249283/38de1f50-feab-4018-9f6e-270610618188.png)
 
<h3>（3）バッテリーパックの品番とロット記号の確認</h3>
バッテリーパックの品番とロット記号は、バッテリーパックの銘板をご確認ください。
対象機種の上記対象製造期間内でもバッテリーパックのロット記号によって対象外の製品があります。
回収対象品は、ロット記号が「対象バッテリーパックの品番とロット記号」に該当するものとなります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/249283/1751518b-3866-2d6b-f00a-cf7e12902941.png)

<h4>（4）対象のバッテリーパックはご使用にならないでください</h4>
■CF-S8/S9/S10シリーズ、またはCF-N8/N9/N10シリーズ
　バッテリーパックの品番・ロット記号の確認とお申込みはこちらhttps://askpc.panasonic.co.jp/vsew/pc_battery_checks/s8_n8