OmniAICreator/Qiita-1.07M huggingface dataset:
Ruby on Rails チュートリアル 第２章　エラー修正

# 概要
Ruby on Rails チュートリアル 第２章`https://railstutorial.jp/chapters/toy_app?version=5.1#cha-a_toy_app`での`rails test`でエラーになったので、修正メモ

# エラーメッセージ
``` ターミナル
root@00f84fd5aa17:/myapp# rails test
Running via Spring preloader in process 885
Run options: --seed 52045

# Running:

.#<Micropost:0x0000562d269dbb98
 id: 980190962,
 content: "MyText",
 user_id: 1,
 created_at: Wed, 12 Jun 2019 23:57:39 UTC +00:00,
 updated_at: Wed, 12 Jun 2019 23:57:39 UTC +00:00>
F...F..........

Finished in 1.642912s, 9.7388 runs/s, 11.5648 assertions/s.

  1) Failure:
MicropostsControllerTest#test_should_create_micropost [/myapp/test/controllers/microposts_controller_test.rb:19]:
"Micropost.count" didn't change by 1.
Expected: 3
  Actual: 2

  2) Failure:
MicropostsControllerTest#test_should_update_micropost [/myapp/test/controllers/microposts_controller_test.rb:39]:
Expected response to be a <3XX: redirect>, but was a <200: OK>

16 runs, 19 assertions, 2 failures, 0 errors, 0 skips
```

#　原因
`@micropost.user_id`の値が１で@userを見つからずエラーなっていた。
fixture(DBテストデータ)のUser.idが1じゃなく 9834334でpostデータのuser_idが１なのが原因でした。（自分の環境だけ？）　DBのauto_incrementを修正でも可能なのかな

# 修正箇所
`setup do`で取得した`@user.id`をcreate,updateのPOSTデータとして指定しました。  

```microposts_controller_test.rb
require 'test_helper'

class MicropostsControllerTest < ActionDispatch::IntegrationTest
  setup do
    @user = users(:one)
    @micropost = microposts(:one)
  end

  test "should get index" do
    get microposts_url
    assert_response :success
  end

  test "should get new" do
    get new_micropost_url
    assert_response :success
  end

  test "should create micropost" do
    assert_difference('Micropost.count') do
      post microposts_url, params: { micropost: { content: @micropost.content, user_id: @user.id } }
    end

    assert_redirected_to micropost_url(Micropost.last)
  end

  test "should show micropost" do
    get micropost_url(@micropost)
    assert_response :success
  end

  test "should get edit" do
    get edit_micropost_url(@micropost)
    assert_response :success
  end

  test "should update micropost" do
    patch micropost_url(@micropost), params: { micropost: { content: @micropost.content, user_id: @user.id } }
    assert_redirected_to micropost_url(@micropost)
  end

  test "should destroy micropost" do
    assert_difference('Micropost.count', -1) do
      delete micropost_url(@micropost)
    end

    assert_redirected_to microposts_url
  end
end

```
macOS10.15Betaにしたあと申請したアプリが「Invalid Binary」になる問題

SwiftUIをやりたくてmacOSをβ版にアップデートしてみたものの、（今まで問題なく申請できていた）自分のアプリを申請したときに「ITMS-90111: Invalid Toolchain」になってしまうという現象がありました。

理想的な方法ではないと思いますが、この方法で問題を解決することができたので、他の人のためにメモしておきます😌

＜問題再現手順＞

①macOS10.15 & Xcode10.2.1を使ってアーカイブを作ってAppStoreへアップロード
②AppStoreConnectからアプリ申請
③ステータスが「Waiting For Review」に変更される
④（2−3分後）ステータスが「Invalid Binary」に変わって拒否される

＜対処方法＞

①Macをリカバリーモードで立ち上げて、コマンドラインから以下のコマンドを打ってSIPを無効化してSystemのファイルをいじれるようにする

```
csrutil disable
```

②SystemVersionをお好きな方法で編集

```
/System/Library/CoreServices/SystemVersion.plist
```

上記のファイルの「ProductBuildVersion」という項目が「19A471t」（macOS10.15 Beta1の値）になっていると思うので、「18F203」（macOS10.14.5)に書き換え  

```
<plist version="1.0">
<dict>
        <key>ProductBuildVersion</key>
        <string>18F203</string>
        <key>ProductCopyright</key>
        <string>1983-2019 Apple Inc.</string>
        <key>ProductName</key>
        <string>Mac OS X</string>
        <key>ProductUserVisibleVersion</key>
        <string>10.15</string>
        <key>ProductVersion</key>
        <string>10.15</string>
        <key>iOSSupportVersion</key>
        <string>13.0</string>
</dict>
</plist>
```

③再度Macをリカバリーモードで立ち上げて、SIPを忘れないように有効化しておく

```
csrutil enable
```


④アーカイブして申請


これで安心してSwiftUIを楽しめます😄
Heroku+Railsでの定期処理をささっと（Heroku Scheduler）

## Heroku Schedulerを導入

以下よりアプリにアドオンを追加。
https://elements.heroku.com/addons/scheduler

## Rakeタスクを作成

```bash
rails g task create_log
```

作成されたlib/tasks/create_log.rakeを編集

```ruby:lib/tasks/create_log.rake
namespace :create_log do
  desc "ログを作成" # 説明

  task execute: :environment do #タスク名（今回はexecute）は自由
    Log.create(amount: 100) # ここに処理を記入
  end
end
```
タスクが作成されているかチェック

```bash
rake -T

# ...
# rake create_log:execute                  # 注文を取得
# ...

# 実行
rake create_log:execute
```

## Heroku Schedulerでの設定
Heroku Schdulerアドオンページに行き、「Create Job」からジョブを作成
<img width="615" alt="スクリーンショット 2019-06-14 13.57.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/3371a325-88dc-b5ec-d367-57644cdf78c5.png">

定期処理の頻度と、実行するコマンドを入力し、保存。
<img width="415" alt="スクリーンショット 2019-06-14 14.00.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/75903474-049a-7ec1-c7af-d490e9dc89c7.png">

## 参考
Heroku公式のガイド（英語）
https://devcenter.heroku.com/articles/scheduler
年齢を計算する

## Date型から年齢の整数に変換するコードを毎回書いている気がします

### ruby
```rb
require 'date'
(Date.today.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10_000
```

### ruby(ActiveSupport)
```rb
(Date.current.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10_000
```

```rb
(Date.today.in_time_zone.to_i - birthday.in_time_zone.to_i) / 1.year
```

### javascript
```js
birthDate => Math.floor((new Date() - new Date(birthday).getTime()) / 3.15576e+10);
```
pandasにcsvを読み込み指定列をリストにする

以下のようなCSVファイルから１列目の情報を取得してリストに入れたい場合の方法。

```file:csv
スプラ,1285,1285,2925,名詞,固有名詞,*,*,*,*,スプラトゥーン,スプラトゥーン,スプラトゥーン
さかなクン,1285,1285,5494,名詞,固有名詞,*,*,*,*,さかなクン,サカナクン,サカナクン
```

```python:sample.py
>>> import pandas as pd
>>> userdicdf = pd.read_csv('/usr/lib/mecab/dic/userdic/sample_userdic.csv', sep=',', encoding='utf-8', index_col=False, header=None)
>>> list(userdicdf[0])
['スプラ', 'さかなクン']
```
Rails の session store に Heroku Redis を利用する

