OmniAICreator/Qiita-1.07M huggingface dataset:
【メモ】pictureとsrcsetと私

```haml
.aaa aaaaaaaaaaa
%picture
  %source{media: "(min-width:768px) and (max-width:1112px)", srcset: "/images/TB.png", sizes: "768px"}
  %source{media: "(min-width:1113px)", srcset: "/images/PC.png", sizes: "1112px"}
  = image_tag "SP.png", alt: "デフォ画像"

```

```scss
.aaa{
  color: yellow;
}
@media all and (min-width: 768px) and (max-width: 1112px){
  .aaa{
    color: green;
  }
}
@media all and (min-width: 1113px){
  .aaa{
    color: blue;
  }
}
```
Pythonでリッジ回帰

#まえがき
最小二乗法の解説
https://qiita.com/NNNiNiNNN/items/4fd5367f9ead6e5905a9
↑の記事を読んだ前提で説明します。
# リッジ回帰とは
最小二乗法における、最小化する目的関数は以下のようなものでした。

```math
E(\mathbf{w}) = ||\mathbf{y} - \mathbf{\tilde{X}\mathbf{w}}||^2
```
リッジ回帰における、最小化したい目的関数は以下のものです。

```math
E(\mathbf{w}) = ||\mathbf{y} - \mathbf{\tilde{X}\mathbf{w}}||^2 + \lambda ||\mathbf{w} || ^2
```
ここで加わった$\lambda ||\mathbf{w} || ^2$の項を正則化項といいます。
正則化項とは何かというと、おおざっぱに言って関数の複雑さに対するペナルティです。できるだけ誤差は少なく、しかし関数も複雑にしすぎないように。
今回のリッジ回帰では$\lambda ||\mathbf{w} || ^2$を正則化項として計算します。

λはハイパーパラメータと言いまして、事前に決定しておく定数です。これをいい感じに調整できれば理想的な目的の関数を求められます。

 では最小二乗法の場合と同様に$\mathbf{w}$で微分して

```math
\Delta E(\mathbf{w})= -2 \mathbf{\tilde{X}}^T \mathbf{y} + 2 \mathbf{\tilde{X}}^T \mathbf{\tilde{X}}\mathbf{w} +2\lambda \mathbf{w}\\
=2[(\mathbf{\tilde{X}}^T \mathbf{\tilde{X}} + \lambda \mathbf{I})\mathbf{w} - \mathbf{\tilde{X}}^T \mathbf{y}]
```
これが=0で最小値をとるので、wについて整理して

```math
\mathbf{w} = (\mathbf{\tilde{X}}^T \mathbf{\tilde{X}} + \lambda \mathbf{I})^{-1}\mathbf{\tilde{X}}^T \mathbf{y}
```
標準化しておきましょう。

