OmniAICreator/Qiita-1.07M huggingface dataset:
EPSONグラスのMOVERIOにUnityか直接ビルドで引っかかったメモ

EPSONグラスのMOVERIOにUnityか直接ビルドできないが続いたのでメモ
どれがうまくいった要因か不明なので、現状の設定を記録ます。。

最終的にはできたけど
結構時間がかかった感じだったでする

###1.AndroidStudioの設定
AndroidOSの5.*系が使えるようにする感じ？

####MOVERIOが5.1なので5.0と5.1を追加済み
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/41227b3b-f042-f33c-3022-266d778eaf8f.png)

####SDKビルドはどれ使うか不明な感じだったので、ほぼ全部の最新版を追加
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/29f2c07e-ad0c-80a3-28b3-15b9a8af3517.png)

####USBドライバー追加
Google USB Driver
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/b080c331-cf79-370d-9cc2-3fc9a6146f14.png)

###2.Unityの設定
ほぼなにもしない感じでした

####Androidのモジュールをインストール
![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/ded05e88-fc75-32fe-31a1-9f0de43f5968.png)

####SDKなどのパスはチェック入れてあるのそのまま
![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/5f988f88-15a6-4699-d030-4847626ab4ee.png)


###3.MOVERIOの設定

####開発者モードの有効化
最初から開発者モード出てるのでそのままで大丈夫かも

####USBデバックの有効化
設定＞開発者向けオプション＞デバック＞USBデバック

####PC接続時の動作
設定＞ストレージ＞右上の三点リーダ＞USBでパソコンに接続
「メディアデバイス（MTP）」にチェックを入れる

###参考サイト

[Unity]Androidにビルドできない[Android]
https://teratail.com/questions/124693

Unity 実機でのテストについて
https://teratail.com/questions/211418

【Unity2019対応】Androidビルドでエラーが出る場合の対処法
http://nn-hokuson.hatenablog.com/entry/2017/09/05/202327

[Android] ADB接続とUSB接続モード
http://xawa99.blogspot.com/2014/03/Android-ADB-USB-Mode.html

モベリオ（MOVERIO）BT-350
https://www.epson.jp/products/moverio/bt350/
ターミナルがbashで、command not foundになる時の対処方

bashになり、何かおかしい、、、
command not foundしか返答がない、、、

```
bash-3.2$ 
bash-3.2$ end
bash: end: command not found
bash-3.2$ no
bash: no: command not found
bash-3.2$ v
bash: v: command not found
```

そんな時は、

```
bash-3.2$ exit
exit
[name]MacBook-Pro:[name]$ 
```

exitと打つだけで元に戻ります！
UnityのプロジェクトをGitHubで管理する際にハマったこと【随時更新】

<img width="480" alt="スクリーンショット 2020-01-02 0.21.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348026/efd5d6fd-636b-e4f1-05ed-4ccfef3112c9.png">
---

## TL;DR
タイトル通りなので割愛

## はじめに
Unity初心者がGitHubでハマるポイントをまとめておきます。

UnityプロジェクトをGitHubで共有しようとしたら、
諸々のミスで作成データが吹っ飛んだりしたので。

## 前提
- Unity初心者です
- 基本的にはうちわ向けのメモですm.  . m

##やると死ぬこと

#### 1. Unityプロジェクトを保存する前にプロジェクトが存在するディレクトリのパスを変更する
~~それは、そう...~~
Unityが参照しているディレクトリの場所は変更しないようにしましょう(月並感)

これをやってしまいましたが、これをしてしまう少し前に、
たまたまGitHubに上げておいたので「よかった〜」と思ったのですが...

#### 2. Unityプロジェクトを保存して閉じる前に、GitHubにコミット
これをしてしまったので、上の事件のあとcloneしてきたディレクトリにも、いまいち変更が反映されていませんでした(死)

