OmniAICreator/Qiita-1.07M huggingface dataset:
HTMLの超基本！〜初心忘れるべからず。〜

めっきりhamlばかりでフロントを書いておりHTMLで久しく書いていなかったのですが、最近HTMLに触れて復習になったのでここにも書いておこうと思います。

##HTMLとは
HTMLとはウェブページの土台を作るための言語です。表示したい文字や情報をタグで挟むことによりそれを実現していきます。
とまあ簡単に説明しましたがとりあえずはタグではさむことが重要なんだな、くらいで大丈夫だと思います。

###HTMLをブラウザで表示する
```
<!DOCTYPE html>
<html>
<head>
<title>Qiita</title>
</head>
<body>
<h1>HTMLの超基本！</h1>
<p>HTMLとは</p>
</body>
</html>
```
最低限のHTMLの基本形を書いたサンプルコードを用意しました。
実際に手を動かした方が分かりやすいのでこれをブラウザで表示してみます。
(※使用ツールはVSCodeです。)
![スクリーンショット 2020-07-09 1.08.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568349/96bd6673-0710-ecfa-2c09-8514efbc5658.png)
まずはサンプルコードを使用ツールにコピペします。
(※ここで注意点としてはファイル名を必ず○○○.htmlの形式で保存してください。今回はtest.htmlとしています。)
![スクリーンショット 2020-07-09 1.13.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568349/7b7ce614-853f-b324-7926-50b660dda2fd.png)
ブラウザへ行きファイルを開きましょう。
![スクリーンショット 2020-07-09 1.13.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568349/d5cb1acb-240d-cbb7-f75c-4ad1b50b03d8.png)
ブラウザでHTMLが表示されるかと思います。
![スクリーンショット 2020-07-09 1.14.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568349/45ddd319-8f3b-824a-a5df-1d1cbe9c5f10.png)

```
<p>HTMLとは</p>
↓
<p>HTMLをブラウザに表示してみる</p>
```
pタグで挟まれた部分を変更してみます。
![スクリーンショット 2020-07-09 1.14.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568349/b8e7235e-0343-4d48-9166-0214610b16a3.png)
ブラウザに戻りリロードしてみると表示も変わりました。

###HTMLの基本構造
```
<!DOCTYPE html>
```
ファイルの先頭のこれは「このファイルはHTMLの文書です」という宣言の役割を果たします。

```
<head>
<title>Qiita</title>
</head>
```
headタグの中には「ウェブページの情報」を書きます。
例えば「検索エンジンやブラウザがそのページを理解するための情報」「CSSファイルの読み込み設定」などです。
headタグの中身は基本的にはブラウザ上に表示されません。今まで見てきた通り「Qiita」の文字はブラウザ上には表示されていませんね。

```
<body>
<h1>HTMLの超基本！</h1>
<p>HTMLとは</p>
</body>
```
したがってウェブページの画面に表示されるのはbodyタグの中のものだけになります。

###まとめ
headタグの中でウェブページの情報設定をし、bodyタグの中にウェブページの画面に表示したいものを書くというように覚えましょう。
bodyタグで使うタグの種類はたくさんあるのですがそれはまた別の記事にしようと思います。
dumpされた改行テキスト入りのCSV（TSV）ファイルを、Excelでいい感じに並べた話

# 背景
「このダンプファイル見といて」
「あ、ファイルダンプしといたんでいい感じにしといてもらっていいですか」

エンジニアならまあよくある話。しかし。。。

```
これ「テキストの項目に改行入っとるやんけ。。。」
```
って絶望することはままある。

## 絵面で言うとこういう状況
エクセルにCSV（TSV）ファイルとかをインポートしようとして。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/e7135368-ab64-8936-1a66-8975355fe585.png)

見事にこうなる。うえぇぇ。テキスト型のカラムの中に有る改行のせいでガッタガタで一列に収まらん。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/dd920cf0-23a6-da54-0edb-c9c610bf97b2.png)

そんなわけで、多分これからも度々困る自体に備え、備忘を残す次第。あと我ながら職人芸を披露したなと勝手な自己満足を披露したい次第。

# やったこと

## 初手：手当り次第に改行を消す
とりあえず改行があってはにっちもさっちもいかんということで、悪さをする改行を、正しい改行もろとも消す。
といってもただ消したら復活ができないので、あとで戻せるよう`[[br]]`みたいな適当な記号に置換しておく。

サクラエディタを使うとこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/a53c2b83-7ae6-08e3-ef26-acf3403484e8.png)

結果はこんな感じになる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/f21e24ef-ed40-b01d-8b9d-5e8d61fc57da.png)

## 2手目：行頭1項目目であるはずの箇所を正規表現で気合で抜き出す
テキストファイルは全ての改行が[[br]]で置換されて1行のテキストファイルに。これを改めて、1レコード1行の形式に直すため、行頭1項目目に相当する箇所を正規表現で抜き出す。ここはちょっと腕の見せ所。幸い今回は、行頭1項目目は「14桁の整数」出会ったことが判明したのでそのように正規表現を使う。

（手前の元々改行だった[[br]]）＋（15桁の整数）をサクラエディタで置換するとこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/943d6529-439d-5bf1-d1e0-d6e09c08ee04.png)

さすれば無事に１レコード１行のファイルが完成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/da48a821-2af2-0b8d-340a-820b357cfaf7.png)

## 3手目：エクセルにインポート
こうなってしまえばエクセルにインポートするのも容易いこと。おおお、冒頭の絶望が嘘のようだ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/e3ee1e60-7697-c4a6-3332-7d8e381542c4.png)

エクセルのインポート結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/012c364a-d710-7440-d79c-c9e4ece7ee0a.png)

## 最終手：セル内の改行もどきをちゃんとした改行に戻す
これもちょっと癖のあるテクニックなので覚えておきたいところ。エクセルは「Ctrl+J」でセル内の改行を生み出せるという謎の呪文がある。
これで改行もどき[[br]]を置換する。さらば。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/bcde40ff-f44d-08af-8ff2-27f5ad3ea1de.png)

置換結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/43a1a2a9-b56e-734a-3867-330cbf328125.png)

できたーーーーーーーーーーーーーーーーーー。くーーーーーーーーーーーーーーーーー。

# おしまい

こうした日常に潜む、エンジニアの苦悩を襲うタスクを抹殺していきたい。
UiPath：本日の半期、四半期を得る方法

## 皆もすなるQiitaといふものを、儂もしてみむとてするなり。

と言う訳で、こん＊＊は！はなっち！です。

DateTime型ってのは、単に日付とか日時を格納して、.ToString辺りで文字列化して、ファイル名の一部にしてみたりって位しか使っていなかったんですが、業務要件によっては「**年度**のフォルダの中にファイルがあるんだよね」なんて言われてしまって。。。