```math
(\mathbf{\tilde{X}}^T \mathbf{\tilde{X}} + \lambda \mathbf{I})\mathbf{w} = \mathbf{\tilde{X}}^T \mathbf{y} \tag{1}
```
これでAx = bの形で解けます。
# 実装してみよう
基本的に[前回](https://qiita.com/NNNiNiNNN/items/4fd5367f9ead6e5905a9)と同じコードを使います。
まず訓練用データが

```python
import numpy as np

# y = w[0] + w[1]x[1] + w[2]x[2]型。
# w = [1, 2, 3]とする。
X = np.random.random((100, 2)) * 10 # 0から1*10の範囲をとる100*2の行列
y = 1 + 2 * X[:, 0] + 3 * X[:, 1] + np.random.randn(100)
#x0とx1の座標からyを作成。randnで本来の値にノイズを加えている。
```
さらに以下を付け加えて

```python
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from scipy import linalg # linalg.solve(A, b)

lambda_ = 1 # ハイパーパラメータを1とする。

Xtil = np.c_[np.ones(X.shape[0]), X]
c = np.eye(Xtil.shape[1]) # 単位行列を作る
A = np.dot(Xtil.T, Xtil) + lambda_ * c # (1)式を確認しよう
b = np.dot(Xtil.T, y)
w = linalg.solve(A, b) # (1)式をwについて解く。

xmesh, ymesh = np.meshgrid(np.linspace(0, 10, 20),
                            np.linspace(0, 10, 20))
zmesh = (w[0] + w[1] * xmesh.ravel() +
        w[2] * ymesh.ravel()).reshape(xmesh.shape)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X[:, 0], X[:, 1], y, color='k')
ax.plot_wireframe(xmesh, ymesh, zmesh, color='r')
plt.show()
```
それで出力はこんな感じ。
![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/356208/7a1a0fa8-7709-00a1-b346-6c4b7a739dd5.png)
出力できました。

#まとめ
リッジ回帰とは回帰分析に正則化項$\lambda ||\mathbf{w} || ^2$を加えたものです。
「関数の複雑さを減らすこと」がどういう意味かは次回、汎化と過学習についてみてみましょう。

『機械学習のエッセンス』という本を参考にしました。この本についてまとめていきます。
前回:最小二乗法
https://qiita.com/NNNiNiNNN/items/4fd5367f9ead6e5905a9
次回:過学習
https://qiita.com/NNNiNiNNN/items/d87990a6eef72a3815a3
2日目(1)：Ruby認定試験による確認

更新記録
　2019/03/06 最後のコードに全角空白が含まれていて、エラーを起こす辺り、修正

#使用環境
```ホストOS: Windows10 home
仮想環境OS: Ubuntu Bento/Bionic
Ruby：2.51
Rails:5.2.2
エディタ:nano
```

#Ruby認定試験による知識等確認

##ソースコードの文字コードをUS-ASCIIに設定のマジックコメント

```
1, # coding: us-ascii
2, # encoding: us-ascii
3, # -*- charset: us-ascii -*-
4, # CODING: US-ASCII
```
1，2，4は同義で、正解。3はPython。

##例外処理（begin  rescue ensure end
Wikipediaによると
>プログラムの上位の処理から呼び出されている下位の処理で継続不能、または継続すれば支障をきたす異常事態に陥ったとき、制御を呼び出し元の上位の処理に返し安全な状態になるよう回復処理をすること。

```
begin
  # 例外が起こりうるコード1
rescue => # 変数(例外オブジェクトの代入)
  # 例外が起きた場合のコード2
ensure
  # 例外の有無に関わらず、実行するコード3 
end
```
1で例外が起きなかったら、表示結果は1且つ3の表示結果、起きた場合は2且つ3の表示結果となる。
例外処理コードとして、ensureが用いられないパターンもある。
その他、rescueの中でretryを用い、beginが成功するまで繰り返す処理がる。(無限ループ注意）

##Rubyにおける定数と変数
下コードの実行結果は『10と表示された後、警告が表示され100と表示される。』

```
MAX=10
print MAX
MAX=100
print MAX
```
Rubyにおいて、アルファベット大文字から始まる識別子(ABCやAbc)は定数である。
他言語では定数を再定義しようとすると、警告が出て、結果、再定義できない。
Rubyにおいては、警告が出たのち、そのままデータがオーバーライトされる

##可変長引数
```
def foo(*a)
  p a
end
foo(1,2,3)
#実行結果　[1,2,3]
```
*を1個付けると、引数を複数指定でき、引数は配列として受け取られる。
*を2個付けると、オプション引数となり、Hashとして受け取られる。

##範囲オブジェクトとeach文
###.to_iメソッド
文字列を10進数の表現と見なして整数に変換します。

```
#引数baseを取ることもでき、その引数で何進数かを示す。
#デフォルト値は10であり、引数指定しない場合は10進数となる。
変数.to_i(2)
```

###範囲オブジェクト
```
def hoge
  x = 0
  (1...5).each do |i|
    x += 1
  end
  puts x
end
hoge
#実行結果　4
```
まず『数A...数B』に関して、これはAからBまで繰り返すの意。ただし、Bは含まれない。
そのため、『1...5』は、1から4までの4回分繰り返す。
一方で、『1..5』は5を含み、1から5までの5回分繰り返す。
因みに、『1..5』『101..105』『2001..2005』だろうと5回分。

##uptoメソッド
```
money = 1000
オブジェクト.upto(max) do |i|
  実行処理
end
 
money = 100
1.upto(3) do |i|
  money = money * 1.1
end
puts money.to_i
```
uptoメソッドは、変数に「対象オブジェクトが持つ数値」から「max」までを順に代入しながら、処理実行。
1回繰り返す毎に1ずつ数値は増加します。（ここでは１から３までの3回。『1..3』と同義。
また、downtoメソッドもあり、これは1回繰り返すごとに1ずつ数値が減少する。
timesメソッドも参照すべし

##stepメソッド
```
オブジェクト.step(limit, stepno) do |変数|
  実行する処理1
  実行する処理2
end
```
はじめに、stemnoを『数値間隔』とするとわかりやすい。
対象オブジェクトを持つ数字から順に代入しながら、処理を実行。
1回繰り返すごとに、stepnoで指定した数値間隔ごとに、数値が増加する。

##☆範囲オブジェクト、uptoメソッドまとめ
```
money = 1000
rate = 1.1
2001.upto(2004) do |i|
  money = money * rate
  puts "I got #{money.to_i} in #{i}."
end
#実行結果
# I got 1100 in 2001.
# I got 1210 in 2002.
# I got 1331 in 2003.
# I got 1464 in 2004.
```
これは、下とも書けると思った。

```
money = 1000
rate = 1.1
(2001..2004).each do |i|
  money　= money * rate
  puts "I got #{money.to_i} in #{i}."
end
#実行結果
# I got 1000 in 2001.
# I got 1000 in 2002.
# I got 1000 in 2003.
# I got 1000 in 2004.
```
**コメントにより、タイプミス(全角空白)を指摘して頂いた**
正しくは

```
money = 1000
rate = 1.1
(2001..2004).each do |i|
  money *= rate
  puts "I got #{money.to_i} in #{i}."
end
```
2日目に行ったScaffoldによる掲示板作成も同投稿する予定だったが、それをすると記事が長く、
内容も全く異なり、解りにくくなるため、投稿を分けることにする。
[2日目(2)：Scaffoldを用いた掲示板作成](https://qiita.com/OriverK/items/3b12f4d2f09f207a4dfa)
Google Search Console から 再クロール依頼

#SEO対策でHTML5準拠したので、早く見に来て欲しいからやってみた

HTML5準拠は、こちらからチェック
https://html5.validator.nu/

所有権を確認するのに、環境的に一番楽そうなAWS route53でTxtレコードを追加した。
spfレコードもあるので2行。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/364471/22330e88-7e68-b613-a428-1e451b482b8b.png)


サイトマップなんてないので、URL検索から依頼
![image.png](https://qiita-image-store.s3.amazonaws.com/0/364471/bbdad090-7ee1-0281-e266-ea8932dce354.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/364471/8f5de91a-a8fd-c2db-b285-34c7ea0c9a24.png)
とのこと

# おまけ 検索順位チェッカー
http://checker.search-rank-check.com/
[WIP] ActiveRecord::Railtie と establish_connection

## establish_connection
> データベースと接続するためのメソッド。
通常は明示的に呼び出すことはない。
しかし、
複数のデータベースを使用し、モデルごとに接続先DBが異なる場合は、クラス定義の内側で明示的に呼び出す必要がある。

一般的には、database.ymlに接続先DB情報を記載しておき、シンボルとして参照する。

```database.yml
***:
  adapter: ...
  database: other_database
  pool: 5
  username: USERNAME
  password: PASSWORD
  host: localhost
```

```models/~~.rb
  establish_connection :***
```

DBの接続情報はサブクラスへ引き継がれる

[Railsで複数のデータベースを使用する
](https://www.techscore.com/blog/2012/12/12/rails%E3%81%A7%E8%A4%87%E6%95%B0%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B/)

## ActiveRecord::Railtieのinitializerを上書き

Rails上でActiveRecordを使うと `config/database.yml` を読み取ってよしなに `establish_connection` をしてくれるが、
そのへんの処理を自分で定義したい場合、Railtieの initializer を上書きする必要がある。

```/vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.1/lib/active_record/railtie.rb
    # This sets the database configuration from Configuration#database_configuration
    # and then establishes the connection.
    initializer "active_record.initialize_database" do
      ActiveSupport.on_load(:active_record) do
        self.configurations = Rails.application.config.database_configuration

        begin
          establish_connection
        rescue ActiveRecord::NoDatabaseError
          warn <<-end_warning
Oops - You have a database configured, but it doesn't exist yet!

Here's how to get started:

  1. Configure your database in config/database.yml.
  2. Run `bin/rails db:create` to create the database.
  3. Run `bin/rails db:setup` to load your database schema.
end_warning
          raise
        end
      end
    end
```

[ActiveRecord::Railtieのイニシャライザを上書きする](https://qiita.com/ikm/items/9d11e5bcaf7e5784eeaa)
【React Navigation】ヘッダーを透明にして影を消す方法

# headerTransparentをtrueに　
さっそくコードですが、

```js
const MainStack = createStackNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    Details: {
      screen: DetailsScreen,
      navigationOptions:() => ({
        title: '',
        headerTransparent:true,  //<-ここでヘッダーを透明に
      })
    },
  }
);
```

このようにすることでヘッダーを透明にして影を消すことができました。

# 試したがダメだった方法
[https://github.com/react-navigation/react-navigation/issues/790](https://github.com/react-navigation/react-navigation/issues/790)
ここなどに書いてあるのですが、

```js
  navigationOptions = {
      headerStyle: {
        elevation: 0,
        shadowOpacity: 0
      }
  }
```
このようにしても自分はうまくいきませんでした...
`backgroundColor = "transparent`にしていたからかも？

とりあえず、自分は
`headerTransparent:true`
とすることでうまくいったのでもしよければ試してみてください！
[gradle] クラスパスに空白が含まれる場合にpathingJarが効かない

# 発生した課題
先日 [grailsでrun-appしたらブートしなくなった](https://qiita.com/loopsketch/items/80a53760abe7b5d78afd) という記事を書きましたが、gradleで構築する機会があったので参考にしたpathingJarを入れて動かすパターンでやってみたのですが、どうやらクラスパスに空白が含まれているとうまく動かない、ということがわかりました。自分のPCは入社時に予め会社の人がセットアップしてくれたのですが、フルネームで空白が。なので、ホームディレクトリまでのパスに空白が入っています。orz

# 対処
jarに埋め込むクラスパスは空白区切りです。パスに含まれる空白は%20でエスケープするみたいです。pathingJarのjarファイルのパスをcollectしているところで、空白を置換するようにします。

```groovy:build.gradle
... 前略 ...
task pathingJar(type: Jar) {
    dependsOn configurations.runtime
    appendix = 'pathing'

    doFirst {
        manifest {
            attributes "Class-Path": configurations.runtime.files.collect {
                it.toURL().toString().replaceFirst(/file:\/+/, '/').replace(' ', '%20')
            }.join(' ')
        }
    }
}
... 後略 ...
```
# Grailsに応用
Grailsでは pathingJar = true という裏技が用意されているのですが、同様に起動しない謎の状況に見舞われました。そこで以下のように記述します。pathingJarのままタスクを書くと既にあるよと怒られるので、pathingJarExタスクとしました。

```groovy:build.gradle
... 前略 ...
// grails {
// 	pathingJar = true
// }
task pathingJarEx(type: Jar) {
    dependsOn configurations.runtime
    appendix = 'pathing'

    doFirst {
        manifest {
            // Build the Class-Path for absolute paths based on runtime dependencies.
            attributes(
                'Class-Path': configurations.runtime.files.collect {
                    it.toURL().toString().replaceFirst(/file:\/+/, '/').replace(' ', '%20')
                }.join(' ')
            )
        }
    }
    exclude { it.file.absolutePath.contains('assetCompile') }
}
... 中略 ...
bootRun {
    ... 中略 ...
    dependsOn pathingJarEx
    doFirst {
        classpath = files("$buildDir/classes/main", "$buildDir/resources/main", "$projectDir/gsp-classes", pathingJarEx.archivePath)
    }
}
... 後略 ...
```

# 参考
[grailsでrun-appしたらブートしなくなった](https://qiita.com/loopsketch/items/80a53760abe7b5d78afd) 

[[Gradle] Createprocess error=206 への対処 [備忘録]](https://qiita.com/ksh-fthr/items/4a45d2a61db5a4b812f4)
関数名でオブジェクトに対して変数を使う

Sessionの値によってcheckboxにcheckedをつけようと思い、調べると以下のように記述すれば良いことを理解した。

```javascript
//例
document.(参照するフォームのname).(参照するコントロールのname).checked = true;

//name属性に対してjavaScriptの変数を代入したがエラーになる
function setCheckBoxChecked(Session, targetInput) {
  if (Session === 'true') {
    document.form.targetInput.checked = true;
  }
}

```

checkedが未定義と怒られてしまう。書き方あってるよなー・・・

```javascript
Cannot set property 'checked' of undefined
```


どうやらオブジェクトに対して変数を使う場合は以下のように書くようだ。

```javascript
    document.form[targetInput].checked = true;
```


## 参考
[チェックボックスがチェックされているか取得する](https://www.ipentec.com/document/javascript-get-checkbox-value)
[JSでオブジェクトの指定に変数を使う。](http://kobazlab.main.jp/2016/06/08/js%E3%81%A7%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E6%8C%87%E5%AE%9A%E3%81%AB%E5%A4%89%E6%95%B0%E3%82%92%E4%BD%BF%E3%81%86%E3%80%82/)
環境（本番、テスト、開発、 etc.）を判別して分岐するような実装は避ける

## 問題提起

例えば、以下のようなコードを見かけたことはありませんか。僕はあります。

```php:sample.php
if (APP_ENV === 'production') {
    // 本番環境でのみ動作するコード
}
```
※コードはPHPですが、特定言語に依存する話ではありません。
※ドメイン（FQDN）で分岐するのも同類です。

事例としては、本番だけ特定のアドレスにメールを飛ばしたいとか。
開発環境でだけログを出したいとか。

ですが、このような実装は避けるべきと考えます。
理由は端的にいうと「テストしにくいから」

上記上げたコード、どうやってテストしたらいいでしょうか？

* 本番でテストする？
  * 本番環境でテスト、とは...
* テスト環境の `APP_ENV` を一時的に `production` にする ？
  * 他の箇所にも影響しますよね...
* `if (APP_ENV === 'production' or true) {` と一時的無理やり通るようにする？

どれも場当たり的な対応という印象が拭えません。

## 解決策

では、どうすればいいかというと

「その機能を使うか否かを判別するためのスイッチを環境変数として用意する」

例えば、環境変数で AWESOME_FUNCTION_SWITCH というのを作ります。

```shell:.env
AWESOME_FUNCTION_SWITCH=0
```

※ ここでは .env ファイルで定義していますが、OSの環境変数で定義してもOK

で、プログラム側では、この環境変数を見て処理を分岐します。

```php:sample.php
if (getenv('AWESOME_FUNCTION_SWITCH') === '1') {
    // AWESOME_FUNCTION の実装
}
```

このようにすれば、手元の環境でテストしたいときは
環境変数の値を変更すれば良いだけになり、プログラム内から環境による分岐処理を無くすことができます。
iosアプリからのdynamoDBスキャンができない

ややハマりしたので、備忘録
曖昧な理解のまま、この記事を書いてますので、誤り等あればご指摘ください。


#dynamoDBの公式のドキュメントどおりに記述してもスキャンできない

公式のドキュメント↓　古いのかな？いつのものか確認出来てないです。ごめんなさい。
https://docs.aws.amazon.com/ja_jp/aws-mobile/latest/developerguide/how-to-ios-dynamodb-objectmapper.html#perform-a-scan

公式によると

```
 let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
 let scanExpression = AWSDynamoDBScanExpression()
 scanExpression.limit = 20

dynamoDBObjectMapper.scan(Book.self, expression: scanExpression).continueWith(block: { (task:AWSTask<AnyObject>!) -> Any? in
     if let error = task.error as? NSError {
         print("The request failed. Error: \(error)")
     } else if let paginatedOutput = task.result {
         for book in paginatedOutput.items as! Book {
             // Do something with book.
         }
     }
 })

```

となっているのですが、コンパイルエラー



scanメソットは、AWSDynamoDBPaginatedOutput型 をもらってくるらしいので、下記で動きました。

```
 let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
 let scanExpression = AWSDynamoDBScanExpression()
 scanExpression.limit = 20

dynamoDBObjectMapper.scan(Book.self, expression: scanExpression).continueWith(block: { (task:AWSTask<AWSDynamoDBPaginatedOutput>!) -> Any? in
     if let error = task.error as? NSError {
         print("The request failed. Error: \(error)")
     } else if let paginatedOutput = task.result {
         for book in paginatedOutput.items{
             // Do something with book.
             print(book)
         }
     }
 })


```
いつも調べてしまっていることの私的メモ

文書型宣言を<!DOCTYPE html>にするとHTML5。

HTML5以前
→type="text/javascript"が必要（scriptタグ内をJavaScriptとして処理させるため）
HTML5から
→typeの指定が無い場合はデフォルトでJavaScriptとして処理される


HTML5以前
metaタグでブラウザキャッシュの制御が可能だった。

HTML5
マニュフェストファイルの使用も非推奨化になる
WEBサーバーのシステムに依存した書き方がほぼ必須になったよう

ドットが「任意の1文字、なにか1文字」という意味をもつので、特殊な意味を打ち消すための「¥」を前につけて意味を打ち消す。

ブラウザによってはこの円マーク「¥」が、バックスラッシュ「\」で表示されるので注意。


. = なにか1文字、なんでもいい1文字
* = 直前の文字を0回以上繰り返す
(.*) = なんでもいい1文字を、0回以上繰り返す。つまり、あらゆる文字列を表現できる。

正規表現のパターン内を括弧()を使ってグループ化することで、変数「$1」「$2」...の部分に、マッチした文字列が代入される
後方参照について

$1 = この場合、ここに(.*)が代入される。つまり、文字なしを含む、あらゆる文字列。
例えば、「hoge.html」「sample」「文字なし」など、何でも。
Amazon ElastiCacheについてまとめてみた

# ElastiCache
ElastiCacheとはKVSキャッシュサービスです。  
KVSキャッシュサービスを使用する目的は「データのコピー(キャッシュ)に超高速で低コストなアクセスを提供すること」です。  
DBへのクエリはkey-valueのペアを検索するよりも時間がかかるため、高速でデータにアクセスしたい場合にElasticCacheを利用します。  
key-valueのvalueには複雑なデータ構造を保持することはできないため、既に加工済みのデータやデータベースへのクエリ結果を格納します。  
このように静的なクエリの結果をデータベースから取得しElastiCacheに格納し、ElastiCacheからデータを取得することで
データベースへのクエリを投げる回数が減り、より高速にコストも減らすことができます。  
キャッシュエンジンはMemCachedとRedisの二つから選択できます。  
どちらもKVS形式のインメモリキャッシュですがMemCachedはマルチノードのキャッシュクラスタを構成し、
Redisはマスタ - スレーブ構成となります。  
<img width="1020" alt="ElastiCache-useCase.png" src="https://qiita-image-store.s3.amazonaws.com/0/294042/4bb7ddd7-0961-44ef-6019-6c6dcebae7f1.png">
Slackの投稿をCrowiに登録する

# 概要
Slackの投稿内容をWikiサイトCrowiに登録するPythonスクリプト。
無料版のSlackの場合、メッセージが1万件を超えると自動で古いメッセージが削除されてしまう。
無料版でも過去のメッセージは参照できるようにしたい！という貧乏根性からCrowiに登録できるようなスクリプトを作った。

Crowiは内部でElasticsearchにデータを格納しているため、メッセージの検索もしやすく大事な内容が埋もれなくなったのも良かった。

# 使い方
### Slack APIトークンの取得
権限的には強すぎて良くないがlegacy tokenを利用する。
以下のサイトから取得する。
※legacy tokenはroot権限のようなもので危険なので流出しないように注意

https://api.slack.com/custom-integrations/legacy-tokens

### Crowi APIトークンの取得
ユーザー設定ページからAPIトークンの取得ができる。
<img width="971" alt="スクリーンショット 2019-03-06 11.22.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/245430/cd886817-8f5c-32c7-b81f-22e5ebe6b32b.png">

### GitHubからソースコードをダウンロード

```
$ git clone https://github.com/hamaryz/slack2crowi.git
$ cd slack2crowi
```

### APIトークン情報などをセット
setup.pyを実行して先ほど取得したAPIトークンやCrowiのURL情報をセットする。

```
$ python setup.py
input slack token: [Slack APIトークンを入力]
input crowi token: [Crowi APIトークンを入力]
input crowi URL(including http or https): [CrowiのURLを入力]  (ex. https://example.com)
```

setup.pyを実行するとconfig.iniが作成され、中にトークン情報が埋められる。

```
$ ls
README.md	crowi.py	setup.py	slack2crowi.py
config.ini	preprocess.py	slack.py
```

### 登録スクリプトの実行
登録したいチャネル名を指定してslack2crowi.pyを実行する。

```
$ python slack2crowi.py -n [Slackチャネル名]
```

### 出力
エラーが発生しなければ、Crowiの以下のパスにSlackメッセージが登録される。

/slack/[Slackチャネル名]


# まとめ
Slackの投稿内容をCrowiに簡単に登録できるようになった。
CrowiのフォークであるGrowiも同じAPIを持っているので登録ができる。
あとはcronなどに実行コマンドを登録しておけば自動でCrowiに過去のメッセージをためられる。

いまはlegacy tokenを使っていたり、出力メッセージも直近の100件のみだったり、添付ファイルも登録しないなどと、人によっては使いにくい部分もあるので、要望があれば改善していこうと思う。

最後にソースコードはこちら
https://github.com/hamaryz/slack2crowi
アプリ開発でのSNS認証のクライアント、サーバーの連携

# SNS連携とは
このQuiitaでもよく見られる,ログイン時の「Twitterで登録」などのものです。
<img width="321" alt="スクリーンショット 2019-03-06 10.51.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/220683/1136143e-93f6-c648-7df4-e681db7ff022.png">


今回は

* firebaseなどのmBaasを使わない
* WebViewを使わない
* モバイルアプリ

という条件での
クライアント、サーバーの連携方法をご説明します。(OAuth認証)


# クライアント
基本的にクライアント側で認可サーバと連携し、ユーザのアクセス許可をもらいます。
クライアントのフレームワークに準拠しているSNS各種のSDKによって、最近は簡単に実装できています。

認可サーバーから、ユーザー固有のアクセストークンを取得します。
これをサーバーに送ります。

## 例 SwiftのTwitterSDKを用いた認可サーバーとの連携
```swift
TWTRTwitter.sharedInstance().logIn(completion: { (session, error) in
    if (session != nil) {
        print("signed in as \(session.userName)");
    } else {
        print("error: \(error.localizedDescription)");
    }
})
```

# サーバー
クライアントでアクセストークンを取得したからといってそのままアクセストークンをDBに保存してはいけません。なぜなら最近のSNSのアクセストークンは有効期限や使用回数制限などの使用制限が設けられているからです。これにより、複数回の同一文字列のアクセストークンの使用が不可能になっています。
したがって次回ログイン時で特有のUserかを判別するために、アクセストークンではない、別のdataを判別dataにする必要があります。
例えば、メールアドレスです。アクセストークンを使ってSNS提供サーバーから様々なデータを取得することができますが、その一つにメールアドレスもあります。
メールアドレスの利点は、万が一SNSの認可サーバーが使えなくなったりした時に、代用としてメールアドレスログインとして、SNSから取得したメールアドレスを使ったりすることができることです。（ただし、どのSNS提供サーバーでもメールアドレスの取得が可能である訳ではないかつ、SNSで登録したメールアドレスをユーザーが紛失している可能性もああるので、ベストでマストな要件ではないです。）

## 例 RubyOnRailsでのaccess_tokenを用いたemailの取得

```ruby
require 'koara'
module FacebookService
  class << self
    def fetch_mail(access_token)
      Koala::Facebook::API.new(access_token).get_object('me')['email']
    end
  end
end
```
Nuxt.jsでUIフレームワーク内のSass変数を上書きして、コンポーネントでも使う

# 概要

Nuxt.jsでUIフレームワークを使ってるときにフレームワークの標準のカラーテーマを上書きして、上書きした値をSass変数にしてコンポーネント内で使いたい、なんてことありませんか？

今回はbootstrap-vueとbuefyを例にその方法を紹介したいと思います。

# bootstrap-vue

bootstrap-vueが既にインストールされている前提で話します。
まだインストールしていない人はcreate-nuxt-appでbootstrap-vueを選ぶか、公式ドキュメントでインストール方法を調べましょう。

まずSassが使えるようにします。

```shell
npm i node-sass sass-loader
```

次にassets内にbootstrap-vue内の変数上書き用のSassファイルを作ります。上書きするためにここでbootstrapとbootstrap-vueのscssファイルをインポートします。

```sass:assets/style/_override.scss
$primary: red;

@import 'bootstrap/scss/bootstrap.scss';
@import 'bootstrap-vue/src/index.scss';
```

次にNuxt.jsを以下のように

```js:nuxt.config.js

export default {
  css: ['@/assets/style/_override.scss'],

  modules: [
    'bootstrap-vue/nuxt',
  ],

  // _override.scssで既に読み込んでいるのでここはfalseにする
  bootstrapVue: {
    bootstrapCSS: false, // or `css`
    bootstrapVueCSS: false // or `bvCSS`
  },
}
```

これでbootstrap-vue内の$primaryがredになります。
variantプロップスでprimaryを選んだ場合も赤になります。

**しかしこれではコンポーネント内のstyleブロックで$primaryを呼んだらエラーになります。**

$primaryをグローバルにするためにもうひと工夫します。
先日書いた[Nuxt.jsでグローバルSass変数を使いたいんじゃ](https://qiita.com/yusuke_ten/items/1d4f26f2abc44271219a)を使うとうまくいきます。

とりあえず@nuxtjs/style-resourcesをインストールします。

```shell
npm
npm i @nuxtjs/style-resources
```
次にグローバルにしたいSass変数を記入します


```sass:assets/style/_variables.scss
$primary: red;
```

最終的にNuxt.config.jsが以下のようになります。

```js:nuxt.config.js

export default {
  css: ['@/assets/style/_override.scss'],

  modules: [
    'bootstrap-vue/nuxt',
    '@nuxtjs/style-resources'
  ],

  // _override.scssで既に読み込んでいるのでここはfalseにする
  bootstrapVue: {
    bootstrapCSS: false, // or `css`
    bootstrapVueCSS: false // or `bvCSS`
  },

  styleResources: {
    scss: ['@/assets/style/_variables.scss']
  },
}
```

これで$primaryがグローバルになりました。

# buefy

buefyもbootstrap-vueとほぼ同じです。
違うのは_override.scssとnuxt.config.jsです。
以下のようにします


```sass:assets/style/_override.scss
@import "~bulma/sass/utilities/_all";

$primary: red;

@import "~bulma";
@import "~buefy/src/scss/buefy";
```

```js:nuxt.config.js

export default {
  css: ['@/assets/style/_override.scss'],

  modules: [
    'nuxt-buefy',
    '@nuxtjs/style-resources'
  ],

  // _override.scssで既に読み込んでいるのでここはfalseにする
  buefy: {
    css: false
  },

  styleResources: {
    scss: ['@/assets/style/_variables.scss']
  },
}
```

# 終わりに

他のUIフレームワークでは試したことがないのですが、ほぼ同じ手順で行ける気がします。
Vuetifyなんかはもう少し簡単かもしれません。
大事なのは上書きするためのSassとグローバルに適用するためのSassの２つを用意することです。
この問題で躓いている人の参考になればと思います。
AWS RDS パラメータグループをPowerShellで設定する

#はじめに
Edit-RDSDBParameterGroupのヘルプには変更するパラメータの指定が
-Parameter \<Amazon.RDS.Model.Parameter[]\>
と書かれているが、ここってどう書けばいいの？
という人向け。


#コード

このサンプルでは
パラメータグループファミリー：aurora-mysql5.7
タイプ：DB Parameter Group
で作成したパラメータグループを変更しようとしています。

##パラメータ決め打ち

パラメータが変動しないのであればParameterの初期化で入れてしまうこの書き方で良いと思う。

```PowerShell

$SplattingParameter = @{
  DBParameterGroupName = "sampleparametergroup";
  Parameter            = (
    @{
      ParameterName  = "default_tmp_storage_engine";
      ParameterValue = "MyISAM";
      ApplyMethod    = "pending-reboot";
    },
    @{
      ParameterName  = "binlog_cache_size";
      ParameterValue = 65535;
      ApplyMethod    = "pending-reboot";
    }
  );
  Region               = "us-east-1"
}
Edit-RDSDBParameterGroup @SplattingParameter
```

##パラメータ変動

何かの仕組みの中に組み込み、変更するパラメータが増減するならこの書き方。
この例では無条件で入れていますが$ParameterArrayに追加する前に条件分岐したり、
ループの中に組み込んでも良いでしょう。

```PowerShell
$ParameterArray = @()

$ParameterArray += @{
  ParameterName  = "default_tmp_storage_engine";
  ParameterValue = "MyISAM";
  ApplyMethod    = "pending-reboot";
}

$ParameterArray += @{
  ParameterName  = "binlog_cache_size";
  ParameterValue = 65535;
  ApplyMethod    = "pending-reboot";
}

$SplattingParameter = @{
  DBParameterGroupName = "sampleparametergroup";
  Parameter            = $ParameterArray;
  Region               = "us-east-1"
}

Edit-RDSDBParameterGroup @SplattingParameter
```
MySQLでALTER TABLE ADD COLUMN IF NOT EXISTS的なことがしたい

# やりたいこと
- テーブルにカラム追加するとき、そのカラムがないときだけカラム追加するようにしたい  
  -> 『Duplicate column name』エラーを無視したい
- Flywayで実行するとき、カラム追加が上手くいってなければFailedにしたい

# SQL
プロシージャを利用する。

```SQL:alter_table.sql
DROP PROCEDURE IF EXISTS alter_table_procedure;

DELIMITER //

CREATE PROCEDURE alter_table_procedure()
BEGIN
  /* SQLEXCEPTIONを無視するように設定 */
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
  
  /* 以下のALTER TABLEで『Duplicate column name』エラーが発生してもプロシージャは正常終了する */
  ALTER TABLE user ADD COLUMN age INT NULL AFTER name;
  ALTER TABLE user ADD COLUMN address VARCHAR(50) NULL AFTER age;
END //

DELIMITER ;

CALL alter_table_procedure();

DROP PROCEDURE alter_table_procedure;

/* 追加対象のカラムをSELECTすることで、もしカラム追加できていなかったらエラーとなり
   Flywayのhistoryはfailedとなる */
SELECT age, address FROM user;
```
ES6でJavascriptが簡単にかける！便利な追加機能とは？

# ES6とは

ES6とは、ECMAScriptのバージョン6のことです。
現在では標準化され、正式にはES2015と呼びます。

ECMAScriptとは、、Javascriptの仕様、ルールのようなものです。

# ES6から加わった機能

## constとlet
今まで変数宣言は`var`だけで行っていました。
しかし、新しく以下の2つが追加されました。

- let   :再宣言NG
- const :再宣言NG再代入NG

## 変数のスコープ
- var   :関数内
- let   :ブラケット{}のブロック内
- const :ブラケット{}のブロック内

関数functionのスコープもブロックスコープになっています。


## セミコロンは要らない？
文の最後は区切りとして、セミコロンを付けることが一般的でした。
しかし、ES6ではセミコロンがなくても正常に動くようになりました。

## 即時関数をブロックスコープで

即時関数ってこんなもの。

```js
    ($function(){
        var num = 1;
    })
```

読み込んだらすぐに実行される。
ブロックスコープが使えなかったので、即時関数が必要でした。

ブロックスコープを使えば、

```js
    {
        let num = 1
    }
```
で実行できます。

## アロー関数
アロー関数とは、`=>`を使って関数リテラルを表現したものです。

`var 関数名 = (関数リテラル)`

一般的に関数リテラルは、
`function(引数,…){関数の処理}`
と書いていました。

アロー関数では、この関数リテラルを

`(引数,…) => (関数の処理)`

という風に簡単に表せます。

## for of

```js
    for(要素 of 反復できるオブジェクト(配列など)){
        各要素への処理
    }
```

## 関数のデフォルト引数

```js
    function test(引数 = "デフォルト値"){
        処理
    }
    test();
    test("hoge");
```

関数の仮引数の定義で、値を代入しておくと、引数がなかった場合のデフォルト値として使えます。
ランダム文字列を生成する

# 何をしたいか
パスワードに使えるランダムな文字列を生成したい。
pythonのバージョンは3.6.8です。

# コード

```
>>> import random, string
>>> print("".join(random.choices(string.printable[:94], k=8)))
\xE}4kSe

```

# 簡単な説明

```
>>> print(string.printable)
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
```
印刷可能な ASCII 文字で構成される文字列です。パスワードにするには空白文字や改行コードは邪魔なので、

```
>>> print(string.printable[:94])
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
```

の部分のみとしました。場合によってはバックスラッシュも消したくなりそうなので、

```
print("".join(random.choices(string.printable[:94].replace("\\", ""), k=8)))
```

とするといいかもしれません。
GrafanaからTypetalkに通知したいのでWebhookした

# 経緯

- Grafanaからアラート通知したいな
- Slackとかだったら簡単にGrafanaからアラート通知できるらしいよ
- でもうちのチャットツールはTypetalkなんだ

# Webhook用エンドポイント書いた

https://github.com/ckitidle/grafana_typetalk_notification

GrafanaのNotification用pluginは書けなさそう？なので、Grafanaの通知JSONを整形してTypetalkに投稿するWebhookエンドポイント。
Nodeを練習がてら雰囲気で書いた。
~~雑に書いたparser.js部分を可変すればメッセージも変えられるんじゃあないでしょうか。~~
EJSを使うように実装を変更しました。
[初心者向け]六つの手順でjQueryプラグインを使いこなす！

#この記事の対象者
jQuery初心者向けです。
自身のサービスにこのプラグインを使いたい、いい感じのプラグインを見つけたわいいが、さてさてどう扱えばいいのかさっぱりだ！といった方の役に立つものです。
#目次
1. この記事の目的
2. jQueryプラグインとは
3. 必要なもの
4. [本題]jQueryプラグインの使い方
5. [終わりに] jQueryプラグインの捉え方

#この記事の目的
記事主用の備忘録。
記事主と同じことで悩んだ方への手助け。
jQueryプラグインをもっと活用していこうぜ！

#jQueryプラグインとは
jQueryの拡張機能です。
記事主は、UIを手軽にリッチなものにしてくれるパッケージツール、と言った認識です。

#必要なもの
- 自分のhtmlファイル(もしくはphpファイル)
- 自分のjsファイル（プラグインを発動させるためのもの）
- 使いたいプラグインのファイル

#[本題] jQueryプラグインの使い方
**記事主の思う六つの手順**
1. 使いたい機能を持ったプラグインを探す
2. 1で見つけたプラグインをダウンロード（もしくはCDN。ほとんどがダウンロードするものだと思います。）
3. ダウンロードしたプラグインのzipファイルを解凍
　→そのフィル内にあるindex.htmlとかを開いてみる
　→英語がほとんどだがとりあえずは頑張って読んでみる(Google翻訳かけるもあり。)
　→そしたら大概何ができるかわかる
4. 自分の作品にそのプラグインの機能を搭載したい箇所に、idなりclassなりをつける
5. .jsのファイルを作成し、$(4でつけたidとか).なんとか(){何か書くかも};ってかく
　　- 4でつけたidとか　=　セレクタ
　　- なんとか　=　メソッド　(※大抵そのプラグインの機能を一言で言い表す命名になっている。)
6. 物によっては{}の中に何か書くこともある
　　- 何か書くかも　=　数値の指定等をこちらですることもある。

#[終わりに] jQueryプラグインの捉え方
プラグインをダウンロードしたわいいが、どうしたらプラグインは発動するんじゃーーー、と頭を抱えたことは懐かしいです。
**「たった一行コードを追加するだけで、欲しい機能を搭載できる」**とか謳われているのはプラグインのおかげなんですね。**プラグイン発動のトリガーとなるコードを自身のjsファイルに記述する**、と言う意味だと理解できますね。

いつかは自分のオリジナルのプラグインを作ってみたいものです。
技術力を磨かなければ。日々精進！
RustでGUI 〜GUIライブラリ比較編〜

# RustのGUIライブラリ
実はまだ世間ではRustでGUIを作成しようにも良さげなライブラリでこれだ！というものがまだ決まっていません。
なので良さげなの簡単なライブラリの比較をしていきます。
ここではそれぞれのライブラリでボタンを押すと数字が増える"カウントアップ"というプログラムを作って比較してきます。

コードなどの確認等は[ogata-k/GUI_cmp](https://github.com/ogata-k/GUI_cmp)を確認してください。
各ライブラリの説明は各リンク先に貼ってあります。

# GUIライブラリ
* [**azul**](https://github.com/maps4print/azul): [RustでGUI 〜azul編〜](https://qiita.com/ogata-k/items/fc1e21d2ba707a8b9ae7)
* [**conrod**](https://github.com/PistonDevelopers/conrod): [RustでGUI 〜conrod編〜](https://qiita.com/ogata-k/items/0a27e82ab3dc2636ea07)
* [**gtk**](https://github.com/gtk-rs/gtk): [RustでGUI 〜gtk編〜](https://qiita.com/ogata-k/items/76ff6c46ac49239685de) 
* [**iced**](https://github.com/hecrj/iced): [RustでGUI 〜iced編〜](https://qiita.com/ogata-k/items/1ceb8be3bbf81cc8d5cf)
* [**OrbTk**](https://github.com/redox-os/orbtk): [RustでGUI 〜OrbTk編〜](https://qiita.com/ogata-k/items/c9b0d421b550600ce8d9)

# 最後に
まだまだ[crates.io](https://crates.io/categories/gui)で調べればGUIライブラリは見つかるので「これも調べてほしい！」というライブラリがあれば教えていただけると、記事に追加するかもしれません。
今まで勘違いしていたPythonの.strip(), .lstrip(), .rstrip()


# Introduction

今まで.strip(), .lstrip(), rstrip()の挙動を間違って理解していた自分への戒めとして、この記事を掲載します。

# 端から指定した文字列を除去する便利なメソッドたち

例えば、文字列 a = 'TATATATATATAGCAGGATCATAATCATAGATATATATATA' から右端の'A'を除去したいとします。するとこれを行うPythonの処理と、その実行例は

```python
>>> a = 'TATATATATATAGCAGGATCATAATCATAGATATATATATA'
>>> a.rstrip('A')
'TATATATATATAGCAGGATCATAATCATAGATATATATAT'
```

のようになり、確かに右端から'A'が一つ無くなっていることがわかります。

# 複数文字を除去対象に指定した場合

では、今度はa.lstrip('TGA')としてみましょう。この実行結果はどうなるでしょうか。

```python
>>> a.lstrip('TGA')
'CAGGATCATAATCATAGATATATATATA'
```

私の勘違いポイントは「.lstrip('TGA')とすると、文字列'TGA'が左端から除去される」というものでした。でもこれは間違いです。本来の挙動は、この例では**文字'T', 'G', 'A'以外の文字が現れる場所まで、左端から削除し続ける**というものです。文字列ではなく各文字が現れなくなる場所、この例では'C'まで処理が行われるということに、今更気づいたのでした。

文字の順序は関係ないため、'AGT'としても同様の結果が得られます。

```python
>>> a.lstrip('AGT')
'CAGGATCATAATCATAGATATATATATA'
```

# 特定の順序に沿った文字列のみの削除は.replace()で

章タイトルにある通り、特定の文字列を**その順序のままに削除を行いたい場合は.replace('文字列', '')**とすると、望ましい結果が得られます。

```python
>>> a = 'TATATATATATAGCAGGATCATAATCATAGATATATATATA'
>>> a.replace('TAG', '')
'TATATATATACAGGATCATAATCAATATATATATA'
```

文字列'TAG'が削除されていることがわかります。
主要クラウドサービスのIPアドレス範囲(IP address range of major cloud service)

##AWS
https://ip-ranges.amazonaws.com/ip-ranges.json

[AWS IP アドレスの範囲](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-ip-ranges.html)

##GCP
https://www.gstatic.com/ipranges/goog.json

[Google の IP アドレスの範囲を取得する](https://support.google.com/a/answer/10026322?hl=ja)

##Azure
https://www.microsoft.com/en-us/download/confirmation.aspx?id=56519

##Facebook
CloudではありませんがFacebookクローラーのIP

```sh
$ whois -h whois.radb.net -- '-i origin AS32934' | grep ^route
```
[Facebookクローラー](https://developers.facebook.com/docs/sharing/webmasters/crawler)
ADのユーザー情報、PC情報を一覧出力する方法

#ADに登録されているPCを一覧出力する方法


```powershell

Import-Module ActiveDirectory

$op = "C:\temp\AD_Workstations.csv"

$Datas = @()

#「-SearchBase」キーワードでADのツリーを指定すると、配下ユーザーを一括出力できる。
$Data  = get-adcomputer -LDAPFilter "(name=*)"   -SearchBase "OU=xxxxxxxx,DC=xxxxx,DC=com"  -Properties *   | select Name,IPv4Address,Description,Enabled,LastLogonDate,CanonicalName


#出力方法の指定
$Data  | Export-Csv  $op -encoding Default -NoTypeInformation

```

#ADのユーザーを一覧出力する方法


```powershell

Import-Module ActiveDirectory

$op = "C:\temp\AD_Users.csv"

$Datas = @()

#「-SearchBase」キーワードでADのツリーを指定すると、配下ユーザーを一括出力できる。
$Data  = get-ADUser -LDAPFilter "(name=*)"   -SearchBase "OU=xxxxxxxx,DC=xxxxx,DC=com"  -Properties *   | select Name,Surname,GivenName,Description,DisplayName,EmployeeNumber,mail,Department,Title,Company,Office,PostalCode,Country,State,City,Enabled,OfficePhone,MobilePhone,Fax

#「$Data +=」とすれば、追加で複数個所のADのツリーから配下ユーザーを一括出力できる。
$Data += get-ADUser -LDAPFilter "(name=*)"   -SearchBase "OU=yyyyyyyy,DC=xxxxx,DC=com"  -Properties *   | select Name,Surname,GivenName,Description,DisplayName,EmployeeNumber,mail,Department,Title,Company,Office,PostalCode,Country,State,City,Enabled,OfficePhone,MobilePhone,Fax

#出力方法の指定
$Data  | Export-Csv  $op -encoding Default -NoTypeInformation

```
気になる技術要素　自分用メモ

# 気になる技術要素　自分用メモ
- Git導入
    - サービス利用？（GitHub／GitLab）
    - オンプレGit？
- 自動ユニットテスト
    - テストコードを書くのを当たり前にするためには？
    - [参考：テスト自動化について、調べてみた](https://qiita.com/yutachaos/items/857472c7d3c65d3cf316)
    - [参考：経験0の経験0による経験0のためのテスト啓蒙](https://qiita.com/SpicyCoffee/items/2bb90f47ed81db02e694)
- 開発手法（ウォーターフォールの代替／ウォーターフォールとの併用）
    - アジャイル／Scrum　アジャイル的手法の部分活用も含めて
    - テスト駆動開発
    - ドメイン駆動設計
- クラウド
    - ベンダー毎の特徴まとめ
        - AWS
        - GCP
        - Azure
        - Oracle？その他？
    - マルチクラウドの可能性（組み合わせとか）
    - ハイブリッドクラウド
- CI
    - CIツール
        - Jenkins
        - CircleCI
        - Travis CI
    - プロダクト環境でのCI導入ルール
- 主流として扱う言語選定
    - 利用中言語の扱い検討
        - Java
        - PHP
        - .Net系
    - 未経験言語の導入是非検討
        - Python
        - Scala
        - Go
        - R
- AI,機械学習
- Kubernetesってなに？
- Docker活用
- 構成管理ツール
    - Ansible？Chef?
    - クラウド環境で活かせる？
- マイクロサービス
tig 使い出してかなり経つので .tigrc を晒します


git 使いですがもっぱら cli で使っているのです。でも、ペアプロとかモブプロとかするときに他メンバーに見えやすいように SourceTree とか使っていたわけで。

さて、tig を使い出してから

* ターミナルから離れずに操作できる スゲー
* 横から後ろからディスプレイを覗くメンバーにもわかりやすい スゲー
* git 初心者にも help モード見せながら操作できるのでわかりやすい スゲー
* ｽｹﾞ━━━━━━ヽ(ﾟДﾟ)ﾉ━━━━━━!!!!

なので、嬉しくなっちゃったので .tigrc を晒します。カスタマイズのベースとでもして戴ければ。
インストールとか使い方とは先達ページがいっぱい有るので ggr ですが、ちょー簡単に使い方書くと、

1. repo ディレクトリで `tig` 立ち上げて
2. `s` で status みて
3. `u` で stage に追加して
4. `C` で commit して
5. `P` で push して
6. `F` で fetch する

みたいな感じです。
取り敢えず `h` でヘルプモードにすればなんとかなる。
戻るときは `q` で。

``` .tigrc
color default           250             234
color 'Author '         15              default
color 'Commit: '        242             default
color 'Merge: '         45              default
color id                167             default
color date              242             default
color graph-commit      161             default
color status            15              default
color delimiter         90              default
color cursor            234             7
color help-group        161             default
color main-tracked      105             default             bold
color cursor            226             94
color title-focus       234             250
color title-blur        234             250
color diff-stat         45              default
color diff-index        14              default
color diff-add          40              default
color diff-del          161             default
color diff-chunk        190             default

set main-view   = date id author:email-user commit-title:graph=yes,refs=yes
set blame-view  = date:default author:email-user id:yes,color line-number:yes,interval=1 text
set pager-view  = line-number:yes,interval=1 text
set stage-view  = line-number:yes,interval=1 text
set log-view    = line-number:yes,interval=1 text
set blob-view   = line-number:yes,interval=1 text
set diff-view   = line-number:yes,interval=1 text:yes,commit-title-overflow=no

# set vertical-split = yes
set vertical-split = no
# set vertical-split = auto

set line-graphics = utf-8
# set tab-size = 4
set tab-size = 2
# set ignore-space = all
set ignore-space = at-eol
set ignore-case = true
set split-view-height = 80%
set diff-options = -m --first-parent
set mouse = true
set editor-line-number = yes
set refresh-mode = auto
#set refresh-mode = after-command
#set refresh-mode = periodic
#set refresh-interval = 1
set diff-highlight = true

color diff-header       default red
color diff-chunk        black   white

# set key 'g' / goto file top
bind generic g      move-first-line

# set key 'G' / goto file bottom
bind generic G      move-last-line
bind main    G      move-last-line

# set key 'E'
bind generic E      view-grep

# set key 'F'
bind generic F      ?git fetch %(remote)
bind main    F      ?git fetch %(remote)

# set key 'U'
bind generic U      ?git pull %(remote)

# set key 'C'
bind generic C      !git commit
#bind refs    C      !git commit
bind main    C      !git commit

# set key 'P'
bind generic P      ?git push -u %(remote) %(repo:head)
```
GitHub備忘録

#はじめに
[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている<@kento_o>です。

GitHubは複数人で行うプロジェクトのバージョン管理や、オープンソースの様々なソフトウェアの配布などに、極めて便利で有益な効果をもたらします。

実務でも優先度が高いGitHubについての備忘録を記事にします。



#GitHub用語集


専門用語の意味をまとめると、

| Git用語       |       意味 　　　　　　　　　|   
|:-----------------|------------------:|
|     リポジトリ      |     ファイルやディレクトリの状態を記録する場所    |
| リモートリポジトリ           |            専用のサーバに配置し複数人で共有するリポジトリ |
| ローカルリポジトリ             |              ユーザー人ひとりが利用するために、自分の手元のマシン上に配置するリポジトリ |
| ベアリポジトリ               |                ワークツリーを持たず、チェックアウト、マージができないリポジトリ。（可能なリポジトリをノンベアリポジトリと呼ぶ） |
| ワークツリー             |       履歴・バージョン管理を行いたいファイルがある場所。       |
| インデックス          |           コミットしたいファイル、またはファイルの一部を登録する場所。 |
|       ステージ    |              ワークツリーからコミットしたいファイル、またはファイルの一部をインデックスに登録すること。 |
|      ハンク      |            「ここを変更したよ」という範囲 |
|       コミット       |              インデックスに登録してある変更対象をローカルリポジトリに反映すること。 |
|       リセット       |                コミット前の変更をローカルリポジトリの状態に戻す、または特定のコミットまで状態を戻すこと。（ただし特定のコミットまで戻せるのはローカルリポジトリに限られる。） |
|      ヘッド       |             「今、作業中」というブランチ、コミット。 |
|    チェックアウト    |           上記のヘッドを切り替えること。 |
|      プッシュ        |              ローカルリポジトリの変更をリモートリポジトリに反映させること。
|     フェッチ     |       リモートリポジトリからデータをローカルリポジトリまで取得する。（ただし取得するだけで何もしない）     |
|    プル    |        フェッチ＋マージのアクションを行う。データを取得した後、ローカルリポジトリとリモートリポジトリの変更をワンアクションで実行可能。（マージしたくない時にプルしてしまった場合は、戻したいコミットのIDを調べて、git reset --hard IDで元に戻せる。）       |
|      マージ      |          異なるブランチの変更を反映させること。お互いの変更履歴が残る。   |
|       リベース       |        異なるブランチの変更を反映させること。変更履歴が片方に集約される。       |
|       コンフリクト       |        マージ対象の２ファイルで同じ箇所が変更されており、自動でマージができないこと         |
|      ブランチ       |        履歴管理を枝分かれさせてたもの。ブランチを使うことにより、複数の履歴を並列に管理できる。      |
|    フォーク    |              リモートリポジトリをコピーしてリモートリポジトリを作成すること。 |
|  クローン           |   リモートリポジトリをコピーしてローカルリポジトリを作成すること。     |
|　プルリクエスト　|　    フォークしたリポジトリでの変更を、フォーク元のリポジトリへ反映するよう依頼すること。 |
|　　.gitignore　|　履歴管理の対象外とするファイルを登録するところ。対象範囲は各リポジトリ。　　|
|　.gitignore　　|　履歴管理の対象外とするファイルを登録するところ。対象範囲は**全ての**リポジトリ。　　|








#ツール
現在使用しているツール
・OS 「Linux mint 19.1 Tessa」

・エディタ　「Atom　1.33.1」

・ターミナル　「Guake Terminal」

・シェルスクリプト 「bash or zsh」





#GitLab
おまけ程度に載せています。
[このニュース](https://www.ossnews.jp/oss_info/GitLab)に書いてあることを要約すると、
「Gitリポジトリをプロジェクト単位で管理可能」「クローズドな環境で、独自のGitHubに似たサービスを構築可能」という理解をしました。

#最後に
参考サイト

・[Git/GitHubコマンド集](https://qiita.com/forest1/items/adf683c4cc2f8cdd6a24)
・[今日からはじめるGitHub](https://employment.en-japan.com/engineerhub/entry/2017/01/31/110000)
・[GitLab](https://about.gitlab.com/)
・[サルでも分かるGitHub入門](https://backlog.com/ja/git-tutorial/)

DockerやKubernetes、AWSやクラウドサービスが今後のメジャーなサービスになると予想されるので、最新の情報を常にインプットし、積極的なアウトプットを心がけていきます。。。

~~ギット　スコシ　ワカッタ~~
SQLServerのスクリプト実行するならSSMSよりもsqlcmdの方が高速だった。

# 概要
SQLServerをメンテナンスするのに、SSMS(SQL Server Management Studio)を使うのが、定番だと思います。
ですが、本番DBからデータをスクリプト化して、デバックDBへ移して、という作業がデータ量の増加に従って徐々に辛くなってきました。
SSMSは、スクリプトのデバック機能を持っているので、実行が遅いしメモリを喰うのでしょう。
スクリプトを分割するなど騙し騙し作業していたのですが、sqlcmdを使えば、簡単に回避できました。

## sqlcmdとは
sqlcmdは、SQLServerをコマンドラインから操作するユーティリティです。
たぶん、SSMSをインストールすると使えるようになります。

## スクリプト投入例
SSMSでは、メモリオーバーになってしまう量のスクリプトを実行したい場合には、下記のようにパラメーターを指定して実行します。
認証などが必要な場合には、別途パラメーターを追加してください。

```
sqlcmd -S SERVERNAME -d SQLDBNAME -i C:\Users\user\Documents\data_20190304.sql
```

SSMSに比べて、スクリプトの分割の必要も無く、実行速度も速いです。
BigObjectの小さな不具合

workbanchからデプロイする分には何も問題ないんですけどね。

### 画面から作成
Spring'19から、入り口がworkbenchだけだったカスタムBigObject作成が画面からも登録・編集できるようになりました。

しかし、数値型の桁数がいくら編集しても18桁固定になってしまう問題があるようです。
他の型の項目作成時にも似たような問題があるかもしれないので、画面から作成する方は作成後のBigObjectを見直すと良いと思います。
調べても見つからなかったので、ひとまずこの事実をネットの海に公開することにしました。
TypeScriptでSlack slash commandを作ってみる

# やること

TypeScriptを使ってSlackのslash commandを作ってみようと思います。botも便利ですがslash commandも使い慣れると便利ですよ！最近JavaScriptで色々作れるので他の言語触らなくなりつつある...良いのか悪いのか(´・ω・｀)

# 作るもの

## コマンド

```
/timecard [in/out] [id]
```

## 仕様

* 社内の勤怠APIに対してパラメータを付与してAPIにGETリクエストをする。
* パラメータは2つ。

# Slash command作成

## パッケージのインストール

適当にディレクトリを作って`npm init -y`を実行して、パッケージをインストール。

```
npm i express typescript ts-node body-parser @types/express @types/body-parser
```

package.jsonのscriptsに以下を追加しておく。

```
"start": "./node_modules/.bin/ts-node app.ts"
```

## 枠を作る

ルートディレクトリにapp.tsを作成して以下のコードを記述。動作確認用のAPI（仮）も用意しておきます。

```ts
import * as http from 'http';
import * as express from 'express';
import * as bodyParser from 'body-parser';
import nodeFetch from 'node-fetch';

const app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get('/api', (req, res) => {
    res.json({
        message: "Hello!"
    });
});

app.post('/', (req, res) => {
    console.log(req.body.text);
});

http.createServer(app).listen(8081);
```

Slack slash commandはPOSTで飛んでくるのでapp.postで受けます。

## Slack App設定

Slackで作成したslash commandを使えるようにしていきます。

### アプリの登録

作成したslash commandを使いたいワークスペースにログインした状態で[slack api](https://api.slack.com/)にアクセス。右上のメニューにある`Your Apps`をクリックして`Create an App`ボタンをクリック。
モーダルダイアログが表示されるので以下を入力（内容は適当に）。

```
App Name: アプリ名
Development Slack Workspace: 利用するワークスペースを選ぶ
```

入力したら`Create App`ボタンをクリック。
作成が終わったらメニューの`Features`から`Slash Commands`を選択して`Create New Command`をクリックします。
画面全体にモーダルが表示されるので以下を入力（内容は適当に）。

```
Command: slash command名。ex. /scsample
Request URL: Slash commandがリクエストするURL。ex. https://example.com/sc
Short Description: Slash command概要。ex. xxxAPIを叩く
Usage Hint: パラメータのヒント。ex. [in/out] [id]
```

URLはテスト段階ならngrokとかで一時的に公開する形で良いかと思います。
入力が終わったら`Save`をクリック。

### Slackへのインストール

メニュー上のプルダウンが先程作成したApp名になっているかと思います。その状態でメニューの`Settings`から`Install App`をクリック。`Install App to Workspace`をクリックします。インストール確認画面になるので`許可する`ボタンをクリックします。

### 動かしてみる

Slackを開いてインストールしたワークスペースで先程登録したslash commandを実行してみましょう。slash commandを実行して`test`と表示されればOKです！terminal上でパラメータの確認ができますので、パラメータを送ってみてください。

## 作り込んでいく

```ts
import * as http from 'http';
import * as express from 'express';
import * as bodyParser from 'body-parser';
import nodeFetch from 'node-fetch';

const app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// API Stub
app.get('/api', (req, res) => {
    res.json({
        message: "Hello!"
    });
});

app.post('/', (req, res) => {
    console.log(req.body.text);
    nodeFetch('http://xxx.api/api')
        .then(aRes => {
            if (!aRes.ok) throw new Error(`Sorry. API HTTP Status code ${aRes.status}`);
            return aRes;
        })
        .then(aRes => aRes.json())
        .then(json => {
            res.send(json);
        })
        .catch(err => {
            // for error
            console.dir(err);
            res.send("Sorry. Server error.");
        });
});

http.createServer(app).listen(8081);
```

これをベースに作り込んでいけばOKかなと思います。

# 最後に

やってみたらそんなに難しいことじゃ無かったです。
Vue.jsで大きなObjectを扱うときはObject.freezeすると100倍くらい速くなるよ

タイトル通りなのでとりあえず結果を見てもらいましょう。

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="js,result" data-user="isuke" data-slug-hash="EMNpVM" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="EMNpVM">
  <span>See the Pen <a href="https://codepen.io/isuke/pen/EMNpVM/">
  EMNpVM</a> by isuke (<a href="https://codepen.io/isuke">@isuke</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

実行結果 ↓

![スクリーンショット 2019-03-06 8.53.06.png](https://qiita-image-store.s3.amazonaws.com/0/152997/f1eed6b2-316d-79f4-87a5-be61b4d89858.png)

正確な測定ではないですが明らかな速度の違いがわかります。

と、言うことで大きなObjectを扱うときは`Object.freeze`するといいよ。

<font color="Gray">(新旧の差をとって、差分だけ更新しようとしていた私の苦労は何だったんだ。)</font>

## ちょっと注意

- 件のObjectをレンダリングする場合はこれをしてもボトルネックの解消にはならない可能性があります。結局レンダリングに時間かかっちゃいますからね。
- `devtools`が有効になっているかどうかで結果に差があるかもです。`devtools`がゴニョゴニョしているかもしれないので。
- vuexの場合、`strict`モードが有効かどうかで結果に差があるかもです。[参考1](https://vuex.vuejs.org/ja/guide/strict.html#%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83-vs-%E6%9C%AC%E7%95%AA%E7%92%B0%E5%A2%83) [参考2](https://forum.vuejs.org/t/adding-many-objects-to-vuex-state-is-slow/10492)

## 参考

https://github.com/vuejs/vue/issues/4384
Elmのエラー invalid argument (invalid byte sequence)

## VSCodeでElm本を写経している時に出会ったエラー

### 出会った場所
ローカルブラウザでみる。
elm reactor
http://localhost:8000
このページを開いた時に、

> A web handler threw an exception. Details:
.\README.md: hGetContents: invalid argument (invalid byte sequence)

と表示される。

### 原因
ファイルの文字コードがUTF-16だった。

### 解決
ファイルの文字コードをUTF-8に直す。
正常に表示される。
Google スプレッドシートを python3 で 代入・更新 (Quickstart)

こちらで行ったのと同様のことを、
[Google スプレッドシートを python3 で 代入・更新](https://qiita.com/ekzemplaro/items/801d0d2d08a60f60f874)
Quickstart で書かれている方法で行ってみました。
[Python Quickstart | Sheets API](https://developers.google.com/sheets/api/quickstart/python)

まずは、credentials.json　を取得して、作業フォルダーに入れます。

## プログラム

```py:api_create.py
#! /usr/bin/python
#
#	api_create.py
#
#						Mar/06/2019
# ------------------------------------------------------------------
import sys
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# ------------------------------------------------------------------
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']

# ------------------------------------------------------------------
def insert_data_proc(service):
	SPREADSHEET_ID = '******'
	RANGE_NAME = 'Sheet1!A1:E4'
	sheet = service.spreadsheets()
	ValueInputOption = 'USER_ENTERED'
	body = {
		'values': [
		['t1301','小山',39561,False,'2015-3-12'],
		['t1302','下野',72843,False,'2017-6-22'],
		['t1303','栃木',59218,False,'2013-9-9'],
		['t1304','佐野',37129,False,'2011-10-5'],
		],
	}

	result = service.spreadsheets().values().update(
		spreadsheetId=SPREADSHEET_ID, range=RANGE_NAME,
		valueInputOption=ValueInputOption, body=body).execute()
#
	print(result)
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
	with open('token.pickle', 'rb') as token:
		creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
	if creds and creds.expired and creds.refresh_token:
		creds.refresh(Request())
	else:
		flow = InstalledAppFlow.from_client_secrets_file(
			'credentials.json', SCOPES)
		creds = flow.run_local_server()
	# Save the credentials for the next run
	with open('token.pickle', 'wb') as token:
		pickle.dump(creds, token)

service = build('sheets', 'v4', credentials=creds)

insert_data_proc(service)
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

## 実行結果

```text
$ ./api_create.py
*** 開始 ***
{'spreadsheetId': '1pKrdehHogQfW8gGPhDaAL0f-gRfiNjUdr_VkWv1gldk', 'updatedRange': 'Sheet1!A1:E4', 'updatedRows': 4, 'updatedColumns': 5, 'updatedCells': 20}
*** 終了 ***
```

## 確認したバージョン

```text
$ python --version
Python 3.12.7
```

## エラー対策

次のエラーが出た場合の対策です。

```text
ACCESS_TOKEN_SCOPE_INSUFFICIENT
```

対策

```bash
gcloud auth application-default login
```
Angular の ngOninitの必要性 ~なぜconstructorではダメなのか~

# Angularとは
「Angular（アンギュラー）」は、Googleによって開発されているJavaScriptフレームワークです。
アプリケーションを作成する時、ページをクリックしたときに発火させたいイベントが多々あります。それを実現させたいとき、ngOninitが必要となります。(constructorではできない）

# constructorとは
Typescript,Javascriptに付随するものである
Classの初期化時に発火する

```typescript
class Hoge {
    id: number
    constructor(num: number) { 
        this.id = num;
    }
}
```

```typescript
let h = new Hoge(1)
console.log(h.id)
==> 1
```

# ngOnInitとは
Angularに付随するものである。
Lifecycleの一部
Lifecycleとは、ディレクティブやコンポーネントが変化するタイミングで、コールバックを設定できる仕組みである。

つまり、AngularのLifeCycleに乗っ取った処理をすることができるのである。
下記で使用しているのは、AngularのLifeCycleの一つのngOnInitである。(Componentの初期化時に発火する)

```typescript
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-hoge',
  templateUrl: './hoge.component.html',
  styleUrls: ['./hoge.component.scss']
})
export class HogeComponent implements OnInit {

  constructor(
  ) {
   console.log('constructor');
  }
 
  ngOnInit() {
    console.log('ngOnInit');
  }
}
```

```typescript
===> 'constructor'
===> 'ngOnInit'
```

# まとめ
Angularでは、constructorは、component作成途中で実行されます。
ngOnInitはcomponent作成後に呼び出されます。
したがって、アプリケーションを作成する時、ページをクリックしたときにイベントを発火させたいというようなUIUX観点から見た要件は、ngOnInit(LyfeCycle)を使用することで簡単に実現することができるのです。

# 参考

http://blog.yuhiisk.com/archive/2016/05/02/angular2-lifecycle-hooks.html