# 参考
- [Heroku Redis \- Add\-ons \- Heroku Elements](https://elements.heroku.com/addons/heroku-redis)
- [Heroku Redis \| Heroku Dev Center](https://devcenter.heroku.com/articles/heroku-redis)

# 1. Heroku CLI で アドオン を追加

heroku CLI で heroku-redis アドオンを追加する

```shell-session
$ heroku addons:create heroku-redis:hobby-dev 

Creating heroku-redis:hobby-dev on ⬢ xxxxx... free
Your add-on should be available in a few minutes.
! WARNING: Data stored in hobby plans on Heroku Redis are not persisted.
redis-xxxxx-xxxxx is being created in the background. The app will restart when complete...
Use heroku addons:info redis-xxxxx-xxxxx to check creation progress
Use heroku addons:docs heroku-redis to view documentation
```

heroku CLI で 環境変数 `REDIS_URL` (Redis のエンドポイント)が追加されてることを確認する

```shell-session
$ heroku config

=== shakestagram Config Vars
...
REDIS_URL: redis://xxxxx@xxxxx:xxxxx
...
```

# 2. Rails で session store の設定

*Gemfile*で `redis-rails` を導入する

```ruby
# Gemfile
gem 'redis-rails'
```

redis のエンドポイントを環境変数 `REDIS_URL` から取得するように設定する

```ruby
# config/initializers/session_store.rb
if Rails.env.production?

  # Production では session_store に Redis を利用する
  Rails.application.config.session_store :redis_store, {
    servers: ENV['REDIS_URL'],
    expire_after: 1.week
  }

else
  # Production以外 では session_store に cookie_store(default) を利用する
  Rails.application.config.session_store :cookie_store, expire_after: 1.week

end
```
【R言語】楽天のレビューデータをスクレイピングしてみた

趣味の範疇ですが、着実にデータ加工おじさんとなりつつある筆者です。
「データ加工が楽しくなってきたし、次はAmazonでもスクレイピングしてみっか！」と意気込んだまではよかったのですが、[すでに偉人が成し遂げられていた](https://qiita.com/A_KI/items/6863d158b9c938055f5a)ことが判明しまして、速攻で轟沈した次第。

諦め悪くも楽天のレビューデータをスクレイピングしてみたので、どなたかのご参考にでもなれば幸いです。

###参照先のレビューデータ

~~Amazonに比べてレビュー数が少なくてアレですが~~
今回参考に使用するデータはサンクチュアリ社から出版されているミニマリストしぶさんの[『手ぶらで生きる。 見栄と財布を捨てて、自由になる50の方法』](https://review.rakuten.co.jp/item/1/213310_19053873/1.1/)を参照先にしました。
面白いから未読の人は読んでみてね。

![手ぶらで生きる.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162354/04253446-b22c-9fad-6614-dd517c125ab9.png)


###実装

では、早速実装してみます。
まずはパッケージの宣言、それから読み込みたいWebページの情報をread_html関数により抽出します。

```r:rakuten_review.r
# ライブラリ -------------------------------------------------------------------

pacman::p_load(pipeR,textreadr,rvest,lubridate,tidyverse)


# ソース本文 -------------------------------------------------------------------

url_txt <- "https://review.rakuten.co.jp/item/1/213310_19053873/1.1/"

#ページの読み込み
data <- read_html(url_txt)
```

次に投稿者、内容、使いみち、使う人、購入した回数の情報それぞれの情報を下記のコードのように抽出します。
~~できれば評価（星〇点）も抽出したかったのですが、構造を見たところ画像データが埋め込まれているようでして、どうやったら抽出できるかわからなかったので断念しました。~~
(2019/06/19修正)大変ありがたくコメントいただける方がいらっしゃいまして、星の数も無事取得することができました。
ご指摘くださった方、ありがとうございます。

```r:rakuten_review.r
#投稿者
name <-data %>>%
    html_nodes(xpath = "//dt[@class = 'revUserFaceName reviewer']") %>%
    html_text(.,trim = FALSE)

#内容
review <-data %>>%
  html_nodes(xpath = "//dd[@class = 'revRvwUserEntryCmt description']") %>%
  html_text(.,trim = FALSE)


#使いみち
use <-data %>>%
  html_nodes("#revRvwSec .revRvwMain .revRvwMainInr .revRvwUserMain .revRvwUserDisp .revUserDispList") %>%
  html_text(.,trim = FALSE) %>>%
  as.data.frame() %>>%
  filter(grepl("商品の使いみち", .))

#商品を使う人
user <-data %>>%
  html_nodes("#revRvwSec .revRvwMain .revRvwMainInr .revRvwUserMain .revRvwUserDisp .revUserDispList") %>%
  html_text(.,trim = FALSE) %>>%
  as.data.frame() %>>%
  filter(grepl("商品を使う人", .))

#購入した回数
nof <-data %>>%
  html_nodes("#revRvwSec .revRvwMain .revRvwMainInr .revRvwUserMain .revRvwUserDisp .revUserDispList") %>%
  html_text(.,trim = FALSE) %>>%
  as.data.frame() %>>%
  filter(grepl("購入した回数", .))

#星の数
stars <- data %>>%
  html_nodes(xpath = '//*[contains(concat( " ", @class, " " ), concat( " ", "value", " " ))]') %>%
  html_text(.,trim = FALSE)
```

データを抽出したら最後に結合し、確認してみます。

```r:rakuten_review.r

df <- tibble(name, review, use, user, nof,stars)  

view(df)  

```

![df.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162354/5beb03a2-8ea1-ec14-6cf1-3e0ff2f024f0.png)


できました！
ここまで出来れば解析が捗りそうですね。
やっていきましょう。
【速報】Ruby の trunk に pipeline operator がはいった

[ブログ記事](http://secret-garden.hatenablog.com/entry/2019/06/14/002651)からの転載です。

## 追記

pipeline operator の議論は RubyKaigi 2019 の Ruby Committers vs the World で話が出ていたみたいですね。


* [[JA|EN] Ruby Committers vs the World - YouTube](https://www.youtube.com/watch?v=5eAXAUTtNYU&amp=&feature=youtu.be&amp=&t=1944)



取り急ぎまとめ。
今日、Ruby の開発者会議に参加させて頂いて、さっき返ってきて ML みてたんですがいつの間にか [pipeline operator](https://github.com/ruby/ruby/commit/f169043d81524b5b529f2c1e9c35437ba5bc3a7a) がマージされていました。
思わず3度ぐらい ML と commit を見直してしまいました。
え、ほんまに？？？


* commit: [Add pipeline operator [Feature #15799] · ruby/ruby@f169043 · GitHub](https://github.com/ruby/ruby/commit/f169043d81524b5b529f2c1e9c35437ba5bc3a7a)
* issues: [Feature #15799: pipeline operator - Ruby trunk - Ruby Issue Tracking System](https://bugs.ruby-lang.org/issues/15799)

開発者会議では議論されてなかったんですが、終わったあとに何があったんや…（会場の都合でオフライン勢は先に解散してオンライン勢で議論が続いていたみたい。
と、言うことでこの機能の提案自体は前から興味があったので現時点でどうなっているか簡単にまとめてみました。


## `|>` でメソッド呼び出し

今までは以下のように `.` でメソッドを呼び出したんですが、

```ruby
foo()
 .bar(1, 2)
 .display
```

`|>` でもメソッドを呼び出せるようになりました。

```ruby
foo()
 |> bar 1, 2
 |> display
```

上記の違いをみてもらうとわかると思うんですが、今までは `plus(5, 2).to_s(2)` のようにメソッドチェーンする場合、 `()` を付ける必要がありました。
しかし `|>` を使用すると `()` をつけずに `plus 5, 2 |> to_s(2)` のようにメソッドチェーンする事が出来ます。
これにより `plus 5, 2` というメソッド呼び出しをチェーンする場合、いちいち `plus(5, 2)` と書かずに `plus 5, 2 |> to_s(2)` というようにメソッドチェーンする事が出来ます。

## 使用例

```ruby
def plus(a, b)
  a + b
end

# p plus(5, 2).to_s(2) と等価
p (plus 5, 2 |> to_s(2))
# => "111"


# x = (1..).take(10).map { |e| e * 2 }
x = (1.. |> take 10 |> map { |e| e * 2 })
# => [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
```

こんな感じで `|>` を使うことが出来ます。
その他、詳しい使用例は [Ruby 開発者会議の議事録](https://docs.google.com/document/d/1XP_e-3utXlCaxZLJrov6c428ZNaMPmxa3eh9MASrzkI/edit#)を参照してください。


## 注意点

`|>` は優先順位が低いため代入演算子やメソッドの引数に渡す場合に注意があるようです。

```ruby
p plus 5, 2 |> to_s(2)
```

の場合は

```ruby
p(plus 5, 2) |> to_s(2)
```

と解釈され、

```ruby
x = 1 + 2 |> to_s(2)
```

は

```ruby
(x = 1 + 2) |> to_s(2)
```

のように解釈されるみたいです。
これを回避する場合は明示的に `()` をつけて処理する必要があります。

```ruby
def plus(a, b)
  a + b
end
p (plus 5, 2 |> to_s(2))
# => "111"

x = (1 + 2 |> to_s(2))
p x
# => "11"
```

## 所感

これ、提案を見たときからめっちゃ便利そうーけど Ruby 的にはどうなんだろうなあ…と思っていたんですがあっさりマージされて面食らっています。
もうちょっと `|>` の記号とか議論されるのかと思っていましたが…。
で、実際書いてみてどうなのかと言われると慣れると『ああ、引数を渡したから `()` でくくって…』みたいなストレスがなくなるので意外としっくり来ますね。
Ruby はメソッド呼び出しで `()` を省略出来るのでかなり親和性が高いと思います。
なんというか書いてて気持ちがいいというか。
このあたりは実際に使ってみない事にはわからないと思うので『なんではいったの？』って思う人は1度使ってみてほしいです。
コードリーディングの面でいえば慣れるまでに時間がかかるとは思うんですが果たしてどうなるのか…。
ってか、Ruby 2.7 での追加機能がやばすぎてやばい。
Pythonで論理プログラミングを行う　〜芸人は誰かを推測する〜

# まず始めに
Deep learningの勉強をしようと思った時に基礎的なことから学びたいと思い、勉強してみました。基本的なAIを学ぶために必要な論理プログラミングの実装を行ってみた。

参考にした本はこちらです。
[PythonによるAIプログラミング入門] https://www.oreilly.co.jp/books/9784873118727/

# 今回使用したもの
python3.6
kanren

# 論理プログラミングとは
プログラミングのパラダイムの一つ。パラダイムは、プログラムを書くときの構成やその方法につい手の考え方の枠組ということなようです。プログラムのパラダイムには、様々な種類があって、よく聞くオブジェクト指向型もその一つです。細かい種類の紹介は省きます‥
今回は、その中でも論理型と呼ばれるものに焦点を当て、行っていきたいと思います。

「論理型では、事実と推論する際の規則から成るデータベースの上で自動的に推論することによって計算を行います。つまりは、事実となるデータが無ければ、論理プログラミングを行うことは困難になると言うことです。ここでいう事実は、処理中のプログラムとデータ中で真となる文のことらしいです。」


# パズルの解法（論理プログラミングの少し応用）
今回は、パズルの条件を決めることでプログラムが解を求めるようにプログラミングしていきます。
ある4人の情報を設定し、欠けた情報をプログラムが教えてくれるというものです。4人の名前は、Bob、James、Zaksho、Kenjiであり、それぞれ異なる仕事をしており、異なる色の服を着ており、異なる国に住んでいるとします。

- Bobは青い服を着ている。
- ITエンジニアはカナダに住んでいる。
- Zakoshoはアメリカに住んでいる。
- 黒い服を着ている人はオーストラリアに住んでいる。
- JamesはITエンジニアである。
- Kenjiはオーストラリアに住んでいる。
- パイロットはフランスに住んでいる。
- 芸人をしているのは誰だ？

目標は芸人をしている人を見つけることです。では、実際にコードを書いて芸人を見つけましょう！！！！！(なんとなく答えは想像できますが‥)

```python3:pazule.py
from kanren import *

people = var()

kisoku = lall((eq, (var(), var(), var(), var()), people),
              (membero, ('Bob', var(), 'blue', var()), people),
              (membero, (var(), 'ITエンジニア', var(), 'Canada'), people),
              (membero, ('Zakosho', var(), var(), 'USA'), people),
              (membero, (var(), var(), 'black', 'Australia'), people),
              (membero, ('James', 'ITエンジニア', var(), var()), people),
              (membero, ('Kenji', var(), var(), 'Australia'), people),
              (membero, (var(), 'パイロット', var(), 'France'), people),
              (membero, (var(), '芸人', var(), var()), people),
             )

solver = run(0, people, kisoku)
0
output = [question for question in solver[0] if '芸人' in question][0][0]
print(output + ' is 芸人')
```
これを実行すると、
```Zakosho is 芸人 
```
というような結果が出てきました！

#表の表示をするために

上述のものに以下を書き加えると、

```python3:pazule.py
print('details:')
name = ['Name', 'job', 'Color', 'Country']
print('\n' + '\t\t'.join(name))
print('=' * 57)
for item in solver[0]:
    print('\t\t'.join([str(x) for x in item]))
```

##表
```
details:

Name		job		Color		Country
=========================================================
Bob		パイロット		blue	    France
James	ITエンジニア	~_9		   Canada
Zakosho		芸人		~_11		USA
Kenji		~_13	black	    Australia
```

次回は、ヒューリスティック探索などについて書いてみようと思います。
もしくは、遺伝的アルゴリズムについて書くかもしれないです。
Property Wrappersで値の検査をしてProperty Wrappersを学んでみた

Swift5.1（？）の新機能Property Wrappersを学ぶために、Property Wrappersを使った値の検査を書いてみました。

まず検査を担当する、Wrapperすると言ったら良いのかな？の型です。

```swift
@propertyWrapper
struct Condition<T> {
    let inCond: (T) -> Bool
    let outCond: (T) -> Bool
    var _value: T!
    
    init(in inCond: @escaping (T) -> Bool, out outCond: @escaping (T) -> Bool) {
        self.inCond = inCond
        self.outCond = outCond
    }
    
    var value: T {
        get {
            precondition(outCond(_value))
            return _value
        }
        set {
            precondition(inCond(newValue))
            _value = newValue
        }
    }
}
```

@propertyWrapperを付けて記述します。inCond・outCondは代入時・読み出し時の検査です。@propertyWrapperではvalueプロパティの宣言が必要です。

次にConditionを利用するコードを書いてみます。

```swift
class A {
    @Condition(in: { !$0.string.isEmpty }, out: { $0.string == $0.string2 })
    var b: B
    
    func copy() {
        $b._value.copy()
    }
}

struct B {
    var string: String
    var string2: String = ""
    
    mutating func copy() {
        string2 = string
    }
}

var a = A()
a.b = B(string: "test")
a.copy()
print(a.b)
```

Aには@Conditionを付けて宣言したvar b:Bがあります。このプロパティbがConditionでラップされていることになります。
`a.b = B(string: "test")`で代入するときに@Conditionのinが実行されてpreconditionに渡されます。
`print(a.b)`で読み出すときにoutが実行されます。
もし`B(string: "")`（空文字列）を代入するとinがfalseになってpreconditionでクラッシュします。a.copy()を行ってB.stringをB.string2に代入しておかないとoutがfalseになってクラッシュします。
`func copy()`では、$b._value.copy()を実行しています。もしb.copy()を行うと@Conditionの読み出しが発生してoutがfalseになるのでクラッシュしてしまいます。ですので、@Conditionを回避するにはCondition._valueを直接操作する必要がありました。

これでだいたいの動作が把握できたように思います。

この検査、ちょっとDbCっぽい記述かなと思いました。クロージャをラップしてDbCの様な記述ができると面白いと思いましたが、

```swift
@Condition(...)
var f: (String) -> String
```

のfの型のConditionでの処理が思いつきませんでした。
GoでJWTまわりTips

[jwt-go](github.com/dgrijalva/jwt-go)まわりのTips

## 基礎

以下の記事が参考になる

>Go言語で理解するJWT認証 実装ハンズオン - Qiita
https://qiita.com/po3rin/items/740445d21487dfcb5d9f

## claimsにstructを使う

上記の例ではmapを使っているがstructを使うときは以下のようにする
https://godoc.org/github.com/dgrijalva/jwt-go#example-NewWithClaims--StandardClaims

独自のfieldを使うときは以下を参考にする（StandardClaimsを埋め込んだstructを使う）
https://godoc.org/github.com/dgrijalva/jwt-go#ex-NewWithClaims--CustomClaimsType

## contextからclaims取得

例

```go
func GetIDFromContext(r *http.Request) (uint, error) {
	user := r.Context().Value("user")
	claims := user.(*jwt.Token).Claims.(jwt.MapClaims)

	sid, ok := claims["sub"].(string)

	if !ok {
		return 0, errors.New("id type not match")
	}

	id, err := strconv.Atoi(sid)
	if err != nil {
		return 0, err
	}
	return uint(id), nil
}
```

structとしてパースしたいが、[auth0/go-jwt-middleware では内部でjwt.Parseを使っている](https://github.com/auth0/go-jwt-middleware/blob/master/jwtmiddleware.go#L203)のでmapで参照する。

jwt自体にはstructとしてパースする関数ParseWithClaimsがある
https://godoc.org/github.com/dgrijalva/jwt-go#ex-ParseWithClaims--CustomClaimsType

## test

```go

// func Something(w http.ResponseWriter, r *http.Request) のテスト

// token取得しておく

req := httptest.NewRequest(http.MethodGet, "/", nil)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %v", token))

w := httptest.NewRecorder()

h := JwtMiddleware.Handler(http.HandlerFunc(Something))

h.ServeHTTP(w, req)

if w.Code != http.StatusOK {
	t.Errorf("failed something. want %d got %d (%v)", http.StatusOK, w.Code)
}
```

## [swag](https://github.com/swaggo/swag)用Header設定

認可が必要なハンドラに以下を設定する

```go
// @Param Authorization header string true "Bearer"
```

>How to add the custom request header · Issue #29 · swaggo/swag
https://github.com/swaggo/swag/issues/29

例

```go
// Something godoc
// @Summary Something
// @Description Do something
// @ID get-something
// @Produce  json
// @Param Authorization header string true "Bearer"
// @Router /something [get]
func Something(w http.ResponseWriter, r *http.Request) {
}
```
Cloudformationでエラー: Has prohibited field Resource 

こんな感じのテンプレートで表題のエラーが発生。

```yaml
    LaboLambdaRole:
      Type: AWS::IAM::Role
      Properties:
        Path: /
        RoleName: "LaboLambdaRole"
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action: sts:AssumeRole
              Principal:
                Service:
                  - lambda.amazonaws.com
            - Effect: Allow
              Action: s3:ListAllMyBuckets
              Resource: "arn:aws:s3:::*"
        ManagedPolicyArns:
          - arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess
```

# エラー

```bash
An error occurred: LaboLambdaRole - Has prohibited field Resource (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument; Request ID: 11ee95fd-xxxx-xxxx-xxxx).
```

# 結論
`AssumeRolePolicyDocument` は `AssumeRole` のためのセクションであり `Resource` は定義できない。
`AWS::IAM::Policy` を利用する。


```yaml
    LaboLambdaRole:
      Type: AWS::IAM::Role
      Properties:
        Path: /
        RoleName: "LaboLambdaRole"
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action: sts:AssumeRole
              Principal:
                Service:
                  - lambda.amazonaws.com
        ManagedPolicyArns:
          - arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess

    LaboLambdaRolePolicies:
      Type: "AWS::IAM::Policy"
      Properties:
        PolicyName: "root"
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            -
              Effect: "Allow"
              Action: s3:ListAllMyBuckets
              Resource: "arn:aws:s3:::*"
        Roles:
          -
            Ref: "LaboLambdaRole"
```
C#でSlackへWebSocket接続(RTM)

[Slack Platform: Community | Slack](https://api.slack.com/community)でリンクされている
[Inumedia/SlackAPI: .NET Implementation of the Slack team communication platform API.](https://github.com/Inumedia/SlackAPI)
を使う。

.nugetはzipなのでそのまま解凍して.dllを取得できる。(GitHubのリリースよりあたらしいみたい)

OAuthトークンはアプリを作った画面のもので良い。

https://api.slack.com/apps
で見れる・作れるアプリにBotを追加して、
https://api.slack.com/apps/{AppsID}/bots
のトークンを使う。

有象無象のアプリには使わないので、URLを使ったcodeの取得や認証は必要なし。(というかそれで取得した結果が設定画面上で見れるOAuth Tokenと一緒)

メッセージをPostするならSlack APIが使う`Newtonsoft.Json.dll` を取得してリンクする必要があるが、
バージョンをあわせるために現時点での最新の12ではなく9(9.0.1)のdllを取得する。 GitHubから。

サンプルのコードが非常に罠で、

```csharp

        SlackSocketClient client = new SlackSocketClient("tokeen");
        client.Connect((connected) =>{
            Console.WriteLine("cone");
            // This is called once the client has emitted the RTM start command
            //clientReady.Set();

        }, () =>{
            Console.WriteLine("cone2");
            // This is called once the RTM client has connected to the end point
        });

```

と書いてもコールバックに入らない。
つまりはWebSocketの通信が確立されない。

これは`SlackSocketClient`のbaseの`SlackClient`の`Connect`を実行しているからで、
Websocketのための通信には

```csharp
client.ConnectSocket(() => {
    Console.WriteLine("ConnectSocket");
});
```

こっちを使う。

`client.OnMessageReceived`などは`ConnectSocket`によって得られる`SlackSocket underlyingSocket;`で行われる。

…が、Windows 7では.Net FrameworkがWebSocketにデフォルト対応していないので、結局使えないのである。

[System.Net.WebSocketsはWindows 7では動かない - はつねの日記](http://hatsune.hatenablog.jp/entry/2017/10/07/173313)
>延長サポートの終了こそ2020年1月14日ということでまだ先ですが

半年切りました…

使いたいなら自分でWebsocket用ライブラリに差し替えるコードを書いてビルドするしかないかなあ。

# 参考

[SlackでOAuth2を利用したときのメモ - Qiita](https://qiita.com/subarunari/items/3e4c6060fcefd4c65257)
シェルソート

- 挿入ソートを「大雑把にやる」ことを繰り返すことで全体を整列させていくのがシェルソート
    - 「`width`ごとに挿入ソートをする」を繰り返す
- 「シェル」は人名

```go
func ShellSort(target []int) []int {
	n := len(target)
	width := 1
	for width < n {
		width = 3*width + 1
	}
	for width > 1 {
		width /= 3
		log.Printf("---- width: %d ----\n", width)
		for i := width + 1; i < n; i++ {
			v := target[i]
			j := i - width
			for v < target[j] {
				log.Printf("%v\n", target)
				target[j+width] = target[j]
				j -= width
				if j < 0 {
					break
				}
			}
			target[j+width] = v
		}
	}
	return target
}
```

```
2019/06/14 13:07:37 Target: [0 7 5 6 3 10 1 8 2 4 11 9]
2019/06/14 13:07:37 ---- width: 4 ----
[0 7 5 6 3 10 1 8 2 4 11 9]
[0 7 1 6 3 10 5 8 2 4 11 9]
[0 7 1 6 2 10 5 8 3 4 11 9]
[0 7 1 6 2 10 5 8 3 10 11 9]
2019/06/14 13:07:37 ---- width: 1 ----
[0 4 1 6 2 7 5 8 3 10 11 9]
[0 1 4 6 2 7 5 8 3 10 11 9]
[0 1 4 6 6 7 5 8 3 10 11 9]
[0 1 2 4 6 7 5 8 3 10 11 9]
[0 1 2 4 6 7 7 8 3 10 11 9]
[0 1 2 4 5 6 7 8 3 10 11 9]
[0 1 2 4 5 6 7 8 8 10 11 9]
[0 1 2 4 5 6 7 7 8 10 11 9]
[0 1 2 4 5 6 6 7 8 10 11 9]
[0 1 2 4 5 5 6 7 8 10 11 9]
[0 1 2 3 4 5 6 7 8 10 11 9]
[0 1 2 3 4 5 6 7 8 10 11 11]
2019/06/14 13:07:37 Sorted: [0 1 2 3 4 5 6 7 8 9 10 11]
```
java scriptの変数、varとletの違い。

java scriptの変数宣言する際に注意しなければならない、varとletの違いについて解説したいと思います。因みにconstについては特にここでは取り上げませんのでご了承下さい。

##varとletの違い
var
　変数を宣言し、ある値に初期化することもできる。
let
 ブロックスコープのローカル変数を宣言し、ある値に初期化することもできる。

変数にはグローバル変数とローカル変数があります。
変数を関数の外側で宣言すると、その変数はその文書のどのコードからも使用できるグローバル変数となり、変数を関数の内側で宣言すると、その変数はその関数の中でしか使用できないローカル関数となります。ここまではvarとletでは違いがありません。

ブッロクスコープのローカル変数を宣言とletの説明に書いてありますが、ここが大きな違いになります。

ECMAScript2015より前のJavaScriptにはブロックスコープありません。ブロックスコープとはif、for、whileなどに用いられる｛　｝で囲んだ部分を指します。

次の例を見てみましょう。

``` sample.js
if (true) {
  var x = 5;
}
console.log(x);  // x は 5
```

varで宣言したこの場合、ブロックの外からxの値を参照することができてしまいます。
なぜならECMAScript2015より前のJavaScriptにはブロックスコープがないからです。
しかしこれをletで宣言した場合は以下のようになります。

``` sample.js
if (true) {
  let y = 5;
}
console.log(y);  // ReferenceError: y が定義されていない
```

上のコードではyはReferenceError、yは定義されていないよとコンソールに表示されました。つまりブロック内のyとブロックの外のyは別のものであると言うことです。

##変数の巻き上げ
もうひとつ、巻き上げと言われる点に違いがあります。
javaScriptには、例外を発生させることなく後に宣言した変数を参照できるというものがあります。これを巻き上げと言います。しかし、巻き上げられた変数はundefinedを返す事に注意してください。
言葉で説明しても分かりずらいと思いますので例を見てみましょう。

```sample.js
console.log(x);    /*undefined*/
var x = 3;
```

この場合巻きあけがおこなわれない場合はReferenceErrorが返ってくるはずです。しかしこの巻き上げによって変数xはundefinedを返しました。
これが巻き上げと言われるものです。
ECMAScript2015では、let(const)は巻き上げは行われません。そのため変数宣言前に変数を参照するReferenceErrorになります。
実際に見てみましょう。

```sample.js
console.log(x); 
   /*ReferenceError*/
let x = 3;
```
このようになります。
因みにこの巻き上げは関数でも違いがあります。
関数では、関数宣言のみ巻き上げが行われ、関数式は巻き上げが行われません。

```sample.js
/*関数宣言*/

foo(); 　　 /*"bar"*/

function foo() {
  console.log('bar');
}


/* 関数式 */

baz(); 　/* TypeError: baz は関数ではない*/

var baz = function() {
  console.log('bar2');
};
```

今回はこれで以上です。
間違いなどあればご指摘ください。
AWS Batchでストレージ容量を増やそうとしたらDockerが起動しなくなった

AWS Batchのストレージ容量を増やそうとEC2を作ってAMIをとろうとしたらDockerが起動しなくなっていたので内容をメモしておく。

# 現象

https://aws.amazon.com/jp/premiumsupport/knowledge-center/increase-default-ecs-docker-limit/

の手順でAWS Batchのストレージ容量を増やそうとEC2を作ってAMIをとろうとしたらDockerが起動しなくなっていた。

/var/log/dockerを見ると以下のようなエラーが出ていた。

```text
time="2019-06-14T02:04:44.849321733Z" level=error msg="[graphdriver] prior storage driver overlay2 failed: overlay2: unknown option dm.basesize"
Error starting daemon: error initializing graphdriver: overlay2: unknown option dm.basesize
```

# 対応方法

以下のように--storage-driver devicemapperを追加してdockerのストレージドライバを変更した。

```bash
#cloud-boothook
#!/bin/bash

cloud-init-per once docker_options echo 'OPTIONS="${OPTIONS} --storage-driver devicemapper --storage-opt dm.basesize=20G"' >> /etc/sysconfig/docker
```

# 原因

ここらへんの対応でDockerのデフォルトストレージドライバが変更になったらしい。
https://github.com/moby/moby/releases/tag/v1.13.1

AMIからEC2を起動する際にセキュリティアップデートが走ってDockerがアップデートし、デフォルトストレージドライバが変わってオプション指定が不整合になった？
curlでステータスコードを取得する

# とあるURLのステータスコード

至ってシンプルに、200とか、404とか取得したいなー。と。

`curl -LI [URL] -o /dev/null -w '%{http_code}\n' -s`
で取得できまする。

```e.g.
curl -LI https://www.favy.jp/hogehoge -o /dev/null -w '%{http_code}\n' -s
```

# とある複数URLのステータスチェック

`curl -LI [URL1] -o /dev/null -w '%{http_code}\n' -s >> tmp.txt`
を複数行に渡って書いたシェルファイルを作って実行しよう。

```
vim test.sh
```

```test.sh
curl -LI https://www.favy.jp/hogehoge -o /dev/null -w '%{http_code}\n' -s >> tmp.txt
curl -LI https://www.favy.jp/hogehoge2 -o /dev/null -w '%{http_code}\n' -s >> tmp.txt
curl -LI https://www.favy.jp/hogehoge3 -o /dev/null -w '%{http_code}\n' -s >> tmp.txt
curl -LI https://www.favy.jp/hogehoge4 -o /dev/null -w '%{http_code}\n' -s >> tmp.txt
・
・
```

チェックはこれで。

```
less +F tmp.txt
(tail -f tmp.txt)
```

※あまり大量にやっちゃ駄目よ。
【GitHub】CLIツールのHubを使ってターミナルからリモートリポジトリを操作しよう

#概要
Githubでのよくやる操作（リポジトリ作成，プルリク作成，イシュー作成，ブラウザを開く）をターミナルからCLIを使って操作してしまう話

#使うツール
[Hub](https://github.com/github/hub)

#Hubのインストール
```shell:shell
$ brew install hub
```

#リポジトリ作成
```:shell
$ hub create
```

#プルリク作成
```:shell
$ hub pull-request
//nanoエディターが開く
```
<img width="832" alt="スクリーンショット 2019-06-14 12.22.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390000/e7e063e7-49e5-c53b-925f-ad575d04f318.png">

Ctr+oでセーブ
Ctr+Xで終了する

#イシュー作成
```:shell
$ hub issue create
//nanoエディターが開く
```
<img width="832" alt="スクリーンショット 2019-06-14 12.28.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390000/8224190b-b7ad-89f0-5762-d966697da723.png">

#ブラウザで開く
```:shell
hub browse --
```

#Happy Hacking :sunglasses: !
GitHubへパスワードを含むファイルを誤ってpushした時、そのブランチを消しても内容はキャッシュされ続ける

タイトルの通りです。

# ではどうすればいいのか  
こういう時は慌てず、下記を参照して歴史修正をしましょう。  
https://help.github.com/en/articles/removing-sensitive-data-from-a-repository

# すでに消してしまった場合
この場合の解決策はGitHubへ問い合わせ中です。
ひとまずAPIキーなどは即座に変更するべきでしょう。

# 詳細
## はじまり
パスワードを含むファイルを間違えてcommitして、しかもpushしてしまったこと、エンジニアなら一度は経験するのではないでしょうか。
ここにも一人、そういううっかりさんがいたとします。`add-password`なんていう分かりやすいブランチをpushしてしまいました。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75888/00cee429-da2f-e9c3-605e-c65841068278.png)

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75888/6b409b6a-5a2e-50b0-8454-d2797fd43060.png)

しかし幸いにもあなたは、このPRを出す前にミスに気づくことができました。
そこでこのブランチを消すために、以下の画面からブランチを削除します。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75888/5ce06ebe-bfc0-2d97-60ee-9da860ce4f59.png)

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75888/279384b3-f914-ee4d-ae2e-9ae937efa7cb.png)

これで一安心。あなたはpasswordファイルを含まないコミットを作り、PRを出しました。

## 一安心・・・と思いきや
しかし数日後、Googleから「君のAPIキー漏れてるよ」と警告メールが来ます。
そんなはずはありません。そのブランチは消してある、と思いつつメールのURLを開くと...。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75888/1ba9a6da-a7e1-4a3c-a430-32740cdacf4d.png)

**なんか残ってる。**
URLをよく見ると、`https://github.com/<リポジトリオーナー>/<リポジトリ名>/blob/<commitのsha1>/<ファイル名>`となっています。更に良く見ると画面の[Tree]のところにcommitのsha1値が入っていることがわかります。
具体的にはこんなURLです。
https://github.com/akihiro-iwata/check-gitub-feature/blob/2bd6037d68c20fcf3f53261981c0ad1152277680/password.txt

**つまりブランチを消しても、その内容はGitHub上でキャッシュされ続けるため、パスワードは依然としてWeb上に公開されたままだったのでした。**

# 結論
GitHubへパスワードを含むファイルを誤ってpushした時、そのブランチを消しても内容はキャッシュされ続ける
【UE4】アニメキャラのあり得ない髪型を再現するPhysicsの設定方法

グーグル先生に聞いて、その通りにしても髪が粗ぶりまくりだったんですが解決しました。
自分の設定じゃないと粗ぶりまくります。どこがほかの人違うのか（汗

ツインテとかインテークとかの、重力無視した特殊な形の髪は、髪型通りにボーンを仕込むと、
Unreal4 Physics設定では、重力で真下に直線的に引き延ばされるので、変わってしまいます。
発想の転換で、ならば、髪型を無視してボーンを直線に仕込めば勝ちじゃね？　とやってみたら
出来ました。まぁあたりまえか。

その時の作業記録
**まずは、DCCツールでのボーン定義のとき　直線的に配置します**
![20190607a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/ab8827ec-acee-7784-522b-9d960c014c41.jpeg)

で、私流のPhysics設定
**１．コライダー**
![20190607b.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/91190b03-6c5b-c456-3fa1-91f84663a732.jpeg)
他の人の解説動画なんかだと、「LinerDamping」スルーなんですが、わたしの場合これを強めないと粗ぶります。
![20190607c.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/9e415af6-ef68-9c3b-4a4f-c983836c852c.jpeg)
サイズは極力小さくします。髪の形沿ってなくても、ボーンの節々でも当たればメッシュ全体的には
もぐりこまないですよね。

**２．回転軸**
![20190607d.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/ea5fee76-78dc-7610-3041-78c827912f5a.jpeg)

**３．スケルタルメッシュの設定**
![20190607e.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/675c903e-dbf0-e9aa-836f-8d67a9b9c082.jpeg)

**４．BPでボーンのフィジクス有効化**
　コライダーを付けたボーンを指定していきます。めんどくさがってRootなんかに設定すると大変なことになりますｗ
![20190607f.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/1d7d6ac1-7324-130d-da98-dac539508f35.jpeg)

**５．おまけで、例のアレを揺らす設定**
ポイントは回転軸ではなく、移動軸の設定にすることかも
緑の細い線が可動範囲です
少し惜しいのが、重力で下に垂れ下がる点ですが、それはそれでリアルかもｗ
![20190607omake1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/8a1396ea-27c4-6ab5-09a3-5ebe4528555c.jpeg)
![20190607omake2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/3d66c66b-95cc-13e3-2f5a-723a06c85c7d.jpeg)
NodeOptionsによるROS2ノードの初期化について

[ROS2関係トップページへ](https://qiita.com/NeK/items/7ac0f4ec10d51dbca084)

# Dashing Diademataからの初期化方法
[公式のRoadmap](https://index.ros.org/doc/ros2/Releases/Release-Dashing-Diademata/)にあるようにDashing Diademataからノードを初期化方法が変わった(まだ前の方法も使えるけど)．
Crystal ClemmysでのROS2ではノードの初期化として以下の二種類のコンストラクタが用意されていた([公式apiより](http://docs.ros2.org/crystal/api/rclcpp/classrclcpp_1_1Node.html#ab28b0b3c08b1a3597b1e0442822f46f2))．

```c++:c++の場合
rclcpp::Node::Node(
  const std::string & node_name, 
  const std::string & name_space="", 
  bool use_intra_process_comms = false)

rclcpp::Node::Node(
  const std::string & node_name,
  const std::string & name_space="",
  rclcpp::Context::SharedPtr context,
  const std::vector< std::string > & arguments,
  const std::vector< Parameter > & initial_parameters,
  bool use_global_arguments = true,
  bool use_intra_process_comms = false,
  bool start_parameter_services = true)
```

これがnode_name(ノードの名前)とname_space(ノードの名前空間)以外全部＋αをもつNodeOptionsクラスで初期化できるようになった([公式apiより](http://docs.ros2.org/dashing/api/rclcpp/classrclcpp_1_1Node.html#ab28b0b3c08b1a3597b1e0442822f46f2))．

```c++:新方法
rclcpp::Node::Node(
  const std::string & node_name,
  const NodeOptions & options = NodeOptions())

rclcpp::Node::Node(
  const std::string & node_name,
  const std::string & name_space,
  const NodeOptions & options = NodeOptions())
```
ちなみにNodeOptionsのところに引数を与えないとNodeOptions()によってデフォルト値を持ったものが自動的に渡される．
NodeOptionsの詳しい情報は[公式のapi](http://docs.ros2.org/dashing/api/rclcpp/classrclcpp_1_1NodeOptions.html)から．

# 推奨されるクラスのコンストラクタ
推奨されるコンストラクタは以下のようになる．
ちなみに，ここでの考え方としては

- ノードの名前は固定
    - ここではhoge_nodeとしている
- 同一ノードを複数起動させる場合，名前空間(name_space)で区別

としている．
ノードの名前を都度変えたい場合は，node_nameに関してもコンストラクタに記載することになる．

- クラス名
    - Hoge

```c++:hoge.hpp
class Hoge : public rclcpp::Node{
...
public:
  Hoge(const rclcpp::NodeOptions & options = rclcpp::NodeOptions());
  Hoge(const std::string & name_space, const rclcpp::NodeOptions & options = rclcpp::NodeOptions());
};
```

```c++:hoge.cpp
...
Hoge::Hoge(const rclcpp::NodeOptions & options = rclcpp::NodeOptions()) : Hoge("", options){}

Hoge::Hoge(const std::string & name_space, const rclcpp::NodeOptions & options = rclcpp::NodeOptions())
: Node("hoge_node", name_space, options){
// コンストラクタの処理
}
```

これを使う場合には以下のようになる(名前空間を使用していない場合)．

```c++:NodeOptionsを使用しない場合
#include <rclcpp/rclcpp.hpp>
#include "hoge.hpp"

int main(int argc, char * argv[]){
...
  auto node = std::make_shared<Hoge>();
...
}
```

```c++:NodeOptionsを使用する場合
#include <rclcpp/rclcpp.hpp>
#include "hoge.hpp"

int main(int argc, char * argv[]){
...
  std::vector<rclcpp::Parameter> params = { rclcpp::Parameter("use_sim_time", true) };
  rclcpp::NodeOptions node_options;
  node_options.parameter_overrides(params);
  auto node = std::make_shared<Hoge>(options);
...
}
```

# 参考
- [NodeOptionsのAPI](http://docs.ros2.org/dashing/api/rclcpp/classrclcpp_1_1NodeOptions.html)
- [公式のRoadmap](https://index.ros.org/doc/ros2/Releases/Release-Dashing-Diademata/)
    - 使い方の例が少し載っている
- [公式githubのNodeOptions](https://github.com/ros2/rclcpp/blob/master/rclcpp/include/rclcpp/node_options.hpp)
【UE4】初めてのパッケージングでるまづいたこと

### パッケージングで予想外のトラブルで困ったときの話です

最初に余計なプラグインを外しておこうと、　いつのまにか有効にしていた
　**Datasmith Content**
プラグインを無効にします。指示通り、再起動後
![20190614a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/98b67c4a-9904-8d2a-1fb2-ca270d96e7c1.jpeg)

普通に、**ファイル＞プロジェクトをパッケージ化＞Windows＞Windows32**
で始めます。
しばらくすると、赤いメッセージがめさんこ出てきて焦る
大量のログに軽く眩暈を起こしながら赤い部分を中心にみてると、

１．使ってないAnimationBP　※ボーンと関連付けられてないのがエラーになってる
　　消すことで対応
２．しかし、身に覚えのない　**DatasmithContent なんちゃらという赤いメッセージが大量に**
　　※多すぎるので一部のみの画像です
![20190614b.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/3f3ea063-3144-7158-51bd-c857707a999d.jpeg)

３．そしていつのまにか知らぬフォルダ「**BluePrint**」が出現
![20190614c.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435191/0993fb55-a281-4e1d-341c-81000bf453a6.jpeg)


### 結論としては
**１．「BluePrint」フォルダを削除
２．Datasmith Content　プラグインを復活（チェックを入れる）**

でパッケージングができるようになりましたが、原因とか対策が分からないままです。
参考になるか微妙ですが、原因不明のエラーで困ってる方の発想のヒントにでもなれば
【git】コミット間差分ファイル出力(zip保存)

##背景
サーバへのアップを手動でする機会がありました。

その際、「前回アップした最後のコミット」から「最新の状態」までの差分ファイルがディレクトリ構造ごと欲しかったので、その方法の備忘録。

##コマンド

コミット「yyyyyyy」から「xxxxxxx」までの差分ファイルがroot下にある状態で「hoge.zip」として保存されます。

```
git archive --format=zip --prefix=root/ xxxxxxx `git diff --diff-filter=d --name-only yyyyyyy` -o hoge.zip
```

xxxxxxx はコミットID（正確には「コミットSHA-1ハッシュ」というらしい）。

「最新(現在)の状態」までの差分ファイルが欲しいときは「**xxxxxxx**」→「**HEAD**」に変えます。

##参考
こちらの記事を参考にさせていただきました。(というかそのまんま)
[gitで差分ファイルを抽出する](https://qiita.com/kaminaly/items/28f9cb4e680deb700833)
コマンドの詳しい解説が書いてあってわかりやすいです。
LANからでもWANからでも同じコマンドで同じマシンにsshする方法

内容自体は[拾い物](https://unix.stackexchange.com/questions/107225/ssh-access-from-inside-and-outside-a-lan-using-the-same-terminal-command)

同じマシンにログインしたいのに、インターナルとグローバルのIPがそれぞれ違うと毎回コマンドを考えるのに脳みそを使ってしまうので、些細なことだけど結構煩わしい。
sshfsなどを使ってマウントしていると、場所を移すたびにunmountしてホストを修正してマウントし直しをする必要があるなど余計具体的に煩わしい。


## 解決策

上記stackexchangeには複数の解決策が提案されていましたが、自分はこれが一番わかりやすくスマートだと思いました。
コマンドの返り値によって使用する設定を選択できる `Match`という文法の存在がいちばんの肝です
以下のように設定することで、`ssh host`でどこからでも所定のマシンに接続できます


```~/.ssh/config

Match host Host exec "[[ $(curl -s ipinfo.io/ip) != '12.345.67.89' ]]"
    User user
    HostName 12.345.67.89

Match host Host exec "[[ $(curl -s ipinfo.io/ip) == '12.345.67.89' ]]"
    User user
    HostName 192.168.2.7
```
Windows10でWi-Fiの状態を示すアイコンが消えた時の対処

#はじめに
Windows10でテザリングをしようとした時に、Wi-Fiのアイコンが消えた時の対処方法です

##現象
wi-fiの状態を示すアイコン（電波っぽいやつ）が無い
![wifi-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/88c46d9b-ab4d-9fbe-fb4e-2c328c24f6d8.png)

ここにも無い
![wifi-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/bab87d3a-cf9b-ad96-fa71-c91585059fc9.png)

##対処方法
１．サービスを開く
![wifi-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/9f57ee2c-e02b-c454-c6da-34d2b53cc019.png)

２．一覧から「Network List Service」を見る
![wifi-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/3984e260-77c3-5bb7-a0fc-c300d543aff3.png)

３．おそらく「無効」になっているので「自動」にしてあげる
![wifi-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/72c8f4cb-fb1a-4fbc-db3a-be1e2a4593d6.png)

４．再起動する

##結果
Wi-Fiのアイコンが復活してると思います
![wifi-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/0e3a6cf5-d4ca-d1b7-4ec9-9a81d8e3b06a.png)

#おわりに
この現象はWindows10でたびたび起きる（らしい）です

何がトリガーになってるか分かりませんが、NLS（Network List Service）がオフになるみたいですね

働きたくないあまり無意識に寝ながらオフにしてるんでしょうか

それではまた
エクセルでJAVAアプリを超簡単生成！「ワンダーロボ」テーブル設計の手順

「ワンダーロボ」はExcel設計書を自ら分析しAIを利用！
自然言語で記述された業務ニーズをソースコードに転換！


##テーブル設計
テーブルとは情報を格納する、構造体と定義されます。

###ステップ1.　テーブル設計書のテンプレートを利用
###ステップ2.　設定内容をそれぞれ入力
###ステップ3.　ワンダーロボに取り込む

##ステップ1.　テーブル設計書のテンプレートを利用
##ステップ2.　設定内容をそれぞれ入力
・テーブル設計書テンプレートを利用して、赤枠内の各項目それぞれに「設定内容」を入力します。
※テーブルを定義する場合、セルにてエクセル関数は使えません。
#####入力例↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/5b0f3981-b75c-81f5-9c05-c07a6c473972.png)


**・テーブルID：**テーブル名に対応付けてデータベースに登録します。(半角のみ）空欄OK

**・テーブル名：**データベースにテーブルIDと対応付け保存される名称。空欄OK

**・画面作成：**「○」をつけるとテーブル項目を入力編集する管理画面と検索画面を作成します。
                   

**・インポート画面作成：**「○」をつけるとテーブル項目をCSV等の形式により
　　　　　　　　　　　  ファイル一括取り込みのインポート画面を作成します。（画面設計書シート不要）

**・フィールド名：**テーブル項目（フィールド名）としてデータベースに保存します。
　　　　　　　　半角のフィールドIDに対応する名称。空欄NG	
**・フィールドID：**フィールド名に対応付けてデータベースに登録します。(半角のみ）空欄OK

**・データ型：**テーブルフィールドのデータ型　 ドロップダウンから選択　空欄NG
　　　　　　　　（データ型：文字列・整数・日付・時刻・日付時刻・double・text・blob）
**・桁数：**テーブルフィールドの桁数（文字数）をデータ型によって設定します。
　　　　　　　・文字列：指定必須
　　　　　　　・整数・double　：指定可能
　　　　　　　・日付・時刻・日付時刻・text・blob：指定不要

**・必須：**「○」をつけると入力必須。入力項目が空欄だとチェックされてしまい、保存更新ができません。
		
**・主キー：**「○」をつけると該当フィールドを主キーに指定し、フィールド内で重複値を登録できないようにします。
		
**・デフォルト値：**フィールドの初期表示値

**・値内容：**　　
①自動採番の設定
　　　　　・自動採番に設定すると該当フィールドの表示種類が採番項目になります。
　　　　　・フィールドのデータ型を文字列に指定します。
　　　　　・フィールドの桁数が自動採番の桁数より長い必要があります。
　　　　　・フィールドのタイプが自動採番の際は、オートインクリメント型となり使用回数
　　　　　　によって番号が自動的に増加されて発番されます。
②DropdownListの設定
　　　　　・候補値をリストで直接入力します。
　　　　　・「保存値:表示値;」　　　例：「“0:日本;”」
　　　　　・保存する値と画面表示名称を「：」で区切り、リストの値を「；」で区切ります。
　　　　　・候補値リストを設定すると該当フィールドの表示種類がDropdownListになります。	
　　　　　・DropdownListには複数の候補値を入力できます。
　　　　　　例：フィールド「国名」の値で「“0:日本;1:アメリカ”」を入力、フィールドの表示が
　　　　　　DropdownListになり、候補値リストは日本とアメリカになります。

　　　　　     "0"/ "1"⇒保存値　　　"日本"/"アメリカ"⇒表示値
　　　　　　※保存値とはデータベースに格納されるデータ値です。
　　　　　　※表示値とは画面で表示されるデータ値です。


**・マスタ：**基本データを管理しやすく設定します。「Y」をつけるとマスタテーブルを自動的に新規作成します。

##ステップ3.　ワンダーロボに取り込む
###ワンダーロボの取り込み先はこちら↓
SaaSForceの開発環境にログインし、設計書ファイルをインポートします。
手順は　**SaaSForceシステム**===>**「システム」**===> **「開発設定」**===> **「システム自動構築」**です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/06d56e51-f2ec-e8c1-9bba-0c8adb9ad1e4.png)

####作成したテーブルの表示例↓
SaaSForceシステム===>「テーブル」===> 「テーブル定義・作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/136190d6-4435-89df-bd5e-f8acf9f985a6.png)
中間テーブルと多対多のアソシエーションについてまとめてみた

DBのレッスンで習った「DB設計」の復習です。
多対多の関係のテーブルをどうやって表すのかが難しかったので、備忘録してまとめてみます。

# まずは一対多のテーブルの作り方から

「生徒」と「部活」のテーブルを例にして考えます。
` 生徒は必ず1つだけ部活を選んで所属する `という前提条件があったとしたら、部活は複数人の部員を抱えていることになるので、一対多の関係が成り立ちます。
どの生徒がどの部活に所属しているか分かるようにしたい場合、部活のidを生徒に紐づければ良いので、テーブルは以下のようになります。

```Ruby:studentsテーブル

|Column|Type|Options|
|------|----|-------|
|student|string|null: false, index: true|
|club_id|integer|null: false|

Association
belongs_to :club
```

```Ruby:clubsテーブル

|Column|Type|Options|
|------|----|-------|
|club|string|null: false, index: true|

Association
has_many :students
```

これらをもとにデータを入れるとこんな感じになります。
`studentsテーブル`

|id|student|club_id|
|------|----|-------|
| 1 |田中　太郎|3|
| 2 |山田　花子|1|
| 3 |高橋　順子|1|

`clubsテーブル`

|id|club|
|------|----|
| 1 |バスケ部|
| 2 |野球部|
| 3 |ハンドボール部|

この二つのテーブルから、田中太郎さんはハンドボール部に所属していて、山田さんと高橋さんはバスケ部に所属しているというデータをとることができます。

# 多対多の関係のテーブルの定義の方法

ではもし前提条件が`生徒は複数の部活に所属しても良い`となったらどうなるでしょう。
上の生徒のテーブルにカラムを足して以下のようにしたとします。

`studentsテーブル`

|id|student|club1|club2|
|------|----|-------|-------|
| 1 |田中　太郎|3|2|
| 2 |山田　花子|1| |
| 3 |高橋　順子|1|3|
これは良くない例です。なぜなら、このように所属しているクラブを重複して書く書き方は、データベースの設計として間違ってるためです。そこで、中間テーブルを用意する必要があります。
`中間テーブルとは、多対多の関係を表すために用意するテーブル`です。
今回の場合、どの生徒とどの部活が結びつくかを表すテーブルをもう一つ用意すればいいので、そのテーブルをrelationsと名付けます。

`studentsテーブル`

|id|student|
|------|----|
| 1 |田中　太郎|
| 2 |山田　花子|
| 3 |高橋　順子|

`clubsテーブル`

|id|club|
|------|----|
| 1 |バスケ部|
| 2 |野球部|
| 3 |ハンドボール部|

`relationsテーブル`

|id|student|club|
|------|---|---|
| 1 |1|3|
| 2 |1|2|
| 3 |2|1|
| 4 |3|1|
| 5 |3|3|

こうすることで、studentカラムやclubカラムを重複することなく、関係を表すことができます。
定義の方法は以下のようになります。

```Ruby:studentsテーブル

|Column|Type|Options|
|------|----|-------|
|student|string|null: false, index: true|

Association
has_many :relations
has_many :clubs, through: :relations
```
```Ruby:clubsテーブル

|Column|Type|Options|
|------|----|-------|
|club|string|null: false, index: true|

Association
has_many :relations
has_many :students, through: :relations
```
二つのテーブルのAssociationに注目するとさっきまでの定義になかった`through: :relations`が見られます。これは、中間テーブルを明確に表すために必要な定義です。
*`また、中間テーブルはthroughの前に定義する必要があります。 
これはプログラミングが上から順番に読まれる性質があるためです。`*

```Ruby:relationsテーブル

|Column|Type|Options|
|------|----|-------|
|student|references|null: false, foreign_key: true|
|club|references|null: false, foreign_key: true|

### Association
belongs_to :student<br>
belongs_to :club<br>
```
relationsテーブルでは、指定するカラム名をstudent_idとせずにstudentとし、型はinteger型ではなくreference型にします。これはinteger型だと外部キー制約にならないためです。
Associationはひとつずつの組み合わせを表すためbelongs_toでそれぞれのテーブルを指定します。


# まとめ
1.中間テーブルとは多対多の関係の2つのテーブルをつなぐためのテーブル
2.中間テーブルでない2つのテーブルでは、Associationで
`thorough: :中間テーブル`　と記述する必要がある
3.中間テーブルでは、カラム名に_idは省き、型はreference型を指定する。


# 参考ページ
[railsガイド](https://railsguides.jp/)
[railsで多対多のアソシエーションの作り方と、出来ること](https://qiita.com/Kohei_Kishimoto0214/items/cb9a3d3da57708fb52c9)
[Railsの外部キー制約とreference型について](https://qiita.com/ryouzi/items/2682e7e8a86fd2b1ae47)
Windows for DockerでFlaskを動かすときにつまづいた

# つまづいたこと
Macで開発していたFlaskというか、DashのWebアプリをWindowsに持ってきてDocker上で実行すると、OSError: [Errno 8] Exec format errorが出て動かなかった

# 解決
単純ですが、PythonでShebangを指定するのを忘れていました。

```application.py
#!/usr/bin/env python
```

ちなみに以下のShebangを指定すると当たり前ですが、Permission deniedでエラー

```application.py
#!/usr/local/bin python
```
あと、基本的なことですが文字コードも大事です。
うっかりCRLFでファイルを保存して、Docker上のUbuntuで動かすと
No such file or directoryって言われます。
しっかりLFで保存します。

こんなことで2時間も使ってしまった。。。
Gasでgoogle Spreadsheetをjsonで返す方法

とりあえず適当に入力する
![スクリーンショット 2019-06-14 9.56.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115687/4bef43a6-571a-6466-e7df-fc47566eafc3.png)


お次は`ツール ＞ スクリプトエディタ`でスクリプト書いていきます

![スクリーンショット 2019-06-14 9.57.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115687/606cca9b-7acb-a82b-31e5-e1700be0b6e0.png)


ソースは下記から引用
>https://www.koreyome.com/web/make-spreadsheet-to-json-at-google-apps-script/

```
function getData(id, sheetName) {
  var sheet = SpreadsheetApp.openById(id).getSheetByName(sheetName);
  var rows = sheet.getDataRange().getValues();
  var keys = rows.splice(0, 1)[0];
  return rows.map(function(row) {
    var obj = {}
    row.map(function(item, index) {
      obj[keys[index]] = item;
    });
    return obj;
  });
}
 
function doGet(request) {
  var func = 'jsondata';
  var data = getData('xxx_スプレッドシートのURL_xxx', 'Sheet1');
  return ContentService.createTextOutput(func + '(' + JSON.stringify(data, null, 2) + ')')
  .setMimeType(ContentService.MimeType.JAVASCRIPT);
}
```

あとは公開するだけ
![スクリーンショット 2019-06-14 10.01.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115687/0c190909-ac3f-b861-9522-e0a22f5ee7d7.png)


赤枠で囲っているURLをgetするだけ
![スクリーンショット_2019-06-14_10_02_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115687/0803c042-bdf5-36cc-efe1-3d47ea6e3c33.png)


こんな感じでjson吐いてくるyo
![スクリーンショット 2019-06-14 10.06.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115687/7c164458-f078-3f16-4512-a0fa8f5c9267.png)
PostgreSQL: 現在のスキーマを切り替えるクエリには `set search_path = スキーマ名;`

PostgreSQLで現在のスキーマを切り替える方法を紹介する。

psqlコマンドで対話ターミナルを開く:

```
psql
```

対話ターミナル上で下記クエリを実行すると、現在のスキーマが切り替わる:

```
set search_path = スキーマ名;
```

実行例

```
root=# select current_schema();
 current_schema
----------------
 public
(1 row)

root=# set search_path = posts;
SET

root=# select current_schema();
 current_schema
----------------
 posts
(1 row)
```

## 関連

* [PostgreSQL: スキーマを一覧表示するコマンドは `\dn` - Qiita](https://qiita.com/suin/items/5ba2428c1cf4a67042af)
* [PostgreSQL: 現在のスキーマ名を表示するクエリには `select current_schema();` - Qiita](https://qiita.com/suin/items/f86ffb67d91a64779591)
PostgreSQL: 現在のスキーマ名を表示するクエリには `select current_schema();`

PostgreSQLで現在のスキーマ名を表示するクエリを紹介する。

psqlコマンドで対話ターミナルを開く:

```
psql
```

対話ターミナル上で下記クエリを実行すると、現在のスキーマが表示される:

```
select current_schema();
```

実行例

```
root=# select current_schema();
 current_schema
----------------
 public
(1 row)
```

## 関連

* [PostgreSQL: スキーマを一覧表示するコマンドは `\dn` - Qiita](https://qiita.com/suin/items/5ba2428c1cf4a67042af)
* [PostgreSQL: 現在のスキーマを切り替えるクエリには `set search_path = スキーマ名;` - Qiita](https://qiita.com/suin/items/d700e5c375d66288c3b8)
passenger-docker 内のパッケージをアップグレードする

# 解決方法

Dockerfileに以下のコマンドを追加する

```dockerfile:Dockerfile
RUN apt-get update && apt-get upgrade -y -o Dpkg::Options::="--force-confold"
```



# 参考情報

## 公式

https://github.com/phusion/passenger-docker

アップグレードコマンドは公式リポジトリのREADMEに記載されていた。
READMEでも **最新のセキュリティアップデートを入手するなどの目的で、このOSを随時アップデートすることをお勧めします。(和訳)** とアップグレードが推奨されていた。

## バージョン

上記コマンドを追加したところ、実行前後で nginx / passenger のバージョンは以下のようになった
（確認日：2019/6/14）

パッケージ | Upgrade前 | Upgrade後
:--- | :--- | :---
nginx | 1.14.0 | 1.15.8
passenger | 5.3.3 | 6.0.2
CentOS7にNFSサーバーを秒で構築

## 概要
Kubernetesで利用するPersistent Volumeを簡易的に作りたかったので、秒でNFSサーバーを構築した。

### 関連記事
- [【KubernetesのPersistentVolume】その１- 外部ストレージをPodにmountする](https://qiita.com/Esfahan/items/7ad7695ea78c7630239a)
- [【KubernetesのPersistentVolume】その２- Dynamic Provisionerを使ってNFSサーバーをPodにmountする](https://qiita.com/Esfahan/items/68e2d97545091cb6d0ac)

## 環境
- CentOS 7.6
- nfs-utils-1.3.0-0.61

## NFSサーバーのインストール
NFSにするサーバーで以下を実行

接続許可設定は環境にあったものに変更してください。

```bash:nfs-installer.sh
#!/bin/bash
sudo yum install -y rpcbind nfs-utils

# mountするディレクトリ
sudo mkdir -p /var/share/nfs

# 共有ディレクトリを設定
EXPORTS_FILE='/etc/exports'
# 接続許可設定
DEFINITION='/var/share/nfs 192.168.249.0/24(rw)'

sudo cat ${EXPORTS_FILE} | grep -w "${DEFINITION}" > /dev/null 2>&1
if [ $? = 1 ]; then
  sudo echo "${DEFINITION}" >> ${EXPORTS_FILE}
  sudo exportfs -ra
  sudo exportfs -v
else
  echo 'Alreday defined.'
fi

# Domain の行にドメイン名を指定します。ここで指定したドメイン名は NFSv4 が内部的に使用します
# Domainはサーバ・クライアントで共通であればなんでもいいようです
IDMAPD_FILE='/etc/idmapd.conf'
ORIGINAL='#Domain = local\.domain\.edu'
REPLACED='Domain = local\.domain\.edu'

sudo sed -i -e "s/${ORIGINAL}/${REPLACED}/g" ${IDMAPD_FILE}

# 起動
sudo systemctl start rpcbind
sudo systemctl start nfs-server
sudo systemctl start nfs-lock
sudo systemctl start nfs-idmap
sudo systemctl enable nfs-server

# firewalld
sudo firewall-cmd --permanent --zone=public --add-service=nfs
sudo firewall-cmd --reload
```

実行

```shell-session
$ chmod u+x nfs-installer.sh
$ sudo ./nfs-installer.sh
```

## Clientでの作業
mountする側のサーバーで実行。こちらでもrpcbind nfs-utilsが必要。

```bash:client.sh
#!/bin/bash
NFS_SERVER='NFSサーバーのIPアドレス'
REMOTE_VOLUME='/var/share/nfs'
LOCAL_VOLUME='/mnt/nfs'

sudo yum install rpcbind nfs-utils -y
# mountする
sudo mount -t nfs ${NFS_SERVER}:${REMOTE_VOLUME} ${LOCAL_VOLUME}
```

実行

```shell-session
$ chmod u+x client.sh
$ sudo ./client.sh
```

## mountされたか確認
### NFSサーバー

```shell-session
$ sudo touch /var/share/nfs/sample.txt
```

### Clientサーバー

```shell-session
$ ls /mnt/nfs
sample.txt
```

## unmount
client側で実行

```shell-session
$ sudo umount /mnt/nfs
```

## root権限でNFSのmount先に書き込みができない
/etc/exportsにno_root_squashを付ける。

```lang:/etc/exports
/var/share/nfs 192.168,1.0/24(rw,no_root_squash)
```

NFSでは、デフォルトでroot権限でのmount先の領域に書き込みができないようになっている。
mount先のroot権限を持っていなくても、リモートからroot権限での書き込みができてしまうことがセキュリティ上よくないからだ。
no_root_squashを付与することで、root権限での書き込みが可能となる。

参考：https://okwave.jp/qa/q6145679.html

## 参考
- [CentOS 7でNFSサーバを構築してみた](https://qiita.com/tanuki_mujina/items/5c706b2eab6e7eed71fd)
- [NFSv4でマウントするとnobodyになる](https://qiita.com/zkangaroo/items/17e3813ccb6ffaa38a28)
- [NFSv4 サーバーの基本設定と起動](https://www.turbolinux.co.jp/products/server/11s/user_guide/nfssetup.html)