OmniAICreator/Qiita-1.07M huggingface dataset:
Tableau Publicに取り込んでピボット加工した時系列データのメンテナンス。更新情報を追加する小技メモ【消費支出】

##ピボットで縦長にした「消費支出」データ

Tableau Publicに「消費支出」のデータを取り込みを可視化続けています。
色んなパターンのデータを取り込んでおり、整理が難しくなっています。
今回もメンテナンスに少しとまどったので、その更新方法をメモ代わりに投稿しておきます。

https://www.stat.go.jp/data/kakei/sokuhou/tsuki/index.html

例えば、以下のように都市別に集計できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0ab8067d-d1b5-49db-f6b5-c1a96d4cf70d.png)

データは総務省統計局の[「e-Stat」](https://www.e-stat.go.jp/)から取得しました。
以前インポートしたデータはピボット化したので、時間軸と値列、地域列の3列にまとまっています。
しかし、通常「e-Stat」からエクスポートした状態では時間軸が横に並びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/28773c60-ebf6-3df4-0bc8-d5ed5ac893cb.png)

Tableau Publicにインポートすると、更新分（月）が横に並びます。
この状態を、これまでのスタイルに整形して統一する方法にまず多少手間取りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/faa11aee-2581-3428-6692-8c102c44b4c2.png)

##「ピボットにデータを追加」メニューを利用

**「ピボットにデータを追加」**を使えばよいことがわかりました。
ある列を選択して右隅をクックし、**「ピボットにデータを追加」**をすると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/1f1b294e-579f-5723-1771-70d1f196a5cc.png)

以下のように「時間軸」列に加わりましたが、「時間軸」列が自動的に**文字列型**に変換されました。
変換された状態でワークシートの可視化画面に戻ると、**日付型**でグラフを作成していたので、アラートが出ます。
ワークシートに移る前にひと作業必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/8097b895-ab5e-95fc-fcb0-0421ade5f972.png)

##列の「型を変更」

「YYYY年MM月」は元々列名なので文字列型に変わってしまうようです。
以前「時間軸」列を作った際は時系列推移として可視化するために、「日付型」に変換しました。

　※型が合わず「ピボットにデータを追加」がうまくいかないことがあります。
　※その場合は**「時間軸」列を「文字列型」に変更**してから行います。

今回は、自動的に時間軸列が「文字列型」に変換され、更新分のデータが追加されたので、「日付型」に戻します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/d418157f-70ae-98df-1f3e-d06275369889.png)

「消費支出」列も「文字列型」に変わっていたので、「整数型」に戻しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/175af55a-3b43-be02-37c5-113665d58b3b.png)

##「フィルター」を使い確認

ワークシート（可視化画面）に移ると、更新されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/99da1da7-a2e1-31be-d36f-375585d999c7.png)

更新されたことがわかりにくいので、「月」フィルターを追加し「7月」を選択し、「2021年」を選択した状態にしました。
「7月の消費支出の経年変化」のグラフを目立つようにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/89b6da27-b610-b87c-eca0-5765b0aad597.png)

**了**
intellijコミュニティ版をhomebrewでいれる

※ 執筆当時の情報です
※ mac向けです
Homebrew2.7からcaskがコマンドではなくオプションになったので、新しいコマンドで記事書きます。

```
> brew search --cask intellij
==> Casks
intellij-idea                                        homebrew/cask-versions/intellij-idea-ce19
intellij-idea-ce                                     homebrew/cask-versions/intellij-idea19
```

有料版をいれる方は上、無料版をいれる方は下。

```
> brew install --cask intellij-idea-ce
```
(どちらも`--cask`オプションなしでも動きます。すごい。)

以上！

## 補足

よくみるけど`cask`って何？
macのGUIもhomebrewのようにコマンド一発でインストールできるようにしたものです。

brewがビールを醸造するみたいな意味なので、連想してタルってネーミングにしたんだと思います。
続・GradleでCodeArtifact自動化

