OmniAICreator/Qiita-1.07M huggingface dataset:
開発環境から本番環境にテーマを公開(Shopify)

開発環境から、本番環境にテーマを公開する際、
公式とは違う方法(?)で納品したので備忘録として。

おそらく一般的な本番公開方法

`所有者権限をクライアントに譲渡する`
https://www.shopify.jp/blog/partner-development-stores

のですが、今回は

`開発したテーマを開発環境から本番環境に移行する`

方法で納品しました。

作成して納品して終わり。ではなく、今後も定期的に依頼があると思うので、
開発環境を残しておくのは大事かなと思います。

ざっと、雑に説明。(スミマセン)

##環境
・Shopify partnersで開発環境を作成
・無料テーマのMinimal(11.7.20)をカスタマイズして開発
・納品時、クライアントはShopifyの契約済み

#公開方法

###①本番環境のAPIのPWを発行する

APIのPW発行は開発環境を作成する時と同じ作業なので、問題ないかと。
テーマをdownloadしなくていいので、違いはそこくらい。
設定もほぼ同じで大丈夫です。一度行った事があると思うので説明は省略します。

Admin API権限の

```
テーマ 
テーマテンプレートとアセットを表示または管理する
```

を `読み取りおよび書き込み`にするのをお忘れなく。
私は最初やってなくてエラー出て怒られました！

ここでは、`①権限の変更 ②Admin APIのPWをメモ`だけでOKです。

(既存テーマを使用している場合は、一応開発環境のテーマ名を変更しておく)

参考サイト
↓
https://medium.com/@yonemoto/shopify-theme-kit-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%86%E3%83%BC%E3%83%9E%E9%96%8B%E7%99%BA-55ced8ab3de9

###②config.ymlにproductionを追加

開発環境がdevelopmentで、本番環境がproductionと呼ぶらしい。(へ〜。)

```config.yml
development:
  password: shppa_000000000000......
  theme_id: "102000000000"
  store: https://shopifysite-dev.myshopify.com
production:
  password: shppa_000000000000......
  theme_id: "102000000000"
  store: https://shopifysite.myshopify.com
```


developmentはTheme Kitの開発環境をローカルに持ってきた時に、作成しています。
なので今回はproductionを追加。

passwordは先ほど①で発行したAPIのPW。
storeは、本番環境のURL
theme_id、これに引っかかった。
開発環境で作成したテーマのidかと思っていましたが、

`本番環境にダウンロードしてあるテーマのid`です！

もしテーマがなかったら、ダウンロードしてください。DebutでもMinimalでもなんでもOK。

本番環境にダウンロードしたテーマに、上書きする形で開発環境のテーマを入れます。

欲しいのはidだけなので、無料テーマを適当に入れればOKという事です。

production関連のコマンド(というかTheme Kitに関して)が公式サイトに出てるので、こちら確認してみてください。
https://shopify.github.io/themekit/commands/

####今使用している環境のテーマのidを取得する方法はこれ。

```
theme get --list -p=shppa_000000000000...... --store=https://shopifysite-dev.myshopify.com
  [102078415014] Narrative
  [102078677158] Boundless
  [102079463590][live] ThemeName [Minimal]
  [106414538918] Debut
  [113151508646] Boundless
  [113909334182] Venture
```
[live]が現在のテーマ

参考サイト
↓
https://qiita.com/pakchandae/items/f72caedc661590d35488

###③開発環境のテーマを本番環境にデプロイする

theme deploy -a


##出てきたエラー一覧

あと、本番に公開する時に地味にてこずったので、
打ったコマンドと表示されたエラーを一応置いときます。つ

一応解決してるので、参考になれば。と。

////
theme deploy -a
↓

```
invalid environment [production]: (invalid store domain must end in '.myshopify.com')
```
↓
ケツは.myshopify.comだよ。確かに。.myshopify.com/まで入れてたわ。すまん。

////

theme deploy -a --allow-live
↓

```
[API] This action requires merchant approval for read_themes scope.
(このアクションは、read_themesのスコープにマーチャントの承認が必要です。)

とか

[development] 132|134 [============================================================================>-]  99 %
requested theme was not found
```
↓
権限が少なかったわ、すまん。設定し直すわ。
"公開方法"の"①本番環境のAPIのPWを発行する"の"①権限の変更"に戻る。

そして

```
[production] 134|134 [==============================================================================]  100 %
[development] 134|134 [==============================================================================]  100 %
```
気付いたら、100%になっていて、

アップされていましたとさ。
ここのコツは、エラーが何度出ても、`theme deploy -a --allow-live` を押しつづける事です。

雑に説明してすみません。。。。



##参考サイト

https://shopify.github.io/themekit/commands/


https://ja.ojit.com/so/shopify/1854175
https://qiita.com/pakchandae/items/f72caedc661590d35488
React　学習帳その２　イベントとstateとメソッド

#イベント
javascriptでも使ってた、何かをきっかけに別の処理を走らせるやつ。
クリックしたとき、とかの。
タグの中にイベントをアロー関数を使って指定できる。
アロー関数はJavascriptなので`{}`で囲むのを忘れない。:point_up_tone2:

```react
 <button  イベント名 = {()=>{処理}}>ぽちっ</button>
```
イベント名のところはボタンをクリックしたときに処理をしたいなら`onClick`イベントをつかう。

#state
stateとは、変数みたいなやつ。けどこれはユーザーの動きによって変わる。
コンストラクタで定義する:point_up_tone2:

##stateの定義
`this.state = {プロパティ名:'値'}`←オブジェクト

```react
class App extends React.Component{
constructor(props){
super(props);
//コンストラクタ内↓で定義
this.state = {name:'たろう'}
}
}
```
上から３行目までは呪文。。。



##stateの呼び出し
```java
 //取得
console.log(this.state)
//表示
<h1>僕の名前は{this.state.name}</h1>
```
##stateの変更
```react
this.setState({プロパティ名:変更後の値})
```

変更するときは直接代入してはいけない決まりがある。必ず`setState`を使う。:point_up_tone2:
`this.state`に直接代入していい場所はコンストラクタだけ。
###複数のstateを更新するときは、`,`で区切る。

```react
this.setState({
プロパティ名１:変更後の値１,
プロパティ名２:変更後値２
})
```
#メソッド
イベント内でメソッドを呼び出すことができる。

##メソッドの定義
`メソッド名(){処理内容}`
メソッドはクラスの中で定義。
メソッドには引数を渡すことができる。

```javascript
class App extends React.Component{
メソッド名(){
//処理内容
}
}
```
##メソッドの呼び出し
`イベント名 = {()=>{this.メソッド名()}}`

```react
//jsx内
<button  イベント名 = {()=>{this.メソッド名()}}>ぽちっ</button>
```
OpenstackのVMをレスキューCDから起動する

起動途中で止まってしまうVMを物理サーバのようにレスキューモードで起動する方法。
コンパネからでは出来ないため、openstackコマンドから実施します。

VMは起動していても停止していてもできますが、停止はsoft shutdownのためACPIが動く環境でないと停止されません。
なので、VMは停止させてからの方が良いかもしれません。

また、レスキューCDのイメージを先行してglanceに登録しておきましょう。

## レスキューモードに移行
openstackコマンドが利用できるノードにログインします。(今回はコントロールノードで実施します)

レスキューモードに移行します。

nova rescue --image <レスキューisoのイメージUUID> <対象VMのUUID>
例)

~~~
(keystone)# nova rescue --image 6a207a98-8f39-47ea-aa1d-56f59c1389f2 987426d4-cdd0-435e-9553-9b7eb7367c95
~~~

コンパネ上でVMのステータスが「レスキュー中」となります。
この状態でコンパネまたはVNCでアクセスするとisoからVMが立ち上がります。

## レスキューモードの解除

openstack server unrescue <対象VMのUUID>
例)

~~~
(keystone)# openstack server unrescue 987426d4-cdd0-435e-9553-9b7eb7367c95
~~~

### エラーになった場合
レスキューモードに移行せず、VMのステータスがエラーとなった場合はDBのレコードを直接編集し、対処します。
phpMyAdminなどでデータベース名 novaの instancesテーブルの対象VM行の vm_stateの値を rescuedへ修正します。
VMのステータスがレスキュー中となるので、項目2の「レスキューモードの解除」を実行します。
[Rails]ルーティング設定大全

# ルーティングの定義方法
## 通常の定義方法

