OmniAICreator/Qiita-1.07M huggingface dataset:
Docker で MySQL 起動時にデータの初期化を行う

主に開発用とで docker で MySQLを動かす際に、起動時にサンプルデータなど初期データを登録しておきたいことがあります。

docker の MySQL image では `/docker-entrypoint-initdb.d/` というディレクトリ内に初期化用のSQLやスクリプトを置くことで、最初に image を起動したときにデータの初期化を自動的に行う仕組みがあります。

本記事ではその設定方法について簡単に記載します。

# ディレクトリ構成
```
├ root
    ├ mysql
        ├ data
        ├ init
        |    ├ 1_ddl.sql
        |    ├ 2_data.sh
        |    └ data.csv
        └ Dockerfile
    └ docker-compose.yml
```

## mysql
### init/1_ddl.sql
table の作成などを行う SQL

```
CREATE DATABASE IF NOT EXISTS sada;
CREATE TABLE IF NOT EXISTS sada.masashi(
  `id` int(11) NOT NULL,
  `name` varchar NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

### init/2_data.sh 
CSVデータの import 処理を行う shell script

```
mysql -uroot -pmysql --local-infile sada -e "LOAD DATA LOCAL INFILE '/docker-entrypoint-initdb.d/data.csv' INTO TABLE masashi FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\n'"
```

### init/data.csv
CSV ファイル

```
"sada masashi"
...
```

### Dockerfile
init ディレクトリの内容を、 /docker-entrypoint-initdb.d/ に copy するよう Dockerfile で記述します。

```
from mysql:5.6
 