ってのは、[UiPath：本日の年度を得る方法](https://qiita.com/HANACCHI/items/1910825a0fda31976c81)で書いたネタ。

####今回は、「半期毎でフォルダを分けているんだよね」「うちは四半期毎でまとめているんですよ」なんて言う場合に使うロジックのお話。

**年度**を求めるのには、.AddMonths(-3).Yearを使用すればいい。その際に月と言うのは、.Monthと言うメソッドがあるので、簡単に取得できる。
月が得られるって事は、その値が１～６だったら**上半期(1H)**、７～１２だったら**下半期(2H)**。更に言うと、その値が１～３だったら**第1四半期(1Q)**、４～６だったら**第2四半期(2Q)**、７～９だったら**第3四半期(3Q)**、１０～１２だったら**第4四半期(4Q)**、になる訳で。

|日付|年度|月|半期|四半期|月 / 3|
|:-------|:--:|:--:|:--:|:--:|----:|
|2020/03/01|2019|12|2|4|4
|**2020/04/01**|**2020**|**1**|**1**|**1**|0.333333333333333
|2020/05/01|2020|2|1|1|0.666666666666667
|2020/06/01|2020|3|1|1|1
|**2020/07/01**|**2020**|**4**|1|**2**|1.333333333333333
|2020/08/01|2020|5|1|2|1.666666666666667
|2020/09/01|2020|6|1|2|2
|**2020/10/01**|**2020**|**7**|**2**|**3**|2.333333333333333
|2020/11/01|2020|8|2|3|2.666666666666667
|2020/12/01|2020|9|2|3|3
|**2021/01/01**|**2020**|**10**|2|**4**|3.333333333333333
|2021/02/01|2020|11|2|4|3.666666666666667
|2021/03/01|2020|12|2|4|4
|2021/04/01|2021|1|1|1|0.333333333333333

こんな感じ。

さて半期ルール（１～６を１、７～１２を２にする）を求めるには、6で割ってやればよく、四半期だとしたら3で割ってやればよい。
ただ、小数点以下の値が出てきてしまうので、そこんとこを上手い事やらなければならない！

そんな時、役に立つのが**「三角関数や対数関数などの一般的な数値関数の定数と静的メソッドを提供する」Math クラス**ですね。
Mathクラスには、数学的な関数群を保有していて、今回は、**「指定した数以上の数のうち、最小の整数値を返す」.Ceiling メソッド**を使用します。

Math.Ceiling(0.666666666666667)は、「0.666666666666667」より以上の、最小の整数値を返すので、「1」となりますね。
Math.Ceiling(2)は、「2」より以上の、最小の整数値を返すので、「2」となりますね。

※参考：似たような関数で、**「指定した数以下の数のうち、最大の整数値を返す」Floor **メソッドがあります。
※シーリングファン（天井に取り付ける扇風機）の「Ceiling」ですね。フロアランプ（床置きのランプ）の「Floor」ですね。

という訳で、半期を得るには、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/2c5d0267-2420-1cd1-0786-27aee60d393b.png)
左辺：半期（Int32)
**右辺：CType(Math.Ceiling(計算日付.AddMonths(-3).month / 6), Int32)**

四半期を得るには、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/fb098852-dc5d-cedf-5f14-386dfb5c6d99.png)
左辺：四半期（Int32)
**右辺：CType(Math.Ceiling(計算日付.AddMonths(-3).month / 3), Int32)**

##おわりに
いかがでした？
DateTime型はExcelシート上の日付でフィルタリング範囲に使ってみたり、先の例のように業務で管理単位とするなど、様々なシーンで扱うことが多い**型**です。是非UiAthでのロボ開発の一助になればと思っています。

ありがとうございました！
Eclipse のプラグインアップデートサイトをミラーする方法

逐次、補強予定 :sweat_smile: 

# Metadata の取得

```
 eclipse -nosplash -verbose
 -application org.eclipse.equinox.p2.metadata.repository.mirrorApplication
 -source ミラー元URL (例: http://download.eclipse.org/releases/2020-06)
 -destination ミラー先URL (例: file:/tmp/2020-06-Mirror/)
```

# Artifacts の取得

```
 eclipse -nosplash -verbose
 -application org.eclipse.equinox.p2.artifact.repository.mirrorApplication
 -source ミラー元URL (例: http://download.eclipse.org/releases/2020-06)
 -destination ミラー先URL (例: file:/tmp/2020-06-Mirror/)
```

# 参考文献