```ruby

get '/post/:id', to: 'posts#show'
```

##resorces
リソースフルな一連のルーティングを生成する。(7つのアクション)

```ruby

resources :posts
```

- paramオプション

セグメント:idは、paramオプションで任意の値に変えることができる。

```ruby

resources :posts, param: :no

#=> /books/:no
```

- only, exceptオプション

ルーティングを特定のアクションに限定したり、ルーティングから特定のアクションを除外したりすることができる。

```ruby

resources :posts, only: [:show]

resources :posts, except: [:show]
```

- collection、 memberオプション

collectionはidが必要ないルーティングに使用し、memberはidが必要なルーティングを使用する。

```ruby

resources :posts, only:[] do
  collection do
    get :post_lndex , to: 'posts#post_index'
  end
  member do
    get :post_edit , to: 'posts#post_edit'
  end
end
```

##resource

単数形リソース（id参照を必要としないリソース）を使用する時に使う。(indexアクション以外)

```ruby

resource :user
```

##root
アプリケーションルートのルーティングを生成する。

```ruby

root 'welcome#index'
```

##HttpHelpers
代表的なHTTPメソッドのヘルパーメソッドが定義されている。

- match

matchではviaオプションを使って複数のHTTPメソッドに対応するルーティングを生成することができる。

```ruby

match '/posts/:id', to: 'posts#update', as: 'post', via: [:put, :patch]

#=> PUT|PATCH /posts/:id(.:format) posts#update
```

- anchor

anchorオプションをfalseに設定すると、pathで始まるリソースに一致するリクエスト全てで有効となる。

```ruby

match 'posts', to: 'posts#index', anchor: false, via: :get
```

##scope
様々なスコープを作り、ルーティング設定を記述することができる。

```ruby

scope '/posts' do
  get ':id', to: 'posts#show'
end

#=> GET /books/:id(.:format) posts#show
```

- controller

スコープ内でcontrollerオプションで指定されるcontrollerを使う。

```ruby

scope '/posts', controller: :posts do
  get '/', to: :index
  post '/', to: :create
end

#=>  GET /posts(.:format) posts#index
#=>  POST /posts(.:format) posts#create
```

- action

スコープ内でactionオプションで指定されるactionを使う。

```ruby

scope '/posts/:id', controller: :posts, action: :update do
  match '/', via: [:put, :patch]
end

#=> PUT|PATCH /posts/:id(.:format) posts#update
```

- module

スコープ内でmoduleオプションで指定されるmoduleを使う。

```ruby

scope '/admin', module: :admin, as: :admin do
  get '/', to: 'admin#index'
end

#=> GET /admin(.:format) admin/admin#index
```

- namespace

ルーティングの頭にnamespaceの名前が付く。

```ruby

namespace :admin, as: 'admin' do
  # do something
end
```

#参考

[Railsのルーティングを理解する](https://debug-life.net/entry/103)
pythonでmatplotlibがなんでインストール出来ないんだ！！

#この記事の内容
この記事では僕がpythonのライブラリーとして有名な**matplotlib**をインストールするのにとても苦労したので、matplotlibがインストール出来ない時の対処法について自分メモとして残して置きます。もしわからない事、意見がある人は遠慮なくコメントを書いてください。

#状況説明
python3.9を使っていて作図をしたかったので、pip3を使ってライブラリーのmatplotlibをインストールするために次のコマンドを打った

```terminal
pip3 install matplotlib
```

![スクリーンショット 2020-10-28 23.23.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/745630a3-f7d9-ce04-1b00-ea74a44f80c0.png)

**sudo**コマンドを使って管理者権限で実行しても同じエラーを吐く。パソコンの調子が悪いからインストール出来ないと思いパソコンを再起動するがまたエラー吐く。もうヤダー誰かﾀｽｹﾃ

#原因究明
茶番はここまでにして、しっかりと原因を調べましょう。エラーの1行目をコピーしてgoogle翻訳に投げて見ましたが致命的なエラーであることしか分かりませんでした。そこでmatplotlibのインストールのエラーについて調べました。そして調べた結果**matplotlib**のライブラリーが3.7.5ぐらいまでしか対応していませんが、僕の使っているpythonのバージョンは3.9でバージョンが対応していません。なので大人しくpythonのバージョン3.7.5を新しくダウンーロードして再度コマンドを実行しましたが、またエラーが起こりました。どうやら3.9のフォルダーを削除しないと許してくれない見たいです。なので大人しくpython3.9を削除しましょう。次の二つのコマンドを実行してくだいさい。

python3.9があるフォルダーに移動

```terminal
cd /Library/Frameworks/Python.framework/Versions
```

python3.9のフォルダーを削除

```terminal
rm -rf 3.9
```
これでpython3.9が完全に削除されたハズです。
最後にmatplotlibをもう一度インストールして見ましょう。

```terminal
pip3 install matplotlib
```
インストールが成功したのがわかると思います。
せっかくなので作図をして見ましょう。
![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/210a9a10-74d3-93b3-8972-4268a7cea6dc.png)

ソースコード

```python

import matplotlib.pyplot as plt
import pandas as pd

Number = [1, 2, 3, 4, 5, 6]
Score = [48, 39, 45, 48, 39, 45]
plt.plot(Number,Score)
plt.show()
```
このグラフは僕の単語テストの結果です(笑い)

#終わりに
終わりよければ全てよしmatplotlibがインストールできてよかったです。
Confluence メモ#1（TeamCalendarに祝日を入れたい）

##Confluence メモ #1
### Attlasian社のConfluenceに利用するTeamCalendarに祝日を入れるときに試行錯誤したので、まとめました。
初歩中の初歩　かつ　Techでも何でもないです。

■ 流れ
・やりたいこと
・結果の手順
・試行錯誤したこと
・今後こんなのできたらいいな～

---
さっそく、、、
####やりたいこと
旧）祝日がなく、予定のみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160422/c51f9a0f-d315-5684-fa04-6b19c7c50dea.png)

新）祝日が加わる（赤枠）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160422/93832d14-67b0-7f4b-e558-41d3c6fb3d0a.png)
今はこの状態で運用してます。
（なんでこの機能がそもそもないんだ、、、と思いつつ、試行錯誤しました。）

####結果の手順
手順としては
 1. 祝日用のカレンダーを作成する
 2. 祝日用のカレンダーをTeamCalendarに取り込む
以上！！

#####まず「1. 祝日用のカレンダーを作成する」
・Confluenceのカレンダー作成から「URLによる購読」を使う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160422/0151b76f-679d-a316-f409-023dae9483bc.png)
・こちらの画面でicsのURLを貼り付ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160422/57631677-ed57-ff74-e657-ce31ce5a6c2e.png)
・その際に使うURLはこちら！！（さすがGoogleさん）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160422/830e0146-5770-b81d-ede1-b55a1c7b5fe1.png)
すると・・・これができる！（あとは取り込むだけ！）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160422/2fa67d17-224b-312f-0c2e-4420a26b3155.png)

#####「2. 祝日用のカレンダーをTeamCalendarに取り込む」
作った祝日にどんどんイベントを入れてもいいんやけど、マスタにしておいた方が何かと効率がいいので、以下手順で取り込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160422/e64ed6b1-4bc6-fa9c-9668-ce705ac06210.png)


以上で、こんなカレンダーができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160422/93832d14-67b0-7f4b-e558-41d3c6fb3d0a.png)

####試行錯誤したこと
試行錯誤したこととしては
・icsを取得できるんだから、それをインポートすればよくね？
→icsで100年分の祝日が取ってこれるならありやったんだが、実はとってこれない・・・
 なので、先ほどのリンクからicsを取得してインポートしても1年分しか祝日が入んない！！ウンヨウツライ。

####今後こんなのできたらいいな～
・土日を表示させたくない。（フィルターの世界でできそう？？）
・
WordPressのテンプレートでは$postsを使うべきではない

# 結論
WordPressのテンプレートでは`$posts`はメインループの記事リストを指すため、利用すべきではない。

# 何があったか

```php
<?php
  $args = array(
    'post_type' => 'post', `
  );
  $posts = get_posts($args);
  foreach ($posts as $post) :