COPY init/* /docker-entrypoint-initdb.d/
 
CMD ["mysqld"]
```

 /docker-entrypoint-initdb.d/ の中のファイルは、`1_, 2_ ...` などと数字で prefix が記されているファイルの昇順で実行されていきます。


## root

```
docker-compose.yml
version: '3'
services:
  mysql:
    build: ./mysql
    container_name: mysql56
    environment:
      MYSQL_ROOT_PASSWORD: mysql
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/init:/docker-entrypoint-initdb.d
    ports:
      - 3306:3306
```

# 起動

```
$ docker-compose build
(snip.)
$ docker-compose up
(snip.)

mysql56  | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/1_ddl.s
mysql56  | Warning: Using a password on the command line interface can be insecure.
mysql56  |
mysql56  |
mysql56  | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/2_data.
mysql56  | Warning: Using a password on the command line interface can be insecure.
```

ちょっとコマンド内で直接パスワード指定していたりとイケてないので上記例では warning が発生していますが、mysql の docker container が起動したタイミングで、データの初期化処理が行われているのが確認できます。

これで、docker をローカル環境で動かす際に、ただ起動するだけで MySQL に対してテーブルの作成やデータの投入まで行うことができます。
IEでローカルのproxy.pacが読み込めない

#結論
- IE11の仕様でローカルに配置したproxy.pacは読み込めない（file://~~でアクセスできない）
- レジストリを変更する回避策が存在したが、Windows10（CreatorsUpdate以降）からは使えない
- 対策はWebサーバを立ててproxy.pacを配置し、http://~~でproxy.pacを読み込むこと

##参考サイト
[IE11でローカルに配置されたプロキシ自動構成スクリプトが読まれない件](https://611kilometer.tumblr.com/post/81629718589/ie11%E3%81%A7%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AB%E9%85%8D%E7%BD%AE%E3%81%95%E3%82%8C%E3%81%9F%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7%E8%87%AA%E5%8B%95%E6%A7%8B%E6%88%90%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%8C%E8%AA%AD%E3%81%BE%E3%82%8C%E3%81%AA%E3%81%84%E4%BB%B6)

##経緯など
IEしか使えないアプリにアクセスするため、pacファイルを使ってプロキシの経路を制御する要件が発生した。
ネット上のテンプレートを見ながら作成し、ローカルに配置して読み込ませるも効いていない（proxy経由を指定したサイトなのに直接接続してしまう）。設定を共用しているChromeはなぜか意図通りにproxyを経由する。**IEとchromeでpacの文法が違う？**との盛大な勘違いで大幅に時間をロスした。

同じような人が増えない事を祈り、有益な情報を掲載されている参考サイトの情報拡散にご協力差し上げたいとの意図から、本投稿を作成するものであります。

##多分一番簡単なWebサーバの建て方
Linuxにnginx入れてpacファイルを以下に配置。
`/usr/share/nginx/html/proxy.pac`

インターネットオプションの「自動構成スクリプトを使用する」に以下を記載。
`http://<IP address>/proxy.pac`
Spring Boot + Micrometer + Prometheus Exporter で任意のメトリクスを簡単に取得する

ここでは Spring Boot + Micrometer + Prometheus Exporter の組みわせで任意のメトリクスの取得を行う方法について書きます。


# Settings
Spring Boot が導入されている環境で Micrometer を有効にするには、pom や gradle などで必要なライブラリを設定します。

## example
ここでは pom の例を書きます。

```pom.xml
<!-- 必須 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-core</artifactId>
    <version>${micrometer.version}</version>
</dependency>
<!-- spring boot 1.5x を使っている場合は必要 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-spring-legacy</artifactId>
    <version>${micrometer.version}</version>
</dependency>
<!-- 以下、Prometheus Exporter を有効にする場合は必要 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <version>${micrometer.version}</version>
</dependency>
<dependency>
    <groupId>io.prometheus</groupId>
    <artifactId>simpleclient</artifactId>
    <version>${prometheus.version}</version>
</dependency>
<dependency>
    <groupId>io.prometheus</groupId>
    <artifactId>simpleclient_common</artifactId>
    <version>${prometheus.version}</version>
</dependency>
```

## micrometer-core
micrometer を使用する際に必須となるライブラリです。

## micrometer-spring-legacy
micormeter は Spring Boot 2,x から公式のメトリクスツールの扱いになっています。その関係もあり、2.x より古いバージョン（1.5.x）を使用する場合は、バックポート用のライブラリが必要です。1.5.xの環境で動かしているのであればこちらを指定します。

## micrometer-registry-prometheus / simpleclient /simpleclient_common
取得したメトリクスをどのような形で伝搬・表示させるかについては、`micrometer-registry-**` というライブラリで任意のものを選択します。

ここでは Prometheus Exporter を使いたいので、prometheus 関連の registry を指定します。

また、prometheus 関連の処理を Java で行う場合は、prometheus が提供しているライブラリ（simpleclient、simpleclient_common）も指定する必要があります。

# Code
アプリケーションコードへの埋め込み方は以下です。

## Counter を初期化
初期化した Counter を用いて increment

```SadaController.java
@RestController
public class SadaController {
    @Autowired
    protected MeterRegistry meterRegistry;
 
    private Counter metricsCounter;

    @PostConstruct
    public void init() { 
        metricsCounter = meterRegistry.counter("api.sada.count"); // initialize
    }
 
    @RequestMapping(path = "/sada", method = { RequestMethod.GET })
    @ApiOperation(value = "sada")
    @ApiResponses(value = { @ApiResponse(code = 200, response = String.class, message = "echo") })
    public String sada(@RequestParam(name = "echo", required = false, defaultValue = "masashi") @Valid String echo) {
        metricsCounter.increment(); // increment
        return echo;
    }
```

## Prometheus Exporter
micrometer-registry-prometheus をライブラリに追加していると、Spring Boot 起動時に自動的に `/prometheus` エンドポイントが有効になります。

標準で JVM や Thread の状態についてメトリクスが取得できるようになっています。

それに加えて、上述のようなカスタムメトリクスについても、Prometheus Exporter 経由で取得可能となります。

```
# TYPE api_sada_count_total counter
api_sada_count_total 15.0
```

上記は、上述の Controller を呼び出した回数が、メトリクスとして取得された例です。

このような形で取得したメトリクスについては、Prometheus や Datadog に取り込むことが可能です。


# まとめにかえて
Micrometer の最もシンプルな使い方は以上ですが、他にも多種多様な機能があるので、詳しく知りたい方は公式ドキュメントに Go だ。

https://micrometer.io/docs
Azure Automationアカウントの証明書を更新する

# 警告メッセージ

Automationアカウントを開くと、「実行アカウントとクラシック実行アカウントの証明書の有効期限が切れました」というメッセージが表示されていました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/8ca26a0d-cfad-2955-ccc8-cab1b10be89a.png)

でもRunbookは問題なく動作していたのでなんでだろーと思い調べたので残しておきます。

# 原因は？
Automationアカウントを作るとAzure ADにサービスプリンシパルが作成されます。
このサービスプリンシパルは証明書を使った認証方式になっており、この証明書の有効期限が切れたよというメッセージでした。

# 証明書切れたのになんでRunbook動いてたか？
動かしていたRunbookがたまたま認証しないものだけだったためです。
検証のためRunbook内で認証させようとするとエラーになりました。

```text:実行コマンド
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Add-AzureRMAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationID $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint
```

```text:エラーメッセージ
Add-AzureRMAccount : AADSTS70002: Error validating credentials.
AADSTS50012: Client assertion contains an invalid signature. [Reason - The key used is expired
```

証明書期限切れの認証エラーですね。

# 対処する

* 事前に証明書の有効期限を確認しておきます。Automationアカウントのページから[証明書]を選択してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/36ce153a-e788-3c01-c9df-30d4ae61cdba.png)

* 概要ページのエラーメッセージをクリックします
* [Azure実行アカウント]→[証明書の更新]の順に選択します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/fa6e8eb1-f5ac-62d9-9bd0-8cf948e2f004.png)

* メッセージが出るので[はい]を選択します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/51cafb54-eb15-cad4-811c-8ec2b2ee0be5.png)

* 証明書が更新されていればOKです
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/ab07a6be-0d93-acd4-2cb0-ee54ccc3c8d8.png)

# クラシックアカウントも対応する

いまさらクラシックのコマンドを実行することはないような気もしますが、エラーメッセージが出てるのは気になるので一応やっておきます。

* 更新手順は前述の実行アカウントと同じですが、グレーアウトされて選択できない場合があります
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/1f24b0fc-6cde-16bd-fd5d-48e60a33f431.png)

* サブスクリプションの共同管理者でないとクラシックアカウントは操作できないようなので、操作しているアカウントに権限を追加します
[共同管理者を追加または変更する](https://docs.microsoft.com/ja-jp/azure/billing/billing-add-change-azure-subscription-administrator#add-or-change-co-administrator)

* 操作できるようになったら以降の手順は同じです
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/19da04b3-7872-0f1f-82f1-faced5df93f9.png)

# 追記：期限切れ前にSlack通知する
[Azure Automationアカウントの証明書期限が切れる前にSlack通知する](https://qiita.com/shingo_kawahara/items/1c165be4ef354f8feb40)

# 追記：クラシックアカウントステータスが「不完全」と表示されたら
アカウントはあるが証明書がないなど、状態異常になっているようです。
クラシックアカウントを削除して、再作成したら改善しました。
使わないなら削除したままでもよいですね。

* 「不完全」と表示されている
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/bc07505b-ee83-6600-445b-340ffec86f5e.png)

* クラシックアカウントを選択して「削除」します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/eccd066d-a714-62cc-270f-328fb5234ff5.png)

* 「不完全」表示が消えて再作成できるようになります
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180335/ecba9432-0c27-98d6-72b1-5f9b5d85984e.png)
Railsチュートリアル第14章でアホみたいにハマった独学者の備忘録 part2

[前回の記事](https://qiita.com/UKiABe/items/119566372386389c96b6)に続き、またハマりました。

#ハマったところ
Follow機能とUnｆollow機能のバックエンドの実装部分。
すでにビューの部分（Followボタン、Unfollowボタン）はできている。

**コントローラーでUnfollowされるユーザー情報を取得するところに疑問が生まれ、
考え込んでしまった。**

controllerに、ユーザーをFollowするcreateアクションと
Unfollowするdestroyアクションを追加するのですが、そのアクションの中身の部分です。
以下にコード示します。

#疑問になったコード

```ruby:app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController
  before_action :logged_in_user

  def create
    user = User.find(params[:followed_id])
    current_user.follow(user)
    redirect_to user
  end

  def destroy
    user = Relationship.find(params[:id]).followed
    current_user.unfollow(user)
    redirect_to user
  end
end
```

上記コードの`destroy`アクションでは
`user = Relationship.find(params[:id]).followed`
で変数`user`を取得し、`unfollow`メソッドの引数として利用しています。
URLに含まれている`params[:id]`でRelationshipモデルのidを検索しているんです。
え、なんで？①　`followed_id`を検索するところじゃないの？？
え、なんで？②　`find(params[:id])`って`params[:id]`で`followed_id`カラムを検索するって意味だっけ？？

目には見えないrelationshipモデルを取り巻く情報の流れが頭に構築できていなかったんですね。
次の項で解決に至った箇所を示します。

#viewファイルのerb(埋め込みルビー）が解決の糸口に
Unfollowボタンを表示するパーシャルコードを以下に示します。

```ERB:app/views/users/_unfollow.html.erb
<%= form_for(current_user.active_relationships.find_by(followed_id: @user.id),
             html: { method: :delete }) do |f| %>
  <%= f.submit "Unfollow", class: "btn" %>
<% end %>
```

このコードが生成するHTMLは以下です。

```html
<form class="edit_relationship" id="edit_relationship_90" action="/relationships/90" accept-charset="UTF-8" method="post">
  <input name="utf8" type="hidden" value="✓">
  <input type="hidden" name="_method" value="delete">
  <input type="hidden" name="authenticity_token" value="RRvQ5/IIXUuXjUCJzhpDrXBtFOZ6gTHkonrkOn3wFO4SJPNMPwTESu0+8dB+QeSfI8+14AUbgLDOzRalKq3YBw==">
  <input type="submit" name="commit" value="Unfollow" class="btn" data-disable-with="Unfollow">
</form>
```

`action=`の部分が`/relationships/90`なので`params[:id]=90`でdeleteメソッドすることになってます。

#解決！
あー、followしたりunfollowしたりする度に、その関係性をRelationshipモデルに生成しているんですね。
FollowボタンとUnfollowボタンを押した場合、生成されるHTMLのaction属性は、1ずつ増えた:idを有するURLになっていました。

Unfollowの流れ
1.Unfollowボタンには、Relationshipモデルのidを含むURLをaction属性にもつHTMLがある
2.params[:id]をidにもつrelationshipを取り出す
3.followedメソッドで、フォローされているユーザーを取り出し、変数userへ代入
4.unfollowメソッドで現在ログインしているユーザーから、userをフォローしているというデータを削除

find(params[:id])じゃフォローしてるやつのデータ取り出せないだろう！と思ってしまったというお話でした。
Railsすごすぎ。
じゃんけんアプリの答えが知りたい

import android.app.Activity;
import android.graphics.Color;
import android.media.Image;
import android.support.v4.widget.TextViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Random;

public class MainActivity extends AppCompatActivity {


        private int selectedItem = -1;




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }



  //  public void onClickAction(View view) {
  //      ImageView image =(ImageView)findViewById(R.id.imageView);
   //     image.setImageResource(R.drawable.Androidkun);

  //  }

    public void itemSelectAction(View view) {
        ImageView[] items = new ImageView[3];
        items[0] = (ImageView)findViewById(R.id.imgGu);
        items[1] = (ImageView)findViewById(R.id.imgch);
        items[2] = (ImageView)findViewById(R.id.imgPa);

        for (int i = 0; i < items.length; i++){
            if(items[i] == view) {
                items[i].setBackgroundColor(Color.RED);
                selectedItem = i;
            }
            else {
                items[i].setBackgroundColor(Color.WHITE);
            }
        }

    }

    public void startClickAction(View view) {
        int[] item = {R.drawable.j_gu02,R.drawable.j_ch02,R.drawable.j_pa02};
        Random rd = new Random();
        int cpu = rd.nextInt(3);


        ImageView src =(ImageView)findViewById(R.id.imgCpu);
        src.setImageResource(item[cpu]);

        //ImageView cpu = (ImageView) findViewById(R.id.imgCpu);
       // cpu.setVisibility(View.INVISIBLE);

        //ImageView cpu = (ImageView) findViewById(R.id.imgCpu);
        //cpu.setVisibility(View.VISIBLE);

    }

    private int judgement(int cpu) {
        int result = -1;

        if (selectedItem == 0 && cpu == 1 || selectedItem == 1 && cpu == 2 || selectedItem == 2 && cpu == 0) {
            result = 0; //プレイヤの勝ち
        } else if (selectedItem == 0 && cpu == 2 || selectedItem == 1 && cpu == 0 || selectedItem == 2 && cpu == 1) {
            result = 1;   //プレイヤーの負け
        } else if (selectedItem == cpu) {
            result = 2;    //引き分け
        } else {
            result = -1;   //勝ち、負け、引き分け以外　 （基本的にこない）
        }
        return result;



   private int judgement(int cpu) {



        /*if (selectedItem == 0 && cpu == 1 || selectedItem == 1 && cpu == 2 || selectedItem == 2 && cpu == 0){
            TextView.setText("勝ち");
        }else if(selectedItem == 0 && cpu == 2 || selectedItem == 1 && cpu == 0 || selectedItem == 2 && cpu == 1){
            TextView.setText("負け");
        }else if (selectedItem == cpu){
            TextView.setText("引き分け");
        }*/







    }
    }


}
Visual Studio Codeの設定メモ

筆者の設定メモ。

#文字コード変換

デフォルトではすべてのファイルが「UTF-8」で開くようなので、自動判別する設定を実施

- [File]-[Preferences]-[Settings]

Files:Auto Guess Encodingにチェックを入れる（以下画像左のチェックボックス）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276568/c6c88b37-77f5-19c7-fc6b-169768b6933d.png)