- [Equinox p2 Repository Mirroring - Eclipsepedia](https://wiki.eclipse.org/Equinox_p2_Repository_Mirroring)
- [plugins - Downloading Eclipse plug-in update sites for offline installation - Stack Overflow](https://stackoverflow.com/questions/1371176/downloading-eclipse-plug-in-update-sites-for-offline-installation)

# おまけ

コマンドラインでプラグインをインストールする方法。

- [Equinox p2 director application/Examples/Install into dropins - Eclipsepedia](https://wiki.eclipse.org/Equinox_p2_director_application/Examples/Install_into_dropins)
- [Installing Eclipse features via the command line with the p2 director | vogella blog](http://blog.vogella.com/2012/04/04/installing-eclipse-features-via-the-command-line-with-the-p2-director/)
- [Installing eclipse plugins via command-line - Techscape](https://blog.ramdoot.in/installing-eclipse-plugins-via-command-line-20c2fbbde843)
ローランドの名言をコールバック関数を使って出力してみる

Javascriptにおいて
関数を変数として扱う場合も多いらしいので、
いろんな方法でローランドの発言を出力してみる。

## 通常

```js
console.log('俺か、俺以外か');
```


## 関数

```js
function roland(){
  console.log('俺か,俺以外か');
}

roland();
```

## コールバック関数（変数代入）

```js
function roland(callback) {
  console.log(callback());
}

const remark = function() {
  return '俺か俺以外か';
}

roland(remark);
```

`console.log(callback());`
は関数の実行結果が返ってくる

`console.log(callback);`
は関数自体が返ってくる

## コールバック関数（無名関数）

```js
function roland(callback) {
  console.log(callback());
}

roland( function() {
  return '俺か、俺以外か';
})
```

## コールバック関数（文字列結合）

```js
function roland(me, otherThanThat) {
  console.log(me(otherThanThat))
}

roland( function(otherThanThat) {
  return '俺か' + otherThanThat;
}, '俺以外か');
```

ここ一番ややこしい。。


## コールバック関数(演算)

```js
function roland(a, b, callback) {
  const result = callback(a, b);
  console.log(result);
}

function remark(a, b) {
  return a + b;
}

roland('俺か', '俺以外か', remark);
```
ReactotronをAndroid Emulatorに繋ぐ

## 前提
- Expo SDK37.0
- Reactotron Version 2.17.1 

## 問題
- ReactotronがAndoidのEmulatorに繋がらない

## 方法
```.bash
adb reverse tcp:9090 tcp:9090
# 確認
adb reverse --list
```


## 参考文献
- https://github.com/infinitered/reactotron/issues/162#issuecomment-365585508
Rails6のAPI使用でCookieを有効にする

## 概要
RailsでAPIを使用するときに、セッション等でCookieを使いたくなる時があると思います。調べるとけっこう記事が出てくると思いますが、何種類か対応方法があるみたいで、今回はRails6でも上手くいった方法を書きます。

## 対応
### 【application_controller.rbの設定】
* `ActionController::Cookies`を読み込みます。記事は[rails-apiでcookieを使う](https://pocke.hatenablog.com/entry/2016/06/23/193232)を参考にしました。


＜＜2020/7/31追記＞＞`ActionController::Base`を継承する時のみ以下を設定してください、`ActionController::API`を継承するときは不要です。

* CSRFトークンチェックを回避したい場合は`skip_before_action :verify_authenticity_token`で回避してください。`protect_from_forgery with: :null_session`だとCookieが使えなくなります。なお、[[Rails] CSRFトークンチェックでエラーになるのを回避する方法](https://qiita.com/jshimazu/items/d3ba24aed445d3b0a7cf)を参考にしています。

```application_controller.rb

class ApplicationController < ActionController::Base
  include ActionController::Cookies

  skip_before_action :verify_authenticity_token

end

```

### 【application.rb】
* 今回は`config.api_only`設定はtrueを前提とします。falseにするとCookieは使えるようになりますが、API利用前提とは少し外れるので。
* `ActionDispatch::Cookies`と`ActionDispatch::Session::CookieStore`を使用します。[Rails の API モードでセッションを有効にする](https://daido.hatenablog.jp/entry/2020/05/06/143145)を参考にしました。私の環境だと`ActionDispatch::ContentSecurityPolicy::Middleware`を使わなくてもCookie使えましたが、環境によっては使う必要があるのかもです。

```application.rb
# requireの設定は記載省略しています
module WebApi
  class Application < Rails::Application
    config.load_defaults 6.0

    config.api_only = true
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore
  end
end

```
SSHログイン時の "Activate the web console with: XXX" を消す方法

CentOS8 にSSHログインすると毎回毎回`Activate the web console with: systemctl enable --now cockpit.socket`と表示されてうざい。

# 原因は新機能「ウェブベース管理ツール」

CentOS8 から[Cockpit](https://cockpit-project.org/)というウェブベースの管理コンソールが導入されている。

表示されている`systemctl enable --now cockpit.socket`を叩くことで管理コンソールが使えるようになる。

![alt](https://cockpit-project.org/images/screenshot/overview-f33.webp)


# いらないものは捨てましょう

どうせウェブベースの管理コンソールなんて使わないのでスッキリ削除する

```shell
systemctl stop cockpit
dnf remove -y cockpit
rpm -e cockpit-system
rpm -e cockpit-bridge
rpm -e cockpit-ws
rm -Rf /run/cockpit
rm -Rf /etc/cockpit
rm -Rf /usr/share/cockpit
rm -Rf /var/lib/selinux/targeted/active/modules/100/cockpit
rm -Rf /usr/share/selinux/targeted/default/active/modules/100/cockpit
```

## 参考

[uninstall/remove cockpit · Issue #12507 · cockpit-project/cockpit · GitHub](https://github.com/cockpit-project/cockpit/issues/12507)
iPhoneアプリが待機中のままダウンロードできない 

私のiPhoneXでは、wifiルーターの変更などで新しい
ネットワークに接続した際、iPhoneアプリの
ダウンロードが全く進まないという現象が起きます。

app storeアプリを起動→右上の人のシルエット
一番下までスクロールして「サインアウト」
再びサインインするとダウンロードが進みました。
Carthageで使うXcode・Swiftのバージョンをコントロールする

最近複数の仕事をしていて、Xcodeのバージョンをいくつか使っているんですが
carthageでライブラリーアップデートしてSwiftバージョン違うって言われると辛いですよね
あれめちゃくちゃ長いんですよ
1日溶ける

# 本題

バージョンが合っていないとこういうエラーが出てきます

```
<unknown>:0: error: module compiled with Swift 5.2.4 cannot be imported by the Swift 5.1.2 compiler: /Users/XXXXX/ios/yyyyyy/Carthage/Build/iOS/Hoge.framework/Modules/Hoge.swiftmodule/x86_64-apple-ios-simulator.swiftmodule
```

現在使っているXcodeを確認する

```
xcode-select --print-path
```

変更する

```
sudo xcode-select --switch <path-to-beta-xcode>/Contents/Developer
```

参考
https://stackoverflow.com/questions/37867753/change-carthage-swift-version

# Cocoapodsの場合

環境設定から変更できます

![スクリーンショット 2020-07-09 0.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/015c442e-9b28-e455-4587-e0b00f357007.png)

これcarthageに反映されないんですね。
なぜ import React from 'react' するのか

## なぜReactをimportする必要が？

reactのアプリケーションを書いていると、何も考えずに`import React`しませんか？
僕は何も考えていません。importし忘れたらエラーが出るのでimportしてました。

```react
import React from 'react';
import SomeButton from '~/components/SomeButton';

function RenderButton() {
 return <SomeButton color="blue" />
}
```

上記のコードを見ていただければ分かる通り、`React`なんてどこにも使ってないですよね。
では何故importする必要があるのか。

## JSXはReactのシンタックスシュガー
これが答えでした。

```React
<SomeButton color="blue" />
```
は

```React
React.createElement(
  SomeButton,
  { color: 'blue' }
)
```

のシンタックスシュガーです。
そのため、JSX記法を使う際にはスコープ内にReactが存在する必要があります。

```react
import React from 'react';
import SomeButton from '~/components/someButton';

function RenderButton() {
 return <SomeButton />
 // return React.createElement(SomeButton, { color: 'blue' }) 
}
```

ちなみにwebpackなどでバンドルせず、scriptタグでReactを読み込んでいる場合はグローバルスコープにReactがあるのでimportなどは不要です。
Djangoで既存のモデルに後からDateFieldを用いた項目を追加するときの注意点

#はじめに
開発中、後から既存のモデルに項目を追加する時に少し操作が必要であることを知ったのでその知見についてまとめました。

#既存モデル

まずは簡単のために以下のような単純なモデルがあることを想定します。

```Python
class NameModel(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name
```

ここに`DateField()`を用いた項目を追加することを考えます。

#項目追加

以下のように項目を追加します。

```Python
class NameModel(models.Model):
    name = models.CharField(max_length=50)
    date = models.DateField() #追加

    def __str__(self):
        return self.name
```

モデルを変更したのでマイグレーションします。

```
$ python manage.py makemigrations
```

ここで以下のようなメッセージが表示されます。

```
You are trying to add a non-nullable field 'date' to NameModel without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit, and let me add a default in models.py
Select an option:
```

このメッセージはnullである`date`を追加しようとしているがそれはできず、解決するためには二つの選択肢のいずれかを選べという意味です。

これは元々あったデータを入力するには当然dateという項目は存在せず、よって中身がnullになってしまっていることによってこれが生じています。

2)はモデルを作り直すという選択肢なのでここでは1)を選択することにします。

すると

```
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>> 
```

と表示されます。
これはdateに対して何を入れますか？という意味なので、ここは指示にしたがってtimezone.nowを追加します。

以上で完了です。

またこれは`DateField`の引数に`null=True`を設定することで回避することもできます。

何か不手際がございましたらご指摘よろしくお願いします。
Tableau Desktop・Tableau Online（Server）とSnowflakeにて統合ユーザーIDで利用する方法の紹介

## 注意事項
本情報は、2020年7月8日時点での情報です。
最新情報は、ドキュメントにて確認してください。

## 概要
tableauを利用するときに統合ユーザーでの認証(SSO)が利用できますが、クラウド利用時においては、データソースの現実的な選択肢がsnowflakeのみであることがわかりました。本記事では、Azure ADにて、Snowflake、および、Tableau Onlineに認証する方法をご紹介します。

必要となる手順については、Qiitaに個別の記事として投稿しております。

- [Tableu Onlineに対してAzure ADアカウントによるシングルサインオンの設定](https://qiita.com/manabian/items/661be0326d55533bdb05)
- [Snowflakeに対してAzure ADアカウントによるシングルサインオンの設定](https://qiita.com/manabian/items/1384c43a9398bf325f1d)
- [Snowflakeに対してTableau Desktop・Tableau Online（Server）によるOAuth認証（Azure AD）の設定](https://qiita.com/manabian/items/c17e8690d178806d8df0)


## 統合IDの必要性について
データ活用を推進するためには、データベースへの接続をエンドユーザーに許可することが重要です。ただ、個人単位でのユーザー作成は管理が煩雑となることから、１つのユーザーアカウントを使い回している方も多いのではないでしょうか。Azure ADアカウントを利用すれば、ユーザー個人へのデータベース接続が可能となります。

## Tableau Online（Server）におけるデータソースの制約
Tableauにおいて、ライブ接続する際のTableau Online（Server）がデータソースに対してKerberos認証が基本となってしまうことです。PaaS型データベースではkerberos認証をサポートしていないことが多く、ADサーバーの構築も面倒なことが多いです。

> Viewer (ビューアー) 認証資格情報: ビューアーの認証資格情報は、SSO (通常は Kerberos) を使用してデータベースに渡されます。

引用元：[パブリッシュされたデータにアクセスするための認証資格情報を設定する](https://help.tableau.com/current/pro/desktop/ja-jp/publishing_sharing_authentication.htm)


## Tableauにて統合IDを利用する方法
解決策の１つとしては、Tableau ServerのデータソースとしてOAuth認証が可能なSnowflakeを利用することです。

Google Big Queryも対応可能なようですが、ラムダアーキテクチャにおけるサービスレイヤーとしての同時実行性という観点で懸念があります。Tableauのデータ抽出機能利用時には、最適な選択肢の１つとなりますが、ライブ接続に利用するには難しいと考えてます。


## 導入後のイメージ
### Tableau Desktopでの利用イメージ
Tableau Desktopにて、Snowflake接続する際にAzure ADアカウントを利用できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d6efd05d-cf22-dcea-8405-f8ca59a3f024.png)

### Tableau Onlineでの利用イメージ
Tableau Onlineでも同様に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9de0f056-836e-52b7-fa14-58199d18b9da.png)

Tableasu Desktopからパブリッシュする場合、"認証"にて"ユーザーにメッセージを表示"を選択することで、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/da5dfe5d-bb42-29fe-6a5f-3e3060152ac7.png)

Tableau OnlineにてSnowflakeへの認証確認があり、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c80d1011-5968-e5b7-75f5-e42683ca87e6.png)

認証後にデータを確認できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/77fc53e5-f3e1-7d44-7f84-44e38fabf2a3.png)


### snowflakeでの利用イメージ
Snowflakeへブラウザにて接続する際には、"Log in using AzureAD"を選択すればログインできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a727bfd5-33b0-b05b-1131-ad83e6566bb0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/406351bf-53ab-2fa6-7dd5-6927fe251cb3.png)

### aginity proからの利用イメージ
"CONNECTIONS"を"SAML"にすることでログインできます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/7105148c-a0e4-fda4-ad2c-dce750099613.png)


## まとめ
Tableau Server利用時には、Snowflakeをデータソースとして利用することで、ユーザーIDを利用可能であると説明しました。
データ抽出時にはシングルサイオンにてデータアクセス制御を実施したい場面が多々あるため、他のサービスにも対応していただきたいです。
Snowflakeに対してTableau Desktop・Tableau Online（Server）によるOAuth認証（Azure AD）の設定

## 概要
Snowflakeに対して、Tableau Desktop・Tableau Online（Server）によるAzure ADアカウントによるOAuth認証により接続する方法を紹介します。

## 事前準備
下記記事を参考に、Azure ADアカウントにてSnowflakeへログインできるように設定を実施してください。

[Snowflakeに対してAzure ADアカウントによるシングルサインオンの設定](https://qiita.com/manabian/items/1384c43a9398bf325f1d)

## 手順
### 1.Snowflakeに接続し、accountadminにて下記のSQLを実行します
```sql
--Tableau DesktopからのOAuth認証を許可
use role accountadmin;
create security integration td_oauth_int1
  type = oauth
  enabled = true
  oauth_client = tableau_desktop;

--Tableau Online、および、Tableau ServerからのOAuth認証を許可
use role accountadmin;
create security integration ts_oauth_int1
  type = oauth
  enabled = true
  oauth_client = tableau_server
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/214fd5e3-39e8-afa4-7198-1202063328dd.png)

### 2. Tableau Desktopから接続できることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a594122a-6d26-ad31-b550-cf6063d61e27.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/4ce01430-bb16-8962-7aa8-15e3087945fe.png)

### 3. 2で作成したデータソースをパブリッシュ後、Tableau Onlineから接続できることを確認します。パブリッシュしたアカウントとは、別のアカウントで確認しております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/7f80b4d2-562b-7ce2-13b1-110888954f69.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/16b4777b-3c0d-b15a-cbbb-dfe1c155c6e2.png)

## よくあるエラー
特になし

## 参考リンク
- [パートナーアプリケーション用Snowflake OAuth の構成](https://docs.snowflake.com/ja/user-guide/oauth-partner.html)
文系卒だけどいきなりRuby on Railsの勉強をはじめてみた #7 ユーザー登録

チュートリアルを進めるにあたり、逐次ゴール設定をすると良いのかもしれない。
「今日は◯章の◯までやる」など。

# 7.1 ユーザーを表示する
最初に行ったことは、デバッグ情報を表示させること。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648931/c71a1836-1cbe-a2a3-f58a-b6c2effb6b99.png)

>デバッグとは、コンピュータプログラムに潜む欠陥を探し出して取り除くこと。

次にデータベースに存在するユーザーの情報をshowページに表示させる。
埋め込みRubyを書くことで表示できるというところはなんとなく理解しやすい。
ユーザー情報の他にも現在時刻も表示できたりするっぽい。

# 7.2 ユーザー登録フォーム
この章では、ユーザーを登録するためのページを作成する。
ページにはフォームが埋め込まれており、入力した情報をもとにユーザー情報を作成する。

フォームのベースはHTMLで、埋め込みRubyによって表現されているようだ。

フォームの項目にはタイプがいろいろある。
テキストだと文字通りテキストを入力する。
パスワードという形式にすると、入力した文字が黒塗りされる。（よくみるやつ。）

ここは、「まあフォームについてなんとなく知っといてね〜」くらいの温度感な気がする。

# 7.3 ユーザー登録失敗
ここから少し難易度があがる印象。
フォームで入力された情報をパラメーターを介してコントローラーに渡すということをやっていく。

この章の演習はいまの自分にはむずすぎたのですべて飛ばした。

# 7.4 ユーザー登録成功
この章では実際にフォームを用いて新規ユーザー登録をする。

実際にユーザー登録をやってみたあとに、コンソールで登録したユーザーを検索するとちゃんとデータベースに存在していることを確認した。

# 7.5 プロのデプロイ
SSL対応させようね、という内容の章。
SSLは聞いたことはあるものの、いまいち理解はしていなかったのでこれを機に調べた。

>SSL（Secure Sockets Layer）とは、インターネット上におけるウェブブラウザとウェブサーバ間でのデータの通信を暗号化し、送受信させる仕組みのことです。
インターネット上で頻繁に送受信される氏名・住所・メールアドレスなどの個人情報や、ショッピングの決済に必要なクレジットカード情報、ログインに必要なID・パスワードといった情報は、常に悪意ある第三者から狙われております。
SSLは、これらの重要な情報を、悪意ある第三者による盗聴を防いだり、送信される重要な情報の改ざんを防ぐ役割を持っています。

暗号化してるから安心やってことらしい。
7章、むずかった。
curl でダウンロードしつつ任意の場所にtar展開する

`ruby:2.6.5-slim-stretch` のDockerイメージを使い yarn を入れるのに苦労したので記録を残しておきます。

RUN部分の抜粋。

```
ENV YARN_VERSION=1.22.4
RUN bash -c "curl -sL --compressed https://yarnpkg.com/downloads/${YARN_VERSION}/yarn-v${YARN_VERSION}.tar.gz | tee >(tar zx -C /usr/local/ --strip=1 --wildcards yarn*/bin --no-same-owner --no-same-permissions) | tar zx -C /usr/local/ --strip=1 --wildcards yarn*/lib --no-same-owner --no-same-permissions"
```

３つのコマンドをパイプで連結した文字列を用意して `bash -c "curl..."` で実行するようにしています。

はじめに curl を使って指定されたバージョンの yarn を標準出力に表示します。

```
curl -sL --compressed https://yarnpkg.com/downloads/${YARN_VERSION}/yarn-v${YARN_VERSION}.tar.gz
```


tee を使い出力先を分岐します。 `/usr/local/bin` に tar内の `*/bin` 以下を展開します。

```
| tee >(tar zx -C /usr/local/ --strip=1 --wildcards yarn*/bin --no-same-owner --no-same-permissions)
```

同様に `/usr/local/lib` に tar 内の `*/lib` 以下を展開します。

```
| tar zx -C /usr/local/ --strip=1 --wildcards yarn*/lib --no-same-owner --no-same-permissions
```

`bash -c ""` をしているのは、 ２つ目の `| tee >(tar...)` にてプロセス展開を行うためです。

`docker build` を行う際に `sh` 環境で実行されるので、プロセス展開部分で、 `/bin/sh: 1: Syntax error: "(" unexpected` がでてしばらく悩みました…。
(日記1)Microsoft AzureサービスのSQLデータベースのテーブル作成、参照、データの登録をpythonで行う方法

#前書き
Microsoft AzureのSQLデータベースを使用して学校のプロジェクトを進めたい、
プログラムで、MicrosoftのSQLデータベースにアクセス出来たら、もっと便利だな、
と思い、作成いたしました。

#注意
この記事はMicrosoft Azureサービスで、SQLデータベースを作成していることを前提にしています。
(私は、初期設定はサンプルのデータがあるものにしました)
<img width="871" alt="スクリーンショット 2020-07-08 22.43.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670396/01157c58-ae41-e5c2-9251-75dfd993cf57.png">

#必要なpythonのモジュール
**pydbc** ...pythonのプログラムを使用して、データベースにアクセス出来るモジュール
(pydbcの説明は、あくまでも簡単な説明です。もっと、詳細を知りたい方は申し訳ございませんが、web等で調べてください)

pydbcはMacOSだと、pipで手軽にインストール出来ますが、OSの種類によってインストールの仕方、ドライバファイルの設定の有無に違いがあるので、もっと、詳細を知りたい方は申し訳ございませんが、web等で調べてください。


#サンプルプログラム
**注意 プログラムの中のXXXXを以下の通りにすると、プログラムを実行出来ます。
<img width="1359" alt="スクリーンショット 2020-07-08 23.27.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670396/91629415-6f6c-8cac-f2a2-d99e8555a193.png">
<img width="861" alt="スクリーンショット 2020-07-08 23.28.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670396/da4f4a39-e2e7-b05b-7ed4-6e3cd1f66a09.png">
・XXXXの一番目に、あなたのMicrosoft AzureのSQLデータベースの概要の画面の赤色のところに書かれている文字列を入れる

・XXXXの二番目に、あなたのMicrosoft AzureのSQLデータベースの概要の画面の緑色のところに書かれている文字列を入れる

・XXXXの三番目に、あなたのMicrosoft AzureのSQLデータベースのクエリエディターの画面のログインに入れる文字列を入れる
(データベースを作るときに作成するサーバー管理者ログインのことです)

・XXXXの四番目に、あなたのMicrosoft AzureのSQLデータベースのクエリエディターの画面のパスワードに入れる文字列を入れる
(データベースを作るときに作成するパスワードのことです)


```python:sample.py
import pyodbc


server = 'XXXX'
database = 'XXXX'
username = 'XXXX'
password = 'XXXX'
driver= '{ODBC Driver 17 for SQL Server}'

#データベースへの接続を行う
cnxn = pyodbc.connect('DRIVER='+driver+';SERVER='+server+';PORT=1433;DATABASE='+database+';UID='+username+';PWD='+ password)
cursor = cnxn.cursor()

#テーブルデータの作成
cursor.execute("CREATE TABLE [dbo].[Sample3](Number  NOT NULL,Height float NOT NULL,Weight float NOT NULL);")

#データの登録
cursor.execute("INSERT INTO [dbo].[Sample3]VALUES(1,181.3,90.8)")

#全データの参照
cursor.execute("SELECT * FROM [dbo].[Sample3]")

#データの出力
data = cursor.fetchone()
print(data)

#データベースへの接続を終了する
cursor.close()
cnxn.commit()
cnxn.close()
```

#結果
<img width="1438" alt="スクリーンショット 2020-07-08 23.47.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670396/25f31502-436d-a077-d3a6-d5df0628cd86.png">



ちゃんと、ローカルのPCで作成し、データを登録したテーブルがデータベースの方にありましたね！
fp-ts 関数合成の基盤

## 関数合成

fp-tsでは関数合成を行うのに`pipe`と`flow`の２種類が用意されている。

monadがー、applicativeがー、とか面倒くさいことを言わない、本当に単純な関数。

なのでクライスリ圏での関数（射）を合成する際には、`>>=`や`>=>`みたいに勝手に関数をliftして合成してくれるわけではない。そのため`map`や`chain`を使って自分でliftして前後で型を合わせる必要がある。

### pipe

```typescript
// 引数が4つの場合
export function pipe<A, B, C, D>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D
): D
```

Haskellの`>>=`演算子っぽい関数合成をしたいときに使う。

```haskell
(>>=) :: m a -> (a -> m b) -> m b
```

### flow

```typescript
// 引数が4つの場合
export function flow<A extends ReadonlyArray<unknown>, B, C, D, E>(
  ab: (...a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E
): (...a: A) => E
```

Haskellの`>=>`演算子っぽい関数合成をしたいときに使う。

```haskell
(>=>) :: (a -> m b) -> (b -> m c) -> (a -> mc)
```

ちなみに`>=>`をfish operatorと呼ぶ、らしい。魚に見えなくもない。なるほど。ただfishを名乗るなら`><>`の方が魚っぽい。
cookieで条件分岐するときはjQueryよりPHPがいいってハナシ。

**「同じページに2回目以降は表示させない」**

というのをやりたかったのですが、
つまったので、苦労の後を記録しておきます。

##jQueryの場合

jQueryのクッキー使うときは、以下のように

- jQuery
- jquery.cookie.js
- cookieを発火させる記述

の順番に記述します。

```html
<script src="js/jquery-3.4.1.min.js" type="text/javascript"></script>
<script src="js/jquery.cookie.js" type="text/javascript"></script>
<script>
    //クッキーがあれば、#js-loaderを非表示にする
    if ($.cookie("access")) {
      $("#js-loader").css('display','none');
    }
    //クッキーを取得させる
    $.cookie("access","topPage"); //2つ目は任意の文字を入れます
</script>
```

こちら参考にしました
-> [jQueryプラグイン「jquery.cookie.js」でcookieを簡単に扱う](https://www.tam-tam.co.jp/tipsnote/javascript/post3109.html)

これでも機能したのですが、
**javascriptの読み込みが遅い場合、
 #js-loaderが最初にちょこっと表示されてしまいます！！！**
これだとクッキーで条件分岐する意味がない。。。。

なので、最初っからキレイに非表示にしたい場合、
PHPを使いましょう！

##PHPの場合
以下のように記述しました。
まず、最初のページに表示させる条件分岐を書き、
その中に、クッキーがあるかどうかで条件分岐させます。

```php

<?php if(is_front_page()):
      if(!(isset($_COOKIE["topPage"]))): //クッキーが保存されていない時 []内は任意の文字
      setcookie("topPage", 1); //クッキーをいれる　2つ目は任意の値を入れます ?>
 <div id="js-loader">
  ローディングアニメーションの要素
 </div>
<?php endif; //クッキーの分 ?>
<?php endif; //is_front_pageの分 ?>
```

これでスッキリ解決しました！！

こちら参考にしました！
-> [PHPでCookieを使う方法【初心者向け】](https://techacademy.jp/magazine/4961)
-> [クッキーの読み込み](https://www.javadrive.jp/php/cookie/index2.html)
【Git】最低限これだけ押さえる！現場で使えるgit rebaseの流れ

最低限押さえておきたいgit rebaseの流れです。
実際に現場向けに作成した手順を汎用的な内容に整理しなおしました。

## 環境
- OS：Windows10
- Git：2.23.0
- 使用ツール：Git Bash

## 使用シーン
1. 先に親ブランチに取り込まれた変更を作業ブランチにも取り込んで使う
2. プルリクエスト(マージリクエスト）時のコンフリクト発生→修正からのビルドエラーの回避
3. ブランチの分岐を減らし、綺麗な状態にする

etc・・・

## イメージ図
イメージ図は以下の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356958/11c43ce9-dc3e-7d3d-1ca8-c66d5474a989.png)
親ブランチをベースにgit rebaseすることにより、
①作業ブランチのコミットが親ブランチの最後尾のうしろに移動し、
②コミットハッシュ値が変わります。

## 手順
名称と手順中の具体値の対応を以下の通りとし、作業ブランチは親ブランチをもとに作成されたものとします。

|名称|手順中の具体値|
|---|---|
|ローカルリポジトリ|/c/work/hoge|
|親ブランチ|develop|
|作業ブランチ|feature/hoge_202007|

(1) 対象のローカルリポジトリに移動

```sh:
$ cd /c/work/hoge
```
(2) 作業ブランチのcommit or stash
ワークディレクトリにcommitされていないファイルがない状態にする
①commitの場合

```sh:
$ git add .
$ git commit -m "コミットメッセージ"
```

②stashの場合

```sh:
$ git stash
```

(3) 親ブランチに切り替える

```sh:
$ git checkout develop
```
(4) 親ブランチにリモートリポジトリの内容を反映、最新の状態にする

```sh:
$ git pull
```
(5) 作業ブランチに切り替え

```sh:
$ git checkout feature/hoge_202007
```

(6) 親ブランチをベースにリベース

```sh:
$ git rebase develop
```
(7) コンフリクトが起きた場合は以下のコマンドで対象を確認し、解消する（コンフリクトなしの場合不要）

```sh:
$ git status
```
→ both modifiedと表示されるファイルが修正対象（一気に表示されないので、ひとつひとつ解消する＆解消できたら、(8)のコマンドを実行する）

(8) コンフリクトが解消できたら、以下のコマンドを順に実行（コンフリクトなしの場合不要）

```sh:
$ git add .
$ git rebase --continue
```
※途中でリベースを取り消す場合は以下のコマンドを実行（変更した内容も取り消される）

```sh:
$ git rebase --abort
```
→ 変更の完了した分も元に戻ります。rebaseが完全に完了した場合は使えないので要注意。

(9) リモートリポジトリにプッシュ

```sh:
# プッシュ前に親ブランチの変更内容が取り込まれていることを確認しておく
$ git log --oneline
# リモートリポジトリにプッシュ
$ git push -f
```

→ 親ブランチに追加された内容が作業ブランチの途中に割り込む形となるため、fオプションで強制的にプッシュします。

(10) 手順(2)でstashした場合は、忘れないうちに戻しておきましょう

```sh:
# stash一覧の確認
$ git stash list
# 最新のstashを反映
$ git stash pop
```

## 注意点
- リベース前後で作業ブランチのコミットハッシュ値が変わる（イメージ図参照）。
- 原則、自身の作業ブランチ以外では実施しないこと。

## 終わりに
時々必要な作業で、そのたびに手間取るので、対策用にまとめました。

## 参考
- [git-stash | git-scm.com](https://git-scm.com/docs/git-stash)
- [色々な git stash | Qiita](https://qiita.com/akasakas/items/768c0b563b96f8a9be9d)
memo AWSデプロイエラー時のコマンド

## 背景
AWSデプロイに詰まったとき、エラーログを見るために頻繁に使用したのでコードをメモしておく

## tailコマンドを使う
ファイルの最後の部分を表示する

## サーバーログ
アプリのリポジトリ上にて

```
tail -n 30 log/production.log
```
* オプションの意味
 * -n　数字 :  ファイルの最終行からその数字行だけ表示できる

## nginxログ
アプリのリポジトリ上にて

```
sudo tail -f /var/log/nginx/error.log
```
* オプションの意味
 * -f: リアルタイムで更新されるログファイルを確認しながらプロセスの挙動を確認できる
  
## unicornログ
アプリのリポジトリ上にて

```
sudo tail -f log/unicorn.log
```


## また、再起動コマンドもよく使ったのでメモしておく
## nginx 再起動
```
sudo service nginx reload
```

## unicorn 再起動
```
ps -ef | grep unicorn | grep -v grep
```
PID：プロセス番号を確認した後

```
kill プロセス番号
```
再起動コマンド

```
unicorn_rails -c /var/www/rails/アプリ名/config/unicorn.conf.rb -D -E production
```
Vue.jsで条件に合わせて属性を変更する

例えばCSSフレームワークbulmaでボタンをクリックできなくする属性disabledを条件によって分岐したい場合でやってみる。
disabled === true のときはボタンが押せなくなり、falseのときは押下可能。
参考: https://bulma.io/documentation/elements/button/


```.vue
<template>
  <div>
    <button class="button" v-bind="buttonAttr"></button>
  </div>
</template>
```

computedでif文や三項演算子で条件分岐してreturnすればよい。
例えばbtnFlgというdataを用意して、それのbool値で判断する場合。

```.vue
export default {
  computed: {
    buttonAttr() {
      return this.btnFlg
        ? { disabled: true }
        : { disabled: false }
    }
  }
```

もちろん、よく使うclassやhrefなどどんな属性でもこんな風に書けるから結構便利。
Gitの基本

# Gitとは
プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システム
集中型バージョン管理システムのSubversionとよく比較されている。

#重要用語
- ワーキングツリー
- インデックス
- ローカルリポジトリ
- リモートリポジトリ
- ブランチ

# ローカルリポジトリの作成からリモートリポジトリへの反映
```
$ mkdir /develop/Git-Tutorial
$ cd /develop/Git-Tutorial
$ git init #ローカルリポジトリを作成し、管理に必要な.gitディレクトリが作成される
Initialized empty Git repository in /develop/Git-Tutorial/.git/

$ echo "test1" > test1.txt
$ git add test1.txt #test1.txtをインデックスに追加する
$ git status #変更状況を確認する
$ echo "test2" > test2.txt
$ echo "test3" > test3.txt
$ git status
$ git add . #変更したも(test2.txtとtest3.txt)のを全てインデックスに追加する
$ git commit -m "first commit" #インデックスからローカルリポジトリへ反映する
$ git commit --amend -m"first commit message is changed" #直前のコミットメッセージを修正する
$ git log #コミットログを確認する
$ git remote add origin [追加したいリポジトリのurl]　＃リモートリポジトリを追加する
$ git push -u origin master #ローカルリポジトリの今いるブランチの内容をリモートリポジトリのmasterブランチに登録する
$ echo "test3 add" > test3.txt
$ git diff #ワーキングツリーとインデックスとの差分を確認する
$ git commit -m "test3 add message"
$ git diff --staged #インデックスと最新のコミットとの差分を確認する
$ git push -u origin master 
```

#リモートリポジトリのデータを取得しマージする
```
git clone [リモートリポジトリのurl] #リモートリポジトリのデータをローカルにコピーし、管理に必要な.gitディレクトリが作成される
git fetch origin #リモートリポジトリのデータをダウンロードするが、ローカルリポジトリのファイルは更新されない
git log origin #リモートリポジトリから取得した履歴を表示する
git merge origin master #リモートリポジトリのマスターブランチのデータを今いるブランチにマージする
git pull origin master #「git fetch + git merge」でリモートリポジトリから最新のデータを取得し、ローカルリポジトリのマスターブランチを更新する
```

#後からgitの管理対象外にしたくなった場合
.gitignoreを作成して、除外したいファイル名を書き込む
・gitignoreに「*.exe」のように記述することも可能
※「・gitignore」そのものをgit addする必要は無い

###特定のファイルを除外する場合
```
touch .gitignore
echo "ファイル名" >> .gitignore
git rm --cache "ファイル名"
git commit -m "ファイルをgit管理から除外"
git push origin master
```

###特定のディレクトリ配下全てを除外する場合
```
echo "ディレクトリ名" >> .gitignore
git rm -r --cache "ディレクトリ名"
git commit -m "ディレクトリをgit管理から除外"
git push origin master
```

###カレントディレクトリ配下全てgit管理から一度除外する
※一度綺麗にして追加し直すようなことは通常はやらないので推奨しない

```
git rm -r --cached .
git commit -m "カレントディレクトリ配下を全て除外する"
git push origin master
```
Command Line要点一覧

- **「touch ファイル名」**で空のファイルを作成できる。
`ex）touch beginner.text`

- **「cat ファイル名」**でファイルの中身を表示できる。
注意）catコマンドを実行したときに、存在しないファイルを指定するとエラーが出力される。エラーが出た場合、実行したコマンドは無効になる。
※catはcatenate(つなぐ、連結する)の略で、本来は複数のファイルを連結させる為のコマンド

- **「mkdir ディレクトリ名」**で新たにフォルダを作成できる。
  ※mkdirはmake directoryの略

- ディレクトリを指定せずに**「cd」**のみで実行すると、ホームディレクトリと呼ばれるディレクトリに移動することができる。ホームディレクトリは、「~」で表される。ホームディレクトリは、ユーザーが作業をするときに起点にするディレクトリのことを言う。ユーザーが起点とするディレクトリのため、簡単に移動できるようになっている。
※cdはchange directoryの略

- ファイルを移動させるには、mvコマンドを使う。**「mv ファイル名 ディレクトリ名」**とすることで指定したディレクトリにファイルを移動させることができる。
mvコマンドでは、ファイル1つずつだけでなくディレクトリごと移動させることもできる。**「mv 移動させたいディレクトリ名 移動先のディレクトリ名」**とすることで、そのディレクトリ以下のファイルやディレクトリも一緒に移動する。
※mvはmoveの略

- ファイルやディレクトリの移動に使ったmvコマンドは、ファイル名を変更することにも使える。**「mv 現在のファイル名 新しいファイル名」**とすることでファイル名を変更できる。
`ex) mv beginner.txt dojo.txt`

- ファイルをコピーするにはcpコマンドを使う。**「cp コピーするファイル名 新しいファイル名」**とすることでコピーすることができる。

- cpコマンドでは「-r」を付けることで、ファイルだけでなくディレクトリもコピーすることができる。**「cp -r コピーするディレクトリ名 新しいディレクトリ名」**とすることでコピーできる。
`ex)  cp r HTML Ruby`
※「-r」をつけずにディレクトリをコピーしようとすると、エラーが出力され、コピーは実行されない。
※cpはcopyの略

- ファイルを削除するにはrmコマンドを使う。**「rm ファイル名」**とすることで削除できる。
※rmはremoveの略

- rmコマンドは「-r」を付けることでディレクトリも削除することができる。**「rm -r ディレクトリ」**とすることでディレクトリを削除できる。
※cpと同様に「-r」を付け忘れるとエラーとなるので注意する。

#一覧表

| コマンド            | 内容               | 注意    | 略 |
|:-----------------|:------------------|:------------------|:------------------|
| 「touch + ファイル名」  | 空のファイルを作成    |                ||
| 「cat + ファイル名」    | ファイルの中身を表示   |存在しないファイルを指定するとエラーが出力される|catenate(つなぐ、連結する)の略|
| 「mkdir + ディレクトリ名」| 新たにフォルダを作成  |                |make directoryの略|
| 「cd」             | ホームディレクトリに移動 |            |change directoryの略|
| 「mv + ファイル名 + ディレクトリ名」| 指定したディレクトリにファイルを移動|               |moveの略|
| 「mv + 移動させたいディレクトリ名 + 移動先のディレクトリ名」| そのディレクトリ以下のファイルやディレクトリも一緒に移動 |             ||
| 「mv + 現在のファイル名 + 新しいファイル名」 |ファイル名を変更|              ||
| 「cp + コピーするファイル名 + 新しいファイル名」| ファイルをコピー|              |copyの略|
|「cp + -r + コピーするディレクトリ名 + 新しいディレクトリ名」 |ファイルだけでなくディレクトリもコピー |「-r」を付け忘れるとエラーとなる              ||
|「rm + ファイル名」 | ファイルを削除|              |removeの略|
| 「rm + -r + ディレクトリ」| ディレクトリを削除| 「-r」を付け忘れるとエラーとなる||
PrometheusのNode exporterをdockerで起動してちゃんとホスト側のメトリクスを収集させる方法

```bash
docker run -d \
  -v "/proc:/host/proc:ro" \
  -v "/sys:/host/sys:ro" \
  -v "/:/rootfs:ro" \
  --net="host" \
  quay.io/prometheus/node-exporter
```
Docker ComposeでWordPressを設定する

# 作業ディレクトリの準備
「wordpress-test」という作業ディレクトリを作成

```bash
mkdir wordpress-test
```

# docker-compose.ymlを作成する
作業フォルダ上で`docker-compose.yml`を作成。

```yml:docker-compose.yml
version: '3'

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

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
volumes:
    db_data:
```

# ブラウザで動作確認
`http://localhost:8000`でアクセス
[PHP]パッケージ管理ツールComposerを図で理解する

## 概要
PHPのパッケージ管理ツール**Composer**について図を用いてまとめました。
Composerは既にインストールしている前提で説明します。

## Composerとは？
**PHPのパッケージ管理ツール**です。

## パッケージ管理ツールとは？
プロジェクトが必要とするライブラリやパッケージを、**依存関係**を考慮した上で管理してくれるツールです。

## 依存関係とは？
ライブラリやパッケージには依存関係があります。
例えば以下のようなものです。
(1) ライブラリAを使いたい場合、ライブラリBとライブラリCが必要である
(2) ライブラリAのバージョンが2の場合、ライブラリBのバージョンは3が必要である

この例でいくと、Composerは

(1) ライブラリAを指定してインストールすると、自動でライブラリBやライブラリCもインストールしてくれる
![composer_ex1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/e203a3e5-edd0-5799-e2d5-a8d06b4b4614.png)

(2) ライブラリAをバージョン2へアップデートすると、自動でライブラリBのバージョンを3へアップデートしてくれる
![composer_ex2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/0767d849-e386-72fc-d53b-31cfb9ee55ae.png)
ということをしてくれます。

## ライブラリの指定

プロジェクトに追加したいライブラリを指定するためのファイルが**composer.json**です。
composer.jsonには、プロジェクトに必要な**ライブラリのリストとバージョン**を記載します。
<img width="893" alt="Laravelの例" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/c65abe45-8437-2c2a-5aae-95a78c4bfc33.png">

このファイルは直接作成＆編集するか、以下のようなコマンドで操作することができます。

```bash
$ composer init # composer.jsonを作成
$ composer require パッケージ名 # composer.jsonにパッケージを追加
```

## ライブラリの読み込み
ライブラリをインストールするためには以下のコマンドを打ちます。

```
$ composer install
```

実行すると、以下のことが起きます。

- **composer.lock**が生成される
- ライブラリのソース本体が**vendor**ディレクトリにインストールされる

![composer_ex3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/80e543e3-c15a-e5f6-58dd-c0c85aef1dd2.png)


ただし、プロジェクトに**既にcomposer.lockが存在している場合**はそちらの情報で優先的にインストールされます。
（チームで開発する場合や、Laravelなどのフレームワークで環境構築した場合など）

![composer_ex4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/d6425a51-b6dc-7594-ec93-db7b1f17b04f.png)


**composer.lockの有無にかかわらず**、composer.jsonから再度依存関係を解決してインストールを行いたい場合は以下のコマンドを打ちます。

```
$ composer update
```
![composer_ex5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/096b1799-5c15-2008-fd4b-2c41212c2e3d.png)


## composer.lock
composer.lockには実際にライブラリのどのバージョンがインストールされたかが具体的に記載されます。
チームで開発する場合はこれを利用することによって、開発環境のライブラリによる差分をなくすことができます。
<img width="899" alt="スクリーンショット 2020-07-07 23.19.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/d8365ad2-4d14-ea81-5004-70c8a2add012.png">

## vendor
インストールされたパッケージのソース本体が格納されます。
<img width="498" alt="スクリーンショット 2020-07-07 23.21.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/4464ec6f-ae1c-d405-4802-0281f11f6cce.png">


## 参考

[Composerの導入＆使い方（初心者の復習用） - Qiita](https://qiita.com/suke/items/770bccf8a43f9247daf5)
[composer.json、composer.lockって何なの？という人向けのまとめ - Qiita](https://qiita.com/masarufuruya/items/23131a465b7e9c8f3060)
[Composer は何者か。あるいは install と update の違い。そしてオートロードの仕組み。 | ごみばこいん Blog](https://gomiba.co.in/blog/archives/883)

## 最後に
Composerおじさんは賢い。ありがとうおじさん。
そのうち余裕があったらJavaScriptのパッケージ管理ツールnpmについてもまとめようと思います。
記事に間違いや不明な点なあればご指摘お願いします。
JSモジュール

## fun-hooks

```js
import funHooks from 'fun-hooks';

let createHook = funcHooks({
  useProxy: false,
  ready: funHook.ASYNC | funcHooks.QUEUE
});

// Sync (before, after)
function sum(a, b) {
  return a + b;
}

let hookedSum = createHook('sync', sum);

// before
hookedSum.before(function(next, a, b) {
  a = a + 1  
  next(a, b);
});

// after
hookedSum.after(function(next, result) {
  next(result + 1);
});

let result = hookedSum(1, 1);

// hookedSum(1, 1) => hookedSum.before(1, 1) => sum(2, 1) => hookedSum.after(3) => 4

// Async (before, after)
function increment(a, b, callback) {
  callback(a + 1, b + 1);
}
let hookedIncrement = createHook('async', increment);

hookedIncrement.before(function(next, a, b) {
  a = a + 1;
  next(a, b);
});

hookedIncrement.after(function(next, a, b) {
  next(a, b + 1);
});

hookedIncrement(1, 1, function(a, b) {
  console.log(a, b); // 3, 3
});
```
ゼロから始めるLeetCode Day80「703. Kth Largest Element in a Stream」

# 概要

海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

どうやら多くのエンジニアはその対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイトであり、海外のテックカンパニーでのキャリアを積みたい方にとっては避けては通れない道である。

と、仰々しく書いてみましたが、私は今のところそういった面接を受ける予定はありません。

ただ、ITエンジニアとして人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

Python3で解いています。

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day79「1282. Group the People Given the Group Size They Belong To」](https://qiita.com/KueharX/items/9b363058156070ca5a0a)


[Twitter](https://twitter.com/kueharx)やってます。

**[技術ブログ](https://kueharx.blogspot.com/)始めました！！**
技術はLeetCode、Django、Nuxt、あたりについて書くと思います。**こちらの方が更新は早いので**、よければブクマよろしくお願いいたします！

＃問題
[703. Kth Largest Element in a Stream]()
難易度はEasy。

問題としては、ストリーム内の`k`番目に大きい要素を見つけるクラスを設計してください．これは、ソートされた順番の中で`k`番目に大きい要素であって、`k`番目の異なる要素ではないことに注意してください。

`KthLargest`は、整数`k`とストリームの初期要素を含む整数配列`nums`を受け入れるコンストラクタを持ちます`KthLargest.add`メソッドを呼び出すたびに、ストリーム内の`k`番目に大きい要素を表す要素を返します。


>Example:

>int k = 3;
int[] arr = [4,5,8,2];
KthLargest kthLargest = new KthLargest(3, arr);
kthLargest.add(3);   // returns 4
kthLargest.add(5);   // returns 5
kthLargest.add(10);  // returns 5
kthLargest.add(9);   // returns 8
kthLargest.add(4);   // returns 8

要はコンストラクタと`add`メソッドを実装してくださいね、ってことですね。

この問題を取り扱ったのは、Googleのコーディング面接をパスした人がおすすめしているLeetCodeの問題集に載ってたからです。

[コーディング面接対策のために解きたいLeetCode 60問](https://1kohei1.com/leetcode/)

面白そうなので一通り解いてみようかなーと思います。
最近新しい問題ばかり解いていましたし、久々に面白そうな取り組みになりそうです。

# 解法
ヒープの問題ってことで、大人しくヒープを使います。
優先度付きキューとも言いますね。

一見この問題簡単そうに見えますよね。

毎回要素を追加した後にソートしてその中から`k-1`の要素を返してあげれば良くね？となりそうですが、ソートという処理は重いので普通に時間切れになると思います。

例えば、以下のような処理ですね。

```python
def add(val):
    lists.append(val)
    self.lists.sort()
    return self.lists[self.num-1]
```

これでは`add`が呼ばれる度にソートがかかり、要素が増えれば増えるほど重くなっていきます。

なので最初から要素を追加する時に優先度付きのキューを使って管理してしまえばわざわざソートしなくてもいいよね？ってことです。

ヒープを使ったものとして以下のコードを書きました。

```python
import heapq

class KthLargest:
    def __init__(self, k: int, nums: List[int]):
        self.lists,self.num = [],k
        for i in nums:
            self.add(i)

    def add(self, val: int) -> int:
        heapq.heappush(self.lists, val)
        if len(self.lists) > self.num: 
            heapq.heappop(self.lists)
        return self.lists[0]

# Your KthLargest object will be instantiated and called as such:
# obj = KthLargest(k, nums)
# param_1 = obj.add(val)
# Runtime: 136 ms, faster than 45.40% of Python3 online submissions for Kth Largest Element in a Stream.
# Memory Usage: 17.6 MB, less than 78.45% of Python3 online submissions for Kth Largest Element in a Stream.
```

こうすることで最初に与えられた要素から全ての要素をヒープとして扱い、`lists`の長さの値が`num`と同値になるまでひたすら`pop`、すなわちリストから最小値を取り出すため、非常にスムーズに処理が行われます。

書いてて思ったのですが、ヒープで書いたことほとんどなかったような気がするので復習がてらいい勉強になりました。

では今回はここまで。お疲れ様でした。
Snowflakeに対してAzure ADアカウントによるシングルサインオンの設定

## 概要
Snowflakeに対して、Azure ADアカウントでログインするまでの設定手順を説明します。

## 手順
### 1.Azureポータルでのエンタープライズアプリケーション作成
#### 1-1.Azureポータルにて、Azure Active Directoryにある”エンタープライズアプリケーション”を選択し、”新しいアプリケーション”を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/4c543446-7041-fb42-4fdc-e78c335ed1c8.png)

#### 1-2."ギャラリーから追加する"でSnowflakeを探し、適切な名前を設定した上で"追加"を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f0ddf9ea-2192-1816-78d6-f37f8eabde10.png)

#### 1-3."シングルサインオン"→"SAML"を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/7f20a9c9-cfa4-844c-2a90-c88c7559e8be.png)

#### 1-4."基本的な SAML 構成"にて、下記の設定を行い、"保存"を選択します。
| 番号 | 項目    | 設定値                     |
| ---- | ------- | -------------------------- |
| 1    | 識別子  | {snowflakeのURL}           |
| 2    | 応答URL | {snowflakeのURL}/fed/login |
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/27ec654f-e015-338f-89e3-dcf69041a1e0.png)

#### 1-5.”3 SAML署名証明書”→”証明書 (Base64)”をダウンロードし、ファイルを開き内部の値を控えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/176c3472-4b51-a4df-8c78-7fc039989021.png)

#### 1-6.”4 {アプリケーション名}のセットアップ”→”ログインURL”の値を控えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/fc6ed4d5-45aa-7c1b-f66f-d2b5ce28f3ca.png)

#### 1-7.”ユーザーとグループ”→”ユーザーの追加”を選択し、ログイン許可したいユーザーを登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/254f2e87-aae5-c091-4d43-12e26605e373.png)

### 2.SnowflakeにてAzure ADアプリケーションの登録とユーザー作成
#### 2-1.”accountadmin”にて、下記のSQLを変更したものを実行し、Azure ADアプリケーションを登録します。
```sql
use role accountadmin;
alter account set saml_identity_provider = '{
"certificate": "{1-5の証明書の値}",
"ssoUrl":"{1-6のログインURLの値}",
"type":"custom",
"label":"AzureAD"
}';
alter account set sso_login_page = TRUE;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/35fffb17-2cf8-9046-0313-70861ea6ed90.png)

2-2. 下記のSQLを変更したものを実行し、ユーザーを登録します。

```sql
--Azure ADユーザーアカウントにて、Snowflakeにアカウント作成
use role accountadmin;
CREATE USER {Snowflakeのユーザー名} PASSWORD = '' LOGIN_NAME = '{AzureADでのメールアドレス}' DISPLAY_NAME = 'Snowflakeでの表示名';

--sysadminロールを付与
grant role sysadmin to user {Snowflakeのユーザー名};

--デフォルトのロールを、sysadminに変更
alter user {Snowflakeのユーザー名} set default_role=sysadmin;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a6afa829-204c-5e82-d423-577607af89f4.png)

2-3. 再度Snowflakeにブラウザで接続し、"Log in using AzureAD"を選択し、ログインできることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f5877a41-f6ac-25c5-8a9a-f9d96b488435.png)

## よくあるエラー
### ゲストユーザーを登録する場合

ゲストユーザーを登録する場合には、エンタープライズアプリケーションにて、`一意のユーザー`を`user.mail`に変更する必要がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/4eb4b4f8-4e52-3003-1421-44a656d8196d.png)



## 参考リンク
- [チュートリアル: Azure Active Directory と Snowflake の統合](https://docs.microsoft.com/ja-jp/azure/active-directory/saas-apps/snowflake-tutorial)
- [外部 OAuth 用Microsoft Azure AD の構成](https://docs.snowflake.com/ja/user-guide/oauth-azure.html)
SVProgressHUDが左上に固定される場合

## SVProgressHUDがなぜか左上に表示される場合
SVProgressHUDの中心が(0, 0)になってしまうことがあるようです。
その場合の応急処置。

```swift
func application(_ application: UIApplication, 
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 
{
    // Override point for customization after application launch.  

    SVProgressHUD.setOffsetFromCenter(
        UIOffset(horizontal: UIScreen.main.bounds.width/2,
                   vertical: UIScreen.main.bounds.height/2)
    )
}
```

オフセットを調整して中央に来るようにする。
あまりよろしくないが、急ぎの場合はこれで。

###よくあるコードをSwiftで
あまり関係ないかもしれないけど、、、ずれを検出するコード

```swift
extension SVProgressHUD {

    static func adjustSVProgressHuDHudViewCenter() -> CGFloat {
        var keyboardWindow: UIWindow?
        for window in UIApplication.shared.windows {
            if window.nameOfClass == UIWindow.nameOfClass {
                keyboardWindow = window
                break
            }
        }
        
        if let keyboardWindow = keyboardWindow {
            for possibleKeyboard in keyboardWindow.subviews {
                if possibleKeyboard.nameOfClass == "UIPeripheralHostView" ||
                    possibleKeyboard.nameOfClass == "UIKeyboard"
                {
                    return possibleKeyboard.bounds.height
                }
                else {
                    if possibleKeyboard.nameOfClass == "UIInputSetContainerView" {
                        for possibleKeyboardSubview in possibleKeyboard.subviews {
                            if possibleKeyboardSubview.nameOfClass == "UIInputSetHostView" {
                                return possibleKeyboardSubview.bounds.height
                            }
                        }
                    }
                }
            }
        }
        return 0
    }
}


extension NSObject {

    static var nameOfClass: String {
        return NSStringFromClass(self).components(separatedBy: ".").last!
    }

    var nameOfClass: String {
        return NSStringFromClass(type(of: self)).components(separatedBy: ".").last!
    }
}
```