// （以下省略)
?>
```

このように記述したところ、メインループの記事が`get_posts()`で取得した記事に置き換わりました。
get_posts()はメインループに影響を与えないはずなので、この挙動に最初混乱しました。

原因は受け取る`$posts`という変数で、メインループで表示される記事リストを格納しているようです。
結果として`get_posts()`で受け取った内容でメインループの記事リストを上書きしていました。

```php
$found_posts = get_posts($args);
```

のように別の変数名で受け取るべきのようです。

# 考察
`wp-includes/class-wp.php`の中を覗いたところ

```php
public function register_globals() {
	global $wp_query;

	// Extract updated query vars back into global namespace.
	foreach ( (array) $wp_query->query_vars as $key => $value ) {
		$GLOBALS[ $key ] = $value;
	}

	$GLOBALS['query_string'] = $this->query_string;
	$GLOBALS['posts']        = & $wp_query->posts;
	$GLOBALS['post']         = isset( $wp_query->post ) ? $wp_query->post : null;
	$GLOBALS['request']      = $wp_query->request;

	if ( $wp_query->is_single() || $wp_query->is_page() ) {
		$GLOBALS['more']   = 1;
		$GLOBALS['single'] = 1;
	}

	if ( $wp_query->is_author() && isset( $wp_query->post ) ) {
		$GLOBALS['authordata'] = get_userdata( $wp_query->post->post_author );
	}
}
```

とありました。`$wp_query`はメインクエリを保持するグローバル変数です。
`$posts`は`$wp_query->posts`の参照渡しのようですね。


# 参考
[関数リファレンス/register taxonomy](http://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/register_taxonomy#Reserved_Terms)
Laravel Blade で改行コードを改行タグに変換する

## 概要

Laravel Blade で改行コード(`\n`)を改行タグ(`<br>`)に変換する。
共通で使えるヘルパーファイルを用意して共通のグローバル関数を作ります。

## 環境

- PHP 7.4.4
- Laravel 7.26.0

## helpers.php を作成する

```php:app/helpers.php
<?php declare(strict_types=1);

use Illuminate\Support\HtmlString;

if (! function_exists('html')) {
    /**
     * @param string $value
     * @return HtmlString
     */
    function html(string $value): HtmlString
    {
        return new HtmlString(nl2br(e($value)));
    }
}
```

(短くて良い感じの関数名を思いつきませんでした...)

## composer.json に追記する

```json:composer.json
    "autoload": {
        "files": [
            "app/helpers.php"
        ],
        // ...
    },