VSCode再起動後、自動判別できていることを確認。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276568/a82132f7-a70d-3e0e-b62e-595196a37887.png)

#ショートカットキー

- JSON形式の自動整形

Alt＋Shift＋F
今Ubuntu16.04でL2TP/IPSecなVPN接続をする

ちょっとハマったのでメモとして．
内容としては「公式ドキュメントをくまなくよめ」が総括です．
それと，ネット上の情報は古いものが多くてビルド方法に悩んだのもありました．

# やりたかったこと

Ubuntu 16.04 で L2TP / IPSec なVPN接続をしたかった(クライアント側の話)．

# 経緯

apt で network-manager-l2tp と network-manager-l2tp-gnome をインストール．
その後，ネットワークマネージャでVPNの諸々を設定．
他のPC (Windows / Linux) やスマホでも接続した経験があるVPNサーバだったので，サーバ側に問題はないと思われる．
にもかかわらず，接続がタイムアウトしてつながらなかった．

# 対処

apt ではなく，ソースから network-manager-l2tp をインストールした．

ただし，[公式リポジトリ](https://github.com/nm-l2tp/network-manager-l2tp) のReadme.mdを読むだけだと，Ubuntu16.04ではバージョン不整合でconfigureが通らない．

公式リポジトリのWikiの[Building](https://github.com/nm-l2tp/network-manager-l2tp/wiki/Building)に詳細なビルド方法が書かれており，こちらに書いてあるとおりにビルドしたらバージョン問題は解決．

簡単に言えば，Ubuntu 16.04 ではネットワークマネージャのバージョンが古いので，それ用のブランチをチェックアウトしてこい，という話だった．
この一言がReadmeに書いてあれば…

## おまけ : 具体的な手順

```
sudo apt remove network-manager-l2tp*
mkdir ~/tmp
cd tmp
git clone -b nm1-2 https://github.com/nm-l2tp/network-manager-l2tp.git
cd network-manager-l2tp
./autogen.sh
./configure \
  --disable-static --prefix=/usr \
  --sysconfdir=/etc --libdir=/usr/lib/x86_64-linux-gnu \
  --libexecdir=/usr/lib/NetworkManager \
  --localstatedir=/var \
  --with-pppd-plugin-dir=/usr/lib/pppd/2.4.7
make
sudo make install
```

最初にaptでインストールしたnetwork-manager-l2tpたちをアンインストール．
その後，公式リポジトリからブランチを指定してcloneし，設定ファイルを作り，makeし，インストールする．
後からvue-routerを導入した時の手順

# 導入
```zsh:パッケージ導入
npm install --save-dev vue-router
もしくは
yarn add vue-router --dev
```

```javascript:router.js導入(rootディレクトリで新規作成)
import Vue from 'vue';
import VueRouter from 'vue-router';
import Top from './components/Top.vue';
import Hage from './components/Hage.vue';
import Hoge from './components/Hoge.vue';

Vue.use(VueRouter);

const routes = [
    { path: '/', component: Top },
    { path: '/hage', component: Hage },
    { path: '/hoge', component: Hoge },
];

const router = new VueRouter({
    routes,
    mode: 'history'
});

export default router;

```

自分の場合はApp.vueでほかコンポーネントを管理していたため、以下のように修正

```javascript:メインコンポーネントのtemplate部分修正
<template>
  <div>
    <router-link to="/">
      top
    </router-link>
    <router-link to="/hage">
      hage
    </router-link>
    <router-link to="/hoge">
      hoge
    </router-link>
    <router-view></router-view>
  </div>
</template>
```

自分の場合、エントリポイントがmain.jsになっており、以下のように修正

```javascript:エントリポイントの修正
import Vue from 'vue'
import App from './App.vue'
+ import router from './router'

Vue.config.productionTip = false

new Vue({
+ router,
  render: h => h(App)
}).$mount('#app')

```
ransack、フォーム作成時にmatcherが同名になった時の解決方法

# ransackでフォームフィールド名が同じになってしまう問題
まず起きることはないが、どんな状況で起き得るか

```ruby:Userモデル
name: String # 本名
profile_name: String # サイト上で表示する名前
......
```

```ruby:Profileモデル
name: String # いろいろな経緯があって生まれてしまったモデルの名前
......
```

## この状況でransackのフォームを作成すると問題が起きる
* どちらも `profile_name_cont` になってしまうのだ。


```slim:ransack_form.slim.erb
= f.label :profile_name_cont, 'サイト上の表示名(user.profile_name)'
= f.check_box(:profile_name_cont)

= f.label :profile_name_cont, 'Profileの名前(user.profile.name)'
= f.check_box(:profile_name_cont)
```

この場合 同じクラスのメソッドが優先されるので検索されるのは

`user.profile_name` だけであり、`user.profile.name` の検索は行われない。


結論：処理としては `User` モデルの `profile_name` カラムの検索だけちゃんと動作する。


## 2通りの解決方法
- 設計ミスなのでカラム名を変更する、おそらくこれがもっとも良い解決方法。
- `user.profile.name`は ransack を使わずに検索を実装、検索結果を結合する。


## 検索結果を結合する場合の実装方法
`user.profile.name` の検索は `ransack` に載せることができないので
別で検索処理を作成して `` 結果を結合 `merge` する戦法をとった


### 検索結果のマージ
基本的な部分は省略するが、ransackと通常の検索結果の `merge` はこんな感じでできる。

```rb:merge
result = User.ransack(ransack_params).result.order(id: :desc)
result.joins(:profile).merge(Profile.where(name: "ほげ"))
```



# 試してみたがダメだった `delegate` と `ransackable_attributes`　を使った実装

`ransackable_attributes` で検索可能な要素一覧を表示できる

```rb
User.ransackable_attributes
```

これ毎に `Search Matchers` が利用可能なので、ここに `profile_dot_name` を追加
そのキーワードでも検索できるようにしてみた。

```rb
  def self.ransackable_attributes(auth_object = nil)
    %w(name profile_name profile_dot_name)
  end
```


`profile_dot_name`で検索した際に　`Profile` モデルの `name`を参照するように
`delegate`を定義。

```rb:user.rb
delegate :name, to: :profile, prefix: :profile_dot
```

## 結論：ransackが直接SQLを発行してしまうため、`delegate`で定義した `profile_dot_name` は利用できないのである。

```sql:例
Mysql2::Error: Unknown column 'users.profile_dot_name' in 'where clause': SELECT  `users`.* FROM `users` WHERE 
.....
```

ちなみに結構ライブラリの中身書き換えてエラー出ないようにしてみたものの最終的にここで詰まって死亡しました
No enclosing instance of type Hoge is accessible. 

# 概要

こんなコードを書いてみたらエラーが発生したので、メモ。

```java
public class Hoge {
    private class Fuga(){
        public String name;
    }
    public static void main(String[] args) {
        Fuga fuga = new Fuga();
    }
}
```

```
No enclosing instance of type Hoge is accessible. 
Must qualify the allocation with an enclosing instance of type Hoge 
(e.g. x.new A() where x is an instance of Hoge).
```

Hoge クラスの内部にアクセスできないよエラー！

# 解決方法

## Fuga を static クラスにする

```java
public class Hoge {
    // static class にする
    private static class Fuga(){
        public String name;
    }
    public static void main(String[] args) {
        Fuga fuga = new Fuga();
    }
}
```

## Hoge を生成してから Fuga を生成

```java
public class Hoge {
    private static class Fuga(){
        public String name;
    }
    public static void main(String[] args) {
        // 一度 Hoge のインスタンスを生成してから Fuga のインスタンスを生成
        Hoge hoge = new Hoge();
        Fuga fuga = hoge.new Fuga();
        // これでもできる
        Fuga fuga2 = new Hoge().new Fuga();
    }
}
```
std::chronoで小数点のdurationを使う

c++のプログラムの計算時間を計るのに、std::chrono を使っていたけど、std::chrono::millisecondsでは荒すぎるし、std::chrono::microsecondsでは、分散を求めるときにオーバーフローするし、困った。
調べてみると、std::chrono::duration::count()は小数点も返せるみたいなので、その方法をメモ。

# 小数のstd::chrono::duration型を作って使う

```c++
// float型で、1/1000秒単位の duration
using ms_f = std::chrono::duration<float, std::raito<1, 1000>>;

auto t0 = std::chrono::system_clock::now();
SomeProcessing();
auto t1 = std::chrono::system_clock::now();

// ミリ秒単位だけど、ミリ秒未満も切り捨てられない！
float dt = std::chrono::duration_cast<ms_f>(t1 - t0).count();
```

system_clockなので、ミリ秒以下の精度があるかどうかは別問題。
ProgateでSQLを学習してみた（2）

#ProgateでSQLを学習してみた（2）
SQL学習の続き

・WHEREで条件設定する（レッスン1）
・比較演算子、LIKE、NOT、NULL・IS　NOT　NULL,AND・OR（レッスン1）
・ORDER BY、LIMITで加工（レッスン1）
・DISTINCT、四則演算（レッスン2）
・集計関数（SUM、AVG、COUNT,MAX・MIN）（レッスン2）

今回はここから↓
**・グループ化（GROUP BY、HAVING)　（レッスン2）**
**・サブクエリ（レッスン3）**
**・複数テーブルの使用（JOIN、LEFT JOIN）（レッスン3）**

##グループ化（GROUP BY、HAVING)　
グループ化は苦手・・イメージをつかみにくかったんですが
Progateさんで学習するうちに
イメージがつかめてきた！・・気がします

Progateさんの解説だと
「データベース内の同じ日付のデータをグループとしてみましょう」
というのが非常に「グループ」の例えとしてわかりやすかったです

書籍で学習してたときは「種類」でグループ化っていう例えだったので
いきなり「文具」「台所用品」「洗面道具」って・・わかりにく！

```sql
SELECT SUM(price),日付のカラム
FROM purchases
GROUP BY 日付のカラム;　←日付ごとに買い物の合計金額を表示する
```
家計簿のイメージ！わかりやすい！

実務だと複数のカラムをグループ化しないといけないけど
基本形として覚えておくと後に助かりそうです
あと、必ずグループ化したカラムもSELECTの後に書くっていうのも
表示したいカラムが多い場合は忘れがちなので肝に銘じます

###GROUP BYとWHEREを一緒に使う
GROUP BYを使用するときに条件をつけたい場合があります
そのときは「WHERE」と「HAVING」という句がありますが
データをくくるタイミングによって、どちらを使うか変わってきます
>①WHERE文でキャラクターが「○○○」であるレコードを検索する 
②日付でグループ化する 
③集計関数で集計する

上記が「WHERE」を使ったときの処理の流れです
条件で絞りこんだデータをさらにグループで切り分ける、ということですね

```sql
SELECT SUM(price),日付のカラム　←③集計する
FROM purchases
WHERE character_name="○○○" ←①条件でデータを絞る
GROUP BY 日付のカラム;　←②日付でグループ化する
```
対して「HAVING」の場合は
>実行順序によって、WHEREとHAVINGは検索対象に違いがあります。
WHEREはグループ化される前のテーブル全体を検索対象とするのに
対し、HAVINGはGROUP BYによってグループ化されたデータを
検索対象とします

なるほど！

>HAVINGはグループ化された後のテーブルから検索するため、
条件文で使うカラムは必ずグループ化されたテーブルのカラムを使う


```sql
SELECT SUM(price),character_name
FROM purchases
WHERE category="雑費"
GROUP BY character_name
```
clipboardにHTML, CSSをコピーするボタンを設置

「ある範囲のHTML, CSSをクリップボードに一発でコピーできるボタンが欲しい」という件に難儀したのでメモに残す。

# 難儀した箇所

HTMLで囲われたテキストをコピーするには`clipboard.js`などを使って実装できるが、HTMLやCSSのコピーは正面突破しようとするとできないので、工夫が必要だった。

# どうしたか

`clipboard.js`では、`value`評価される部分をクリップボードにコピーする仕様になっているっぽかったので、HTML, CSSを取得した上で`input value`に一旦入れてあげ`value`評価させた上で、`input value`を取得するようにした。
`input`要素については`style="display: none"`で表示させないようにした。

```example.html

<div id="clipboard">
  <input id="clipboard-text" type="text" value="" style="display: none" />
  <button class="btn copy-dom-to-clipboard-btn" data-clipboard-action="copy" data-clipboard-text="">Copy DOM</button>
</div>

<script type="text/javascript">
  $(document).ready(function() {
    $('.copy-dom-to-clipboard-btn').on('click', function() {
      // プレビュー画面のHTML, CSSの取得
      var copyTarget = document.querySelector("CSS指定").outerHTML + document.querySelector("div idなど").outerHTML;
      // HTML/CSSをコピーするにはDOM内でvalue評価しないといけないので対応する。
      var clipBoardVal = $('#clipboard-text').val(copyTarget);
      $('.copy-dom-to-clipboard-btn').attr('data-clipboard-text', clipBoardVal.val());
    });
    var clipboard = new Clipboard('.copy-dom-to-clipboard-btn');
    // コピーした時にアラートを表示する (成功時)
    clipboard.on( "success", function(e) {
      e.clearSelection();
      alert( "Copied on Clipboard" );
    });
  });
</script>

```

その他　`clipboard.js`　については下記参照
[clipboard.js](https://clipboardjs.com/)
Grub2.02のコマンドをシェルスクリプトと比較しながら見てみる

grubの記事って少ないんですね、30件くらいしかありませんでした。

ここでのシェルスクリプトとはbashの事を指しています。

# 何これ

- Grubはあまり使わなくて忘れそうなのでメモ
- 使った事あるコマンドが増えるたびにズラズラと並べていきます。
- 一度に多くのコマンドを確認出来る様にするため、出来るだけワンライナーで記述していきます。

# 書き方

### if [ "1" == "1" ]; then echo true;fi

```bash
全く同じ
```

### if [ "1" == "2" ]; then echo true;else echo false;fi

```bash
全く同じ
```

### [ "1" == "1" ] && echo true

```bash
ifを使わない版、個人的に好んで使用しているが、できなかった
```

### name="sakkuntyo"

```bash
set name="sakkuntyo"
```

### echo $name

```bash
全く同じ
```

### echo ${name}

```bash
全く同じ
```

# 所感
筆者は思いました。

- shellscriptと同じ書き方出来る事多い！！
排他的論理和をJavaScriptで実装してみる

# 経緯
排他的論理和を説明する際に、ネットや書籍に記載されている内容だと概念は理解できるのだが、いまいち消化しきれていない印象を受けた。
※正直なところ、説明する本人も説明する前にネットで確認した。
なのでコードで表現してあげた方がプログラミングをかじった人にしてみれば分かりやすいのでは？
と言う事で記事にしてみた。

JavaScriptで実装した経緯としては、特に準備の必要もなくブラウザさえあれば実行できる手軽さより。

# おさらい
排他的論理和について、簡単におさらいしておくと
以下の表のように**どちらか一方が1の場合にのみ、1となる論理演算である。(両方1はダメ)**

| a | b | c |
|:--|:--|:--|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |

# 実装
断っておくが、JavaScriptでビット演算子が用意されているのは、知っている。

```
var c = a ^ b;
```

ただしそれだと今回の目的から外れるので、自前で実装する。

```
var c = (a & !b) | (!a & b);
```

意外と分かりにくい。
これなら万人に理解できる表で十分かもしれない。

(2018/10/12 追記)
演算子をバイナリ論理演算子（`&&`や`||`）からバイナリビット演算子（`&`や`|`）に変更しました。
Mac OS Mojaveインストール後brew,portエラー

###Mac OSをMojaveにアップデートしてしまい、
####brew、portコマンドが使用できなくなってしまい、、
> #sudo port install phpadmin
 - Error: Current platform "darwin 18" does not match expected platform "darwin 17"
Error: If you upgraded your OS, please follow the migration instructions: https://trac.macports.org/wiki/Migration
OS platform mismatch
    while executing
"mportinit ui_options global_options global_variations"
Error: /opt/local/bin/port: Failed to initialize MacPorts, OS platform mismatch

> #sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14
BuildVersion:	18A391

darwinのバージョンまで調べることができなかった。
[参照:OS Xでバージョンをコマンドラインから確認する方法
](https://rcmdnk.com/blog/2016/02/15/computer-mac/)
参照URLによると、"About This Mac"の"System Report"から、SystemInformationを開き、SoftwareOverviewから確認をすることができるようだ。
![Screen Shot 2018-10-04 at 19.27.14.png](https://qiita-image-store.s3.amazonaws.com/0/275087/517ee715-01b8-b8d1-3846-37d44cb02bed.png)
![Screen Shot 2018-10-04 at 19.27.18.png](https://qiita-image-store.s3.amazonaws.com/0/275087/46f202e8-1055-ddd3-e959-5ce1d2ded39b.png)

MacPortの最新版インストーラーを、[公式](https://www.macports.org/install.php)から拝借し、インストーラーを実行する。

バージョンが古かったので、下記のURLにあったコマンドがエラーとなっていた。
あとは、、メッセージにあった`https://trac.macports.org/wiki/Migration`に従う。

macportのアップデートは完了した。次は、Xcodeだ。
[Xcode最新版でエラー](https://qiita.com/mykhr120/items/c462f07d8a3b6d8e3c6d)
Mojave利用後の困ったこと。

####Mysql,Postgresql
#####Xcode再インストール（Mojaveへアップデート後）
最新Xcode10をWebからダウンロードしたところ、
mysql,Postgresqlを動作させるのにXcode 8.2が必要との
メッセージが出た為、敢えて古いバージョンのダウンロードをしました。

一旦、ダウンロードしてきた最新Xcodeは削除し、
Xcode8.2の適用を実施しました。

※追記: もともとMac Book Airにセットアップ済みのOSがEl Capitanの為、
それをベースとした推奨動作が実行されるのかと推測します。

なので、El Capitanで用いられる最新のXcodeである8.2をインストールする様に
ターミナルからメッセージが出力されたんですね。

Sierra→High Sierra→Mojaveとアップデートを重ねて使用してはいるものの、
その最中にXcodeで開発をする機会があまり、ありませんでした。
（Mac Book Airを購入した際に、Xcode/Object-Cでデスクトップで動作する世界時計を
プログラム組んだぐらい。）

また、最新10ver.はApp storeから再インストールした所、
どちらも上手く動作するようになりました。（現状）

#####古いソフトウェアバージョンで、動作しなかった
####VirtualBox
Webで公開されている最新版を新たにダウンロードし、
インストールした所、きちんと動作しました。
（過去作成したVMもそのまま。
マシンファイルの格納場所が変更されていない為。
確実にバックアップが必要な場合は、取得してから実行してください。）
####Skype
Skypeは新規でアカウント登録が必要でした。
ログインする際に、間違えて新しいメールアドレスを入力してしまったかもしれません。

####Aptana Studio
親切にも過去のmacOSで使用されているJAVAをインストールするメッセージがありましたので、こちらをダウンロードした所、動作しました。
https://support.apple.com/kb/DL1572?locale=en_US


追記１（2019/1/19）
####OSへのLogin画面の壁紙が変更できませんでした。
"<A href="https://www.google.com/search?q=mac+os+login+wall+paper+login+how+to+change&oq=mac+os+login+wall+paper+login+how+to+change&aqs=chrome..69i57.5131j0j8&sourceid=chrome&ie=UTF-8">mac os login wall paper login how to change</A>"でグーグル検索した結果です。
Sierraでの手順は記載があり、mackeeperブログへのリンクもありますが、
com.apple.desktop.admin.pngを/Library/Cachesへコピーして再起動後、
反映確認も、変更されませんでした。
Railsのselect_tagを使う

##select_tag

自分で忘れないよう備忘録として残します。

    <%= select_tag('select_name',options_for_select((2000..2030),class:'option',selected: '2018'))%> 

###できるもの

<img width="384" alt="スクリーンショット 2018-10-11 13.42.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/195314/e89a1681-2d66-c652-d86a-23b1dd68155d.png">
GitHubのソースコードリンクを簡潔にする

ディスカッションの中でOSSのコードをポイントする必要があるとき、GitHubのソースコードページURLを示したりします。
GitHub上のソースは書き換わってしまうかもしれないのでコミットID指定でのURLでないといけません。
すると次のようなURLになります。

https://github.com/increments/kobito.qiita.com/blob/fcd1ca1ae90eb3efb12cc83c2991d353261f8e63/LICENSE.txt#L1

長いURLを折りたたみ表示してくれない環境だと少々邪魔な長さになります。
タグの付いたコミットならIDでなくタグ名を使ったURLにできるので簡潔になるのですが。

しかしここで、gitのコミットIDは前方一致で判定されるので先頭から最低4文字あれば意味をなすという性質がこのURLにも効きます。
つまり、コミットIDを先頭4文字だけにしたこのURLも同じソースコード。

https://github.com/increments/kobito.qiita.com/blob/fcd1/LICENSE.txt#L1
最近のSteamVRにおけるViveTracker挙動が変な理由と対処法(1538437695)

10/4のSteamVR 安定版アップデート(1538437695)でViveTrackerのデフォルト挙動が変わりました。

はるか昔にリリースされたSteamVR対応のガンシューティングを、手持ちのhyper-blasterをつけたViveTrackerで遊ぶことが出来るようになる。
という代わりに、VRChatやVTuber、あるいはIKinema OrionでVive Trackerを使っていた人はSteamVR上で設定変更しないとViveTrackerの挙動が変になった！と困ることになります。それの説明をします。（以下のURLの適当訳です）

Recent Vive Tracker Changes in SteamVR

https://steamcommunity.com/games/250820/announcements/detail/1697186829260359619

デフォルト挙動を変えた理由はViveTracker対応ゲームを増やす為です。

StemaVR対応ゲームは大きく分けて以下の３パターンに分けられます。

1. 体のトラッキング用(VRChatやIsland359など)
2. 専用コントローラに取り付けて遊ぶ(Arizona Sunshine など。こういうコントローラやラケット型のコントローラにVive Trackerを取り付ける https://www.ask-corp.jp/products/hyperkin/vr-accessories/hyper-blaster-for-vive-tracker.html )
3. Tracker非対応（ほとんどのSteam VRゲームはこれ)

今回のアップデートでSteamVR Inputという仕組みによって「ユーザの手に持っているデバイス」というパラメータを用意しました。普段はViveコントローラがこの役目を持ち、3においては振る舞いが変わることはありません。

10/4のアップデートで何がしたかったかというと、ViveTrackeのデフォルトの挙動を1を想定した位置と姿勢だけを出力する物から2,3を想定した（Viveコントローラの代わりに使う）ようにしました。

ユーザは従来挙動に戻すことも出来ます。 VRChatユーザなどでトラッカー挙動を直したい場合は
SteamVRの「Manage Vive Trackers」から**全てのvive tracker設定をdisable** にしてください。するとすべてのSteamVRを利用したアプリ内でのViveTrackerの挙動が今までの通りになります。


これだけを聞くとVRChatユーザにとっては「なんでこんな不便な変更になったの！！」と思われるかもしれませんが、ガンコントローラを買ったユーザが、ガンコントローラ非対応SteamVRゲームをガンコントローラで遊ぶ事が（ゲームのアップデート無しで）行えるようになります。

# IKinema Orionユーザの人へ

上記のようにVive trackerのRoleをdisableにしたらIKinema Orion上のVive Tracker挙動も元に戻りました！やりましたね！！！
![image (1).png](https://qiita-image-store.s3.amazonaws.com/0/40627/87290dd4-ef31-8865-438f-4fbfd22bc62d.png)

何もしないとこんな感じでした

https://twitter.com/shop_0761/status/1049861893958094848

# ViveTrackerを6個以上使う人へ
なんと現在はHMD上の設定画面ではVive Trackerを6個以上繋いでいるとレイアウトが崩れて変更できないTrackerが出てきます。
 **一旦Trackerのペアリング数を3個以下にして、順番に設定していきましょう** もしくはブラウザ上から設定しましょう。
AWS EC2 Lambda CodeBuild Fargate の料金

「ちょっとしたバッチ」的なのを実行したい場合に、料金が何がオトクそうなのか、AWSのいくつかのサービスを均してみた。lambda は CPU 1って書いたけど「メモリに正比例」とのこと。ec2の強いのは除く。ec2はオンデマンド。リージョンはオハイオ。通信量とかその他の料金は考慮していない。fargate はメモリもCPUも自由に設定できるけどいくつを。lambdaもメモリもっと選べる。

| インスタンスタイプ | メモリ (GB) | vCPU | 1 分あたりの料金 (USD) |
|:--|--:|--:|--:|
| t3.nano | 2 | 0.5 | 0.000087 |
| lambda(128M) | 0.1 | 1 | 0.000125 |
| t3.micro | 2 | 1 | 0.000173 |
| t3.small | 2 | 2 | 0.000347 |
| lambda(512M) | 0.5 | 1 | 0.000500 |
| lambda(1024M) | 1 | 1 | 0.001000 |
| fargate | 1 | 1 | 0.001055 |
| c5.large | 2 | 4 | 0.001417 |
| m5.large | 2 | 8 | 0.001600 |
| lambda(2048M) | 2 | 1 | 0.002000 |
| fargate | 2 | 2 | 0.002110 |
| fargate | 3 | 2 | 0.002322 |
| t3.xlarge | 4 | 16 | 0.002773 |
| c5.xlarge | 4 | 8 | 0.002833 |
| lambda(3008M) | 3 | 1 | 0.002938 |
| m5.xlarge | 4 | 16 | 0.003200 |
| fargate | 2 | 4 | 0.003797 |
| fargate | 7 | 4 | 0.004855 |
| build.general1.small | 3 | 2 | 0.005000 |
| t3.2xlarge | 8 | 32 | 0.005547 |
| c5.2xlarge | 8 | 16 | 0.005667 |
| m5.2xlarge | 8 | 32 | 0.006400 |
| fargate | 15 | 8 | 0.009922 |
| build.general1.medium | 7 | 4 | 0.010000 |
| build.general1.large | 15 | 8 | 0.020000 |

codebuild 便利だけど高いな
PowerShellでChatworkにファイルをPOSTする

http://developer.chatwork.com/ja/endpoint_rooms.html#POST-rooms-room_id-files
このAPIを使って単にmultipart/form-dataでpostするだけ！
と思いきや成功が返ってくるのにアップロードされなかったので四苦八苦。
Content-Dispositionの内容やmessageにContent-Typeがあるとアップロードされないようです。

# Invoke-RestMethod版
リクエストボディを気合いで作ります。一時的にファイルに書き出して使います。

```powershell
# params
$filePath = "your/file/path.hoge"
$message = 'メッセージです'
$roomId = 'your chatwork room id'
$token = 'your chatwork token'


# body
$fileName = [System.IO.Path]::GetFileName($filePath)
$UTF8woBOM = New-Object "System.Text.UTF8Encoding" -ArgumentList @($false)
$boundary = '--------------------------n4nd3m011k3d0y0'
$tempFile = './tempfile'
$sw = New-Object System.IO.StreamWriter($tempFile, $false, $UTF8woBOM)
$sw.Write("$boundary`nContent-Disposition: form-data; name=`"message`"`n`n$message`n$boundary`nContent-Disposition: form-data; name=`"file`"; filename=`"$fileName`"`n`n")
$sw.Close()
$fs = New-Object System.IO.FileStream($tempFile, [System.IO.FileMode]::Append)
$bw = New-Object System.IO.BinaryWriter($fs)
$fileBinary = [System.IO.File]::ReadAllBytes($filePath)
$bw.Write($fileBinary)
$bw.Close()
$sw = New-Object System.IO.StreamWriter($tempFile, $true, $UTF8woBOM)
$sw.Write("`n$boundary--`n")
$sw.Close()

# post
Invoke-RestMethod -Method POST -Uri "https://api.chatwork.com/v2/rooms/$roomId/files" -Headers @{"X-ChatWorkToken" = $token} -ContentType "multipart/form-data; boundary=$boundary" -InFile $tempFile

```

# HttpClient版
比較的スマート。日本語ファイル名は文字化けしてしまうのですがどうしても解決せず…。

```powershell
# params
$filePath = "your/file/path.hoge"
$message = 'メッセージです'
$roomId = 'your chatwork room id'
$token = 'your chatwork token'


#
Add-Type -AssemblyName 'System.Net.Http'
$content = New-Object System.Net.Http.MultipartFormDataContent

# file
$fileStream = [System.IO.File]::OpenRead($filePath)
$fileContent = New-Object System.Net.Http.StreamContent($fileStream)
$fileName = [System.IO.Path]::GetFileName($filePath)

$fileContent.Headers.Add('Content-Disposition', "form-data; name=`"file`"; filename=`"$fileName`"");
$content.Add($fileContent)

# message
$StringContent = New-Object System.Net.Http.StringContent($message)
$StringContent.Headers.Add('Content-Disposition', 'form-data; name="message"');
$StringContent.Headers.Remove('Content-Type');
$content.Add($StringContent)

echo $content.ReadAsStringAsync()

# header
$content.Headers.Add('X-ChatWorkToken', $token)

# post
$url = "https://api.chatwork.com/v2/rooms/$roomId/files"
$client = New-Object System.Net.Http.HttpClient
$result = $client.PostAsync($url, $content).Result
$result.EnsureSuccessStatusCode()
echo $result.Content.ReadAsStringAsync()
```

参考：
https://sue445.hatenablog.com/entry/2018/08/02/111403
https://stackoverflow.com/questions/22491129/how-to-send-multipart-form-data-with-powershell-invoke-restmethod
https://get-powershellblog.blogspot.com/2017/09/multipartform-data-support-for-invoke.html
https://qiita.com/sin_tanaka/items/d57ea67351efc1994c48
https://ufcpp.net/study/csharp/lib_file.html
https://blog.shibata.tech/entry/2016/10/02/154329
Linux Mint19でラズパイにSSH接続してGUI操作するまで

# ラズパイでSSHの許可をしておく
これはモニタありの初期設定していた時に済ましておいたので、各自で許可をお願いします

# Linux Mint19での設定
まずラズパイのIPアドレスを把握していないと行けないので、固定していないのであれば調べるためのパッケージをインストールします。
`sudo apt install -y arp-scan`
インストールが終わりましたら`sudo arp-scan -l --interface enp0s25`を実行
(**enp0s25**の部分はLinux Mintで接続しているインターフェース名を入力してください)
![arp.png](https://qiita-image-store.s3.amazonaws.com/0/230050/04423e79-71a8-82d5-be80-5962c38e004d.png)

上画像のようにarp-scanを実行し、ラズパイのIPを見つけることができましたらIPアドレスをメモるかコピーしておいてください。
続いて、ssh接続しGUI操作するための設定をします。
`sudo vim /etc/ssh/ssh_config`を実行し**# ForwardX11 no**のコメントを外し、yesに変更します。
![ssh_config.png](https://qiita-image-store.s3.amazonaws.com/0/230050/3da2ba76-e841-7926-53d0-9c8f3b91a636.png)
上画像では念の為`ForwardX11Trusted yes`のコメントも外しています

# SSH接続してGUI操作
上記手順でラズパイのIPアドレスの特定＆Linux Mintの設定が完了しましたらSSH接続に入ります。
`ssh -X pi@192.168.0.3(ラズパイのIPアドレスを入力)`
上記コマンドを実行するとパスワードが聞かれるので各々で設定したパスワードを入力してください。
設定せず初期のままであれば、パスワードは*raspberry*です。
![ssh_pi.png](https://qiita-image-store.s3.amazonaws.com/0/230050/55ccf929-41c4-6211-738f-b9c4c4cdf5db.png)
接続に成功すると上画像のような画面になり、shellコマンド待機になるかと思います。
`export DISPLAY=Linux Mint19のIPアドレス:0.0`を打ち込み、環境変数を設定しておきます。
同ターミナル上で`chromium-browser`と打ち込むと、Linux Mint側でChromiumが立ち上がれればSSH接続からのGUI操作が完了となります。

メモ感覚でなぐり書きですので、誤字脱字・ご表記など多々あるかと思いますが、コメント頂けると幸いです。
Webサーバーについてまとめ

#Webサーバーとは
- クライアントのWebブラウザ等とHTTP通信規格にしたがって、データの受け渡しを行う役割を果たすPCのこと。
- HTTP通信については、後述

##Webサーバーソフトウェアの種類

| No.|Webサーバーソフトウェア名 |概要|主な言語|
|-----------------:|:------------------|:------------------------|:------------------------|
|1|Apache HTTP Server|・世界中で最も使用されているソフトウェア。<br>・Apacheライセンスというオープンソースのソフトウェア。MPM（マルチ プロセッシング モジュール）の仕組みを持っている為、複数OSをサポートできる。<br>・Unix系では、3つのMPM（prefork、worker、event）を利用できる為、プロセス・スレッドの挙動を切り分けることが可能。|PHPなど|
|2|IIS（Internet Information Services）|・Microsoft 謹製のソフトウェア。Windows標準。<br>・Webサーバーの機能以外に、FTP、SMTP、NNTPの機能をサポート。<br>・2018年10月時点の最新バージョンはIIS 10.0である。(Windows 10 と Windows Server 2016 に付属)|ASP.NET|
|3|nginx|・エンジンエックスと読む。<br>・BSDライクライセンス（「無保証」であることの明記と著作権およびライセンス条文自身の表示を再頒布の条件とする。）<br>・HTTP, HTTPS, SMTP, POP3, IMAPのリバースプロキシ、ロードバランサ、HTTPキャッシュ、ウェブアプリケーション用インターフェース（FastCGI, uWSGI, Phusion Passengerなど）などの機能を持つ<br>・静的コンテンツの処理が高速。<br>・リバースプロキシの機能を持つため、背後にWebアプリケーションサーバを配置して動的なコンテンツを配信したり、ソフトウェアロードバランサやHTTPキャッシュとしても使うこともできる。<br>・Apache HTTP Serverがリクエストの処理にデフォルトでスレッドやプロセス指向のアプローチを用いている一方で、nginxは非同期のイベント駆動アプローチを用いている。<br>・イベント駆動によるアプローチは、高負荷下において、より予測可能なパフォーマンスを提供すると考えられている|PHPなど|

##Webアプリケーションサーバーとの違い
- Webサーバーの挙動
	- 受け取ったリクエストに応じて、Webアプリケーションサーバーに対して処理を依頼して、処理結果を受け取ります。その結果をクライアント側にレスポンスとして返します。
- Webアプリケーションサーバーの挙動
	- Webサーバーから依頼された処理をPHP、Javaなどのプログラム言語で実施、処理結果をWebサーバーに返します。
- Webサーバーは、リクエストに対して、実処理を行わない。WebアプリケーションサーバーはWebサーバーの依頼を受けて、実処理を行い、結果を返す。
- レストランで例えるのであれば、
	- 客（クライアント）がウェイター（Webサーバー）に「オムライスが欲しい」という注文（リクエスト）を投げる
	- ウェイター（Webサーバー）が厨房の調理師（Webアプリケーションサーバー）に「オムライスを料理して欲しい」という依頼を投げる
	- 厨房の調理師（Webアプリケーションサーバー）がオムライスを料理して、ウェイター（Webサーバー）に渡す
	- ウェイター（Webサーバー）が客（クライアント）にオムライスを提供する（レスポンス）

- ちなみにWebアプリケーションサーバーのソフトとして以下が有る。
	- Tomcat：Java
	- GlassFish：Java
	- IIS（Webアプリケーションサーバーとしての機能も持つ）:C#、VB.NETなど
	- Unicorn：RoR
	- Puma：RoR
	
##HTTP通信とは 
- クライアントはWebサーバーに対して要求（HTTPリクエスト）を送る。Webサーバーは要求（HTTPリクエスト）に対する応答（HTTPレスポンス）を返す。
- クライアントは受け取った応答をWebブラウザ等に表示する。
- 例：クライアントがWebブラウザ等で右記のページを表示するとき：  http://www.hoge.co.jp/foo.html
	- 要求（クライアント→Webサーバー「hoge.co.jp」）
		- 「foo.html」のページのデータを送って欲しい
	- 応答（Webサーバー「hoge.co.jp」→クライアント）
		- 「foo.html」のページのデータを送る
JavaScriptやCSSを修正時に確実にブラウザキャッシュを更新させる方法

JavaScriptやCSSを修正したのにブラウザのキャッシュに残っていて、サービスが正常に動かないということがありますよね。お客さんに「多分ブラウザキャッシュの効きすぎで〜」とか言い訳したり、「すみません、スーパーリロードしてください」とか案内したくないわけですが、ブラウザも速度のベンチマークを上げるためにゴリゴリとキャッシュを使ってくるので、ファイルを修正したらしっかりとキャッシュ更新してくれるようにしましょう。

##もはやパラメータ付与だけでは更新してくれないことも

少し前までは、JavaScriptやCSSのパスの最後にGETパラメータで更新日付などを入れておけば、ブラウザキャッシュが更新されていたのですが、ここ１年ぐらい前から、Chromeでパラメータを更新しても同じものとみなしてキャッシュが更新されないことがあります。


##これまでのパラメータによる対応

対象となるJSやCSSのファイルの最終更新日時を使ってパラメータを付与していたが、これではもうダメだ。。

####PHPでの実装例

```php:
<link href="/css/common.css?<?=filemtime("./css/common.css")?>" rel="stylesheet" type="text/css" />
```

##絶対更新させる対応

ページ上のファイル名自体にファイルの更新日時をつけることで全く別のファイルとしてアクセスをさせるようにします。
（common.css  を common_[filemtime].css でアクセスさせる。）
もちろん、ファイル名自体をそのようにつけるのではなく、以下の例ではcommon.cssという名前のままで、サーバにアップします。
PHP単体での対応ではなくなりますが、以下のようにApacheならmod_rewriteなども使って確実に更新しましょう。

####PHPでの実装例

```php:
<link href="/css/common_<?=filemtime("./css/common.css")?>.css" rel="stylesheet" type="text/css" id="common_css" />
```

（ページの階層がまちまちの場合は、パスの書き方は注意しましょう。）


####Apache conf例

```Apache:
<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteRule ^\/css\/([a-z_\.0-9]+)_([0-9]+)\.css$  /css/$1.css?$2 [NC]
</IfModule>
```

##他の方法は無いかな？
都度都度、filemtimeやRewriteが走るので、サーバの負荷的にはあまり優しくないので（いうほどのコストでもないですが）、他の方法も考えてみました。

１．サーバデプロイ時にファイル名自体を設定ファイルで指定した更新日時に変更してアップする
２．サーバデプロイ時にシンボリックリンクを貼る

ちらっとQiitaのHTMLを見た感じだと、更新日時ではなくMD5値を使ってるようですね。
アクセスのたびに都度都度MD5取るのはかなりコスト掛かるでしょうから、おそらくデプロイ、ビルド時に自動的にパスを変換しているんじゃないかなと。
ProgateでSQLを学習してみた！

#ProgateさんでSQLを学習してみた！
今回はSQLにチャレンジしました( ｀ー´)ノ

SQLはEXCELのVBAでデータを取得するのに使ってたので
まっさらの初心者、というわけではないのですが
独学だと自分のスキルがどの位かわかりにくいので復習の意味も込めチャレンジ！

今回学んだことは
**・WHEREで条件設定する（レッスン1）**
**・比較演算子、LIKE、NOT、NULL・IS　NOT　NULL,AND・OR（レッスン1）**
**・ORDER BY、LIMITで加工（レッスン1）**
**・DISTINCT、四則演算（レッスン2）**
**・集計関数（SUM、AVG、COUNT,MAX・MIN）（レッスン2）**
**・グループ化（GROUP BY、HAVING)　（レッスン2）**
**・サブクエリ（レッスン3）**
**・複数テーブルの使用（JOIN、LEFT JOIN）（レッスン3）**

分かってるつもりでも、「そうだったのか！」と
腑に落ちることが多かったです

##WHEREで条件設定する（レッスン1）
基本の部分で「SELECT　* FROM table WHERE 条件」
この文法をまずは習得します　ここは問題なし!(^^)!

##比較演算子、LIKE、NOT、NULL・IS　NOT　NULL,AND・OR（レッスン1）
ここも使用頻度が高い文法
私の中では「NULLはオブジェクトに近い存在（？）なのでISが必要」
こんな納得の仕方でとりあえずクリア

##ORDER BY、LIMITで加工（レッスン1）
「ORDER BY」もDESC、ASCともによく使うので問題なし( ^^) _U~~

**だが、しかし！**
「LIMIT」は使ったことが無かったです(ノД`)・゜・。
「そんな！必要な個数だけデータが取得できる．．．だと？」
なかなかの衝撃・・調子にのってたとこを引きずり降ろされました

```sql
SELECT *
FROM purchases
WHERE character = "わんこ"
LIMIT 10;←　結果の上位10件のみ表示される
```

知識が一つ増えました！Progateさん、ありがとう！

##DISTINCT、四則演算（レッスン2）
これも比較的使っていたのでクリア！( ｀ー´)ノ

そもそもACCESSのクエリでイメージがつかめなかったので
ゴリゴリSQLで解析してたのが、功を奏した（笑）
ただしDISTINCTの対象として複数カラムが使えるかは自信が無いです．．．

##集計関数（SUM、AVG、COUNT、MAX・MIN）（レッスン2）
ここでは「基本構文＋集計関数」という内容ですが
今さらですが「WHERE条件をつけた場合、WHEREが先に実行され、
その結果に対して集計が行われる」

```sql
SELECT SUM(price)
FROM purchases
WHERE character="AAA";　←　ここで絞られたデータを集計する
```

漠然と理解してたつもりでしたが、文字に起こすと理解が深まる気がしました！
Progateさんの解説はすごくわかりやすいです（絶賛！）
vueとfirebaseとローディング画面

# 事の発端

## できたこと
vueとfirebaseをつなげ、googleアカウントからSignInするところまではできた

## 問題
**SignInする前のページ**と**した後のページ**で見せる画面が違うため、リダイレクトさせているけど
SignInする前のページがちょっとだけ見えちゃって**ローディング画面**を置きたかった。

# 解決策

## 説明
- 親コンポーネントのdataにローディング画面のフラグを置く
- `beforeCreate`で`firebase.auth().onAuthStateChanged`を走らせる間、`data`の値を使い、処理が終わったらフラグを変える

## ファイルの構成
```zsh
src/
├ App.vue
└ components/
  ┗ Editor.vue
  ┗ Home.vue
```

## ソース
```javascript
<template>
  <div id="app">
    <div v-if="!loading">Loading...</div>
    <Home v-if='!isLogin && loading'></Home>
    <Editor v-if='isLogin && loading' :user='userData'></Editor>
  </div>
</template>

<script>
import Editor from './components/Editor.vue'
import Home from './components/Home.vue'
import firebase from 'firebase';

export default {
  name: 'app',
  beforeCreate:function(){
    console.log('beforecreate');
    console.log(this.loading);
    firebase.auth().onAuthStateChanged(user =>{
      if(user){
        this.isLogin=true;
        this.userData=user;
      } else {
        this.isLogin=false;
        this.userData=null;
      }
      this.loading=true;
      console.log('end onAuth');
      console.log(this.loading);
    })
  },
  created:function(){
    console.log('create');
    console.log(this.loading);
  },
  data(){
    return{
      isLogin:false,
      userData:null,
      loading:false,
    }
  },
  mounted:function(){
    console.log('mounted');
    console.log(this.loading);
  },
  components: {
    'Home':Home,
    'Editor':Editor,
  }
}
</script>

/*以下、styleは略*/
```

## 結果
[ローディング画面](https://gyazo.com/b75b28070cd4af36a07b0cb88cd05347)

# 参考サイト

[Vue + Firebase + Auth Demo](https://gist.github.com/mickaelandrieu/a66bdf031a3c5fa4caf301504f018904)
Laravel 開発環境構築 備忘録2  laravel mixの設定

Laravelに同梱されてるlaravel mixの設定まで。

## まずはVM内で走らせてみる

``` 
vagrant ssh
cd /home/vagrant/code/myproject/
npm install
npm run dev
``` 

コンパイルはOK。

```
npm run watch
```

このままだとエラーを吐く。cross-envが無いらしいのでインストール。

```
npm install --save-dev cross-env
```

そしてwatch。
VM上だとwatch-pollとする必要があるそう。

```
npm run watch-poll
```

成功。VM上なのでブラウザを開かないため、手動で、、
なおbrowsersyncにはポートが必要になる。

```
http://myproject.test:3000/
```

一見成功。
しかし、コンパイルに時間かかる。。。
さらに、viewsの変更には反応しない。。。
これではちょっと使えない。


## VMに入らず、ローカルのディレクトリ上で走らせてみる

node_modulesは再度インストールしなおす

```
exit
cd myproject
rm -R node_modules/
npm install
```

そして実行。

```
npm run watch
```

ちゃんとviesにも反応。
しかも早いくて快適！
UiPath While/Do While ループを抜けるのにbreakは使えない

タイトルのとおりです

自分がはまった点の記録です

[UiPathのActivitiesGuide](https://activities.uipath.com/docs/break)より
>Exits the For Each activity and continues the workflow with the activity that follows it.

For Each アクティビティでしかbreak アクティビティは使えないようです。

## じゃあ、While/Do While ループを抜けるには？
明示的にループ変数をループ条件Falseとなる値に設定するしかないようです。

以上。
GoogleアナリティクスでQiitaをアクセス解析すると同じページでもページタイトルが２種類になる理由

2018.12.10 更新
Qiitaの仕様が変更されたようです（2018.10.30～）
現在はログインしてもしていなくとも、ページタイトルには「- Qiita」が付く仕様に統一されました。

# はじめに
Qiitaの設定画面でGoogleアナリティクス設定をすることで、自分のどのページ（記事）がよく見られているかなど簡単なアクセス解析をGoogleアナリティクスを利用して行うことができます。

さっそく設定してしばらく見ていると、例えば　行動＞サイトコンテンツ＞すべてのページ　でプライマリディメンションを「ページタイトル」とした時に、同じページ（記事）にもかかわらず２行で分かれて表示されることに気付きました。

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/270785/73d812b8-b479-7a7e-2fb6-14824843df27.png)

１つは　記事タイトル　そのまま
もう一つは　記事タイトル - Qiita　というように末尾に「- Qiita」が付きます。

原因がぱっとわからず、いろいろ実際にアクセスして試してみました。

# 結論
Qiitaにログインした状態でアクセスしたか、否かの違いでした。

> １つは　記事タイトル　そのまま

これは、Qiitaにログインせずに記事を閲覧した時のページタイトル

> もう一つは　記事タイトル - Qiita　というように末尾に「- Qiita」が付きます。

これは、Qiitaにログインした状態で記事を閲覧した時のページタイトル

# おわりに
ページのURLだと判別できないですが、ページタイトルでQiitaログイン（≒Qiitaユーザー）の判別ができるようにしているのですね！
Qiitaユーザー以外の一般ユーザーのページビューが意外とあって驚きでした。
【Unity】Unity ARKitSceneのサンプルを動かしてみた

<b><font color="HotPink">環境メモ</font></b>
⭐️Mac OS Mojave バージョン10.14
⭐️Xcode version 10.0(10A255)
⭐️Unity 2018.2.11f1
⭐️iPhone7  IOS11.4.1


<b><font color="HotPink">Unityで「Build And Run」実行後、Xcodeが起動するので設定する</font></b>
![001.png](https://qiita-image-store.s3.amazonaws.com/0/93155/f11375ae-34a5-9b40-5b68-dd28710291ef.png)

<b><font color="HotPink">Unity起動する</b>
<img width="375" alt="IMG_0009.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/672c0d83-2428-7002-183e-721b8d12381a.png">

<b><font color="HotPink">スマホ画面にTapするとCubeが配置される。OK</b>
<img width="375" alt="IMG_0008.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/e8ba3679-ae8a-25b2-a5d6-2d8a28fc1b7d.png">
axiosのリクエストとレスポンスの内容をconsole.logで共通的に出力する方法

主に開発時にaxiosのリクエスト内容、そしてレスポンスの内容を確認したいことがあると思います。

今回はそんなニーズに対し、各タイミングで内容をconsoleに出力する方法を考えていきたいと思いつず。

## 結論: axiosの`interceptors`を利用して出力処理を挟んでおく

```
axios.interceptors.request.use(request => {
  console.log('Starting Request: ', request)
  return request
})

axios.interceptors.response.use(response => {
  console.log('Response: ', response)
  return response
})

axios.get('https://yesno.wtf/api')

// Starting Request: {リクエスト内容} <- consoleに出力される

// Response: {レスポンス内容} <- consoleに出力される
```

上記の処理を記述すると、axiosの各メソッド実行時にRequestとResponseの内容がconsoleに出力されるようになります。

## 考察

responseだけであれば`then()`メソッドの内部でconsole.logを実行すればいいのですが、ロジック部分にconsole.logを書き込むのは煩雑ですし、requestの内容を出力するとなるとやや面倒です。


そのため`interceptor`、つまりrequest実行時とresponse受取時に処理を追加する部分でconsole.logを追加してあげることで実現しています。

## 参考

- [axiosを乗りこなす機能についての知見集]
(https://qiita.com/terrierscript/items/ccb56b6fc05aa7821c42)
- [How to log all axios calls from one place in code
](https://stackoverflow.com/questions/41751235/how-to-log-all-axios-calls-from-one-place-in-code)
バイナリセーフってなんだよ！？

PHPの本を読んでいたらバイナリセーフって単語が出てきてバイナリセーフなんだよ！？ っとなりました。
よくわからないので自分なりに調べてみました。

## バイナリセーフな関数
バイナリデータを正しく扱うことができる関数

## バイナリセーフでない関数
バイナリデータを正しく扱うことができない関数

## そもそもバイナリデータとは？
コンピュータが扱えるよう2進法に則って0と1の羅列(ビット列)として表現されたデータうち、テキスト(文字)形式ではない任意のデータ形式のこと。
※[http://e-words.jp/w/%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA.html より引用](http://e-words.jp/w/%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA.html)

## 結局、気をつけることは何？
バイナリセーフでない関数を使用するとNULLバイト攻撃にあう

## Nullバイト攻撃とは？
nullバイト（「**\0**」、「**\x00**」などの終端文字とされている文字列）を含めることでセキュリティチェックをくぐり抜けてしまう。
ロケールに基づく文字列比較の関数（strcoll、strcmp）を使用して確認してみる。
返り値は[str1 が str2 よりも小さければ < 0 を、str1が str2よりも大きければ > 0 を、 等しければ 0 を返します。 ※strcmpの公式リファレンスより](http://php.net/manual/ja/function.strcmp.php)

**サンプルコード**

```php
<?php

// ロケールを日本語にする
// ※strcollはロケールが C または POSIX の場合、strcmpと等価なのでロケールの設定をする
setlocale (LC_COLLATE, 'ja_JP.UTF-8');

// 現在のロケールを表示する
echo setlocale(LC_ALL, 0) . PHP_EOL . PHP_EOL;

// 比較対象の文字列をセットする
$str1 = 'こんにちわ\x00ゴリラくん';
$str2 = 'こんにちわゴリラくん';

// strcoll ※バイナリセーフでない関数を使用
// 結果として、「2147483647」を返す（str1の方が大きいと判断している）
echo 'strcoll：' . strcoll($str1, $str2);

echo PHP_EOL;

// strcmp ※バイナリセーフな関数を使用
// 結果として、「-1」を返す（str2の方が大きいと判断している）
echo 'strcmp：' . strcmp($str1, $str2);
```

**出力結果**

```shell
LC_COLLATE=ja_JP.UTF-8;LC_CTYPE=Japanese_Japan.932;LC_MONETARY=C;LC_NUMERIC=C;LC_TIME=C

strcoll：2147483647
strcmp：-1
```

strcollの時は「**\x00**」が終末文字として認識されないため、**str1が大きいと判断される**がstrcmpの時は「**\x00**」が終末文字として認識されるため、**str2の方が大きいと判断される**

気をつけないとNULLバイト攻撃された時にプログラムが意図しない挙動をしそうです。

[上記コードはここにあります](https://github.com/dodonki1223/phpTips/blob/master/BinarySafeSample/BinarySafeSample.php)

## 参考サイト
- バイナリセーフについて
    - [In PHP what does it mean by a function being binary-safe? - Stack Overflow](https://stackoverflow.com/questions/3264514/in-php-what-does-it-mean-by-a-function-being-binary-safe)
    - [23. 関数とバイナリセーフ | 日経 xTECH（クロステック）](https://tech.nikkeibp.co.jp/it/article/COLUMN/20070402/267126/)
    - [[PHP]　バイナリデータとは？バイナリセーフではない関数とは？ アニP](http://anipy.blog.fc2.com/blog-entry-7.html)