結論だけ読みたい人は[こっち](#利用例)

## はじめに
一応、[前回](https://qiita.com/TAC_yacht/items/eb4ca035491dc9a2b77f)それなりにコピペで済むようにはしたものの、冗長であると言わざるを得ない。
そこでプラグインにした。

## プラグインの設定

```groovy:build.gradle
plugins {
  id "io.github.tac-yacht.codeartifact-repository" version "0.1"
}
```
ほかのプラグインも使ってるときは真ん中の行だけ追加
※```settings.gradle```で```pluginManagement.repositories```を設定してる時は```gradlePluginPortal()```の追加を忘れずに

ポータルで各種プラグインごとに例示されてるのと同じではある

## レポジトリの設定
3種類から選べる。

### style A
```aws codeartifact get-repository-endpoint```に渡すオプションと同じスタイル

```groovy:build.gradle
repositories {
    maven(CodeArtifact) {
        domainName = "domain-name"
        repository = "repo"

        //now required. change optionally coming soon.
        domainOwner = "domain-owner"
        region = "region"
    }
}
```

### style B

ARNを渡す

```groovy:build.gradle
repositories {
    maven(CodeArtifact) {
        arn = "arn:aws:codeartifact:us-west-2:111122223333:repository/test-domain/test-repo"
    }
}
```

### style C

```aws codeartifact get-repository-endpoint```で取れるURL

```groovy:build.gradle
repositories {
    maven(CodeArtifact) {
        url = "https://test-domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/npm/test-repo/"
    }
}
```

## 認証の設定

作った順なので非推奨から始まります。今の所、実質[style 3](#style-3) 一択です。
⚠注意：```credentials(AwsCredentials)```は使えません

### style 1

AWSリファレンスと同じ設定方法　あらかじめ取得しといた認証を環境変数にセットした上で以下の設定
※これが面倒くさいからプラグイン作ってるので非推奨

```groovy:build.gradle
repositories {
    maven(CodeArtifact) {
        credentials {
            username = 'aws'
            password = System.env.CODEARTIFACT_AUTH_TOKEN
        }
    }
}
```

### style 2

CodeArtifactのアクセスに使う鍵をべた書きする
※ソースコード共有してたりするとうっかりプッシュとかしかねないので非推奨

```groovy:build.gradle
repositories {
    maven(CodeArtifact) {
        credentials(AwsToPasswordCredentials) {
            accessKey = "myAccessKey"
            secretKey = "mySecret"
        }
    }
}
```

### style 3

~にある.awsに設定済みのプロファイルを参照します。

```groovy:build.gradle
repositories {
    maven(CodeArtifact) {
        credentials(AwsToPasswordCredentials) {
            profile = "myProfile"
        }
    }
}
```

## 利用例

レポジトリと認証の設定を組み合わせた利用例

```groovy:build.gradle
plugins {
  id "io.github.tac-yacht.codeartifact-repository" version "0.1"
}
repositories {
    maven(CodeArtifact) {
        arn = "arn:aws:codeartifact:us-west-2:111122223333:repository/test-domain/test-repo"
        credentials(AwsToPasswordCredentials) {
            profile = "myProfile"
        }
    }
}
```

## 参考先
+ https://docs.aws.amazon.com/ja_jp/codeartifact/latest/ug/maven-gradle.html
+ https://docs.aws.amazon.com/ja_jp/codeartifact/latest/ug/tokens-authentication.html
* [プラグインのソース](https://github.com/tac-yacht/codeartifact-repository-gradleplugin)
* [プラグインポータルでの公開先](https://plugins.gradle.org/plugin/io.github.tac-yacht.codeartifact-repository)
[Flutter] iOSのビルド時に Can't load Kernel binary: Invalid kernel binary format version. のエラーが出た時の対処

## エラー内容
FlutterでiOSの実機でビルドを試みたときに、とあるエラーが出て一向に進まなくなりました。
コンソールには以下のようなエラーが出ていました。

```
[VERBOSE-2:shell.cc(93)] Dart Error: Can't load Kernel binary: Invalid kernel binary format version.
```

## 対処法

まずターミナルで`which flutter`コマンドを流す。

```
% which flutter
~/flutter/bin/flutter
```
のようにFlutterのファイルディレクトリがわかるので、該当箇所まで行って
`flutter > bin > cache` をまるごと削除してしまいます。
  

その後は、`flutter clean`をすると先程削除したファイルが再度生成されるので、`flutter pub get` をしたらビルドが通りました。



Flutterのバージョンを上げて、そのあとダウングレードをしたあとにこのような減少に陥りました。

以上。
【バッチファイル】if分やfor文の注意点。遅延環境変数を知ろう。

#バッチファイルとは（簡単に）
バッチファイルはWindows環境で実行できるコマンドをまとめたテキストファイルです。拡張子は「.bat」です。
複数のコマンドをバッチファイルに書くことで、上から順番に処理してくれます。
システムの運用などで定期的に実行しなければならない処理はバッチファイルに処理をまとめて自動的に実行すると便利です。
Windowsに標準搭載されている「タスクスケジューラ」やサードパーティのタスク管理ソフトウェアなどを使うとより便利に処理の自動化が実現できます。

#if文やfor文を使うときは気を付けて
例えばこんな処理。果たして実行結果はどうなるでしょうか？
#####if文のサンプルコード

```bat:sample_01.bat
@echo off

set val=0

if %val% == 0 (
  set /a val += 1
  echo %val%
)
```

実行結果は以下のようになります。

```bat:実行結果
>sample_01.bat
0
```

「え...１じゃないの！？」と思った方も多いと思います。

このようなことはfor文でも起こります。例えばこんな例。
#####for文のサンプルコード

```bat:sample_02.bat
@echo off

set val=0

for /l %%i in (1, 1, 5) do (
  set /a val+=1
  echo %val%
)
```
これも「１　２　３　４　５」と返ってくると思いきや以下のようになります。

```bat:実行結果
>sample_02.bat
0
0
0
0
0
```

for文でこうなってしまうと、繰り返し途中で条件分岐できないのではと不安になりますよね。。。（安心してください。後ほど解決策を記載します。）
実はこれはバッチ特有の仕組みなのです。まずはこうなってしまう理由を説明します。

#バッチが変数を読み込むタイミング
バッチファイルでは、処理したい行に移ったときに変数が読み込まれます。さらにその変数が読み込まれた時点で、同じ行に存在する同じ変数も読み込まれてしまうのです。
そして重要なのは、たとえ改行していたとしても**カッコ（）**の中の処理は同じ一行として認識されます。
先ほどのif文の例でいうと

```
if %val% == 0 (set /a val += 1　echo %val%)
```
このように一行で認識され、**if**の後の**%val%**が読み込まれると同時にインクリメント処理を飛ばして、最後の**%val%**が読み込まれるのです。

もちろん解決策はあります！

#遅延環境変数を使う
結論から言うと以下のようにしてください。

```bat:sample_01.bat
@echo off

:遅延環境変数を使用する宣言
setlocal enabledelayedexpansion

set val=0

if %val% == 0 (
  set /a val += 1
  echo !val!
)
```

```bat:sample_02.bat
@echo off

:遅延環境変数を使用する宣言
setlocal enabledelayedexpansion

set val=0

for /l %%i in (1, 1, 5) do (
  set /a val+=1
  echo !val!
)
```

**setlocal enabledelayedexpansion**コマンドで遅延環境変数宣言をして、変数を**!val!**のようにビックリマークで囲みます。
こうすることで、**!!**で囲まれた変数は、実際に実行するときに変数を値に置き換えます。
このことを「遅延環境変数の展開」と言うそうです。
if文やfor文のみに関わらず**カッコ()**を使う際は注意が必要ですね。

#最後に
なんだか難しいですが、バッチこ～い！の精神で頑張ります。バッチだけに。。。

#参考サイト

https://wa3.i-3-i.info/word12518.html
Mac(macOS Big Sur)にRust環境を入れてみた。

# はじめに
最近よく目にするRustを実際に試してみたいと思い、自前のMacbookPro(16-inch, 2019)へRust環境を導入、設定してみたので、記事に残しました。なお、今回はIntel Macへの導入になりますので、M1 Macでの導入を検討されている方は、参考サイトに載せたサイトをご覧いただくのが良いと思います。
Homebrewでもインストール可能みたいですが、今回はRustのサイトに載っているインストール方法をそのまま実行しています。

# PC環境
今回Rust環境を導入したPC環境は以下です。

+ MacBook Pro(16-inch, 2019)
  + CPU：Intel Corei9(2.3GHz, 8core)
  + メモリ：16GB
  + OS：macOS Big Sur ver.11.3.1

# Rust環境の導入
Rust環境を導入について以下に記載するが、Rustコンパイラを実行するためにはリンカが必要となるため、先にxcodeを確認する。

### xcodeのバージョン確認

```
$ xcode-select -v
xcode-select version 2384.

$ cc -v
Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin20.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
```
もし、Appleのコマンドライン開発ツールがインストールされていない場合は以下の以下のコマンドでインストールを実施します。

```
$ xcode-select --install
```

### Rustupインストール
Rustupをインストールすることで、Cargoやrustcなど必要なツール類がインストールされます。
インストールを開始すると、rustupのインストール方法に関して選択するメッセージが表示されます。カスタムインストールも可能ですが、今回はデフォルトインストールを選択します。

```
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
info: downloading installer

Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  /Users/XXXXX/.rustup

〜　省略　〜

Current installation options:


   default host triple: x86_64-apple-darwin
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1　　　　

〜　省略　〜

info: default toolchain set to 'stable-x86_64-apple-darwin'

  stable-x86_64-apple-darwin installed - rustc 1.55.0 (c8dfcfe04 2021-09-06)


Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).

To configure your current shell, run:
source $HOME/.cargo/env
```

これでインストールは完了です。ただしパスを設定していないため次にパスを設定します。

# 環境設定
ターミナルを開いた時にパスを通すように設定します。
私のMacの環境では、.zshrcを利用しているため、以下の内容を.zshrcに追加しています。

```:.zshrc
# Rust(20211002 add)
export PATH=${HOME}/.cargo/bin:${PATH}
```

また、sourceコマンドにより手動で環境変数を設定することもできます。

```
$ source $HOME/.cargo/env
```

### バージョン確認

```
$ rustup --version
rustup 1.24.3 (ce5817a94 2021-05-31)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.55.0 (c8dfcfe04 2021-09-06)`

$ rustc --version
rustc 1.55.0 (c8dfcfe04 2021-09-06)

$ cargo --version
cargo 1.55.0 (32da73ab1 2021-08-23)
```
また、```$ rustup show```コマンドでツールキットの情報を表示することができます。

# Rustアンインストール
Rustは、コマンドで簡単にアンインストールすることができます。

```
$ rustup self uninstall
```

# さいごに
Rustのサイトに載っているインストールをごく普通にインストールをしただけ、かつIntel Macに導入しています。
M1 Macの場合、Rosetta2を通してRustを利用することになると思います。参考サイトに丁寧に解説してくださっているサイトを載せておきますので、M1 Macへインストールを考えている方は一度見ても良いと思います。

# 参考サイト
[Rustプログラミング言語サイト](https://www.rust-lang.org/)
[Oxidized Bookshelf](https://blog.rust-jp.rs/tatsuya6502/posts/2020-12-devenv-apple-silicon/)
[リファクタリング]　１週間の投稿数　特定の期間の投稿数表示　scope 引数　map reverse

<h2>初めに</h2>

ポートフォリオで、過去１週間の投稿数を表示させるグラフを作成していましたが、
今回リファクタリングをしてみました。

![スクリーンショット 2021-10-02 21.53.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/5776d8ee-4430-bfcd-917f-6447c1284a8c.png)

<h2>リファクタリング前の実装記事は以下です</h2>

https://qiita.com/ki_87/items/cbfdb803355ba4e4fe55

https://qiita.com/ki_87/items/37e9f42c118f87416aa6

https://qiita.com/ki_87/items/6a0f8f3ee01c538bb75e


<h2>リファクタリング前</h2>

```ruby:post.rb
scope :created_yesterday, -> { where(created_at: 1.day.ago.all_day) }
scope :created_2days_ago, -> { where(created_at: 2.days.ago.all_day) }
scope :created_3days_ago, -> { where(created_at: 3.days.ago.all_day) }
scope :created_4days_ago, -> { where(created_at: 4.days.ago.all_day) }
scope :created_5days_ago, -> { where(created_at: 5.days.ago.all_day) }
scope :created_6days_ago, -> { where(created_at: 6.days.ago.all_day) }
```


<h2>リファクタリング後</h2>

```ruby:post.rb
scope :created_days_ago, ->(n) { where(created_at: n.days.ago.all_day) }
```

<h6>グラフ表示の部分で以下のように記載してあげれば、
６日前の投稿、５日前の投稿などが取り出せます。</h6>

```js:show.html.erb
data: [<%= @posts.created_days_ago(6).count %>,
<%= @posts.created_days_ago(5).count %>,
<%= @posts.created_days_ago(4).count %>,
<%= @posts.created_days_ago(3).count %>, 
<%= @posts.created_days_ago(2).count %>,
<%= @posts.created_days_ago(1).count %>,
<%= @posts.created_days_ago(0).count %>],
```

<h2>さらにリファクタリング</h2>

上記の表示部分も長くなってしまってるので修正します。

```ruby:post.rb
scope :created_days_ago, ->(n) { where(created_at: n.days.ago.all_day) }

#以下追加
def self.past_week_count
 (1..6).map { |n| created_days_ago(n).count }.reverse
end
```

```js:show.html.erb
data: <%= @posts.past_week_count %>,
```

:frowning2:モデルに追加した記述について理解していきます。
リファクタリング前は、created_days_agoに6~０までの引数を与えていましたが、
```(0..６)というrangeオブジェクト```で展開して値を渡すようにします。
そして```map```を使用して配列にします。
```mapは、ループ処理を実行し、処理結果を配列にして返すメソッドです。```
このままだと、0~6になってしまうので、反転させるために```reverse```記載します。


<h2>終わり</h2>
もっと上手にコード書けるように頑張ろうと思いました。
ポートフォリオのフィードバックを丁寧にいただけてありがたい限りです。
Modalで削除機能の実装の仕方（Laravel）

プログラミング初心者です。

##やりたいこと
LaravelでModalを使って削除機能を実装する際に、JavaScriptを使ってのデータの受け渡しに苦戦したので記録します。

##1 Modalを表示させるための削除ボタン

```Blade.php
<a class="btn btn-outline-danger" data-toggle="modal" data-target="#SampleModal" data-title="{{ $sample->title }}" data-url="{{ route('delete.sample',['id' => $sample->id]) }}" > 削除 </a>

```
- ```data-*```でModalやJSにデータを渡せます。
- 今回は```data-title```と```data-url```の値を渡します。（titleやurlは自分で命名できます）
- ```data-target```は必ずModalのidと一緒で、頭に「#」をつけます。
　

##2 Modal実装

```Blade.php
<div class="modal fade" id="SampleModal" tabindex="-1" role="dialog" aria-labelledby="basicModal" aria-hidden="true">
    //form-inline:文字の量に合わせてモーダルの大きさが変化する
    <form role="form" class="form-inline" method="post" action="">
    @csrf
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title" id="myModalLabel">削除確認</h4>
                </div>
                <div class="modal-body">
                    <p></p>
                </div>
                <div class="modal-footer">
                    <a class="btn btn-light" data-dismiss="modal">閉じる</a>
                    <button type="submit" class="btn btn-danger">削除</button>
                </div>
            </div>
        </div>
    </form>
</div>
```
- 元々はfromタグを使っていなく、削除ボタンのところをaタグ使ってhrefでURLを指定していたのですが、データの送信にはaタグは使えず、formタグを使うためbuttonタグに切り替えました。
- fromタグのaction属性とmodal-bodyのpタグを空欄にしています。

##3 Modalにデータ渡すためのJS実装
```Blade.php
//modalにtitleとURLのデータを渡すにはJSが必要
<script>
    window.onload = function() {
        $('#SampleModal').on('shown.bs.modal', function (event) {
            var button = $(event.relatedTarget);//モーダルを呼び出すときに使われたボタンを取得
            var title = button.data('title');//data-titleの値を取得
            var url = button.data('url');//data-urlの値を取得
            var modal = $(this);//モーダルを取得

            //Ajaxの処理はここに
            //modal-bodyのpタグにtextメソッド内を表示
            modal.find('.modal-body p').eq(0).text("本当に"+title+"を削除しますか?");
            //formタグのaction属性にurlのデータ渡す
            modal.find('form').attr('action',url);
        });
    }
</script>
```
- 簡単な説明をコメントに記載しています。
- ```window.onload = function(){}```について、ページや画像などのリソース類を読み込んでから処理を実行したいときに利用するイベントハンドラーと言われるものです。
私の場合これがないと、うまくデータを渡せませんでした。

- 記事を参考にしながら実装したので、正直JavaScriptについて詳しくありません。jQueryのメソッドが使われているので調べてみてください。

##補足
```window.onload = function(){}```について
これ、一つのページに複数使用することができません。
複数使用する場合は、```window.addEventListener('load', function() {}```に変えたところ、うまく実行しました。

##参考
https://qiita.com/kenji__n/items/36b2fd617d49d491c626

https://pisuke-code.com/js-about-window-onload-callback/
【Twitter API】シェアボタンを設置

#はじめに#
　ポートフォリオにTwitterのシェアボタンを付けたくてやってみましたので、備忘録として残しておきます。
これ自体は簡単ですがAPIの申請がなかなかハードル高かったです・・・。

#Twitterシェアボタンの実装方法#
①下記URLのページへ遷移
https://publish.twitter.com/#

②Twitter Buttonsを選択
少し下にスクロールすると、このような画面が出てきます。
一番右のTwitter Buttonsを選択しましょう。
![スクリーンショット 2021-10-02 21.34.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558223/c6f66cdc-e324-0bba-6b9e-54f60ed6ba95.png)

③Share Buttonを選択
するとこのようなポップアップが出てきます。
一番左のShare Buttonを選択します。
![スクリーンショット 2021-10-02 21.35.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558223/e6b6224e-1abf-5d2d-b930-01c2e956d576.png)

④コードをコピー
するとこのような画面が出てきます。コードをコピーすればあとは貼り付けるだけです！
![スクリーンショット 2021-10-02 21.36.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558223/88d8337e-c849-c459-6633-4cb99ba78ccd.png)

```twitter.html
<a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-show-count="false">Tweet</a>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
```

こんな感じになります。
簡単ですね！


#カスタマイズ#
　ツイートの内容をカスタマイズするにはaタグに属性を追加します。

・data-text="テキスト" ・・・　　ツイートに表示するテキストを設定。
・data-hashtags="ハッシュタグ"　・・・　　ツイートに表示するハッシュタグを設定。
・data-size="large" = ボタンサイズを大きくします。
　　
これらの属性を加えることでツイートの内容をカスタマイズできます。
他にも色々種類があるのでやってみましょう！
Rails Model 関連の作成方法

# 多対多

```ruby:post.rb
class Post < ApplicationRecord
  has_many :tags, class_name: 'Tagging'
  has_many :programming_languages, through: :tags
end
```

```ruby:tagging.rb
class Tagging < ApplicationRecord
  belongs_to :post
  belongs_to :programming_language
end
```

```ruby:programming_language.rb
class ProgrammingLanguage < ApplicationRecord
  has_many :tags, class_name: "Tagging"
  has_many :posts, through: :tags
end
```

## #has_many

### 第1引数

`has_many`の第一引数に渡したシンボルがそのままメソッド名になる。
この例では、PostがもつTaggingを`post.tags`で取得できるようになる。
この時、どのクラス名を参照すれば良いのか、それすなわちどのテーブルを参照すればいいのかわからない状態なので　`class_name`オプションにクラス名（モデル名）を指定してあげる。


### through option

`through`オプションは中間テーブルの値を取得する際の関連名（すなわちメソッド名）を指定する。この例でいうとTaggingテーブルが中間テーブルの役割であり、`Post`からの`Tagging`への関連名は`tags`に指定しているのでこれを`through`へ渡す。


### source option
この例ではないがこのオプションも使う場面も出てくることがよくあるので記載する。
先ほどの`through`オプションは、`Post`から`Tagging`への関連名を指定した。
では、`Tagging`から`ProgrammingLanguage`への関連はどうなっているのかというと、`has_many`の第1引数の値となる。つまり、has_manyが以下のようであるとき、

```ruby:relation.rb
has_many :hoge, through: :tags
```
`tag.hoge`によって`ProgrammingLanguage`のレコードをとってくるのである。
よって、この`:hoge`の値は`Tagging`の`belongs_to`メソッドで指定された値と同じである必要がある。

# 参考記事
https://kimuraysp.hatenablog.com/entry/2017/09/05/235816
SSHってなんぞや？

##はじめに

githubやgitlabなどのバージョン管理ツールで「SSH接続」なんてよく聞くかと思います。
ですが、駆け出しエンジニアの僕は、SSH?ってとても疑問に思いました。
なんのためにSSH接続？とやらを行うのか、そもそもSSHとはなんなのか？
という疑問を調べてまとめていきたいと思います。

ぜひ参考にしていただければと思います。

##対象読者
- プログラミング初心者
- 駆け出しエンジニア
- SSHってなんぞや？って方

##SSHとは
「Secure Shell」の略で、ネットワークに接続された機器を遠隔操作し、管理するための手段。
Secureとは安全という意味で、どうやら安全にネットワーク機器を遠隔操作する手段みたいだ。
リモートコンピュータと通信するためのプロトコル。

従来のtalnet⇨パスワードでもなんでもそのまま送る（平文をそのまま送る）
SSH⇨暗号化して送信

###メリット
ネットワーク上の全ての通信が暗号化されるため安全に通信が行える。
認証の仕組みが多様化している。（パスワード、公開鍵、ワンタイムパスワード等）



##SSHを使う理由
現代において、各種サーバー機器は、ほとんどの場合、操作する人から離れた場所にある。
操作する人が安全にインターネット経由で接続できる手段が必要となる。
理由としては、第三者がサーバーにログインできてしまうと、サーバー内でよからぬ操作をされてしまう可能性があるから。
SSHを利用すると、サーバーに安全に接続しできる。

##SSLとは？
似たような言葉で「SSL」というものがある。

下記のような違いがある。
SSH⇨サーバーに接続するのが目的でサーバーの管理者が対象者となる
SSL⇨Webサイトを安全に表示し、Webサイトの閲覧者が対象者となる。

##認証方法
離れた場所にあるサーバへ安全に接続するため、
サーバーへのログインの適正チェックの方法は複数用意されている。

###パスワード認証方式
認証方法：パスワード
安全度：低い

####メリット
設定が簡単

####デメリット
パスワードがバレると終わる（泣）

###公開鍵認証方式
認証方法：「公開鍵」など生成したファイル
安全度：高い

####メリット
暗号化して通信を行い、暗号化した内容を解読するのに秘密鍵がないと解読できないから。
そこまで設定も難しくない。

####デメリット
なんだろう？
秘密鍵を見られたら終わる

公開鍵認証方式の流れ
①クライアント側で秘密鍵・公開鍵を作成
②公開鍵をサーバー側に預ける
③ログインしようとする
④サーバー側で公開鍵で暗号作成
⑤サーバー側からクライアント側に暗号を渡す。
⑥クライアント側で秘密鍵を復号
⑦複合した情報をサーバー側に渡す
⑧既存情報と一致することを確認する

現在は公開鍵認証方式が主に使われている。

###SSH鍵の作り方
環境：Mac OS Big Sur (M1チップ)

ルートディレクトリにて

```コマンド
ssh-keygen -t rsa
```
こちら打ちますと、パスワードが必要かどうかなどが聞かれますが、
特に必要がなければ全て「Enter」でOK。

##SSH鍵が作成されたかの確認方法

ルートディレクトリにて

```
ls -a
```

表示されたディレクトリの中に、.sshがあれば成功。

※　ls -a ディレクトリを全て表示する
lsだけだと隠されたディレクトリが表示されないので注意。

Finderのホームディレクトリで、
Shift＋command+.
でも見ることができます。

```

cat .ssh/id_rsa.pub

```

上記コマンドで公開鍵の内容を見ることができます。

ちなみに.sshの中身ですが、.pubがついているのが公開鍵です。
id_rsa⇨秘密鍵
id_rsa.pub⇨公開鍵

##終わりに
調べているとSSHについてなんとなくわかるようになってきました。
簡単にまとめると
クライアント側で、鍵を二つ作る。
公開していい鍵と、絶対公開してはならない鍵。
公開鍵をサーバー側と共有。
データをクライアント側からサーバー側に投げると、
サーバー側がデータを暗号化してクライアント側に返す。
その暗号は絶対公開してはならない鍵でしか読み解けない。
みたいな感じかな（どんな感じだよ。）

間違ってたらすいません。。。💦

##参考記事一覧

https://www.kagoya.jp/howto/it-glossary/server/ssh/

https://www.idcf.jp/words/ssh.html

https://wa3.i-3-i.info/word11722.html

https://it-trend.jp/encryption/article/64-0057

https://qiita.com/hanlio/items/689d796ec51fcf4c05aa

https://atmarkit.itmedia.co.jp/aig/06network/ssh.html
CentOS7にPHP8.0(+JIT)を導入する

PHP8.0をCentOS7に導入します。

## Remiレポジトリの追加
```
# yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
```

## PHP8.0のインストール
JITを使いたいのでopcache拡張機能も忘れずにインストールします。
他必要な拡張機能諸々も。

```
# yum install -y php80 php80-php-fpm php80-php-mbstring php80-php-pdo php80-php-mysql php80-php-opcache
```

## JITの有効化
JITはデフォルトでバッファサイズが0になっており使えないので、バッファサイズを指定して有効化します。

`/etc/opt/remi/php80/php.d/10-opcache.ini`の最後に以下を追記

```
opcache.jit_buffer_size=100M
```

## メモリexecuteの許可(SELinux環境のみ)

SELinux環境にてPHPを実行しようとすると以下のようなエラーになります。

```
mprotect() failed [13] Permission denied
```

httpd_tに対しhttpd_tmpfs_tのexecuteが許可されていないことが原因ですので、カスタムポリシーを作成してロードします。

```
(setools等インストールしていない場合は以下のコマンドで入れる)
# yum install -y setools selinux-policy-devel
 
# echo '(allow httpd_t httpd_tmpfs_t (file (execute)))' > httpd_jit.cil
# semanage -i httpd_jit.cil
```

## 動作確認

```
# php80 -v
PHP 8.0.11 (cli) (built: Sep 21 2021 17:07:44) ( NTS gcc x86_64 )
Copyright (c) The PHP Group
Zend Engine v4.0.11, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.11, Copyright (c), by Zend Technologies
# php80 -i | grep opcache.jit
opcache.jit => tracing => tracing
opcache.jit_bisect_limit => 0 => 0
opcache.jit_blacklist_root_trace => 16 => 16
opcache.jit_blacklist_side_trace => 8 => 8
opcache.jit_buffer_size => 100M => 100M
opcache.jit_debug => 0 => 0
opcache.jit_hot_func => 127 => 127
opcache.jit_hot_loop => 64 => 64
opcache.jit_hot_return => 8 => 8
opcache.jit_hot_side_exit => 8 => 8
opcache.jit_max_exit_counters => 8192 => 8192
opcache.jit_max_loop_unrolls => 8 => 8
opcache.jit_max_polymorphic_calls => 2 => 2
opcache.jit_max_recursive_calls => 2 => 2
opcache.jit_max_recursive_returns => 2 => 2
opcache.jit_max_root_traces => 1024 => 1024
opcache.jit_max_side_traces => 128 => 128
opcache.jit_prof_threshold => 0.005 => 0.005
```

バージョン−表示で`with Zend OPcache`になっていること、および`jit_buffer_size`が0より大であることを確認します。


## 参考
CentOS7にPHP8.0をyumインストールする方法 | PHP Junkie
https://php-junkie.net/env/php8/

Chapter 7. Writing a custom SELinux policy Red Hat Enterprise Linux 8 | Red Hat Customer Portal
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/using_selinux/writing-a-custom-selinux-policy_using-selinux
selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH.



スクレイピングをするPythonスクリプトを久しぶりに動作させたら以下のエラーが出た．

```
selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home
```

自分のChromeのバージョンとchrome driverのバージョンが異なる場合にエラーになるみたい．

```
import chromedriver_binary
```
をすることで直接PATHを指定する必要はないとのこと．
ただし正しいバージョンのChrome Driverをインストールする必要がある．

Chromeで[chrome://settings/help](chrome://settings/help)にアクセスすると自分のChromeのバージョンを確認できるので，そのバージョンのDriverをインストールする

今回自分は
`94.0.4606.61 `
だったので，

```
$ pipenv install chromedriver-binary==94.0.4606.61
```

とすればOK

ピッタリのバージョンがない場合にはエラーが出るけど，エラーメッセージの中で指定できるバージョン一覧が出てくる

以下はバージョン`98.0.4758.102.0`を指定したけどなかったときのエラーメッセージ
```
Error:  An error occurred while installing chromedriver-binary==98.0.4758.109!
Error text: 
ERROR: Could not find a version that satisfies the requirement chromedriver-binary==98.0.4758.109 (from versions: 2.29.1, 2.31.1, 2.33.1, 2.34.0, 2.35.0, 2.35.1, 2.36.0, 2.37.0, 2.38.0, 2.39.0, 2.40.1, 2.41.0, 2.42.0, 2.43.0, 2.44.0, 2.45.0, 2.46.0, 70.0.3538.16.0, 70.0.3538.67.0, 70.0.3538.97.0, 71.0.3578.30.0, 71.0.3578.33.0, 71.0.3578.80.0, 71.0.3578.137.0, 72.0.3626.7.0, 72.0.3626.69.0, 73.0.3683.20.0, 73.0.3683.68.0, 74.0.3729.6.0, 75.0.3770.8.0, 75.0.3770.90.0, 75.0.3770.140.0, 76.0.3809.12.0, 76.0.3809.25.0, 76.0.3809.68.0, 76.0.3809.126.0, 77.0.3865.10.0, 77.0.3865.40.0, 78.0.3904.11.0, 78.0.3904.70.0, 78.0.3904.105.0, 79.0.3945.16.0, 79.0.3945.36.0, 80.0.3987.16.0, 80.0.3987.106.0, 81.0.4044.20.0, 81.0.4044.69.0, 81.0.4044.138.0, 83.0.4103.14.0, 83.0.4103.39.0, 84.0.4147.30.0, 85.0.4183.38.0, 85.0.4183.83.0, 85.0.4183.87.0, 86.0.4240.22.0, 87.0.4280.20.0, 87.0.4280.87.0, 87.0.4280.88.0, 88.0.4324.27.0, 88.0.4324.27.1, 88.0.4324.96.0, 89.0.4389.23.0, 90.0.4430.24.0, 91.0.4472.19.0, 91.0.4472.101.0, 92.0.4515.43.0, 92.0.4515.107.0, 93.0.4577.15.0, 93.0.4577.63.0, 94.0.4606.41.0, 94.0.4606.61.0, 94.0.4606.113.0, 95.0.4638.10.0, 95.0.4638.17.0, 95.0.4638.54.0, 95.0.4638.69.0, 96.0.4664.18.0, 96.0.4664.35.0, 96.0.4664.45.0, 97.0.4692.20.0, 97.0.4692.36.0, 97.0.4692.71.0, 98.0.4758.48.0, 98.0.4758.80.0, 98.0.4758.102.0, 99.0.4844.17.0, 99.0.4844.35.0)
ERROR: No matching distribution found for chromedriver-binary==98.0.4758.109
```

おそらく近いバージョンを指定すればなんとかなるはず．

バージョンは適当に読み替えてください．
sorcetreeから急にpushできなくなった

github actionを使おうと思って、新しく __.github/workflows/ruby.yml__を作成しました。
*rubyの部分は任意で決められます

とりあえず動くのかの確認をしたかったので、最初は簡単に書きました

```
name: Ruby

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  test:

    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    - name: Set up Ruby 2.6
      uses: actions/setup-ruby@v1
      with:
        ruby-version: 2.6.x
    - name: Build and test with Rake
      run: |
        gem install bundler
        bundle install --jobs 4 --retry 3
        bundle exec rake
```

こんな感じ。
ここでソースツリーからコミットしてプッシュしようとしたらできなかった。

エラー文の大事そうなところ

```
! [remote rejected] yamlfile_edit -> yamlfile_edit (refusing to allow a Personal Access Token to create or update workflow `.github/workflows/ruby.yml` without `workflow` scope)
```

個人のアクセストークンにはworkflowに関する権限がないみたいですね。

github公式　
↓
自分のアイコンをクリック
↓ 
メニューの「Settings」
↓
サイドメニューにある「Developer settings」
↓
ソースツリーで使っているアクセストークンを選択
↓
チェックを入れる画面が表示されるので
workflowにチェックを入れる
↓
push成功！
[メモ] 外部端末からWindows 10 WSLへSSH接続方法（ポートフォワード無し）

# ポートフォワード無しに、外部端末からWindows 10 WSLへSSH接続方法について
WSLのopenssh serverに向けて、Windows側でポートフォワード設定したくなかったので、いろいろ調べて一番簡単だった方法をメモします


## 0. 前提
- SSH clientがインストールされた、メインPCがある
- WSLをインストール済みの、サブPCがある。
    - Windowsユーザー名が「英文字」（漢字ひらカナもできるけど入力がめんどくさいので）
    - Windowsユーザーのパスワードを設定している（パスワード無くていいはずがない）
    - ローカルネットワークのIP addressを知っている（固定IPがおすすめ）


## 1. 準備（サブPCで）
1. [このofficialインストラクション](https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse)に従って、OpenSSH serverを、Windows 10側に（WSL上でない）インストールする
2. `Powershell.exe` を管理者権限で実行し、以下を入力して、startupのときにssh serverが立ち上がるようにする

```
Set-Service -Name sshd -StartupType 'Automatic'
```
そして、再起動する


## 2. 接続方法（メインPCで）
1. ターミナルを立ち上げる
2. 以下のように入力

```
ssh win_user_name@sub_pc_ip_address -t 'wsl ~'
```
`win_user_name`はWindowsのユーザー名、`sub_pc_ip_address`はサブPCのIPアドレス。
パスワードを入力すると、若干間をおけれど、サブPCのWSLに行きます


## 3. 考察

| Pros | Cons |
| ---  | ---  |
| 少なくともポートフォワードよりは圧倒的に簡単 | 1. GUI立ち上げができない 2. パスワード流出したら即アウト |

よりいい方法ありましたら、ご教示ください。

## 参考
https://askubuntu.com/questions/1339980/enable-ssh-in-wsl-system
「ブレークポイントは、現在の設定ではヒットしません。このドキュメントのシンボルが読み込まれていません。」の対処法

# 「このドキュメントのシンボルが読み込まれていません。」と表示される
Win32アプリ開発中、ブレークポイントが無視される状態に陥り。検索しても原因が分からず結局自力で解決した時のメモ。
デバック実行でブレークポイントが赤丸に三角のビックリマークに変化しカーソルを合わせると掲題のメッセージが表示される。
# 原因 
この状態になる原因はいろいろあるらしいが、私の場合何の弾みで弄ってしまったのか、構成プロファイルの**デバック情報の形式**を**"なし"**にしていた事が原因。

# 解決手段
プロジェクトの「**構成プロパティ＞C/C＋＋＞全般＞デバック情報の形式**」を「**エディットコンティニュのプログラムデータベース（/ZI）**」に変更してクリーンビルドする。

#その他の確認項目

###構成プロファイルがDebugではない
プロジェクトの構成プロパティからDebug構成を選択する。

### デバッグの種類が合っていない。
「**構成プロパティ＞デバック＞デバッカーの種類**」に間違った値を指定するとブレークポイントは通常表示されたままスルーされる。
今回の場合、Win32アプリを開発していたので「**自動**」または「**ネイティブのみ**」が正解。

###ストリップされたPDBファイルを使っている
リンカーオプション「**/PDBSTRIPPED**」を指定（**構成プロパティ＞リンカー＞デバック＞プライベート シンボルの除去**にPDBファイルパスを指定）するとシンボル情報を持たないPDBファイルを作成できるが、このPDBファイルを使用すると掲題の問題が出るらしい。

ただし、PDBファイルが指定されたファイル名で作成されるだけなのでこのオプションを指定しただけでは問題は起きない。

_/PDBSTRIPPED (プライベート シンボルの除去)_
(https://docs.microsoft.com/ja-jp/cpp/build/reference/pdbstripped-strip-private-symbols?view=msvc-160)

_Visual Studio デバッガーでのブレークポイントのトラブルシューティング_
(https://docs.microsoft.com/ja-jp/visualstudio/debugger/troubleshooting-breakpoints?view=vs-2019)
※モジュールウィンドウはデバック実行を開始した後でないと開けないので注意。


### Debug版のlibやdllファイルを使用していない。
私の場合、Release構成でビルドした外部のライブラリやDLLを使用していたのでDebug構成でビルドし直したが、そもそもデバック情報の形式が原因で掲題のエラーが発生していたので今となってはこれも原因の一旦だったのかが不明。

# さらに別の原因について参考になるサイト
[https://ameblo.jp/waka21/entry-10289918886.html](https://ameblo.jp/waka21/entry-10289918886.html)
mysqlについて

# 記事の概要
- mysqlの`where exist`構文の作りが理解できなかったため、調査した話。

# 疑問点

```sql
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
```
というようなsqlを見て構文の構成が不明だったので、色々試していたら、

```sql
SELECT column1 FROM t1 WHERE '1';
```
を実行すると、対象テーブルt1の全レコード取得

```sql
SELECT column1 FROM t1 WHERE '0';
```
を実行すると、0行の実行結果となった。
え？where句って、`column=1`みたいな記載じゃなくても動くの？？

# 調査結果

[mysql公式のwhereステートメント説明](https://dev.mysql.com/doc/refman/5.6/ja/select.html#:~:text=where_condition%20%E3%81%AF%E3%80%81%E9%81%B8%E6%8A%9E%E3%81%95%E3%82%8C%E3%82%8B%E5%90%84%E8%A1%8C%E3%81%AB%E5%AF%BE%E3%81%97%E3%81%A6%20true%20%E3%81%AB%E8%A9%95%E4%BE%A1%E3%81%95%E3%82%8C%E3%82%8B%E5%BC%8F%E3%81%A7%E3%81%99%E3%80%82WHERE%20%E5%8F%A5%E3%81%8C%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%80%81%E3%81%93%E3%81%AE%E3%82%B9%E3%83%86%E3%83%BC%E3%83%88%E3%83%A1%E3%83%B3%E3%83%88%E3%81%AF%E3%81%99%E3%81%B9%E3%81%A6%E3%81%AE%E8%A1%8C%E3%82%92%E9%81%B8%E6%8A%9E%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)を見ると…
`where_condition は、選択される各行に対して true に評価される式です。WHERE 句がない場合、このステートメントはすべての行を選択します。`
||
つまり
select時に、一行一行に対してwhereの条件が一致するかを計算し、一致する場合trueを返す。
て事
||
ってことは…

```sql
SELECT column1 FROM t1 WHERE '1';
```
にすると、全行がtrueをみなすような形になり、全行返却されるのか！！

納得 :relaxed:

上記理解できたので、where existの作りも理解できた :sunny:

ただ考察も含まれているので、違う可能性もあります。
（先輩たち、間違った事言ってたら教えてください :bow: ）
Youtube IFrame Player APIで途中から再生させたいとき

Youtubeをメインビジュアルとして埋め込むコーディングのお仕事があったのですが、
なぜかいただいたYoutubeの最初の1秒間が真っ暗だったため、どうにか1秒目から動画をスタートさせたくて、調べて見つかったのでメモメモ。
_φ(･_･。
あれこれ検索したけど、最初からリファレンス読めばよかった...
※取り扱い説明書はちゃんと使う前に読みましょう。電化製品も。APIも。

---

* 参考リファレンス1: [iframe 組み込みの YouTube Player API リファレンス](https://developers.google.com/youtube/iframe_api_reference?hl=ja)
* 参考リファレンス2: [YouTube 埋め込みプレーヤーとプレーヤーのパラメータ](https://developers.google.com/youtube/player_parameters?hl=ja)


APIでのYoutubeの実装は、上記リファレンスページにサンプルコードがあるのでそれで行けました。
※下記のサンプルコードはリファレンスから参照してちょっと削ったり編集したりしたものです。

途中から再生させたいときは、`playerVars`というプロパティを追加して、その中に`start`パラメータを入れます。
他にも`rel`パラメータはよく使います。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Youtube API Test</title>
</head>
<body>
<div id="player"></div>

<script>
	var tag = document.createElement('script');
	tag.src = "https://www.youtube.com/iframe_api";
	var firstScriptTag = document.getElementsByTagName('script')[0];
	firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

	var player;
	function onYouTubeIframeAPIReady() {
		player = new YT.Player('player', {
			height: '360',
			width: '640',
			videoId: 'M7lc1UVf-VE',
			playerVars: {
				rel: 0,    // 0にすると関連動画は同じチャンネルから選ばれる
				start: 9   // Googleのロゴをぶっ飛ばして9秒目からスタート
			},
			events: {
				'onReady': onPlayerReady
			}
		});
	}
	function onPlayerReady(event) {
		event.target.playVideo();
	}
</script>
<script src="https://www.youtube.com/iframe_api"></script>
</body>
</html>
```
【NeosVR】Exportのお話【コンポーネント】

#はじめに
フリック( https://twitter.com/TewiEwi_no96 )です！よかったらフォローしてくださいω
NeosVR(https://neos.com/) というVRプラットフォームに未来を感じています。
Unityの中にダイブしたようなクリエイティブな空間であり、
今では様々な面白く楽しい空間が増えていますので、是非とも遊んでみて下さいω
#導入
NeosVRの技術の一つに、VR内のテキストや写真、音楽、動画、3Dオブジェクト、バイナリデータまでも
自分のパソコンにエクスポートする機能があります。
とんでもない機能ですよね？
それがんなコンポーネントで構成されているのかを解説したいと思います！
(このコンポーネントのExportとCancelボタンは仕様上、他人がExportする事は出来ません。流石！)
#今回、学習できるコンポーネント
・Assets/Export/AudioExportable
・Assets/Export/BinaryExportable
・Assets/Export/TextExportable
・Assets/Export/TextureExportable
・Assets/Export/VideoExportable
・Uncategorized/ModelExportable
・Uncategorized/ExportDialog
・UI/Physical/NeosTextField
・UI/Physical/NeosRadioGroup
・UI/Physical/NeosRadio
・UI/Physical/NeosButton
・Rendering/Visuals/NeosUIStyle

↓NeosVRのコンポーネント一覧はWikiを参照くださいω
(https://neosvrjp.memo.wiki/d/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8%B0%EC%CD%F7)
#オブジェクトの構成
写真のような階層構造にしています！
(分かりやすいように、Slot名をコンポーネント名にしています。)

[title]Export
┣ExportDialog
┃┣NeosUIStyle
┃┣NeosTextField - Name
┃┣NeosRadioGroup
┃┃┣Choice
┃┃┗NeosRadio
┃┣NeosButton - Cancel
┃┗NeosButton - Export
┣ModelExportable
┃┗EmptyObject(参照例)
┣AudioExportable
┃┗StaticAudioClip(参照例)
┣BinaryExportable
┃┗StuticBinary(参照例)
┣TextExportable
┃┗ValueFeld<string>(参照例)
┣TextureExportable
┃┗StuticTexture2D(参照例)
┗VideoExportable
 ┗VideoTextureProvider(参照例)
![2021-10-03 00.32.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556177/05c763de-d3eb-3fac-968e-f5f794021441.png)
<b>下記コンポーネントを編集します</b>
<b>・ExportDialog</b>
_targetFolder : 任意のフォルダPass //ここに保存します。
_style : NeosUIStyle //スタイルの指定(エフェクト)
_name : NeosTextField - Name //このファイル名で保存されます。
_radioGroup : NeosRadioGroup //ラジオボタングループの指定。
_cancel : NeosButton - Cancel　//キャンセルボタンの指定、閉じます。
_export : NeosButton - Export　//エクスポートボタンの指定、エクスポートされます。
_exportOption(list):0:Radio //ラジオボタンの指定
_exportOption(list):0:Exportable //Exportableを指定、画像か動画か音楽か色々
_exportOption(list):0:ExportType //Exportableのタイプを指定、拡張子ですね、詳しくはメモにて！
#メモ - Exportableのタイプ
<b>・Assets/Export/AudioExportable</b>
0:(original format)
<b>・Assets/Export/BinaryExportable</b>
0:(ファイル名)
<b>・Assets/Export/TextExportable</b>
0:text
<b>・Assets/Export/TextureExportable</b>
0:PNG
1:JPG
2:EXR
3:LUT
<b>・Assets/Export/VideoExportable</b>
0:(original format)
<b>・Uncategorized/ModelExportable</b>
0:DAE
1:OBJ
2:PLY
3:FBX
4:STL
5:X
6:GLTF
7:ASSBIN
8:ASSXML
#FUNBOXで支援してもらえると記事を書く励みになります。
https://frick.fanbox.cc
【考察】45歳定年説について

#前書き
今日は横浜ＦＣが勝利した。久しぶりに気分が良い。J1降格候補No.1なのだが、先週の横浜ダービーといい好試合が続いている。
補強した助っ人とチームが馴染んできたということか。最下位のチームが、J1、2位及び3位争いしているチームに好試合を続けている。
窮鼠猫を噛むじゃあないが、残り試合もこの調子で頑張ってもらいたい。

で、今日は気分がとても良いので、最近炎上というか、話題になっている説について語るとする。
サントリーホールディングスの社長、新浪剛史氏の失言、「４５歳定年制」についての考察である。
もしかすると気分を害する人とか、くだらない議論だと一蹴する人もいるだろうが、私も始めはそうだった。出来ればこういう話題は掘り下げたくない。
だが、しかし。新浪氏の失言から暫くたった今でも、この話題が注目されている点について、ふと考察してみたという話である。

ちなみに、私はこの説について、賛成・反対どちらの意見でもない。
というと、卑怯者と思われるかもしれないが、もともと「年齢で判断する人間に共感が持てない」という人間である。
なので、どちらかというと「反対」である、ということは先に宣言しておく。

#本題　「45歳定年説」とは？

2021年9月9日。経済同友会のオンライン夏季セミナーの場において、サントリーホールディングスの新浪剛史社長の発言がきっかけとなった説。
詳しくは、ネットの記事を参照されたい。

https://www.jiji.com/jc/article?k=2021090901120&g=eco

新浪氏はそのセミナーで、「ウィズコロナの時代に必要な経済社会変革について「４５歳定年制を敷いて会社に頼らない姿勢が必要だ」と述べたという。

で、それの発言が炎上した。

ニュースを読んだ私は、当時即座に、「年齢で線引きするな、くだらん」と思って受け流していたが、世間は賛否両論、いまだに盛り上がっているようだ。
ネットはおろか、当社の社内でも度々話題に上がっている。

で。今日、その記事の話題についての社内投稿を読んだ際、ふと考えた。


**45歳で不要（＝経営者が従業員の定年を希望する人）になるのは、「代替が効く人」ではないか？**


別にその人じゃあなくてもよい人材。
例えば、一般論ではあるが、45歳以上の人の「代替が効く人」であれば、その人より、伸びしろがあって、柔軟で、献身的である、そしてコスト（＝給料）も安い、投資対効果の高い人材（≒若い人）に投資した方が良いのではなかろうか？

私が経営者だったら、合理的にみてそう判断するだろうな。本音としては。

でも、この私の理論が「真理」だとすると、「年齢」や「終身雇用・年功序列」という日本的経営を前提に「コスト」を軸に考えたとしたとしても、「45歳定年説」は、その年齢が「45歳」でも遅いくらいだ、と思う。その理論だとすれば、「まだまだ甘いな新浪さん」だと思う。

だって、孔子さんも昔から言っているよね。「三十にして立つ。四十にして惑わず。」って。

#結論　「45歳定年説」とは？

私的解釈である。
前提として、 

**人間は、歳を重ねていくごとに成長していくものである。**

その上で、経営者目線から言えば、

**投資対効果の高い人材に投資をする、というのは経営の鉄則である。**

なので、職業人として誰もが必要なスキル・心構えとしては、

**「代替が効かない、唯一無二の存在」**

を目指すことではなかろうか？

ふむ。以前読んだクレディセゾンの現CTO小野和俊さんのコトバ。「ラストマン戦略」に通じるところがあるな、と思った。

https://qiita.com/takeC74/items/1aa2e2b6b424b24ffe7a


（参考）
「45歳定年説」でググった結果。（1,008,000件ヒット）

https://www.google.com/search?q=45%E6%AD%B3%E5%AE%9A%E5%B9%B4%E8%AA%AC&rlz=1C1GCEA_enJP933JP933&oq=45%E6%AD%B3%E5%AE%9A%E5%B9%B4%E8%AA%AC&aqs=chrome..69i57.7291j0j15&sourceid=chrome&ie=UTF-8

新浪社長のオトモダチ。山﨑元氏のフォロー記事。

https://www.esquire.com/jp/culture/column/a37688853/dol-what-is-wrong-with-the-45-year-old-retirement-age-theory-by-hajime-yamazaki/
30分でできるRubyからTwitterにツイートするプログラム

## ツイートできるまでの流れ
>
１.TwitterDeveloperの登録
２.TwitterDeveloperでプロジェクトの作成
３.APIの取得
４.プログラムの作成・実行

## TwitterDeveloperの登録
当記事では、TwitterDeveloperへの申請は完了しているものとして進めます。

まだアカウントも持っていない人は、これらの記事を参考に登録を行ってみてください！

https://auto-worker.com/blog/?p=3157

https://zenn.dev/specially198/articles/9d1ce6c797bb5b

## APIの取得

プロジェクトを作成し、APIキーを取得します。

以下の４つのキーを取得することでTwitterと連携することができるようになります！
<strong>自分の書いたプログラムとTwitterを繋げる鍵</strong>のようなイメージで大丈夫です！
>
 - consumer_key
 - consumer_secret
 - access_token
 - access_token_secret

では、Developerにログインしてください
https://developer.twitter.com/en
<p>
まずは、[ ＋Create App ] からAppを作成します
![スクリーンショット 2021-10-02 18.06.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/863944/707cff38-e385-44a7-5c83-c890ed52b3cd.png)

Appの名前は適当に決めて入力してください！
![スクリーンショット 2021-10-02 16.46.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/863944/9ad0ccb6-f9db-7e68-73a8-400b6fde19ea.png)

次の画面で、<strong>２つのkeyが取得できる</strong>ため、どこかに控えておきましょう！
 - consumer_key
 - consumer_secret


<strong>残り２つのkey</strong>については、[ Access Token and Secret ] Regenerateボタンを押すことで取得することができます。
 - access_token
 - access_token_secret
こちらもどこかに控えておきましょう！
![スクリーンショット 2021-10-02 18.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/863944/86728abe-f3f6-243a-20bd-b04516f8e560.png)
consumer_keyなどを<strong>控え忘れた</strong>人などは、
[ API Key and Secret ]からRegenerateボタンを押すことで<strong>再発行</strong>することもできます。
##プログラムの作成

https://github.com/sferik/twitter/

コードを書く前に必要なgemのインストールを行いましょう

```ターミナル:ターミナル  
$gem install twitter
```
<p>
下準備が完了したので、プログラムを書いていきます
以下のコードをコピーして、<strong>控えた４つのkeyに修正する</strong>だけです！

あとはこのプログラムを実行することでツイート完了です
ぜひやってみてください！

```ruby:twitting.rb
require 'twitter'

client = Twitter::REST::Client.new do |config|
  config.consumer_key        = "ここにconsumer_key入力してね！"
  config.consumer_secret     = "ここにconsumer_secret入力してね！"
  config.access_token        = "ここにaccess_token入力してね！"
  config.access_token_secret = "ここにaccess_token_secret入力してね！"
end

client.update("Rubyからツイート @gem!")

```
>
<strong><font color='red'>【注意】こちらの４つのkeyは第三者に知られると悪用される可能性があるため、GitHubなど公の場には上げないように気をつけてください</font></strong>

## 【補足】Read-only application cannot POST Error の解決方法
エラーの内容を簡単に説明すると、<strong>書き込みの権限がないため</strong>エラーとなってます
権限は簡単に変更できます！

TwitterDeveloperで、以下のEditから[ Read and Write ]に変更を行う
<strong>権限の設定を変更した場合は、アクセストークンを再発行して使用する必要があります</strong>
![スクリーンショット 2021-10-02 19.16.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/863944/66b9c2d0-db5c-a48a-807a-f6e89ec6f94d.png)
UE4で自作プラグインが消えた話

#事は起こるべくして起こった

もうPC、古いからマザーボードごと、OS再インストール、取り替えだ。
↓
プロジェクトは同期でバックアップとってるし、外付けに全部移してある。UE4はCドライブに残って、消えるけどネットから落とせるし大丈夫だろう。
↓
PC新調
↓
・・・プロジェクトのBPとかC++ソースがエンジンのプラグインとして入ってたあ！死

#気をつけましょう
気をつけましょう（2回目）
【JavaScript】便利な配列操作テクニック集

## 配列内の要素を一意にする
```ts
  const arr = ["A", "A", "B", "C", "C", "C", "B", "D"];
  // eleは要素
  // iはindex
  // selfはarr配列
  // indexOfは配列内から引数で指定した値が最初に現れたindexを返す
  const newArr = arr.filter((ele, i, self) => self.indexOf(ele) === i);
  console.log(newArr); // => ["A", "B", "C", "D"]
```

## ２つの配列を組み合わせた処理
```ts
const func = () => {
  //targetのnameプロパティに一致したarrはidとセットの配列にする

  const arr = ["佐藤", "鈴木","トマト"];

  const target = [
    {
      id: 0,
      name: "佐藤"
    },
    {
      id: 1,
      name: "田中"
    },
    {
      id: 2,
      name: "鈴木"
    }
  ];

  const result = arr.map((ele) => {
    let targetId = "";
    target.forEach((obj) => {
      if (obj.name === ele) {
        targetId = obj.id;
      }
    });
    return targetId === "" ? { name: ele } : { id: targetId, name: ele };
  });
  console.log(result); // => [ { id:0, name:"佐藤" }, { id:2, name:"鈴木" }, { name:"トマト" } ]
};
```
UE4のライティングビルドでCPU温度上がる問題

#多分、基本的な事だから書かれてないのだろうけど

UE4のライティングをビルドすると、SwarmAgentというのが起動してごにょごにょしますが、その時にCPU温度が80度以上に上昇したので解決方法を調べていたら、
SwarmAgentのDeveloperSettingsのLocalJobsDefaultProcessorCount、RemoteJobsDefaultProcessorCountいじるとか、ダウンクロックするとか書かれてましたが、

![qiita01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128851/a756bedf-fd35-0799-8546-dca4949d2125.jpeg)

見落としていたのは、電源オプションの「最小のプロセッサの状態」でした。ここが100%になっていたので、修正したら、温度が上がりませんでした（もちろん速度は落ちましたが）
「最大のプロセッサの状態」に目に行きがちですが、これは思わぬ出来事でした。
JuliaのパッケージをGithubからcloneしてGoogle Colaboratoryで使う方法

# はじめに

Google Colaboratoryはクラウド環境でPythonが実行できるサービスとして有名ですが、Juliaを実行することもできます。Juliaを利用する方法については、以下の記事が参考になります。

https://qiita.com/cometscome_phys/items/1ba6ec181bb0fe1b35d5

ところで、ある程度まとまったコードをすでに書いており、それをGoogle Colaboratoryで使いたいという需要もまたあるのではないかと思います。そこでこの記事では、Juliaの実行環境が構築されていることを前提に、GithubのレポジトリをcloneしてGoogle Colaboratoryで利用する方法をまとめました。


# やり方
JuliaのパッケージがGithubのrepositoryに置いてある場合を考えます。repositoryはPrivateでもPublicでも構いません。

## Personal access tokenを作成する
この記事の執筆時点で、Githubはパスワード認証を廃止しています。代わりに利用できるのがPersonal access tokenを用いた認証です。tokenを作成する方法は[公式ページ](https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)を参照してください。然るべき手順を踏んで"Generate token"すると、`ghp_***************`といった長い文字列が表示されるので、これを記憶しておきます。

## cloneする
次にGoogle Colaboratoryのノートブック（すでに規定のカーネルがJuliaになっているものとします）を開き、以下のコマンドをコードブロックに書きこんで実行します。

```julia
run(`git clone https://USERNAME:TOKEN@github.com/USERNAME/REPOSITORYNAME.git`)
```

ここで、`USERNAME`はGithubのユーザー名、`TOKEN`は上で作成したアクセストークン、`REPOSITORYNAME`はrepositoryの名前です。例えば、ユーザー名が`JohnSmith`、`TOKEN`が`ghp_hogehogehoge`、repository名が`Myrepo`の場合、

```julia
run(`git clone https://JohnSmith:ghp_hogehogehoge@github.com/JohnSmith/Myrepo.git`)
```

となります。``run(`ls -l`)``コマンドを打って、`Myrepo`というディレクトリができていれば成功です。

## パスを通す
cloneしたパッケージをJuliaに認識させる作業を行います。

以下のコマンドをコードブロックに書きこんで実行します。前節でクローンしてきたパッケージ`Myrepo`が、以下のようなディレクトリ構造を持っているとします。

```
C:.
├─docs
├─src
│ ├─MyModule.jl  
│ ├─hoge.jl
| └─fuga.jl
├─test
| └─runtests.jl
├─Manifest.toml
├─Project.toml
└─README.md
```

この場合、ソースコード類は`src`に収められています。ここへのパスを通すには、


```julia
push!(LOAD_PATH, "/content/Myrepo/src")
```

を実行すればOkです。ちなみに、`/content`はGoogle Colaboratoryを立ち上げたときのカレントディレクトリです。これは、``run(`pwd`)``によって確認できます。無事パスが通れば、

```julia
using MyModule
```

によって読み込みができるようになっているはずです。お疲れさまでした。

#サンプル
サンプルは[Gist](https://gist.github.com/Shoichiro-Tsutsui/9d76359d61846fa719d4d5e594282dea)で公開しています。このnotebookをGoogle Colaboratoryにアップロードして、順番にコードブロックを実行すれば動作すると思います。
【チーム開発の基礎】git pull でリモートリポジトリの最新内容を取り込んでから push する【初心者向け】

## こんな時どうしたらいいの？ （業務上でのシチュエーション）

①私は、`feature/1`というブランチで`xxx`という機能を作る作業を進めていました。

②そこに上司のAさんが同じく`feature/1`というブランチにて、`yyy`という機能を作る開発をし始めました。

③Aさんは私よりも作業スピードが早いため先に`yyy`の機能の実装を終え、`"yyyを実装"`というコミットメッセージで`commit`し、リモートの`feature/1`に`push`しました。

④その後、`xxx`の実装が終わった私は、このまま`xxx`を`commit`＋`push`したら`yyy`の機能はどうなるのだろう、、、
と不安になり、この場合の手順を上司に質問したので、それをまとめます。


## 作業手順

### ①`xxx`の実装が完了したら、まず普通にステージング（`add`）+コミット（`commit`）までを行う

```bash
git add ファイル名
```
```bash
git commit -m "xxxを実装"
```

※ここで流れで`push`してしまわないように注意！！

### ②`git pull`で`yyyを実装`のコミットを含むブランチの最新状態を取り込む

```bash
git pull origin feature/1
```

※`feature/1`は今回のシチュエーションのブランチ名なので、各自pullしてくるブランチ名に変更してください。

すると、上司のAさんが実装した`"yyyを実装"`の内容（コード）が自分のローカルリポジトリに反映されるはずです。

ここでもし、`"xxxを実装"`と`"yyyを実装"`の内容で、同じファイルの同じ箇所（行）を変更していた場合、`コンクリフト（競合）`が発生し、git側が「これどっちが正しいの？？」となるため為、「正解はこっちですよ」とする作業を行わなければなりません。
コンクリフトが発生したら上司に確認を取るようにしましょう。

### ③`git push`する

```bash
git push origin feature/1
```

これで`"yyyを実装"`の内容を取り込みつつ`"xxxを実装"`を`commit`+`push`することができます。
続けて`zzz`という作業も安心して進められます。

## 最後に

受託開発系企業に未経験として入社してから２ヶ月が経過し、最近初めてチーム開発を経験させていただく事になりました。

この記事のような初歩的な事が全く理解できていなかったので、上司に質問する毎日です。

特にgitに関しては１つミスると大変なことになりますし、専門用語が多くてネットの記事を読んでいても勘違いが発生しやすい為、気を遣わずに現場の方に質問した方が良いのではないかと思っています。（気を遣って質問せずにミスる方が恐ろしく迷惑をかけてしまいます）

同じ境遇の方、またはプログラミング初学者の方のお役に立てれば幸いです。
2021年Let'sEncryptのルート証明書変更への対応（CentOS7 + certbot 1.11）

2021年10月2日
何やら、趣味で運営している「iOSの買い物アプリ」向けに稼働させているAPI通信がSSLでエラーになっている。
エラー詳細はキャプチャ撮り忘れなので割愛しますが、調べたところ「Let'sEncryptのルート証明書変更への対応」が必要だった。

この対応を「certbot」の設定変更で対応したのでその備忘録。

誰かの役に立てれば幸いです。

# 対応方法
「certbot 1.6」以降のバージョンであれば「--preferred-chain」オプションを利用することで対応が可能。


# OSバージョン確認
```
$ cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
```

#certbotのバージョン確認
```
#certbot 1.6以降のバージョンであれば「--preferred-chain」が利用可能
$ sudo certbot --version
certbot 1.11.0
```


# 対応方法1
certbot renewコマンド実行の際にオプション指定する


```
#dryrun
$ sudo certbot renew --dry-run --force-renewal　--preferred-chain "ISRG Root X1"

#execute
$ sudo certbot renew --force-renewal　--preferred-chain "ISRG Root X1"

```
　

自分はCronを使って定期更新させているので、cronコマンドを書き換える方法ではなく、以下の対応方法「confファイルにオプションを追加する」方法を取りました。

どっちでもいいんですが、個人的にはconfを設定する方が好きです。


# 対応方法2
「/etc/letsencrypt/renewal/」配下の「hogehoge.conf」に「preferred_chain」オプションを追加する。

```
〜中略~
# Options used in the renewal process
[renewalparams]
authenticator = apache
installer = apache
account = xxxxxxxxxxxxxxx
server = https://hogehoge.api.letsencrypt.org/directory
preferred_chain = ISRG Root X1 ←これを追加
```
保存できたら証明書の更新を「--dry-run」してみます。コマンドに「--preferred-chain」はつけません。

```
#dryrun
$ sudo certbot renew --dry-run --force-renewal
```

問題なくsuccessしたので実行します。

```
$ sudo certbot renew --force-renewal
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/hogehoge.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Plugins selected: Authenticator apache, Installer apache
Starting new HTTPS connection (1): hogehoge.api.letsencrypt.org
Renewing an existing certificate for hogehoge.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed with reload of apache server; fullchain is
/etc/letsencrypt/live/hogehoge.com/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following renewals succeeded:
  /etc/letsencrypt/live/hogehoge.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
```

APIにアクセスしたら、ちゃんと動き出しました。
一件落着。
　

趣味のアプリとはいえ、お小遣い程度の売り上げに影響するので、早めに気づいてよかったです。
無料の外形監視でも入れておこうかな。



# P.S.
コロナワクチン打った日だったので腕がちょー痛かったんですが、この作業している時は痛みのことを忘れてました。
集中した開発作業は、痛み止めにもなるんですね。