```

## オートローダーを生成する

```shell-session
$ composer dump-autoload
```

## 使用方法

```php:resources/views/*.blade.php
{{ html("<p>test\ntest</p>") }}
```

`\n` の改行コードは `<br />\n` と変換され、 `<p></p>` はただの文字列として表示されていればokです。

## 補足

`{!! nl2br(e($value)) !!}` でも同様のことが行えますが、不必要に `{!! !!}` のコードが使われることを避けるためです。

## 参考

- [Laravel 自作のヘルパ関数を追加する](https://qiita.com/ucan-lab/items/afae48ee5328b77b6c10)
VSCodeでcv2にエラーがあるっていわれる

# 概要
VisualStudioCodeでpythonのプログラムを書いてました。
OpenCVのライブラリを使用する時にコードに赤線が出たって話です。
![スクリーンショット 2020-10-29 17.10.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395025/0207ce81-e13c-71bd-2752-f233e99d0393.png)

> Module 'cv2' has no 'imread' member

※imread の部分がエラーによって変わります。

# 動作環境
MacOS Catalina
Visual Studio Code 1.39.2
python 3.8.5
opencv-python 4.4.0

## 確認
ちなみにcv2は入ってます。
ここのエラーではないことを最初に確認しましょう。

```py
import cv2
```

この一文でエラーが出る場合はcv2が入っていません。
以下をターミナルで実行してください。

```
$brew install opencv
$pip install opencv-python
```
# 解決方法
VSCodeの設定を開いてください。
Code -> Preferences -> Settings
![スクリーンショット 2020-10-29 17.12.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395025/fb6fb087-c7dd-e4a5-06c8-f7652fd611a6.png)

設定を開いたら上の検索窓で以下を入力して検索。
> python.linting.pylintEnabled

出てきた項目のチェックを外してください。
![スクリーンショット 2020-10-29 17.14.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395025/a0db3c8a-eedf-d6ac-f31a-39fe87971ee3.png)


#結果
消えました。
![スクリーンショット 2020-10-29 17.15.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395025/b0c3fe53-0657-6e20-f964-519077dba334.png)

おしまい
Macの機器やシステム情報の取得ワンライナーの記録

- 普段のMac利用の際に、コマンドでシステム情報を取得したい時がある。
- また、その情報をShell内で利用したい時がある。
- 今回は、Macの機器やシステム情報を取得するコマンドを記録する。

## 結果
- 以下、結果。
- 取得する情報に基づき、各環境にてコマンドの入力。

### モデル

```bash
# モデル情報
# 出力 : MacBook Pro**
info=$(system_profiler SPHardwareDataType | grep 'Model Identifier'); echo "${info#*: }"
```

### プロセッサー

```bash
# プロセッサー
# 出力 : Dual-Core Intel **
info=$(system_profiler SPHardwareDataType | grep 'Processor Name'); echo "${info#*: }"
```

### コア

```bash
# コア
# 出力 : 2
info=$(system_profiler SPHardwareDataType | grep 'Cores'); echo "${info#*: }"
```

### シリアル

```bash
# シリアル
# 出力 : *****
info=$(system_profiler SPHardwareDataType | grep 'Serial Number'); echo "${info#*: }"
```

### UUID

```bash
# UUID
# 出力 : *****-*****-****
info=$(system_profiler SPHardwareDataType | grep 'UUID'); echo "${info#*: }"
```

### メモリ

```bash
# メモリー情報
# 出力 : ** GB
info=$(system_profiler SPHardwareDataType | grep 'Memory'); echo "${info#*: }"
```

### ユーザー

```bash
# ユーザー情報
# 出力 : **** *** (*******)
info=$(system_profiler SPSoftwareDataType | grep 'User Name'); echo "${info#*: }"
```

## 補足
- **取得内容は、扱いやすくするため結果のみを出力。**
- 利用は、以下の形式で実行。
    - `info=$(system_profiler データタイプ | grep 'フィールド名'); echo "${info#*: }"`
- 上記の**データタイプ**と**フィールド名**は以下のコマンドで確認。
    - **データタイプ** : `system_profiler -listDataTypes`
    - **フィールド名** : `system_profiler データタイプ名`
- `system_profiler`で取得できるその他の情報は、[こちらを参考](https://ss64.com/osx/system_profiler.html)

## 参考
- https://ss64.com/osx/system_profiler.html
robolectricのテストが NoSuchMethodError (com.google.common.collect) となるのを対処した

Androidのアプリを開発していて、テストに[roborectlic](http://robolectric.org/)  を導入してみたところ掲題のNoSuchMethodErrorが出たので調査して解決した。
私の場合 `com.google.common.collect.ImmutableList.sortedCopyOf` が無いというエラーだった。

# TL;DR
作成しているアプリケーションが`com.google.apis`など`com.google.api-client`に依存したものを使用している場合、更に依存先である`com.google.guava`のバージョンが古い可能性があるので、`com.google.apis`側で `com.google.guava`への参照を除外するといい。

```groovy:build.gradle(変更前)
dependencies {
    ...
    implementation "com.google.apis:google-api-services-drive:v3-rev197-1.25.0"
    ...
}
```
```groovy:build.gradle(変更後)
dependencies {
    ...
    implementation ("com.google.apis:google-api-services-drive:v3-rev197-1.25.0"){
        exclude group: 'com.google.guava'
    }
    ....
}
```


# 関連

### 依存関係のツリーを表示するコマンド

```
> ./gradlew app:dependencies
```

この結果を`com.google.guava`等で検索すると使っているパッケージとバージョン分かる

### 依存にapiを追加するパターン？
[このIssue][issue][1] にはapiを追加するといけたとの投稿があった

```groovy:build.grade
dependencies {
    ...
    api 'com.google.guava:guava:30.0-android'
    ...
}

```
これでもいけた。apiでなくimplementationでもいけた。
ただバージョンによってはアプリ実行時にDuplicate class のエラーが出ることがあった。
その場合、[stackoverflowの投稿](https://stackoverflow.com/questions/56639529/duplicate-class-com-google-common-util-concurrent-listenablefuture-found-in-modu)[2] によると以下のものも依存に入れると良いらしい。※深く調べてない

```
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
```

場合により使い分けが必要かもしれない。

# 関連リンク
[1] [github.com robolectric/robolectric 4.3: NoSuchMethodError ImmutableList.sortedCopyOf ][issue]
[2] [stackoverflow.com Duplicate class com.google.common.util.concurrent.ListenableFuture found in modules guava-20.0.jar (com.google.guava:guava:20.0)](https://stackoverflow.com/questions/56639529/duplicate-class-com-google-common-util-concurrent-listenablefuture-found-in-modu)
[3] [stackoverflow.com Why does google-api-client depend on guava-jdk5?](https://stackoverflow.com/questions/47126222/why-does-google-api-client-depend-on-guava-jdk5)



[issue]:https://github.com/robolectric/robolectric/issues/5147
[Mac/SublimeText]ショートカットキーを個人的にまとめた。

作業するにあたって、ショットカットキーを使いこなせれば作業効率が測れることを痛感。
すでに利用している方には当たり前だが、
私自身使い始めて、すごく便利であることを実感したため、忘れないよう個人的にまとめる。
随時更新していく。

####【ファイル】
新規タブの作成➡︎　Cmd + N
ファイルを閉じる➡︎　Cmd + W
右タブへの移動➡︎　Cmd + Shift + ] 　もしくは　Cmd + Opt + →
左タブへの移動➡︎　Cmd + Shift + [ 　もしくは　Cmd + Opt + ←

####【ウィンドウ】
1画面　□➡︎　Cmd + Opt + 1
2行　　□ □➡︎　Cmd + Opt + 2
3行　　□ □ □➡︎　Cmd + Opt + 3
2列➡︎　Shift + Cmd + Opt + 2
3列➡︎　Shift + Cmd + Opt + 3
4グリッド➡︎　Cmd + Opt + 5
編集するグループの移動➡︎　Ctrl + 1~4

####【カーソル】
１文字進む➡︎　Ctrl + F
１文字戻る➡︎　Ctrl + B
１行進む➡︎　Ctrl + N
１行戻る➡︎　Ctrl + P

####【編集】
コピー(選択しなければカーソル行をコピー)➡︎　Cmd + C
貼り付け➡︎　Cmd + V
履歴から貼り付け➡︎　Cmd + K + V
インデント（複数行OK）➡︎　Cmd + ]
アンインデント（複数行OK）➡︎　Cmd + [
行の移動(上)➡︎　Ctrl + Cmd + ↑
行の移動(下)➡︎　Ctrl + Cmd + ↓
カーソル行の複製➡︎　Cmd + Shift + D
行の削除➡︎　Ctrl + K
行末まで削除➡︎　Cmd + K + K
行の結合(カーソル行とその次の行が対象)➡︎　Cmd + J
カーソル行の前に改行➡︎　Cmd + Shift + Enter
コメントアウト（すでにコメントアウト済の場合はコメントアウトを削除）➡︎　Cmd + /

####【検索・置換】
検索パレットを開く➡︎　Cmd + F
置換パレットを開く➡︎　Cmd + Opt + F
複数ファイルから検索➡︎　Cmd + Shift + F
関数の定義へ移動➡︎　Cmd + R
ファイル名で検索➡︎　Cmd + P
カーソルの文字列を全検索➡︎　Cmd + Ctrl + G

####【変換】
選択範囲を大文字に変換➡︎　Cmd + K + U
選択範囲を小文字に変換➡︎　Cmd + K + L

####【選択】
カーソル行を選択➡︎ Cmd + Shift + ←もしくは→
行を複数箇所選ぶ➡︎　Cmd + 左クリック(選択したい行)
[Rails]seed_fuで初期データ投入！

# seed_fuとは
[seed-fu](https://github.com/mbleigh/seed-fu)は、すでに存在しているが変更したいレコードだけ更新したり、ファイル単位で実行できたり、簡単に書けるようなシンタックスシュガーがあったりと便利なgemです。

##使い方
1.Gemfileに以下を記述する。

```

gem 'seed-fu'
```

合わせてこちらも実行する。

```

$ bundle install
```

2. seed ファイルを置くディレクトリを作成する。
※db/fixture 以下の seed ファイルはアルファベット順に読み込まれます。読み込む順番を指定する必要がある時はファイル名の始めに数字を入れましょう。

```ruby

# 必ず必要なディレクトリ
db/fixtures

# 環境ごとに異なるデータを作成する
db/fixtures/development
db/fixtures/production
```

3.db/fixturesに以下にseedファイルを作成します。

```01_category.rb

Category.seed do |c|
  c.id = 1
  c.name = 'HTML'
end

Category.seed do |c|
  c.id = 2
  c.name = 'CSS'
end

Category.seed do |c|
  c.id = 3
  c.name = 'Ruby'
end
```

4.seed_fu コマンドを実行する。

```

$ rails db:seed_fu
```

##小技集

####seed_onceを使う
一度データを作成した後は更新したくない場合、 seed_onceを使います。

```ruby

Category.seed_once do |s|
  s.id = 1
  s.name = 'HTML'
end
```

####シンタックスシュガー
seedファイルを作成する時は、これまでのような記述の他に以下のように記述することが出来る。

```ruby

Category.seed(:id,
 { id: 1, name: 'HTML' },
 { id: 2, name: 'CSS' },
 { id: 3, name: 'Ruby' },
)
```

####CSVファイルからデータを作成
※要素をカンマで区切る。(ここでは、id、nameの順)

```db/fixtures/development/category.csv

1,HTML
2,CSS
3,Ruby
```

CSVから読み込む処理を書く。

```db/fixtures/development/01_category.rb

require 'csv'

csv = CSV.read('db/fixtures/development/category.csv')
csv.each do |category|
 Category.seed do |s|
  s.id = category[0] # ここではid
  s.name = category[1] # ここではname
 end
end
```

最後に以下のコマンドを実行

```

$ rails db:seed_fu
```

####ユーザー作成
seed_fuではパスワードがうまく設定されないのでデフォルトのseedでする。

```db/fixtures/development/00_user.rb

User.create!(id: 1, name: 'yuh', email: 'sample@test.com',
password: 'password', password_confirmation: 'password')
```
JVM出现ssl问题而无法访问HTTPS

# 概要
本地测试的时候，表題の問題がよく出会った

# 対応手順
一行解决问题

```
sudo keytool -importcert -file XXXXXX.crt -alias idet-pkks-sb -keystore /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/lib/security/cacerts -storepass changeit -noprompt
```

几个注意点：
- 用的JDK的路径确认清楚，譬如这里我电脑测试用java11.0.8所以是上面的路径
- permission denied的话， 用sudo
- キーストアのパスワードを入力してください: changeit
- 改DockerFile的时候，不想交互可以加上option： `-storepass changeit -noprompt`

# 关于怎么下载cert文件
https://stackoverflow.com/questions/25940396/how-to-export-certificate-from-chrome-on-a-mac

# Reference
https://stackoverflow.com/questions/9210514/unable-to-find-valid-certification-path-to-requested-target-error-even-after-c
サクッと位置情報を取得する

普段はRailsで開発を行っております。
その際、位置情報の取得において意外な箇所でハマってしまったので作成したコードの備忘録？注意喚起？として残しておきます。
GPS情報が取得できない状況だけ見たい方は、`GPSが取得できなかった`まで読み飛ばして下さい。


早速、ターミナル内で位置情報の確認作業を行ってみます。
コードをコピペでも動きます。

環境：
Ruby2.6.6
ImageMagick 7.0.10-34


## Rubyファイルを作成
今回は`gps_test`というディレクトリ内に`main.rb`ファイルを作成しました。
次に以降のコードを記述します。

```main.rb
require 'rmagick'

img = Magick::ImageList.new(File.expand_path('~/Downloads/画像データ名'))
p img
p img.get_exif_by_entry('GPSLatitude')

# 緯度：10進数に変換して出力
exif_lat = img.get_exif_by_entry('GPSLatitude')[0][1].split(',').map(&:strip)
latitude = (Rational(exif_lat[0]) + Rational(exif_lat[1])/60 + Rational(exif_lat[2])/3600).to_f
p latitude

# 経度：10進数に変換して出力
exif_lng = img.get_exif_by_entry('GPSLongitude')[0][1].split(',').map(&:strip)
longitude = (Rational(exif_lng[0]) + Rational(exif_lng[1])/60 + Rational(exif_lng[2])/3600).to_f
p longitude

```

`画像データ名`には読み取りたい画像ファイル（IMG_8765.jpg等）を入れて下さい。


`Magick::ImageList.new(File.expand_path('~/Desktop/画像データ名'))`とするとDesktopから読み込むようになります。（見たままですが..）

僕の場合は、ダウンロードディレクトリの読み込み権限が設定されていなかったので`Desktop`として読み込ませました。



## RMagickをインストール

プロジェクト内のターミナルから下記を実行

```
$ gem install rmagick
```

この際、エラーが出る場合はこちらが参考になると思います。
[gem install rmagick でインストール失敗](https://qiita.com/tajihiro/items/3f10c59f19fcd0a9e660)
[bundle install "rmagick" でインストールができない](https://qiita.com/sho012b/items/362abe993248c686fcf4)


## Rubyプログラムを実行する
```
$ ruby main.rb
```

## 実行結果
```
ruby main.rb
[/Users/tn/Desktop/Akihabara.jpeg JPEG 1200x1600 1200x1600+0+0 DirectClass 8-bit 535kb]
scene=0
[["GPSLatitude", "35/1, 41/1, 5920/100"]]
35.699777777777776
139.7717
```
これでGPSの緯度と経度が取れました！



## GPSが取得できなかった

結論になりますが**iPhoneを使用して撮影した時にHDR画像だったためGPSが取得できなかった。**ということになります。

iPhoneの設定の中に"自動HDR"という機能があります。

自動HDR：
複数の写真がさまざまな露出で高速で連続撮影され、明るい部分と影の細部がきれいに表現された写真に合成する機能のこと。

iPhone端末だと位置情報付き設定にすればでMapが見られる　＝　GPSも取得できるだろう
と思ってましたが、最初に記述した内容では取得できませんでした。
（取得方法知っている方いたら教えて下さい...）

プログラムは間違っていないはずなのになんで取得できないんだろう..って時は
自動HDRをオフになっているか確認した方がいいかもしれません。
これで何時間無駄にしたのだろう..泣
[iPhone　自動HDRをオフにする](https://support.apple.com/ja-jp/guide/iphone/iph2cafe2ebc/ios)

プレビューから位置情報が入っているかどうかの簡易的な確認は行っていました。
[[Mac] 画像の位置情報（ジオタグ）をさくっと確認する方法
](https://rakuishi.com/archives/2104/)

**ただ、なぜ位置情報設定してあるのにGPSが読み込めないのか。設定のパターンがあるのかを検証してみました。**



## パターンの検証(位置情報設定はONの状態)

パターン１　両方ON
「自動HDR（合成機能）」をON　　　　　　　結果：
「通常の写真を残す」をON　　　　　　　　 　→　GPSの読み込みできない

パターン２　片側
「自動HDR（合成機能）」をON　　　　　　　結果：
「通常の写真を残す」をOFF　　　　　　　　 　→　GPSの読み込みできない

パターン３　片側
「自動HDR（合成機能）」をOFF　　　　　　　結果：
「通常の写真を残す」をOFF　　　　　　　　 　→　GPSの読み込みできない

パターン４　参考画像の状態
「自動HDR（合成機能）」をOFF　　　　　　　結果：
「通常の写真を残す」をON　　　　　　　　 　**→　GPSの取得可能**

参考画像：
![スクリーンショット 2020-10-29 15.52.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655853/5205b568-90b8-9c39-f78a-13d543e2ea34.png)



# まとめ
独学で効率が悪いですがこれも１つの経験です！！
今回も少し成長できたと思ってどんどん開発にチャレンジしていきます。
基礎的な内容でしたが、取得方法や注意点が参考になれば嬉しいです。

# 参考

[RMagickを使って画像Exif位置情報を10進値に変換
](http://www.iwazer.com/~iwazawa/diary/2013/03/convert-photo-location-to-digits-with-rmagick.html)
vue.jsを初めて学ぶ ④ [VueCLI 3.7.0 + Vue.js 2系のインストール]

前回の記事

[vue.jsを初めて学ぶ ① [hello world]](https://qiita.com/uechikohei/items/4e44380848d29bf3fd6a)
[vue.jsを初めて学ぶ ② [テンプレート構文]](https://qiita.com/uechikohei/items/dd857da50a3f0237c22b)
[vue.jsを初めて学ぶ ③ [レンダリング] ](https://qiita.com/uechikohei/items/6433c89813cde1c7f1f1)

---

# 目次

[1. Vue-cli ver3 をインストールする](#Vuecli-ver3のインストール)

**2020年10月　現在では、vue.jsがver3 vue-CLIがver4 にアップデートされている。**
**今回は、vue.jsのver2系とvue-CLIのver3.7.0をインストールしたい**


<!-- 1 -->
---

# Vuecli ver3のインストール

各自のターミナルにて、コマンドを入力していく。

```text:vueCLI.ver3.7.0の導入
npm install -g @vue/cli@3.7.0

*ここで3.7.0のvue-cliをインストールしないと、vue create する時に、プロジェクトに対してvue.js3系が適用される。

[バージョン]
vue -V
 => @vue/cli 3.7.0
```


```text:プロジェクト作成
vue create [name]

プロジェクトが作成される。
vue ver2系が[name]インストールされる。

[確認]
npm list vue
=> vue@2.6.12

```

```
cd [プロジェクトname]
npm run serve

local [urlが表示]
network [urlが表示]
```
- localにアクセスすると、vueのapp画面が表示される。


![スクリーンショット 2020-10-28 16.39.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449720/2d1598d5-802f-9280-3dd9-a80c6a528182.png)

```

## 開発環境と本番環境

```text:開発環境
npm run serve

=> HMRが起動する。開発しやすい
```

```text:本番環境
npm run build

=> distディレクトリが生成される。これをs3に投げると静的ホスティングが可能
```


今回のように、vue-cliなどnpmパッケージのverを指定したいときは、

[npmパッケージを検索する所](https://www.npmjs.com/package/@vue/cli/v/3.7.0)

検索してパッケージ名を調べて、目的のverをインストールするようにしましょう！
Terraformの基本コマンド

# Terraform入門
バックエンドおじさんが、とりあえずTerraformへ入門した備忘録です。

## インストール

```bash
$ brew install terraform
$ terraform -v
```

\↓バージョン切り替えをしたい人は、下記インストールして実行↓/

```bash
$ brew install tfenv
$ tfenv -v
$ tfenv install latest
$ tfenv install 0.11.14
$ tfenv list
# バージョン指定
$ tfenv use 0.11.14
```

## Terraformを使用する為の下準備

```bash
$ export AWS_ACCESS_KEY_ID=xxx
$ export AWS_SECRET_ACCESS_KEY=xxx
```

### S3作成(tfstateファイルの管理)
tfstateはインフラの状態管理ファイルです。
tfstateを保存する場所は、複数人のプロジェクトの可用性を考えてS3に逃しておきましょう。

```bash
$ aws s3 mb s3://バゲット名 --region ap-northeast-1
$ aws s3api put-bucket-versioning --bucket バゲット名 --versioning-configuration Status=Enabled
$ aws s3api get-bucket-versioning --bucket バゲット名
{
    "Status": "Enabled"
}
```

### Terraformのディレクトリ構成
手順に従って、3つのファイルを作りました。


```terraform:backend.tf
terraform {
  backend "s3" {
    bucket = "バゲット名"
    key    = "state/service"
    region = "ap-northeast-1"
  }
}
```

```terraform:provider.tf
provider "aws" {
  region = "ap-northeast-1"
}
```

```terraform:versions.tf
terraform {
  required_version = ">= 0.12"
}
```

## Terraform出動
下記コマンド実行し、
・ワークスペースの初期化
・プラグイン導入など

必要なディレクトリを整えてくれます。

```bash
$ terraform init
```

### ワークスペースの追加
今回は検証と本番用のワークスペースを追加していきます。

```bash
$ terraform workspace new stg
$ terraform workspace new pro
$ terraform workspace show
$ terraform workspace select stg
```

<code>workspace new 名前</code>で追加
→<code>show</code>で現在のワークスペースを確認
→<code>select 名前</code>でワークスペースを選択
フォルダ構造を一覧にするExcel VBA

仕事してて、フォルダ構造と収納されているファイルを一覧にしたいなって思ったことないですか？

#Excel VBAで作っておきました。

どうぞ。
使ってください。
編集しないといけない点は、変数”Path”の値だけです。

14年ぶりにプログラミング書いてるので、リファクタリングしてくれる人募集中ですm(__)m


```vb
Dim numOfDelimiter As Long

Sub mainFFs()
   
   'Declare
   Dim subFolders As Object
   Dim Path As String
   Dim rowP As Long
   Dim culP As Long
   Dim numOfSubF As Long
   Dim buf As String
   
   'Set values
   
   Path = "C:\Users\" 'ここに一番上のフォルダを指定してくださいね
   rowP = 1
   culP = 1
   
   'Pathに \ が何個あるか数える
   numOfDelimiter = UBound(Split(Path, "\"))
   
   '指定したフォルダだけ、書いてしまう
   Cells(1, 1) = Path
   culP = culP + 1
   buf = Dir(Path & "\*.*")
   Do While buf <> ""
       Cells(rowP, culP) = buf
       rowP = rowP + 1
       buf = Dir()
   Loop
   
   Call writeSubFFs(Path, culP, rowP)

End Sub

Sub writeSubFFs(Path As String, culP As Long, rowP As Long)
      
   '階層の調整
   Dim curPath As Long '文字カウント数
   curPath = UBound(Split(Path, "\"))
   
   If curPath <= numOfDelimiter + 1 Then
       culP = 3
   Else
       culP = culP + 1
   End If
   
   '*** Process ****
   
   '①フォルダ取得
   Set subFolders = CreateObject("Scripting.FileSystemObject").GetFolder(Path).subFolders
   
   For Each subFolders In subFolders
   
   '②フォルダ記載
       
       Path = subFolders.Path
       Cells(rowP, culP) = Path
       
   '③ファイル取得
       culP = culP + 1
       On Error Resume Next
       buf = Dir(Path & "\*.*")
   '④ファイル記載
       Do While buf <> ""
           Cells(rowP, culP) = buf
           rowP = rowP + 1
           buf = Dir()
       Loop
   
   
       culP = culP - 1
       rowP = rowP + 1
   
       Call writeSubFFs(Path, culP, rowP)
   
   Next subFolders
End Sub
```


因みに、writeSubFFsは自身を再起してます。
（下から４行目のCallで）
理由は、再起しないとSubフォルダ１階層分しか取得できなかったため。

今後の応用としては、パスをリンクにしてみたり、2個のHDDの差分のみを同期するみたいなファイルの前段の処理として利用したり（車輪再発名しそうな予感）、書き出す対象ファイルに条件を付けて、欲しいファイルのみ記載したりなど、色々できますよね。

注意点：
　Cドライブから実行すると、
　私の環境だと、とんでもない量のファイルになりそうでした。
　（以下は、45万ファイル検出くらいで処理を止めました。の図）
　そこまで検出したくない場合は、対象ファイルを限定するなり、行のカウンターに制限を設けるなりした方が良いかもです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154794/09a9707d-185f-6917-b04f-5eef657b3221.png)


#参考にしたサイト

結局これを改編したのが今回のコード
https://www.moug.net/tech/exvba/0060088.html

これそのまま実装したかったけど、basファイルがめんどかった
https://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_110_080.html
https://www.asahi-net.or.jp/~ef2o-inue/download/sub09_020_110.html


SESだと、権限の関係でさわれないフォルダがあるので、on error resume nextで飛ばす
http://officetanaka.net/excel/vba/tips/tips104.htm

今後の応用
http://officetanaka.net/excel/vba/tips/tips95.htm
http://blog.jmiri.net/?p=1763
Gitで差分ファイル一覧を取得

## 目的
任意のブランチ（リビジョン間）で変更されたファイル一覧を取得したい。

## 背景
クライアントに、修正したファイル一覧がほしいって言われたので。
~~git見てくれよ。~~

## コマンド
Windows上だったら、ソースが配置しているフォルダで右クリック→Git Bash Hereでコマンドライン起動してください。

想定している前提イメージは、
feature/developからfeature/hogeブランチを作成
↓
feature/hogeブランチにいろいろcommit (このファイル一覧がほしい）

```:git
git diff --name-only feature/develop..feature/hoge
```

もし、追加したファイルのみ取得したい場合は

```:git
git diff --name-only feature/develop..feature/hoge --diff-filter=A
```

更新したファイルのみ取得したい場合は

```:git
git diff --name-only feature/develop..feature/hoge --diff-filter=M
```

削除したファイルのみ取得したい場合は、

```:git
git diff --name-only feature/develop..feature/hoge --diff-filter=R
```
(Python) 整数値をフラグの集合として扱う

整数値の各ビットをフラグと見なすことで整数値をフラグの集合として扱う Python のクラスを実装してみた。

役に立つことは少なそう。

## 実装
``` python
class IntFlags:
    """整数値をフラグの集合として扱うためのクラス"""

    _alias = []

    def __init__(self, state: int = 0):
        if state < 0:
            raise ValueError
        object.__setattr__(self, "_state", state)

    def __getitem__(self, digit: int) -> bool:
        return (self._state & (1 << digit)) > 0

    def __setitem__(self, digit: int, value: bool):
        if type(value) is not bool:
            raise TypeError
        if self[digit] != value:
            object.__setattr__(self, "_state", self._state ^ (1 << digit))

    def __getattr__(self, key: str) -> bool:
        alias = type(self)._alias
        if key not in alias:
            raise AttributeError
        return self[alias.index(key)]

    def __setattr__(self, key: str, value: bool):
        alias = type(self)._alias
        if key not in alias:
            raise AttributeError
        self[alias.index(key)] = value

    def __int__(self) -> int:
        return self._state

    def __str__(self) -> str:
        return f"{self._state:0{len(type(self)._alias)}b}"
    
    def __repr__(self) -> str:
        return f'<{type(self).__name__} "{str(self)}">'
```

## 使い方
``` python
class UnixPermission(IntFlags):
    _alias = ["execute", "write", "read"]
    
    def __str__(self) -> str:
        return "".join(reversed([char if self[idx] else "-" for idx, char in enumerate("xwr")]))
```

継承してこういうクラスを作ると、以下のように扱える。

``` python
# 初期化
user_permission = UnixPermission(6)
user_permission  #=> <UnixPermission "rw-">
```

``` python
# 個別のフラグにアクセス
user_permission.read  #=> True
```

``` python
# 個別のフラグを書き換え
user_permission.execute = True
user_permission  #=> <UnixPermission "rwx">
```

``` python
# 整数値に戻す
int(user_permission)  #=> 7
```
Java Excelで空白行・列を削除する

大量のデータを含むExcelテーブルを操作する時、データの変更によって空白行・列が残ることがあります。その時になったら、Free Spire.XLS for Javaでなら解決できます。このライブラリを通してExcelワークシートにある空白行・列を一括で削除できます。今、その対策に関連するJavaコードを皆さんと共有させていただきます。

**JARパッケージのインポート**
**方法1：** [Free Spire.XLS for Java](https://www.e-iceblue.com/Download/xls-for-java-free.html)をダウンロードして解凍したら、libフォルダーのSpire.Xls.jarパッケージを依存関係としてJavaアプリケーションにインポートします。

**方法2：** Mavenリポジトリから直接にJARパッケージをインストールしたら、pom.xmlファイルを次のように構成します。

```xml
<repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.xls.free</artifactId>
        <version>3.9.1</version>
    </dependency>
</dependencies>
```


**元のExcelドキュメントは次のとおりです:**
![11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/20ae74ae-fab5-c982-0249-3a3a71c01554.jpeg)



**Javaコード**

```java
import com.spire.xls.ExcelVersion;
import com.spire.xls.Workbook;
import com.spire.xls.Worksheet;

public class DeleteBlankRowsAndColumns {
    public static void main(String[] args) {

        //Excelドキュメントを読み込みます
        Workbook wb = new Workbook();
        wb.loadFromFile("sample1.xlsx ");

        //最初のワークシートを取得します
        Worksheet sheet = wb.getWorksheets().get(0);

        //すべての行をループします
        for (int i = sheet.getLastRow(); i >= 1; i--)
        {
            //空白行かどうかを判定します
            if (sheet.getRows()[i-1].isBlank())
            {
                //指定した行を削除します
                sheet.deleteRow(i);
            }
        }

        //すべての列をループします
        for (int j = sheet.getLastColumn(); j >= 1; j--)
        {
            //空白の列かどうかを確認します
            if (sheet.getColumns()[j-1].isBlank())
            {
                //指定した列を削除します
                sheet.deleteColumn(j);
            }
        }

        //ドキュメントを保存します
        wb.saveToFile("deleteBlank.xlsx", ExcelVersion.Version2016);
    }
}
```


**実行結果：**
![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/f3243c3f-c0ea-1c41-e6b9-2129081610d2.png)
Laravelで画像パスをDBに保存して表示する方法！


今回はLaravelで画像保存するやり方をまとめていくぅ！！

作業フロー
--
初動
・migration 作成
・model 作成
・controller 作成
・viewファイル作成
①DBに画像パス保存のカラム作成(migration)
②モデルの編集
③ルーティング
④シンボルリンクのやつ（php artisan storage:link）
⑤コントローラー編集
⑥viewに画像投稿フォーム作成
⑦表示処理

初動
--
migrationとmodelを同時に生成！

```
php artisan make:model -m Image 
```
controller作成

```
php artisan make:controller  ImageController
```

viewファイル作成

```
ディレクトリー構成
resources/views/image/○○○○blade.php

作成ファイル
index.blade.php
form.blade.php

```
---

①DBに画像パス保存のカラム作成(migration)
--
```
    public function up()
    {
        Schema::create('images', function (Blueprint $table) {
            $table->id();
            $table->string('image');←追記
            $table->timestamps();
        });
    }
```
普通にmigrationしていく！
型はstring(パスは文字列だから？)


②モデルの編集
--
```
class Image extends Model
{
        protected $fillable = [

        'image',

        ];
}
```
$fillableにimageカラムを指定

③ルーティング
---

```
Route::get('/images', 'ImageController@index');画像表示ページ
Route::get('/image/form', 'ImageController@form');画像投稿フォーム
Route::post('/image/store', 'ImageController@store');画像保存
```
画像表示ページ、画像投稿フォーム、画像保存のためのルーティングを記述

④シンボルリンクのやつ（php artisan storage:link）
--
```
php artisan storage:link
```
コンソールで入力
参考 https://readouble.com/laravel/7.x/ja/filesystem.html

⑤コントローラー編集
---
```
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Image ←追記

class ImageController extends Controller

{
    public function index()
    {
     $images = Image::all();//レコード取得
     return view('image.index',compact('images')); //一覧ページ表示
     }

    public function form()
    {
    return view('image.form')//投稿フォーム表示
    }

//保存処理がちょい複雑かもぉ(o_o)「
    public function store()
    {
        //画像の処理
        $image = $request->file('image');//file()で受け取る
        if($request->hasFile('image') && $image->isValid()){//画像があるないで条件分岐
            $image = $image->getClientOriginalName();//storeAsで指定する画像名を作成
        }else{
            return;

    Image::create([
      'image' => $request->file('image')->storeAs('public/images',$image),
     ]);
//storage/app/public/images(imagesは作られる)に保存

    return redirect(/images);//保存処理後一覧ページに飛ばす

    }


```

⑥viewに画像投稿フォーム作成
--
form.blade.php

```
 <form action="/image/store" method="post" enctype="multipart/form-data">
 @csrf
 <input type="file" name="image" accept="image/png, image/jpeg">
 <input type="submit" value="投稿"> 
 </form>
```
formタグに enctype="multipart/form-data" を入れる！

⑦表示処理
index.blade.php

```
@foreach($images as $ image)

<img src"{{ Storage::url($image->image) }}">

@endforeach
```
foreachで回して画像を一枚づつ表示

終わり
---
作業フローにしてまとめてみました！
なぞるだけでできたでしょうか？
もしできたら、これ何って思ったものはググってください！
unityでアニメーションを設定する。　クリックされたらアニメーションが再生するように設定する。

単純にクリックされたらアニメーションが再生されるようにしたかったがいろんな方法がいろんなところに書かれていてよくわからなかった。最終的には
https://freesworder.net/unity-animation-play/
の方法が簡単だったように思う。

以下のようなアニメーションを作った

![ezgif-2-8d13b8b525b8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197731/02f120b0-a628-af53-5823-28d5fb6aba1e.gif)


まず、ガチャ本体のイラストと、動かしたいハンドルの部分のイラストを用意し、Assetsにいれる。

![スクリーンショット 2020-10-29 15.29.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197731/2a9a98b3-0427-9936-8756-f536ee10bc8e.png)


画像二つを画面の方にドロップ
![スクリーンショット 2020-10-29 15.30.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197731/2b7d095e-537d-65ad-0433-5679d30d8239.png)


ハンドルが回るアニメーションを作る
![スクリーンショット 2020-10-29 15.32.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197731/61d4a8aa-9812-3112-f440-3b5ab8b18e62.png)

ウインドウ　＞　アニメーション　＞　アニメーション

を押すとアニメーションウインドウが表示されるようになる
![スクリーンショット 2020-10-29 15.33.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197731/984ff658-879a-caa9-8fe7-03f2158105fc.png)

ここでアニメーションを設定。

![スクリーンショット 2020-10-29 15.34.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197731/fcd755c5-8af0-59a1-b1df-712fa612ad4f.png)

handleAnimationというのがAssetsにできる

![スクリーンショット 2020-10-29 17.12.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197731/8a6e58aa-7ad0-b08c-ec08-4bb2340d34c1.png)

handleを選択して　コンポーネント追加でanimationを追加する

その項目の中に、作成したhandleAnimationを選んでおく


クリックしたときにこのアニメーションを再生するようにスクリプトを作成する
![スクリーンショット 2020-10-29 17.16.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197731/c71e815f-9a18-0067-2d7a-083fe74e5efe.png)

これをhandleにくっつける

![スクリーンショット 2020-10-29 17.17.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197731/c1e18122-3fc2-322f-f573-60649e240ca5.png)

これで完成。
【Gitをやる前に】VCS入門

#書こうと思った背景
会社でGit・GitHubでソースコードのバージョン管理を行うにあたり、そもそも**「バージョン管理する理由ってなんだっけ？？」**ってなったので、会社が紹介してくれた「VCS入門」という資料を読んでみました。その印象に残った点について自分用メモとして引用&記載させていただきます。

※VCS：Version Control System

#印象に残った点

###VCSはルールと対になって初めてその真価を発揮する

>VCSを使えばハッピー・・・なはずでしたが、どうやらVCSを使った「だけ」では、そうはならないようです。

>問題を整理してみると、リポジトリへの反映時に次のようなことが起きているようです。

>**1.「とりあえず」反映している**
**2.「どうやったのか」をメッセージに書いている**
**3.動かないものも反映している**
**4.複数の変更を盛り込んでいる**


>[・・・]


>そこで、まずは最低限作業フォルダーの内容をリポジトリに反映する際のルールを決めましょう。先ほどの良くない例を見れば、守るべきルールが見えてきます。それが次のルールです。

>**・「時間」ではなく「作業」の単位で行う**
**・「どのように」ではなく、その作業を「何故」「何を」「何のために」行うかをメッセージに残す**
**・動かない成果物はリポジトリに反映しない**
**・一度に一つの変更だけ反映する**

>これらのことから、VCSのVersion（バージョン、版）とは「ファイル単位の改訂内容」を表すのではないことがわかると思います。Versionとは「作業単位の変更内容」を表すのです。このことを忘れないようにしてください。

これまで「実務で絶対使うから！」ということで、なんとなくGitを使っていたのですが、その目的を実現するにも、きちんとしたルールを設定しないといけないということですね。

###VCSのルールを設定するための考え方（SCM）を意識して運用せよ

>ここで最初に立ち戻り、VCSを導入することで何がしたかったのか、考えてみることにしましょう。

>VCSがない状態では、次の問題がありました。

>**・作業履歴が残らない**
**・他の人と作業がぶつかる**


>また、VCSを導入した後、ルールが無ければこんな問題がありました。

>**・履歴から目的の変更を探せない**
**・履歴の一つが、どういったきっかけで変更されたかわからない**

>以上の問題から、VCSを使って行いたかった事とは、

>**・各バージョンを識別したい**
**・特定のバージョンを再現したい**
**・何故変更が行われたのか知りたい**
**・他の人と連携して作業を行いたい**


>ともいえると思います。

>これらを実現するための考え方が「SCM（Software Configuration Management、ソフトウェア構成管理）」です。

>[・・・]


>では、構成を管理するとはどういうことかを、そもそもの目的から導くと、次のようになります。

>**ある時点でのソフトウェアを構成する要素すべてを、識別、再現、追跡出来るようメンバー間で成果物を共有し、連携を促すための仕組み、ルール、プロセスを構築し、運用する**

>このためには、最低限その変更がどのような「依頼」によるものなのかを、それぞれの要素に紐付け、その組み合わせの履歴を残していかなければなりません。



###GitHubのissueがなぜ機能として存在しているのか
>SCMは「変更依頼」の管理も含めてSCMである、と説明してきました。主な変更依頼のトリガーとしては、「バグ」、「仕様変更」等があります。

>こういったものは、多くの組織ではそれぞれ「バグ管理票」、「QA票」などで管理されていると思います。しかし、もともとはそれぞれが別文書であるということもあり、**「どこからきてどこへ行くのか」追跡がしにくい**という問題があります。

>このケースへの対応としては、変更依頼のトリガーとなる事象を一元管理する必要があります。**ただ、その数は膨大で、とても手書やExcelシートで管理できるものではありません。**

>そこで、**変更依頼を管理するためのツールの出番です。こういったツールは一般的に「ITS（Issue Tracking System、課題管理システム）」と呼ばれます。**

>ITSでは、Issue（課題）を「Ticket（チケット）」という単位で登録します。このチケットには一意となる番号（チケット番号）が振られ、担当者を割り当てたり、関連する内容をコメントしたりする機能があり、課題を完了したらチケットを「閉じる（クローズする）」決まりになっています。

>これにより、**今残っている課題、終わった課題、誰が担当しているかなどが明確になり、管理が容易になります。**

>また、ITSにはVCSと連携する機能があり、チケット番号をメッセージに入れてそのチケットに関連する履歴を参照したり、完了したことを表すメッセージを入れると自動的にチケットをクローズしたり、といったことが可能になります。

>こういった機能を活用することで、その変更が何を起点に誰が作業し、今終わっているのかどうか、そして作業履歴がどうなっているかを、一気通貫で追跡できるようになります。

GitHubのissueがなぜ機能として存在しているのか、理解しました。。。！

#参考
[VCS入門](https://github.com/masaru-b-cl/introduction-to-vcs/blob/master/readme.md)
React Native でとりあえず入れとけって感じのパッケージ

大体使うパッケージは決まっていると思うので、どんなアプリでも大体必要になりそうなものを集めました。

想定バージョン: 0.63.x

```
yarn add \
    ahooks \
    dayjs \
    react-native-device-info \
    react-native-fast-image \
    react-native-fbsdk-next \
    react-native-gesture-handler \
    react-native-localize \
    react-native-notifications \
    react-native-reanimated \
    react-native-safe-area-context \
    react-native-screens \
    react-native-vector-icons \
    react-native-webview \
    tailwind-rn \
    zustand \
    @invertase/react-native-apple-authentication \
    @react-native-async-storage/async-storage \
    @react-native-community/google-signin \
    @react-native-community/masked-view \
    @react-native-community/netinfo \
    @react-native-firebase/app \
    @react-native-firebase/auth \
    @react-native-firebase/dynamic-links \
    @react-navigation/drawer \
    @react-navigation/native \
    @react-navigation/stack \
    @react-navigation/bottom-tabs

yarn add -D \
    @types/react \
    @types/react-native \
    @types/react-native-fbsdk \
    @types/react-native-vector-icons \
    typescript 
```

# ほぼ確定で入れる系

### react-native-fast-image

標準の Image より早い、キャッシュがちゃんと効いてくれる

### react-native-device-info

バージョン取りたいときとか

### react-native-webview

静的なページの表示で、だいたい使うだろう

### @invertase/react-native-apple-authentication

iOS では必須になりました

### @react-native-async-storage/async-storage

使わないアプリはあんま無さそう

2021/08/16: @react-native-community/async-storage に変わってた

### @react-native-community/netinfo

オフライン表示したい時とか

### react-native-vector-icons

6000種類くらいのアイコンが入ってる

# デファクトスタンダード系

### @react-navigation/native

- @react-native-community/masked-view
- @react-navigation/stack
- react-native-gesture-handler
- react-native-reanimated
- react-native-safe-area-context
- react-native-screens

要件次第だが、付随して下記も入れる。

- @react-navigation/drawer
- @react-navigation/bottom-tabs

### react-native-localize

タイムゾーンとか取得する用

### @react-native-community/google-signin

公式 Google ログイン

### react-native-fbsdk-next

公式 Facebook ログイン。以前は react-native-fbsdk だったがコミュニティに移管された

### react-native-notifications

@react-native-community/push-notification-ios でも良いが、それだと Android と共通化できない

# 必須でもなんでもないが、個人的にいつも使うパッケージ

### ahooks

React Hooks のユーティリティ。 react-use は DOM 依存のため、 React Native では使えない

### dayjs

Moment の代わり

### tailwind-rn

楽にスタイルが定義できる。 Styled Components とかより記述量減らせる

### Zustand

Hooks 時代の状態管理。 Jotai や Recoil などでも OK だが、 React の外でステートをいじりたい場合がネイティブだと多少あるため Zustand を推奨します

# Firebase 認証を入れるなら

- @react-native-firebase/app
- @react-native-firebase/auth
- @react-native-firebase/dynamic-links

dynamic-links はメールアドレスのリンクログインで必要になる。
javax.el.PropertyNotWritableExceptionとなった時の対応方法


# 事象 : 画面からsubmit処理を実行したらBeanに値を設定できないと怒られた
- 環境
    - Windows10 64bit バージョン1909
    - openjdk 11 2018-09-25
    - Eclipse IDE for Enterprise Java Developers Version: 2020-09 (4.17.0)
    - JSF 2.3.9
    - Payara Server 5.194

```bash
javax.el.PropertyNotWritableException: /admin/ponsuke/ponsuke.xhtml @52,92 value="#{item.mailAddress}": The class 'jp.co.my.app.Item' does not have a writable property 'mailAddress'.
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:99)
    at javax.faces.component.UIInput.updateModel(UIInput.java:859)
    at javax.faces.component.UIInput.processUpdates(UIInput.java:773)
    at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:571)
```

Beanに・・・・

```xml
<!-- 省略 -->
  <ui:repeat var="category" varStatus="index" value="#{ponsukeController.categories}">
    <ui:repeat var="item" varStatus="status" value="#{category.itemList}">
        <td class="form-inline">
          <h:inputText value="#{item.mailAddress}" />
<!-- 省略 -->
```

Setterがない？

```java:PonsukeController
// 省略
/** カテゴリ情報リスト. */
@Getter
@Setter
private List<Category> categories;
// 省略
```

## 原因 : 子クラスに`@Setter`がないから
あぁぁぁぁ、`@Value`に`@Setter`は含まれていなかった・・・

> In practice, `@Value` is shorthand for: final `@ToString` `@EqualsAndHashCode` `@AllArgsConstructor` `@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)` `@Getter`, except that explicitly including an implementation of any of the relevant methods simply means that part won't be generated and no warning will be emitted.
> [@Value - projectlombok.org](https://projectlombok.org/features/Value)

```java:Category
import lombok.Value;

@Value
public class Category {
    List<Item> itemList;
}
```

```java:Item
import lombok.Value;

@Value
public class Item {
    int itemId;
    String mailAddress;
}
```

### 対応 : 設定するプロパティのあるクラスのアノテーションを変更する
今回は`@Value`がくっついていて、他のところで`@AllArgsConstructor`の役割を使っているので、
[`@Getter` `@AllArgsConstructor`] + [`@Setter`] = [`@Data` `@AllArgsConstructor`]
へ変更することにした。
`class Category`はプロパティがListで中身しか変更しないのでアノテーションは変更しない。

```java:Item
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Item {
// 省略
```

ちなみに
`itemList`と`mailAddress`プロパティ個別に`@Setter`をつけるとコンパイルエラーになる。
classに`@Value`に加えて`@Setter`をつけてもPropertyNotWritableExceptionが発生した。
`@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)`があるためであろうなぁ・・・と思う。

> To add final to each (instance) field, use `@FieldDefaults(makeFinal=true)`. Any non-final field which must remain nonfinal can be annotated with `@NonFinal` (also in the lombok.experimental package).
> [@FieldDefaults - projectlombok.org](https://projectlombok.org/features/experimental/FieldDefaults)