#### 3. 全てのファイルをアップして死ぬほど時間がかかる
- gitignoreを知らない人向け
    - [こちらの記事](https://qiita.com/inabe49/items/16ee3d9d1ce68daa9fff)などを参考にgithubにアップしないファイルを指定する方法を勉強しましょう

- gitignoreに何か書けばいいんやと思っている人向け
    - [これ](https://www.cg-method.com/entry/unity-gitignore-setting/)をコピペせよ
これをベースにして、各自DLしても問題ないアセットはignoreに追加していくとかがいいかもしれませんね

随時更新していきます！


## 参考
[Unity を GitHub でバージョン管理する](https://qiita.com/hkomo746/items/a6dfa76442a474dfdf3a)
関数

```py:1
def say_hi():
    s = 'Hi'
    return s

result = say_hi()
print(result)
```

```:1に実行結果
Hi
```

```py:2
def what_is_this(color):
    if color == '赤':
        return 'トマト'
    elif color == '緑':
        return 'きゅうり'
    else:
        return 'わかりません。'

r = what_is_this('赤')
g = what_is_this('緑')
w = what_is_this('白')

print(r)
print(g)
print(w)
```

```:2の実行結果
トマト
きゅうり
わかりません。
```
Helmのセットアップに関する個人メモ

## はじめに

**Docker/Kubernetes 実践コンテナ開発入門** でKubernetesを学習中に、Helmのセットアップで躓いたのでまとめました。

## 躓いた点

`helm init`が書籍の記載通りにできませんでした。

```
$ helm init
The Kubernetes package manager

Common actions for Helm:

- helm search:    search for charts
- helm pull:      download a chart to your local directory to view
- helm install:   upload the chart to Kubernetes
- helm list:      list releases of charts

(中略)

Use "helm [command] --help" for more information about a command.
```

## 解決までの手順

- 書籍のサポートページに何か情報がないかどうか確認
    - https://gihyo.jp/book/2018/978-4-297-10033-9/support
    - 特に情報なし
- Helmのバージョンを確認
    - `brew install`した際に、3系がインストールされていることを確認
- 3系でTillerが削除される等、大きな変更があったことを確認
    - https://helm.sh/docs/faq/#removal-of-tiller
- 書籍では、2系が利用されていたので、2系をインストールし直すことにした
    - `brew uninstall`で3系はアンインストール

## Helmの2系をインストール

brewでバージョン指定してインストールしようと思ったのですが、いろいろエラーが出てしまい時間がかかりそうだったので、公式ドキュメントを参考に手動でインストールしました。

https://helm.sh/docs/intro/install/#from-the-binary-releases

### 希望のバージョンをダウンロード

今回は`v2.16.0`にしました。

https://github.com/helm/helm/releases

### ダウンロードしてきた`tar.gz`を解凍

```
$ tar -zxvf helm-v2.16.0-darwin-amd64.tar.gz 
```

### helmバイナリを`/usr/local/bin`に移動

```
$ mv darwin-amd64/helm /usr/local/bin/helm
```

## Helmのセットアップ

インストールした後に、`helm version`。

```
$ helm version
Client: &version.Version{SemVer:"v2.16.0", GitCommit:"e13bc94621d4ef666270cfbe734aaabf342a49bb", GitTreeState:"clean"}
Error: could not find tiller
```

initしてみる。

```
$ helm init

(中略)

Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com 
Adding local repo with URL: http://127.0.0.1:8879/charts 
$HELM_HOME has been configured at /Users/<username>/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
```

initできました。
Tillerのサーバアプリケーションがkube-systemネームスペースにデプロイされていることを確認してみます。

```
$ kubectl -n kube-system get service,deployment,pod --selector app=helm
NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)     AGE
service/tiller-deploy   ClusterIP   10.97.204.96   <none>        44134/TCP   20s

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/tiller-deploy   1/1     1            1           20s

NAME                               READY   STATUS    RESTARTS   AGE
pod/tiller-deploy-565767cb-nwljs   1/1     Running   0          20s
```

最後にバージョンを表示。

```
$ helm version
Client: &version.Version{SemVer:"v2.16.0", GitCommit:"e13bc94621d4ef666270cfbe734aaabf342a49bb", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.16.0", GitCommit:"e13bc94621d4ef666270cfbe734aaabf342a49bb", GitTreeState:"clean"}
```

書籍の記載のように、クライアント(cli)とサーバ(k8sクラスタにインストールされているTiller)のHelmのバージョンを確認できました。
【Rails】sessionメソッドを使った非ログインユーザーの情報管理

初めて記事を投稿します。

現在Web系企業への転職を目指してポートフォリオを作成中です。
その中で、ログインユーザーのセッション管理に**session**メソッドは使用していましたが、
それ以外の用途で、**session**メソッドを使用して、ある機能を実装できたので
記事にして共有したいと思います。

[【参考】 sessionメソッドについて　Railsチュートリアル](https://railstutorial.jp/chapters/basic_login?version=5.1#cha-basic_login)

#元ネタ
現在作成しているアプリにて、登録済みユーザーによって投稿された記事を、
・新しい投稿順
・「いいね」が多い順
での表示に切り替えられるそれぞれ用のボタンを作成しました。

どちらのボタンを選択しているかの判別用パラメータを、
ログインしているユーザーは、DBにてそのユーザーのレコード上に保存していたのですが、
ログインしていないユーザーの場合の管理方法について悩んでいました。

#解決策
Railsのsessionメソッドを使用することで解決しました！
以下該当コードです。

```ruby:sample.rb
class SampleController < ApplicationController

  def home
    if current_user
      current_user.update(order_option: params[:option]) if params[:option]
      option = current_user.order_option
    else
      session[:not_logged_in] = 0 if session[:not_logged_in].nil?
      session[:not_logged_in] = params[:option].to_i if params[:option]
      option = session[:not_logged_in]
    end

    if option.zero?
      @articles = Article.order(created_at: :desc)
    elsif option == 1
      @articles = Article.order(like_counts: :desc)
    end
  end
end
```

```erb:home.html.erb
（略）
<%= render @articles %>
```

ログインユーザー(current_user)がいない場合の処理を
sample.rbのelseのブロックに記述しています。

ポイントは、

```ruby:sample.rb
    else
      session[:not_logged_in] = 0 if session[:not_logged_in].nil?
```
の箇所によって、ユーザーが最初にサイトにアクセスした時は
`session[:not_logged_in]` は生成されていない(nil)ため、
0に初期化されてブラウザに保存されます。

以降は記事の表示順切り替え用ボタンがクリックされた時に
`params[:option]` をコントローラに渡すようにしておけば、

```ruby:sample.rb
      session[:not_logged_in] = params[:option].to_i if params[:option]
```

によって`session[:not_logged_in]` が更新されます。
そして、その値によって、以下のコードにより記事の並び順を変更します。

```ruby:sample.rb
    if option.zero?
      @articles = Article.order(created_at: :desc)
    elsif option == 1
      @articles = Article.order(like_counts: :desc)
    end
```

また、この情報は **session**メソッドの仕様により、
ブラウザが閉じられた時に破棄されます。

#sessionメソッドが、求める仕様を満たしていた
ログインしていないユーザーが記事の表示順を切り替えられるようにするためには、
実装する機能が以下の仕様を満たす必要がありました。

- 他ユーザーの利用状況に左右されない
- 最初にページにアクセスした時だけパラメータを初期化する
- サイトの閲覧を終了し、次回サイトにアクセスした時は情報が残されていない

そして、以下に**session**メソッドの仕様を記載します。

- ブラウザ単位で情報をやりとりできる
- パラメータの初期化を、URL初回アクセス時のみ行わせることができる
- 有効期限が過ぎる、またはブラウザを閉じれば情報が破棄される

**session**メソッドの仕様3つ目は、機能に求める仕様3つ目を
厳密には満たしていませんが、ほぼ条件を満たしており、
今回実装した機能にはうってつけでした。

なお、実装する機能1つ目の仕様はDBでも制御できますが、
2、3つ目の機能をDBで制御しようとすると結構難しいと思います
（私には方法が思いつきませんでした）。

#最後に
**session**メソッドを他の用途で使っている例を見たことがなかったので、
知見の共有になればと思い、今回記事を執筆しました。
お役に立てれば幸いです。

なお、実務未経験で完全独学者がたまたま思いつき、作成した機能なので
「このような実装は実際には行わない」
「ここはこうすると良い」
等、指摘事項がある内容であるかもしれませんので、
その際はコメントでご指導いただけると幸いです。

最後までお読みいただき、ありがとうございました！
githubのpushで、$ git push origin masterがエラーになる

ターミナルで
$ git push origin master
と入力すると、

```bash
! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://github.com/[name]/[github-name].git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details
```

エラーが出てしまいます。

同じエラーメッセージが出た方は、
$ git push -f origin master
と入力すると

```bash
Enumerating objects: 199, done.
Counting objects: 100% (199/199), done.
Delta compression using up to 8 threads
Compressing objects: 100% (186/186), done.
Writing objects: 100% (199/199), 164.33 KiB | 4.98 MiB/s, done.
Total 199 (delta 17), reused 0 (delta 0)
remote: Resolving deltas: 100% (17/17), done.
To https://github.com/[name]/[github-name].git
 + 9e623da...4e78ded master -> master (forced update)
```
成功します！
Travis CI 悪戦苦闘

#Qiita 記事

Travis CIの導入
https://qiita.com/ShoheiObata/items/bad9d6e3fe7664cf0f22

>作成した.travis.ymlをリポジトリのルートに配置してPushする。

なにをしたら、リポジトリのルートに配置してpushしたことになるかがわからない。


CI環境構築 ~ Python編 ~
https://qiita.com/masashi127/items/5bfcba5cad8e82958844

>右上のリンクからGitHubアカウントでサインイン

どこの右上からかがわからない。


Travis CIでPipenv + Pytestの自動テストを行った
https://qiita.com/devara/items/fb0f144ac859f529839a

>後は設定ファイル（.travis.yml）をパッケージに置くだけ


何をしたら置いたことになるかがわからない。

Travis CI + Docker + go test
https://qiita.com/mediba-moritake/items/a994a130bc9c0f4ee962

どの画面で何をするかがわからない。

Travis CIでC++11
https://qiita.com/ar90n@github/items/f33482419e011ba9b29b

>Clang-3.7 + CMake3.2 + Google Testの場合，以下のようにaddonsを.travis.yml追加します．

travis.ymlがどこにあるかわからない。


[iOS]GitHub + Travis CI + Slack
https://qiita.com/m_yukio/items/8ae6497675c15d42635e

>xctoolを使ったビルドの方が楽だと思うが、著者の環境ではビルドエラーとなったため、xcodebuildを使っている。

どういうエラーになったかがわからない。

Travis CIで自動テストして、結果をGitHubのトップページに表示する
https://qiita.com/hoshimado/items/4090d8e64beb8a7f95e1

>リポジトリ側に、設定ファイル「 .travis.yml 」を作成してコミットする。
より詳しくは、以下の公式ドキュメントのGetting Startedを参照のこと。
https://docs.travis-ci.com/user/getting-started#To-get-started-with-Travis-CI

今、読んでます。

# 公式文書

>Prerequisites #
To start using Travis CI, make sure you have:
- A GitHub account.
- Owner permissions for a project hosted on GitHub.

準備
GithubのIDがある。
github上にOwnerのprojectが一つある。

[ここまではOK]

GithubのIDのない方は

GitHub入門 (1) 入門
https://qiita.com/kaizen_nagoya/items/b6f5b1532fd21fec79c8

OwnerのProjectのない方は

資料捜索中。

#youbube


Travis CI + GitHub Pages - Automated deployment
[![Travis CI + GitHub Pages - Automated deployment](http://img.youtube.com/vi/BFpSD2eoXUk/0.jpg)](https://www.youtube.com/watch?v=BFpSD2eoXUk)

Travis CI Tutorial - How to Use Travis CI with Github for Continuous Integration
[![Travis CI Tutorial - How to Use Travis CI with Github for Continuous Integration](http://img.youtube.com/vi/Uft5KBimzyk/0.jpg)](https://www.youtube.com/watch?v=Uft5KBimzyk)

How to start using Travis CI with your GitHub hosted code in 5 minutes
[![How to start using Travis CI with your GitHub hosted code in 5 minutes](http://img.youtube.com/vi/FEXY1ZP-sBs/0.jpg)](https://www.youtube.com/watch?v=FEXY1ZP-sBs)

Setting up Travis CI on an existing Python/Docker project
[![Setting up Travis CI on an existing Python/Docker project](http://img.youtube.com/vi/1PC68ufAn6U/0.jpg)](https://www.youtube.com/watch?v=1PC68ufAn6U)


Travis CI - Part 1 Basic Setup
[![Travis CI - Part 1 Basic Setup](http://img.youtube.com/vi/g0KsiCj3CgQ/0.jpg)](https://www.youtube.com/watch?v=g0KsiCj3CgQ)
Windows PowerShellでopenコマンドの代替

pathを取得

```
> pwd

Path
----
C:\Users\vaaav\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\home\ryosuke-hujisawa
```

開く

```
> Invoke-Item

コマンド パイプライン位置 1 のコマンドレット Invoke-Item
次のパラメーターに値を指定してください:
Path[0]: C:\Users\vaaav\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\home\ryosuke-hujisawa
```
英語の「○○もできないの？」という質問に対して「はい、できます」と返す謎をプログラミングで解明する

英語の否定疑問文「Can't you speak English ? (あなたは英語もできないの？)」に対し、
日本語なら「はい、できません」か「いいえ、できます」と答えるところを、
英語では「No, I can't.」か「Yes, I can.」とYes/Noを日本語と逆に答えますが、僕はどうしてもこれがしっくりきません。

いざ会話のときにすごく混乱します。

というわけで何が起きているのかJavaScriptで書いて頭を整理してみます…。

## 通常の疑問文

```javascript:日本語
const canSpeakEnglish = true

// あなたは英語ができるの？
if (canSpeakEnglish) {
  console.log('はい、できます。')
} else {
  console.log('いいえ、できません。')
}
```

```javascript:英語
const canSpeakEnglish = true

// Can you speak english ?
if (canSpeakEnglish) {
  console.log('Yes, I can.')
} else {
  console.log('No, I can\'t.')
}
```

日本語英語ともにyes/noの差はありません。どちらもごく自然です。

## 否定疑問文

```javascript:日本語
const canSpeakEnglish = true

// あなたは英語もできないの？
if (!canSpeakEnglish) {
  console.log('はい、できません…。')
} else {
  console.log('いいえ、できます！')
}
```

```javascript:英語
const canSpeakEnglish = true

// Can't you speak english ?
if (!canSpeakEnglish) {
  console.log('No, I can\'t.') // どっち！？
} else {
  console.log('Yes, I can.') // どっちやねん！
}
```

なんでそうなるんだ！！

Booleanで書くと：

```javascript
const canSpeakEnglish = true

// あなたは英語もできないの？
if (!canSpeakEnglish) {
  console.log('true、できません。')
} else {
  console.log('false、できます。')
}

// Can't you speak english ?
if (!canSpeakEnglish) {
  console.log('false, I can\'t.')
} else {
  console.log('true, I can.')
}
```

## A. 述べている対象が全然違う

日本語の「はい/いいえ」は条件式（質問）について述べている:
![Screenshot from 2020-01-06 19-07-27_edited_bool_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151137/0fd95865-80f5-9301-ea8b-c928afc3e857.png)

英語の「yes/no」は話している対象自体について述べている:
![Screenshot from 2020-01-06 19-07-27_edited_bool_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151137/8defbb4c-9b5c-6478-025b-b6f2c8791c92.png)

つまり、「日本語と逆にしなきゃ！」という考えを捨てて、
回答の頭につく「yes/no」は日本語の「はい/いいえ」とは存在意義が全く異なることを認識しないと、この違和感はずっと取れないのかもしれない。

（ちなみに勝手にそう行き着いたので、全然間違っているかもしれません…）

「否定疑問文内のnotを無視して答える」とも教えられたことがあるけど、頭の「yes/no」の捉え方はそっちが正しい…？
Herokuでよく使うコマンド

# Herokuのよく使うコマンド

Heroku CLI には便利なコマンドがたくさんありますが、よく使う機能だけ抜粋してみました。
[Heroku CLI Commands](https://devcenter.heroku.com/articles/heroku-cli-commands)

## ログインとログアウト
``` bash:ログイン
$ heroku login
```
``` bash:ログイン
$ heroku logout
```

## デプロイ
``` bash:リポジトリのクローンを作成
$ heroku git:clone -a <HEROKU_APP_NAME>
$ cd <FOLDER_PATH>
```

``` bash:デプロイ
$ git add .
$ git commit -am "コメント！"
$ git push heroku master
```

``` bash:ロールバック
$ heroku rollback v63    #v63 のようにロールバックしたいバージョンを指定。
Rolled back to v63
```

``` bash:リリース履歴
$ heroku releases
=== HEROKU_APP_NAME Releases - Current: v65
Rel   Change                  By                   When
----  ----------------------  ----------           ----------
v65   Rollback to v63         hoge.hoge@qiita.com  2020/01/06 18:54:02 +0900 (~ 14m ago)
v64   Deploy 02c5ba90         hoge.hoge@qiita.com  2020/01/06 03:33:04 +0900 (~ 15h ago)
v63   Deploy 9fd0e397         hoge.hoge@qiita.com  2020/01/04 06:26:45 +0900
v62   Deploy 2088c7a2         hoge.hoge@qiita.com  2020/01/04 06:22:14 +0900
```

``` bash:リリースの詳細情報
$ heroku releases:info v1234
```


## ログ
``` bash:ログ確認
$ heroku logs
```
``` bash:ログ確認(リアルタイム)
$ heroku logs -t
or
$ heroku logs --tail
```

## 設定等確認
``` bash:環境変数
$ heroku config
```
``` bash:アドオン
$ heroku addons
```

## DB接続
``` bash:Postgesql
$ heroku pg:psql
```
【小ネタ】Pythonでtimestamp取得

# はじめに
超小ネタで恐縮ですが、表記の手順に関して自分用メモとして

# コード

```py3
# タイムスタンプ取得

from datetime import datetime
from pytz import timezone
utc_now = datetime.now(timezone('UTC'))
jst_now = utc_now.astimezone(timezone('Asia/Tokyo'))
ts = jst_now.strftime("%Y%m%d-%H%M%S")
print(ts)

```

# 結果例

```
20200106-182252
```

今回は、ユニークなファイル名の一部を作る目的でこのような書式にしましたが、``"%Y%m%d-%H%M%S"``の部分を書き換えれば、いろいろなパターンに応用可能です。
githubの$ git showを終了する方法

ターミナルで
$git show
と入力すると、

```bash
commit [数字] (HEAD -> master)
Author: [名前] <[メール]>
Date:   [日付] +[数字]

    [コミットメッセージ]

diff --git a/[ファイル名] b/[ファイル名]
```

と返ってきます。


終了するには、
q
を打つだけです。
初心者によるプログラミング学習ログ 205日目

# 100日チャレンジの205日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

205日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>205日目<br><br>udemyでwebサイトコーディング<br>progateでRubyちょこっとやってみた<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1213914879125377024?ref_src=twsrc%5Etfw">January 5, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【Catalina】nodebrewからnode, yarnをインストール

#はじめに
node.jsのバージョン管理とyarnのインストールについて
色々な所からインストールしていたら、brew doctorから怒られてしまいました。。。
Catalinaにアップデートしたら、読み込めないし、、、

```
$ node -v
zsh: node: command not found
```

PATHを通すと node -v, npm -v が使えるようですが

せっかくなので、一元管理するため
一度、全てアンインストールしてから再インストールしました。
nodebrewでの管理が上手くいったので、自分用メモとして残しておきます。

nodeの管理はnodebrewで行い、npmからyarnをインストールしました。
※公式では非推奨らしいですが、、、
https://yarnpkg.com/ja/docs/install#alternatives-stable

#node.jsとyarnの削除
今まで入れていたnodeとyarnを全て削除します。

```:（例）Homebrewで入れた場合
$ brew uninstall yarn
$ brew uninstall node
$ rm -rf /usr/local/lib/node_modules
$ brew cleanup
念のため
$ brew doctor
```

アンインストール後にPATHが変更されているので .bash_profile の再読み込み。

```
$ source ~/.bash_profile 
```


# nodebrew のインストール
```
Homebrew から nodebrew をインストール
$ brew install nodebrew
バージョンを確認
$ nodebrew -v
```

実行結果

```
nodebrew 1.0.1

Usage:
    nodebrew help                         Show this message
    nodebrew install <version>            Download and install <version> (from binary)
    nodebrew compile <version>            Download and install <version> (from source)
    nodebrew install-binary <version>     Alias of `install` (For backword compatibility)
    nodebrew uninstall <version>          Uninstall <version>
    nodebrew use <version>                Use <version>
    nodebrew list                         List installed versions
    nodebrew ls                           Alias for `list`
    nodebrew ls-remote                    List remote versions
    nodebrew ls-all                       List remote and installed versions
    nodebrew alias <key> <value>          Set alias
    nodebrew unalias <key>                Remove alias
    nodebrew clean <version> | all        Remove source file
    nodebrew selfupdate                   Update nodebrew
    nodebrew migrate-package <version>    Install global NPM packages contained in <version> to current version
    nodebrew exec <version> -- <command>  Execute <command> using specified <version>

Example:
    # install
    nodebrew install v8.9.4

    # use a specific version number
    nodebrew use v8.9.4
```

# nodebrew の PATH を通す

```
.bash_profile から .zprofile へお引っ越し
$ cat .bash_profile >> .zprofile

.zprofile にPATHを追加
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zprofile

.zprofile を再読み込み。
$ source ~/.zprofile
```

#安定版の Node.js をインストール
```
$ nodebrew install-binary stable
```

ディレクトリが見つからない場合は、作成

```
$ mkdir -p ~/.nodebrew/src
$ nodebrew install-binary stable
```

Node.jsを設定します。

```
利用可能バージョンを確認
$ nodebrew list

current: noneなので、バージョンを指定
$ nodebrew use v12.14.0

Node.js のバージョンを確認
$ node -v
```

# yarnをインストール

```
$ npm install -g yarn
$ yarn -v
バージョンが表示されれば OK
```
Let's Encryptの更新エラーを解決した。

SSLの証明書の有効期限切れでサイトにアクセスできなくなり、更新をしようとしたらエラーになってしまったので、その時の解決方法を残します。

##この接続ではプライバシーが保護されません

サイトにアクセスしたら上記のメッセージが表示され、サイトが見れない。

SSLの証明書の有効期限が切れていたのが原因だった。

Let's EncryptでSSL化したが、その際に行った自動更新の設定がうまくいっていなかったよう。

##Let's Encryptの更新
###更新のチェック
```
$ cd /usr/local/certbot

# 更新ができるかチェック
$ ./certbot-auto renew --dry-run

Challenge failed for domain xxx.com
http-01 challenge for xxx.com
Cleaning up challenges
Attempting to renew cert (xxx.com) from /etc/letsencrypt/renewal/xxx.com.conf produced an unexpected error: Some challenges have failed.. Skipping.
All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/xxx.com/fullchain.pem (failure)
```

could not be renewedとあるので、どうやら失敗したようです。

####./certbot-autoとcertbot
certbot-autoを"wget" や "git clone" コマンドなどでダウンロードした場合は./certbot-autoを使う。
OS のパッケージ管理システムから Certbot パッケージをインストールした場合はcertbotコマンドを入力します。

####--dry-run

実際に更新はかけずに、チェックのみ実行する機能

Let's Encryptでは何度も証明書の発行に失敗をすると、制限がかかってしまい、しばらく発行ができなくなってしまいます。
実際に更新をする前に、--dry-runをつけて問題がないかチェックしましょう。


###nginxの設定変更

```
$ sudo vi /etc/nginx/conf.d/hogehoge.conf
  server {
    listen 80;
# 以下追記
    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root         /var/www/hogehoge/current/public; #ドキュメントルート
    }

    return 301 https://$host$request_uri;　#リダイレクト用
  }
```

###設定の反映

```
$ systemctl reload nginx
```

###証明書更新

```
$ cd /usr/local/certbot

$ ./certbot-auto certonly --webroot -w /var/www/hogehoge/current/public -d www.hogehoge.com --agree-tos -n
Congratulations! Your certificate and chain have been saved at:
```

更新成功しました！

心配な方は更新前に以下のコマンドでチェックをしておきましょう。

```
$ ./certbot-auto renew --dry-run
```

###オプション
--webroot ：サーバーを止めずに証明書を更新するためのもの
-w ：ドキュメントルートを指定
-d ：ドメインを指定 
--agree-tos ：ACME 利用規約に同意
-n：ユーザーからの入力が不要
参考：https://free-ssl.jp/command/

設定の反映

```
$ systemctl reload nginx
```

サイトが無事に表示されるようになりました！

##参考

https://free-ssl.jp/
https://qiita.com/HeRo/items/f9eb8d8a08d4d5b63ee9
https://qiita.com/shozzy/items/372bb9e4a76076d7021e
https://server-recipe.com/1577/#Letsencrypt-3
React hooksの冗長さに、関数を一個作って対応する。

hooksって意外と冗長なコードになりますよね。
実際に、hooksを書くときに、使っているヘルパー関数を紹介します。

以下普通のhooksです。

```js
import {useState} from 'react'

export const customHook = () => {

  const [name, setName] = useState('')
  const [age, setAge] = useState(0)
  const [gender, setGender] = useState('')

  return {
    name,
    setName,
    age,
    gender,
    setGender,
    setGender,
    greeting
  }
}
```

以上のコードは、age, setAgeなど、複数の箇所に似たような変数が散らばっています。そのためtypoしやすい上に、記述量も多くなります。

そこで、hookFactoryと言う、hooksを生成する関数を作成しました。
単純に、useStateの記述を楽にしてくれるだけです。

使用例。

```js
import hookFactory from './hookFactory'

export const customHook = () => {
  const state = [
    ['name', ''],
    ['age', 0],
    ['gender', '']
  ]

  return hookFactory(state)
}
```

hookFactory自体の実装は以下

```js
const hookFactory = (inputs: any) => {
  const hooks = {}
  inputs.forEach(input => {
    const [state, setState] = useState(input[1])
    hooks[input[0]] = state
    hooks['set' + capitalize(input[0])] = setState
  })
  return hooks
}

const capitalize = (s: string) => {
  return s.charAt(0).toUpperCase() + s.slice(1)
}
```




書きやすくなりました。
完
Ruby 2.7.0 で個人的にグッときた新機能をちょっぴり試してみた

# 概要
Ruby 2.7.0 で導入された新機能のうち，次の機能を試してみた．

- `irb` での複数行編集
- パターンマッチ[^2]

[^2]: 関数型言語で広く使われている機能．今回のバージョンで実験的に導入された．

# 詳細
## `irb` での複数行編集
Ruby 2.6 までの対話環境 Interactive Ruby でも複数行の関数などを記述することはできたが

- 一度改行したら前の行に戻れない
- そもそも見づらい

といった問題点が存在した．

![Ruby 2.6 までの複数行編集](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478774/e3f21f5c-1d71-3b4a-0928-7e7a905bee22.gif "Ruby 2.6 までの複数行編集")

しかしRuby 2.7 からは，改行しても前の行に戻ることができ，見た目もわかりやすくなった．

![Ruby 2.7 からの複数行編集](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478774/333a9307-ecbd-3cb3-8f82-565cb8df67ab.gif "Ruby 2.7 からの複数行編集")

## パターンマッチ
前節で例として用いた次の関数[^1]

```ruby
def fact(n)
    if n == 0
        return 1
    else
        return n * fact(n - 1)
    end
end
```
[^1]: 非負整数に対してその階乗を返す関数である．
をパターンマッチを用いて記述すると次のようになる．

```ruby
def fact(n)
    case n
    in 0
        return 1
    in _
        return n * fact(n - 1)
    end
end
```

この例だとパターンマッチの有難みがわかりにくいので，次の例も挙げておく．

```ruby
def arymatch(ary)
    case ary
    in [0, [a, b, c]]
        p a
        p b
        p c
    end
end
```

下記は `arymatch` の実行例である．

```
> arymatch([0, [1, 2, 3]])
1
2
3
=> 3
> arymatch([0])
...(中略)...
NoMatchingPatternError ([0])
```

# 参考
- [Ruby 2.7.0 リリース](https://www.ruby-lang.org/ja/news/2019/12/25/ruby-2-7-0-released/)
- [Ruby 2.7 で導入予定のパターンマッチングを試したら無限大の可能性を感じた話 - Feedforce Developer Blog](https://developer.feedforce.jp/entry/2019/05/17/110000)
要素がpairの時のvectorのソート 

Vectorの要素がPairの時のsort時の挙動は、
-一つ目を昇順にソートする。
-一つ目が同一の場合はさらに二つ目を昇順にソートする。

また、
降順にしたい場合はマイナスを全てに掛けておく
一つ目を昇順、二つ目を降順にしたい場合は,二つ目だけにマイナスを掛けておけば良い。




```cpp
using namespace std;
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
    vector<pair<string,int>> v;
    v.push_back({ "apple",4 });
    v.push_back({ "banana",3 });
    v.push_back({ "melon",1 });
    v.push_back({ "apple",2 });
    v.push_back({ "orange",6 });

    //sort
    sort(v.begin(), v.end());

    for (auto V : v) {
        cout << V.first << " " << V.second << endl;

    }
    //apple 2
    //apple 4
    //banana 3
    //melon 1
    //orange 6

	return 0;
}
githubの$git logを終了する方法

ターミナルで
$git log
と入力すると、

```bash
commit 数字 (HEAD -> master)
Author: [name] <[mail]>
Date:   [date] +数字

    [commit name]

commit 数字
```

と返ってきます。

終了するには、
q
を打つだけです。
Laravel6 on Google App EngineでVue.jsを使った認証を実装する

https://qiita.com/kiyc/items/61ebf1796ba5b46ba833

の続きです。

https://laravel.com/docs/6.x/authentication#authentication-quickstart

```sh
$ composer require laravel/ui --dev
$ php artisan ui vue --auth
$ npm install && npm run dev
```

`.gcloudignore`に`node_modules`を追加します。

```.gcloudignore
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
#   $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore

# PHP Composer dependencies:
/vendor/

.env
/node_modules/
```

`app.yaml`に静的ファイルの設定を追加します。
今回はスタンダード環境にデプロイすることにしました。

```app.yaml 
runtime: php72

handlers:
  - url: /css
    static_dir: public/css
  - url: /js
    static_dir: public/js

env_variables:
  ## Put production environment variables here.
  APP_KEY: YOUR_APP_KEY
  APP_STORAGE: /tmp
  VIEW_COMPILED_PATH: /tmp
  CACHE_DRIVER: database
  SESSION_DRIVER: database
  QUEUE_CONNECTION: database
  ## Set these environment variables according to your CloudSQL configuration.
  DB_DATABASE: YOUR_DB_DATABASE
  DB_USERNAME: YOUR_DB_USERNAME
  DB_PASSWORD: YOUR_DB_PASSWORD
  DB_SOCKET: "/cloudsql/YOUR_CONNECTION_NAME"
```

```sh
$ gcloud app deploy
```

<img width="1239" alt="スクリーンショット 2020-01-06 14.27.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123511/58f6f1db-3fbc-279f-b2de-c7f479a1f055.png">

ユーザ登録すると、`users`テーブルにデータが格納されることを確認出来ました:beer:
デプロイする前にローカル環境でCSSとJSのコンパイルが必要なのが面倒なところです（もしかしてデプロイコマンドに含めることが出来るのかな）
AWSでサブドメインにワードプレスを入れる

# AWSでサブドメインにワードプレスを入れる

メモとして流れだけ書きます。
詳しいことが知りたい方は、コメントください。

## ALBの作成

ALBを作成しておきます。

## Route53の設定

Route53で使用するサブドメインのAレコードに、ALBをエイリアスで追加する

## 証明書の作成

ACMで証明書を取得する。
xxx.com
*.xxx.com

アスタリスクでサブドメインでも効くようにする。
むしろサブドメインしかいらないか。

## EC2でAPサーバの作成

APサーバを作成する
他のWordPressのサーバなどのイメージから複製した。
Apacheなどのルートドメインに、ヘルスチェック用のHTMLを置いておく。
healthcheck.htmlなど。中身は適当

## ターゲットグループの作成

ターゲットグループを作成する。
作成したAPサーバを、追加する。

## ALBの設定

作成した証明書を登録。
80のほうのリスナーに、作成したターゲットグループを追加する。
443のほうのリスナーにも、作成したターゲットグループを追加する。

## ヘルスチェックの確認

ターゲットグループのほうで、APサーバが認識されていることを確認する。
healthcheck.htmlにアクセスして確認する。

## RDSでDBサーバを作成する

DBサーバを立ち上げる。
気をつけるところは、セキュリティグループのところぐらいか。

## wordpressの設置

「日本語 wordpress」で検索し、ダウンロードリンクをコピー。
wgetで、サーバのドキュメントルートに落とす
解凍し配置する。
wp-config.phpに、DBの設定を記述する

## サブドメインにアクセスしてインストール

サブドメインにアクセスしてインストールする
Python: 正規表現による簡易版形態素解析

## SAMPLE
```PYTHON
吾輩|は|猫|で|ある|。|名前|は|まだ|無|い|。
```
## REFERENCE

[正規表現による手抜き形態素解析](https://www.johf.com/log/20130224a.html)

## PYTHON
微妙に改変。

```PYTHON
text_m = []
text = "吾輩は猫である。名前はまだ無い。"
p = re.compile(r"/|[A-Z]+|[a-z]+|[ァ-ンー]+|[ぁ-ん-]+|[ァ-ヶ]+|[一-龍]+|[。、]|/")
m = p.findall(text)
for row in m:
   if re.compile(r'^[あ-ん]+$').fullmatch(row):
      if row[0] in 'はがのにへともでを':
         prefix = row[0]
         token = row[1:]
         text_m.append(prefix)
         if (len(token)>0):
            text_m.append(token)
      elif row[-2:] in 'のでからまで':
         token = row[0:-2]
         suffix = row[-2:]
         text_m.append(token)
         text_m.append(suffix)
      elif row[-1:] in 'もはがでを':
         token = row[0:-1]
         suffix = row[-1:]
         text_m.append(token)
         text_m.append(suffix)
      else:
         text_m.append(row)
   else:
      text_m.append(row)

## output
'|'.join(text_m)
```
ステージごとにAPIを作成することなく 各ステージごとにバックエンドポイントを振りわける

やりたいこと↓。
1つのLambda関数を作成し、それぞれのエイリアスを、各ステージにデプロイする。


大まかな手順は以下のとおりです。

1.Lambdaで新しいバージョンを発行する。
2.Lambdaでエイリアスを作成し、紐づける。
3.APIGatewayでステージ変数を参照する設定をする。
4.Lambda関数に権限を追加する。
5.ステージ変数を追加する。


それではやってみます。



#1.Lambdaで新しいバージョンを発行する。#

「新しいバージョンを発行」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/5fa34ecb-5306-3bb4-d71e-0f2e805212a6.png)

「バージョン：1」を作成しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/93af00c2-c955-9ef7-4e87-90ef94b8132d.png)



#2.Lambdaでエイリアスを作成し、紐づける。#

「エイリアスの作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/365a9432-4f2d-de4c-7e57-e94586799bdd.png)

「dev」→「バージョン：$LATEST」
「ops」→「バージョン：1」
　と同じように2つ作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/aa98b50c-81e0-d4ac-4c56-8ed44b68f6a1.png)

「dev」→「バージョン：$LATEST」のLambda関数は何かしら、変更を加えておいた方が後から動作を確認しやすいかと思います。



#3.APIGatewayでステージ変数を参照する設定をする。#

Lambda関数に後ろに、`:${stageVariables.alias}`をつけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/113281cf-7649-aa40-f8cc-c68315d702ab.png)



#4.Lambda関数に権限を追加する。#

```
$ aws lambda add-permission --function-name arn:aws:lambda:ap-northeast-1:123456789012:function:mylambda:dev --source-arn arn:aws:execute-api:ap-northeast-1:123456789012:79knnfwq4f/*/GET/ --principal apigateway.amazonaws.com --statement-id 48be8170-282c-42c6-bf64-000000000000 --action lambda:InvokeFunction
{
    "Statement": "{\"Sid\":\"48be8170-282c-42c6-bf64-36c6a9a3d95c\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:123456789012:function:mylambda:dev\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:ap-northeast-1:123456789012:79knnfwq4f/*/GET/\"}}}"
}

$ aws lambda add-permission --function-name arn:aws:lambda:ap-northeast-1:123456789012:function:mylambda:ops --source-arn arn:aws:execute-api:ap-northeast-1:123456789012:79knnfwq4f/*/GET/ --principal apigateway.amazonaws.com --statement-id 48be8170-282c-42c6-bf64-000000000000 --action lambda:InvokeFunction

    "Statement": "{\"Sid\":\"48be8170-282c-42c6-bf64-36c6a9a3d95c\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:123456789012:function:mylambda:ops\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:ap-northeast-1:123456789012:79knnfwq4f/*/GET/\"}}}"
}
```



#5.ステージ変数を追加する。#

「dev」と「ops」2つにステージを作成し［ステージ変数］を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/763612c5-9495-113b-eaa7-34b547d9f69a.png)

［ステージ変数］がない場合は「$LATEST」でアクセスされますが
これで、それぞれのAPIへアクセスすると、1つのLambda関数がそれぞれのステージにデプロイすることができました。
子モデルが空なら更新しない belongs_to has_one

# `mark_for_destruction`のフラグを立てる

DBにデータがあれば`child`が削除され、なければそのまま`parent`だけ登録される。
子モデルに`required: false`を設定しないと、子モデルの値が空のときに[xxx を入力してください]的なバリデーションエラーになる。

```rb:child.rb
class Child < ApplicationRecord
  belongs_to :parent, required: false
end
```

```rb:parent.rb
class Clip < ApplicationRecord
  has_one :, :child => :destroy
  accepts_nested_attributes_for :child
  before_save :set_destroy

  def set_destroy
    self.child.mark_for_destruction if self.child.present? && self.child.name.blank?
  end
```

# 別の方法

[nested attributes なレコードを、特定の属性が空の時に削除する
](https://blog.willnet.in/entry/2015/07/25/174044)

`reject_if`と`attributes.merge!(_destroy: 1)`を組み合わせて使う方法もあるそう。
自分の環境では狙い通りに動作しなかった。
[Rails]ログインidと投稿者が一致した時の条件式をモデルに書き出す

ビューに記載していた条件文を可読性、再利用性向上のためモデルに記載する。
※初心者です。ご指摘あればぜひお願いします。
# 環境
`Rails 5.2.3`
`mysql 5.7.28`
`gem Sorcery使用`
#変更前
```ruby:boards_controller
def index
    @boards = Board.all.includes(:user).recent
end
```
```ruby:_boards.html.erb
<% if current_user.id == board.user_id %>
  <div style='display: inline; float: right;'>
    <%= link_to icon('fas', 'pen'), edit_board_path(board), id: :"button-edit-#{board.id}" %>
    <%= link_to icon('fas', 'trash-alt'), board_path(board), id: :"button-delete-#{board.id}",
                method: :delete, data: { confirm: '削除してよろしいですか？' } %>
  </div>
<% else %>
.
.
.
```
# 変更後
```ruby:user.rb
def own_board?(board)
  self.id == board.user_id
end
```
userモデルにown_board?というメソッドを定義し引数でboardを引き渡す。
boardの中はboards_controllerのindexアクションの中身が入っている。
self.idにはログインしているユーザーid、board.user_idにはboardインスタンスのuser_idが入っており、この両者のidが一致した場合という条件文となる。

```ruby:index.html.erb
<div class="row d-flex">
  <%= render @boards %>
</div>
```
indexではパーシャルを読み込んで

[参照]
[まるで魔法だな（パーシャルをrenderし繰り返し処理をする）](https://qiita.com/ShotaroHirose59/items/0f1a447190bbe4aa8a87)

```ruby:_boards.html.erb
<% if current_user.own_board?(board) %>
  <div style='display: inline; float: right;'>
    <%= link_to icon('fas', 'pen'), edit_board_path(board), id: :"button-edit-#{board.id}" %>
    <%= link_to icon('fas', 'trash-alt'), board_path(board), id: :"button-delete-#{board.id}",
                method: :delete, data: { confirm: '削除してよろしいですか？' } %>
  </div>
<% else %>
.
.
.
```
current_userというインスタンスにはログインユーザーの情報が入っていて(Sorcery内でメソッド定義)このインスタンスメソッドとしてown_board?を呼び出している。
2020年 総額10億円 お年玉キャンペーン の参加者を全員取得してみた

# 「2020年 総額10億円 お年玉キャンペーン」の参加者一覧

[総額10億円のお年玉キャンペーン](https://twitter.com/yousuck2020/status/1212025675055452160)の参加者一覧を見るために、[Yusaku Maezawa (MZ) 前澤友作](https://twitter.com/yousuck2020)さんのフォロワーを全員分取得してみた。

![icons2020](https://ts-3156.github.io/yousuck_followers/icons2020.png)

[参加者の一覧を見る](https://github.com/ts-3156/yousuck_followers/blob/master/campaign2020/README.md)

#### キャンペーン参加者のフォロー数

試しに参加者のフォロー数の分布をグラフにしてみました。見事にべき乗則に従っており、幅広い層の方が参加していることが見て取れます。

![friends_count](https://ts-3156.github.io/yousuck_followers/campaign2020/friends_count_chart.png)


#### 「RTしたユーザーの一覧」ではなく「フォロワーの一覧」を取得した理由

直接的に参加者一覧を取得するのであれば、「リツイートした人」を取得すれば良さそうですが、フォロワーの一覧取得にした理由は下記の通りです。

1. 「RTとフォロー」が応募条件なので、簡易的な集計であればフォロワーを取得してもおよそ同じ結果になる
1. 「RTをしたユーザーの一覧」よりも「フォロワーの一覧」の方が取得が（費用面で）かなり簡単

データ分析等の目的でユーザーのプロフィール一覧が必要であったり、さらに厳密なRTチェックをしたい方は、お気軽にご連絡ください。
眺めて覚えるC言語 その4 PythonからC言語を呼ぶ(引数)　double

#Pythonから実数のa,b,cを引数としてa*b/cを返り値として受け取る。

```capi.py
a,b,c=10.0,20.0,3.0
d=capi.Fcal(a,b,c)　#c言語で計算
print(a*b/c) #pythonで計算
print(d)

実行結果
capi>python capi.py
66.66666666666667
66.66666666666667
```

```capilib.c
#include <Python.h>
static PyObject* Fcal(PyObject* self, PyObject* args){
    double a,b,c,d;
    if (!PyArg_ParseTuple(args, "ddd",&a,&b,&c)){
        return NULL;
    }
    d=a*b/c;
    return Py_BuildValue("d", d);
}
// Function Definition struct
static PyMethodDef myMethods[] = {
    { "Fcal",Fcal, METH_VARARGS, "Fcal a*b/c"},
    { NULL }
};
static struct PyModuleDef myModule = {
    PyModuleDef_HEAD_INIT,"myModule","C API Module",-1,myMethods
};
PyMODINIT_FUNC PyInit_myModule(void){
    return PyModule_Create(&myModule);
}
```
**注目ポイントは、**

```p.c
double a,b,c,d;
    if (!PyArg_ParseTuple(args, "ddd",&a,&b,&c)){
        return NULL;
    }
    d=a*b/c;
    return Py_BuildValue("d", d);
```
　1.　"ddd"は、doubleに変換している。
　2.　Py_BuildValue("d", d)は、戻り値を倍精度で戻している。
　　　floatで計算するとpythonの値と異なってしまう。

```setup.py
from distutils.core import setup, Extension
setup(name = 'myModule', version = '1.0.0',  \
   ext_modules = [Extension('myModule', ['capilib.c'])])
```
**ライブラリの作成**

```
capi>python setup.py install
```
Mac > スクリーンショットから余白を取り除く（影を消す）



Macのデフォルトでは、
↓のようにウィンドウの周りに影付きでスクリーンキャプチャされてしまう。

![Kobito.rB8vWr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/df30aa4d-893c-0dbd-d1c6-a2ac0b567eba.png "Kobito.rB8vWr.png")


余白（影）なしで画像を保存するには、
ターミナルにて以下を打つ


```
defaults write com.apple.screencapture disable-shadow -boolean true
killall SystemUIServer
```


# 参考


[How to disable the drop-shadow in Mac OS X window screenshots](https://www.macgasm.net/news/mac-app-store/disable-dropshadow-mac-os-window-screenshots/)


[Disable the screenshot shadow on Mac OS X | The Electric Toolbox Blog](https://electrictoolbox.com/disable-screenshot-shadow-mac-osx/)


[Take Control of the Mac Command Line with Terminal, 2nd Edition - Joe Kissell - Google ブックス](https://books.google.co.jp/books?id=mT_CDwAAQBAJ&pg=PT118&lpg=PT118&dq=defaults+write+com.apple.screencapture+disable-shadow+-boolean+true&source=bl&ots=GrE1GXMsfn&sig=ACfU3U0Ph0qUq5HypPL7I7SeMIFE3Wa6WA&hl=ja&sa=X&ved=2ahUKEwiz_crHnO7mAhUtBKYKHXEXDjw4ChDoATAIegQIChAB#v=onepage&q=defaults%20write%20com.apple.screencapture%20disable-shadow%20-boolean%20true&f=false)
【React,FontAwesome】react-fontawesome(Solid Style)で指定するiconの名前の指定方法

# この記事を書いた経緯

[公式サイト(英語)](https://www.npmjs.com/package/@fortawesome/react-fontawesome)を見ている時、使いたいアイコン名の指定の仕方に戸惑ったため、こちらの記事ではアイコン名の指定方法に絞って記載します。
**本記事ではSolid Styleに関してのみ記載します。**

なお、react-fontawesomeのインポートや使用方法については他の日本語サイト等に詳しく記載されておりますので、そちらを参考にしてください。

# 使用したいアイコン名の確認

[こちらのサイト](https://fontawesome.com/icons?d=gallery)で使いたいアイコンを探し、クリックします。
アイコンの左上に大きく記載されている名前がアイコン名です。
### 例
URL: https://fontawesome.com/icons/check-square?style=solid
<img width="1411" alt="IconName.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355459/195df1f0-58a3-4d16-ae20-38eacbf209b0.png">


# 使用したいアイコン名の指定方法

### `@fortawesome/free-solid-svg-icons`からのimport時
```react:App.js
import ReactDOM from 'react-dom'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCheckSquare, faCoffee } from '@fortawesome/free-solid-svg-icons'

//FontAwesomeのアイコン名が「check-square」、「coffee」のアイコンを読み込んでいる
library.add(faCheckSquare, faCoffee)  

```
※[参照URL： npm @fortawesome/react-fontawesome(英語)](https://www.npmjs.com/package/@fortawesome/react-fontawesome)

上記のように`@fortawesome/free-solid-svg-icons`から使いたいアイコン名のオブジェクトを取得するときは、使いたいアイコン名をキャメルケースに書き換え、先頭に`fa`をつけます。

### `<FontAwesomeIcon>`タグの`icon`属性指定時
```react:CoffeeMark.js
import React from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
 
export const CoffeeMark = () => (
  <div>
    <FontAwesomeIcon icon="check-square" />
    Favorite beverage: <FontAwesomeIcon icon="coffee" />
  </div>
) 
```
※[参照URL： npm @fortawesome/react-fontawesome(英語)](https://www.npmjs.com/package/@fortawesome/react-fontawesome)

`<FontAwesomeIcon>`タグの`icon=""`を指定するときは、アイコン名をそのまま指定します。

#　参照URL
[公式サイト | npm @fortawesome/react-fontawesome(英語)](https://www.npmjs.com/package/@fortawesome/react-fontawesome)
[公式サイト | アイコン例　check-square(英語)](https://fontawesome.com/icons/check-square?style=solid)
Automator + AppleScriptでサブフォルダーを作る

## 目標

見積書・請求書・発注書/検収書のサブフォルダーを右クリックのプルダウンメニューから一発で作りたい。

## 環境・アプリ・言語

- OS：macOS Mojave(v10.14.6)
- アプリ：Automator
- 言語：AppleScript

## 手順概略

0. Automator立ち上げ
1. 新規作成
2. クイックアクションを選択
3. ワークフローを選択
4. AppleScriptを実行`をドラッグドロップ
5. AppleScriptを記述
6. 名前をつけて保存
 
## 手順詳細

### 1. Automator立ち上げ

```terminal
$ open /Applications/Automator.app
```
or

Applicationsフォルダーから探して立ち上げる。

### 2. 新規作成

ファイル>新規を選択

![新規作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217743/4bdb9e4d-bffb-2d03-28d8-4bf1077996bc.png)

### 3. クイックアクションを選択

クイックアクションを選択して、`選択`ボタンを押下

![クイックアクション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217743/600d8830-27e5-bda4-530c-0738d83726f5.png)

### 4. ワークフローを選択

`ワークフロー：フォルダ` `検索対象：Finder.app`を選択

![スクリーンショット 2020-01-06 17.43.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217743/9d22a3a7-2814-87d5-6935-e677b4e0bb20.png)

### 5. AppleScriptを実行`をドラッグドロップ

アクション>ライブラリ>Automatorの中から`AppleScriptを実行`をドラッグドロップ

![スクリーンショット 2020-01-06 17.45.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217743/d4e74fea-9ecf-8bdf-44b8-ae415b01988a.png)

### 6. AppleScriptを記述

以下AppleScriptをコピペ
↓

```AppleScript
tell application "Finder"
	try
		set currentfolder to (folder of the front window as string)
	on error
		display dialog "フォルダーに移動して、スクリプトを実行してください。" with icon stop buttons {"Cancel"}
	end try
	try
		make new folder at currentfolder with properties {name:"見積書"}
		make new folder at currentfolder with properties {name:"請求書"}
		make new folder at currentfolder with properties {name:"発注書・検収書"}
	on error
		display dialog "すでに作成済みです" with icon stop buttons {"Cancel"}
	end try
end tell
```

![スクリーンショット 2020-01-06 17.48.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217743/5f6f8f71-a1a5-7ae2-5e87-ee8a0419157c.png)

### 7. 名前をつけて保存

名前を付けて保存

![スクリーンショット 2020-01-06 17.51.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217743/347da85a-e4ce-a835-5658-dbfa65bcb564.png)

## 実行してみる

1. 作りたいディレクトリを右クリック
2. 見積書フォルダ作成を選択
3. できた＼(^o^)／

![スクリーンショット 2020-01-06 18.00.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217743/f19f9aa5-7281-b07c-a4da-05bcdd10b08e.png)
![スクリーンショット 2020-01-06 18.00.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217743/ba844d4f-70f0-48f3-1aee-97a6c94d8dfe.png)

---

### おまけ

[右クリックメニューのサービスで階層になるアイテムの個数を設定する](https://qiita.com/zakihaya/items/106d1b59abe38f99b35a)

```
$ defaults write -g NSServicesMinimumItemCountForContextSubmenu -int 20
```

```
$ killall Finder
```

シンプルに生きたい
PowerShell で Microsoft Graph を実行する

# 前提
- AzureAD にアプリが登録されていること
- 登録されたアプリに Microsoft Graph のアクセス許可が適宜設定されていること
- AzureAD アプリの情報を取得済みであること
  - テナントID（下記の形式の内、どちらか一方）
     - contoso.onmicrosoft.com 形式
     - GUID 形式
  - クライアントID
  - クライアントシークレット

# ユーザー一覧を取得する PowerShell コード
```powershell
Connect-PnPOnline -AppId '<クライアントID>' -AppSecret '<クライアントシークレット>' -AADDomain '<テナントID>'
$token = Get-PnPAccessToken
$url = "https://graph.microsoft.com/v1.0/users"
$headerParams = @{'Authorization'="Bearer $token"}
$contentType = "application/json"
$response = Invoke-RestMethod -uri $url -Method Get -header $headerParams -ContentType $contentType
$response.value | Export-Csv -Path .\users.csv -Encoding UTF8 -NoTypeInformation
```

# 参考記事
PowerShell コードを書く際、こちらの記事を大変参考にさせていただきました。ありがとうございます。
[PowerShell を使ってMicrosoft Teams のいいね一覧をCSV形式で出力する](https://qiita.com/wataruf01/items/a4aa72c65721f1a5dd68)

# 参照
[Connect to the Microsoft Graph using Application Permissions](https://github.com/SharePoint/PnP-PowerShell/blob/master/Samples/Graph.ConnectUsingAppPermissions/ReadMe.md)
【Rails】rails g controllerコマンドで特定のディレクトリ以下にファイルを生成するコマンド

## はじめに
通常は`controllers/`以下に作成されてしまうコントローラーを、特定のディレクトリ以下に作成するコマンドです。

## 環境
```yaml
OS: macOS Catalina 10.15.1
Ruby: 2.6.5
Rails: 6.0.2.1
```

## 通常
今回は、`posts_controller`を`index`アクションと`create`アクション付きで作成する場合を例にします。

通常は、以下のようにして作成しますがこのままでは`app/controllers/`ディレクトリ内に作成されます。

```shell
$ rails g controller posts index create
```

これを`controllers/api/v1/`内に作成したい場合は、以下のようにします。
　
## `api/v1/`以下に作成する場合

```shell
$ rails g controller api/v1/posts index create
```
もしくは

```shell
$ rails g controller api::v1::posts index create
```

どちらも同じように動作します。

## ※余談 不要なものをgeneratorで生成したくない場合
例えば、**scss**ファイルと**helper**ファイルが不要だったりする場合は、以下のように設定すればOKです。

```shell
$ rails g controller api/v1/posts index create --no-assets --no-helper
```

もしくは、`application.rb`で以下のよう作成したくないものに対して`false`を設定するとコマンドで入力しなくても、作成されなくなります。

```ruby:config/application.rb
    config.generators do |g|
      g.template_engine false 
      g.assets false
      g.helper false
      g.test_framework :rspec,
                        view_specs: false,
                        helper_specs: false
    end
```

例えば、上記の設定では

- viewファイル（デフォルトでは`erb`）
- assetsファイル(scss)
- helperファイル
- RSpecの**view**と**helper**に関するspec

が`rails g`コマンドでは自動生成されなくなります。

## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:

## 参考にさせて頂いたサイト(いつもありがとうございます)
- [Rails アプリケーションを設定する - Railsガイド](https://railsguides.jp/configuring.html#%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AC%E3%83%BC%E3%82%BF%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B)
- [Rails のコマンドラインツール - Railsガイド](https://railsguides.jp/command_line.html#rails-generate)
DOM操作 メモ

## DOM操作


```js
///parent内のHTMLを取得します
parent.innerHTML
```

```js
///parent内のテキストを取得します
parent.textContent
```

```js
///parentにex属性を
parent.setAttribute('ex',);
```

### テキストを挿入したい場合

例として以下のHTMLを用意する。

```html
<body>
  <ul id="ul">
    <li id="first">1</li>
    <li id="second">2</li>
    <li id="third">3</li>
  </ul>
  <script src="./main.js"></script>
</body>
```

<img width="570" alt="スクリーンショット 2020-01-05 15.20.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537110/9675bf2e-fa2c-86f2-0681-d1dfe2ec1da7.png">


```js

///parent内の一番下にnodeを挿入。
parent.appendChild(node)
parent.append(node)
```



```js

///parent内のnextの前にnodeを挿入。
parent.insertBefore(node, next)
parent.prepend(node)
```



```js

///parentの前にnodeを挿入。
parend.before(node)
```


```js

///parentの後にnodeを挿入。
///parentの閉じタグの次にnodeを挿入。
parent.after(node)
```


上記のメソッドを使用して、下の画像を実装。

<img width="707" alt="スクリーンショット 2020-01-05 15.26.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537110/db4fc590-72bb-ee4f-397a-f63ae69d030b.png">


####insertBeforeとappendChildを使用

```js

let p = document.createElement('p');

let before = document.createTextNode('before');
p = before;
document.body.insertBefore(p,ul);

let append = document.createTextNode('append');
p = append;
ul.appendChild(p);

let prepend = document.createTextNode('prepend');
p = prepend;
ul.insertBefore(p,first);

let after  = document.createTextNode('after');
p = after;
document.body.appendChild(p);

```

####append,before,append,prependを使用した場合

```js

let p = document.createElement('p');

let before = document.createTextNode('before');
p = before;
ul.before(p);

let append = document.createTextNode('append');
p = append;
ul.append(p);

let prepend = document.createTextNode('prepend');
p = prepend;
ul.prepend(p);

let after  = document.createTextNode('after');
p = after;
ul.after(p);
```

後者の方が簡潔で直感的にかけるため、おすすめ。



### HTMLタグを挿入したい場合

```js

parent.innerHTML(HTML)
```

要素内のHTMLを丸ごと入れ替える。
要素内を書き換えたい時に使用。

```js

///parentのタグの直前にHTMLを挿入
parent.insertAdjacentHTML('beforebegin', HTML)
///parentのタグの直後にHTMLを挿入
parent.insertAdjacentHTML('afterbegin', HTML)
///parentの閉じタグの直前にHTMLを挿入
parent.insertAdjacentHTML('beforeend', HTML)
///parentの閉じタグの直後にHTMLを挿入
parent.insertAdjacentHTML('afterend', HTML)
```
parentを軸として、指定した場所にHTMLを挿入する。

```js

let before = `<p>before</p>`
ul.insertAdjacentHTML('beforebegin', before);

let append = `<p>append</p>`;
ul.insertAdjacentHTML('afterbegin', append);

let prepend = `<p>prepend</p>`
ul.insertAdjacentHTML('beforeend', prepend);

let after = `<p>after</p>`
ul.insertAdjacentHTML('afterend', after);
```

<img width="728" alt="スクリーンショット 2020-01-05 16.14.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537110/1b51d708-a362-8d8c-9eca-8dfecab4dab0.png">


###要素をコピーする

```js

///parentをコピーする。
parent.cloneNode(true)
```

###要素を削除する

```js

///parentからnodeを削除する
parent.removeChild(node)
///nodeを削除する
node.remove()
```


###クラスを変更、追加、削除する

```js
///クラスをexに上書きする
parent.className = "ex";
///exを追加する
parent.classList.add('ex');
///exを削除する
parent.classList.remove('ex');
///exを付け外しする
parent.classList.toggle('ex');
```