OmniAICreator/Qiita-1.07M huggingface dataset:
【Android】EditTextでエンター押下後フォーカスがループしない

# 不具合の事象
2個のEditTextを用意し、それぞれ`android:imeOptions="actionNext"`を付与。
2個目のEditText内でエンターを押した場合、1個目のEditTextにフォーカスがループするときとしない時がある。

|ループする|ループしない|
|----|----|
|![normal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/1d28500e-689f-b4a9-f833-87253b3a274b.gif)|![false.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/79fbbfdb-b6c1-0f4d-a1ce-3007960c6f77.gif)|


# 原因
画面内に`RecyclerView`があるとそれにフォーカスされるので、フォーカスがループされない。`Button`などの他のビューではフォーカスされず、`RecyclerView`のみフォーカスされた。

# 対策
`nextFocusForward`でフォーカスの移動先のビューを指定すればよい。
```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	xmlns:tools="http://schemas.android.com/tools"
	android:layout_width="match_parent"
	android:layout_height="match_parent">

	<EditText
		android:id="@+id/edit_text_1"
		android:layout_width="0dp"
		android:layout_height="wrap_content"
		android:imeOptions="actionNext"
		android:inputType="text"
		android:nextFocusForward="@id/edit_text_2"
		app:layout_constraintEnd_toEndOf="parent"
		app:layout_constraintStart_toStartOf="parent"
		app:layout_constraintTop_toTopOf="parent"/>

	<EditText
		android:id="@+id/edit_text_2"
		android:layout_width="0dp"
		android:layout_height="wrap_content"
		android:imeOptions="actionNext"
		android:inputType="text"
		android:nextFocusForward="@id/edit_text_1"
		app:layout_constraintEnd_toEndOf="parent"
		app:layout_constraintStart_toStartOf="parent"
		app:layout_constraintTop_toBottomOf="@id/edit_text_1"/>

	<androidx.recyclerview.widget.RecyclerView
		android:id="@+id/list"
		android:layout_width="0dp"
		android:layout_height="0dp"
		app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
		app:layout_constraintBottom_toBottomOf="parent"
		app:layout_constraintEnd_toEndOf="parent"
		app:layout_constraintStart_toStartOf="parent"
		app:layout_constraintTop_toBottomOf="@id/edit_text_2"/>
</androidx.constraintlayout.widget.ConstraintLayout>
```
IntelliJ メモ

ショートカットキーはMacのものを記載


### コードをフォーマットする(Reformat Code)
Command + Option + L

### なんでも検索(Search Everywhere)
Shift x2

### ファイル横断テキスト検索(Find in Path)
Command + Shift + F

### 宣言へジャンプ(Go to Declaration or Usages)
Command + B

### 実装クラスへジャンプ(Go to Implementations)
Command + Option + B

### 未使用宣言の検索
Shift x2 + "unused declaration"
メニューバーで、「分析/名前による検査の実行」をクリックします
「未使用の宣言」を入力
「未使用の宣言 Java 宣言の冗長性」を選択

### マルチカーソル
Option + ダブルクリック長押し + 矢印

### キャッシュ削除
Shift x2 + "invalidate caches"
RDSのインスタンスをServerless v2に移行して費用を抑えたい！

RDSの料金がべらぼうに高額になっていたので、開発環境のDBをServerless v2　に移行することになりました。

> `db.r6g.large`で1ヶ月起動した状態で228.3648USD(今のレートで31,632.41円！！！)

インスタンスの種類をメモリ最適化インスタンス(`db.r6g.large`)からServerless v2に、データベースの内容はそのままに、インスタンスの種類のみを移行していきます。

天下のクラメソさんが既に記事を公開されていました。この手順で可能でした(焼き増しスミマセン)

https://dev.classmethod.jp/articles/devio-aurora-serverless-v2/

## 簡単な流れ
リードレプリカをServerless v2で作る。
開発用なので、控えめのACUで作ってます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/ddb65db2-c7b6-333f-a161-979484d50e05.png)

既存のライターインスタンスをフェイルオーバーする。
> フェイルオーバー中

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/0c4e4315-7c1d-3a6b-e2c6-bac04b0b2191.png)

フェイルオーバーが完了し、Serverless v2インスタンスがライターインスタンスに変わりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/c950db5d-91cd-42e6-dafb-220550fea0dd.png)

`application-autoscaling-***` というインスタンスもできています。これは処理が落ち着けばスケールダウンして削除されます。

## ACUの増減を見る方法
CloudWatchの`ServerlessDatabaseCapacity`メトリクスで見ることができます。
展開時のみ上がってますが、すぐに最小値の0.5に落ち着きました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/aaa1f7b8-1318-6527-0573-84c7647d1da2.png)

## どれぐらい安くなるのか試算

スケールダウン中の時間は面倒なのでガバ計算です。

条件
- 8時間(業務時間)=1ACU(2GB)
- 16時間(それ以外の時間)=0.5ACU(1GB)
- 3分×1=スケールダウンタイム

計算式

> (0.20 USD/ACU 時間 × 1 ACU × 8 時間) + (0.20 USD/ACU 時間 × 1 ACU × 3/60時間) + (0.20 USD/ACU時間 × 0.5ACU × 16 時間) 
=3.21USD/日
>

月額97.584USDぐらいですね。弊社の場合、業務時間中の8時間ずっと1ACUということはあまりないと思います。
なので、だいたい1/3までカット！(予定)

やったね！

https://aws.amazon.com/jp/rds/aurora/pricing/
[Vue.js] コンポーネントの値をCSSに渡す方法

## コンポーネントの値をCSSに渡す方法

「v-bind:style」で定義したCSS変数をバインドする

```vue:Hoge.vue
<template>
  <div class="hoge" :style="styles" />
</template>

<script>
export default {
  name: 'Hoge',
  data() {
    return {
      styles: {
        '--hoge': '100px',
      },
    }
  },
}
</script>

<style scoped>
.hoge {
  height: var('--hoge');
}
</style>
```

## propsの値をCSSに渡す場合

computedでCSS変数を定義する

```vue:Hoge.vue
<template>
  <div class="hoge" :style="styles" />
</template>

<script>
export default {
  name: 'Hoge',
  props: {
    height: { type: Number, required: true },
  },
  computed: {
    styles() {
      return {
        '--hoge': `${this.height}px`,
      }
    },
  },
}
</script>

<style scoped>
.hoge {
  height: var('--hoge');
}
</style>
```
【一般】Power BI コネクター

[Sharperlight](https://sharperlight.jp/)にはPowerBIコネクターも備わっているので、ちょっと使ってみます。

Sharperlight Restサービスを起動しておきます。
PowerBIデスクトップを起動して、メニューより**Get Data**に行きます。（日本語版？は日本語表示なんでしょうね。:bow_tone1:）
一覧から**Sharperlight**を選び、`Connect`で次へ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/db5f13be-8a06-4d8c-52bd-b5248afa850a.png)
URLの入力ダイアログが表示されるので、SharperlightのPowerBI用URLを貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/f6d7d6e5-11a9-3230-2b45-cc3917f48ef3.png)
SharperlightのPowerBI用URLは、**パブリッシャー**を起動して、右クリックメニューから**リンク** -> **PowerBI**を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/8cc0752d-3f04-80ab-f454-cdf38258890f.png)
URLがクリップボードにコピーされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/2c7cf8be-fced-864b-2f3b-18e35f7e0853.png)
PowerBIのURLダイアログに貼り付けます。`OK`ボタンで次へ進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/49c657a9-5276-b50f-3fb4-ce455a8d64d6.png)
接続設定のダイアログが表示されるので、今回はこのように設定しました。`Connect`で次に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/94f26461-37c4-8aaa-6f54-f9c0e37dbeb5.png)
認証が通ると以下の画面が表示され、お手持ちのWebレポートの一覧がグループ別に表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/55846d35-7e7f-1c99-4166-1b30453cac76.png)
今回はこれでも選んでみましょうか。`Load`ボタンを押して次に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/767ef5e7-c5e7-b7c1-fa8e-f40ea39e0377.png)
データが読み込まれてモデルの準備ができるます。今回は単純にテーブルとして全ての列を表示してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/514e192b-fae7-b584-8679-909f8abe0acc.png)
といったように、Sharperlightで作成したWebレポートをPowerBIのデータソースとして利用できます。

では、失礼します。
Azureの中の人の記事を読む「Virtual Network NAT」について その１

クラウドの中身がどのような仕組みになっているのかを知るのに、とても参考になるのが中の人が書いている記事です。
たとえばAzureのネットワークについては宇田さんが書かれている記事があります。

https://www.syuheiuda.com/?p=4296

Azure ネットワークのプロダクトマネージャ、Aimee Littleton氏の最近の２つの投稿について二回に分けてとりあげます。

https://azure.microsoft.com/ja-jp/blog/improve-outbound-connectivity-with-azure-virtual-network-nat/

https://azure.microsoft.com/ja-jp/blog/dive-deep-into-nat-gateway-s-snat-port-behavior/

今回は「Improve outbound connectivity with Azure Virtual Network NAT」について見ていきたいと思います。

# Virtual Network NATとは

Aimee Littleton氏の記事に入る前にかんたんにVirtual Network NATについてのおさらいです。
Virtual Network NATはAzureでNATを利用する方法の１つです。NAT Gatewayとも呼ばれます。
NATを利用することで、仮想マシンにパブリックIPアドレスを割り当てることなく、インターネットに出ていくことができます。
NATの実現手段としてはこの他にもLoad Balancerを利用する方法や、Azure Firewallを利用する方法、Azureの既定のNATを利用する方法もありますが、この記事では取り上げません。

# Improve outbound connectivity with Azure Virtual Network NAT

この記事はAzure Virtual Network NATを使って接続性を改善した事例の紹介になっています。

## 当初構成

* アプリケーションがVMSSで動いている
* NATはLoad balancerで行っている
* アプリケーションが利用するREST APIをインターネット越しに呼び出している
* REST APIの前段にはFirewallが入っている

## 当初構成の問題点

* 1つまたは複数の仮想マシンがREST APIエンドポイントからの応答を長時間待つことがある
* これらのレスポンス待ちは最終的にタイムアウトし、接続障害となることがあった

## 当初構成で問題が発生した原因

* REST APIの前段にあるfirewallがAzure ネットワークからの着信接続を無言で切断していた
* この時、対象とされていたのは直近（20秒程度）使用された接続元ポートとIPアドレスからの接続のみだった
* これはfirewallが、同じ送信元IPとポートから来る新しい接続に対して20秒間のクールダウン期間を強制しているために発生していた
* REST APIに新しいコネクションを生成する頻度が高いためにAzure仮想ネットワークからのSNATポートが短期間に再利用されていた
* firewallのクールダウンタイマーを変更することはできなかった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/e6c7d423-4688-3bdf-0b8d-fa02aae3a06d.png)

※[引用](https://azure.microsoft.com/ja-jp/blog/improve-outbound-connectivity-with-azure-virtual-network-nat/)画像です

## Virtual Network NATによる解決

以下の2つの機能によって問題を解決することができたそうです

* Virtual Network NATは大量のポート在庫（最大16個のIPアドレス＝100万以上のSNATポート）からランダムに選択するために、新しいものである確率が高く、問題なくファイアウォールを通過することができた
* ソースポートが再利用される前に、少なくともファイアウォールのクールダウンタイマーと同じ時間、NATゲートウェイによって独自のクールダウンタイマーが設定されている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16609/d1a4e9c6-af7b-4503-46b5-85cf336e30b9.png)

※[引用](https://docs.microsoft.com/ja-jp/azure/virtual-network/nat-gateway/nat-gateway-resource#timers)画像です

### 逆にいうと。。。

上記が「Improve outbound connectivity with Azure Virtual Network NAT」の要約です。
これは逆にいうと、Azure Load balancerを使っている場合はこのような問題が発生するということだと思います。
クラウドのネットワークの接続性は「クラウドのネットワークでは瞬断があるのでリトライしよう」と言われて片付けられてしまうことがありますが、ちゃんと原因を調査してみると、より安定したネットワーク環境を実現できるという事例でもあります。

参考にしてみてください。

次回は「Dive deep into NAT gateway’s SNAT port behavior」を紹介します。
binding.pry

# binding.pry
Gemのpry-railsを追加することで使える機能。
binding.pryを記入した処理を、ローカルサーバーで実行すると記入された場所で処理が中断される。

# エラー　→　仮説　→　デバッグ
今回の場合は、
エラー　　：　NoMethodError in Tweets#index
仮説　　　：　formでパラメーターが送れていない可能性がある
デバッグ　：　binding.pryでparamsをチェック
という流れでデバッグする。

```diff_ruby:例
  # ツイート投稿ボタンが押され、createされる処理
  def create
+   binding.pry
    Tweet.create(tweet_params)
  end
```

#### ターミナルを確認
処理が止まり、irbのように対話可能の状態になる

```ruby:例
Started POST "/tweets" for ::1 at 2020-03-18 17:31:23 +0900
Processing by TweetsController#create as HTML
  Parameters: {"authenticity_token"=>"7imvHaB3Z9fle2uEDeNY5mBJebreoWRs6Scs8zcEHuL5FHWhXS8eOpX8Db8i13SGuV1F8T9fTbgSCuBFkrOmDQ==", "tweet"=>{"image"=>"", "text"=>"aaa"}, "commit"=>"SEND"}
  User Load (0.8ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
  ↳ app/controllers/tweets_controller.rb:50:in `move_to_index'

From: /Users/div-M.T/projects/pictweet/app/controllers/tweets_controller.rb @ line 14 TweetsController#create:

    13: def create
 => 14:   binding.pry
    15:   Tweet.create(tweet_params)
    16: end

[1] pry(#<TweetsController>)> 
```

paramsと入力すれば、ブラウザで入力フォーム(form)から送信したパラメーターが配列の形で出力できる。

```ruby:例
[1] pry(#<TweetsController>)> params
=> <ActionController::Parameters {"authenticity_token"=>"7imvHaB3Z9fle2uEDeNY5mBJebreoWRs6Scs8zcEHuL5FHWhXS8eOpX8Db8i13SGuV1F8T9fTbgSCuBFkrOmDQ==", "tweet"=>{"image"=>"", "text"=>"aaa"}, "commit"=>"SEND", "controller"=>"tweets", "action"=>"create"} permitted: false>
[2] pry(#<TweetsController>)> 
```
[AIX] AIX のブートリストは 5 パスまで

#### はじめに

AIX のブートリストは Firmware、NVRAM の制約により 5 パスまでであることと対応方法を確認しましたので記載します。

この制約は Firmware、NVRAM の仕様によるもので変更できないようです。

```
#bootlist -m normal -v -o                                               
'ibm,max-boot-devices' = 0x5 
```

=> 上記コマンドの結果は、5 パスがブートデバイスの最大値であることを表示しています。


---

#### 環境

・AIX 7.2 TL3 SP1

```
# oslevel -s
7200-03-01-1838
```

・rootvg ミラーリング構成

```
# lspv
hdisk0          00f62fc64a541a41                    rootvg          active
hdisk1          00f98db5233054e3                    rootvg          active

# lsvg -l rootvg
rootvg:
LV NAME             TYPE       LPs     PPs     PVs  LV STATE      MOUNT POINT
hd5                 boot       1       2       2    closed/syncd  N/A
hd6                 paging     16      32      2    open/syncd    N/A
hd8                 jfs2log    1       2       2    open/syncd    N/A
hd4                 jfs2       11      22      2    open/syncd    /
hd2                 jfs2       76      152     2    open/syncd    /usr
hd9var              jfs2       6       12      2    open/syncd    /var
hd3                 jfs2       3       6       2    open/syncd    /tmp
hd1                 jfs2       1       2       2    open/syncd    /home
hd10opt             jfs2       35      70      2    open/syncd    /opt
hd11admin           jfs2       4       8       2    open/syncd    /admin
lg_dumplv           sysdump    32      32      1    open/syncd    N/A
livedump            jfs2       8       16      2    open/syncd    /var/adm/ras/livedump
```

---

#### 確認

何も指定せずディスクパスの上からブートリストを設定した場合は、hdisk0 のパスから順に読み込まれます。
そのためパスの数が多いと、以下のように hdisk0 のみがブートリストに設定されるということが発生します。


```
# bootlist -m normal -o
hdisk0 blv=hd5 pathid=0
hdisk0 blv=hd5 pathid=1
hdisk0 blv=hd5 pathid=2
hdisk0 blv=hd5 pathid=3
hdisk0 blv=hd5 pathid=4
```

--- 

#### 変更方法

hdisk、パスを指定することで、両方の hdisk をブートリストに持つことが可能になります。

```
# bootlist -m normal hdisk0 pathid=0,1,2 hdisk1 pathid=0,1
```

5パスまでは変わりありませんが、設定した hdisk0 と hdisk1 のパスで構成されました。

```
# bootlist -m normal -o
hdisk0 blv=hd5 pathid=0
hdisk0 blv=hd5 pathid=1
hdisk0 blv=hd5 pathid=2
hdisk1 blv=hd5 pathid=0
hdisk1 blv=hd5 pathid=1
```


---

参考

・[bootlist Command](https://www.ibm.com/docs/en/aix/7.2?topic=b-bootlist-command)

以上です。
.envにAPP_KEYがなかった

.envはこのようになっていました。

```
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
```

.envにAPP_KEYがなかったので、後付けをします。

```
$ php artisan key:generate
```
きちんと作成できました🙌




https://qiita.com/yk2220s/items/dcbf54c6d1f33a0cb06f
Emmetでポケモンを召喚する

![ezgif-2-c3e5c78a97.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/e1e2190d-a951-f3fd-bf29-9bdaf72f909c.gif)

<p class="codepen" data-height="512" data-default-tab="result" data-slug-hash="RwMXzMJ" data-user="04" style="height: 512px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/04/pen/RwMXzMJ">
  Pokemon Random</a> by John Doe (<a href="https://codepen.io/04">@04</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`Tab`でEmmetを補完できます。

```html
img[src=https://lorempokemon.fakerapi.it/pokemon/200/$]*6
```

500pxのとき

```html
img[src=https://lorempokemon.fakerapi.it/pokemon//$]*6
```

<!-- sleep 3 && xdotool type -delay 200 'img[src' && xdotool key -delay 200 U003D && xdotool type -delay 200 'https://lorempokemon.fakerapi.it/pokemon/200/$]*6' && sleep 1 && xdotool key Tab -->

# 参考

https://lorempokemon.fakerapi.it/
Firebase Crashlytics の upload-symbols コマンドを直接入手する

## 経緯

Bitcode が有効化されたアプリで、 dSYM　ファイルを AppStoreConnect からダウンロード。
fastlane の `upload_symbols_to_crashlytics` アクションでこれをアップロードする CI / CD のステップを組んでいました。

https://docs.fastlane.tools/actions/upload_symbols_to_crashlytics/

Firebase Crashlytics には dSYM ファイルをアップロードするためのコマンドとして [upload-symbols が同梱](https://github.com/firebase/firebase-ios-sdk/blob/9.0.0/Crashlytics/upload-symbols) されており、`upload_symbols_to_crashlytics` アクションでは、この `upload-symbols` を利用して dSYM ファイルのアップロードを実施しています。

Firebase Crashlytics を CocoaPods で導入していた場合は問題ないのですが、 SwiftPackageManager で導入した場合、配置先のパスが特定できずにうまく動いてくれなかったため、 `upload-symbols` コマンドを別途用意する対応を実施しました。

## 対応方法

前述の通り、 `upload-symbols` コマンドについては Firebase Crashlytics のパッケージに同梱されているため、 curl でホスティング先の GitHub から直接ダウンロードしてしまいます。

```sh
# Firebase バージョンを別途指定する必要がある
$ curl -fsSL https://github.com/firebase/firebase-ios-sdk/raw/9.0.0/Crashlytics/upload-symbols -o ${配置先パス}/upload_symbols
# 一応、実行権限を付与
$ chmod +x ${配置先パス}/upload-symbols
```

あとはこれを `upload_symbols_to_crashlytics` アクションで利用するだけです。
パラメータとして `binary_path` を指定可能なため、これを指定することになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178830/2bae413f-4567-2d82-24cc-dfaf3645adaf.png)

Fastfile の記述としてまとめると以下のようになります。

```ruby
# 一時ディレクトリに配置
binary_path = ENV["TMPDIR"] + "/upload-symbols"

# upload-symbols を直接ダウンロード
sh(
  "curl",
  "-fsSL",
  "https://github.com/firebase/firebase-ios-sdk/raw/9.0.0/Crashlytics/upload-symbols",
  "-o",
  binary_path
)
sh("chmod", "+x", binary_path)

# 直接ダウンロードした upload-symbols を利用して upload_symbols_to_crashlytics 実行
upload_symbols_to_crashlytics(
  dsym_path: "${アップロードする dSYM のパス}",
  gsp_path: "${GoogleService-Info.plist のパス}",
  binary_path: binary_path
)
```


## 備考

fastlnae 側にも該当 issue が立っているのですが、コメント欄にある通り Xcode 14 以降ではそもそも AppStoreConnect からの dSYM ファイルダウンロードが不要になるはずなので、時間が解決してくれそうです。

https://github.com/fastlane/fastlane/issues/17288
検索フォーム

# ルーティング設定

collection... ルーティングにidがつかない
member...　ルーティングにidがつく

memberで指定した場合URLの指定先にidがつくため、詳細ページのようなidが必要な場合に有効。
idが不要な場合は、collectionでルーティングを指定する。

memberの場合
```ruby:例.html.erb
Rails.application.routes.draw do
  resources :tweets do
    member do
      get 'search'
    end
  end
end
```

    	
    Prefix           Verb    URI                                 Pattern
    search_tweet      GET    /tweets/:id/search(.:format)       tweets#search


# form_withで検索フォーム作成

```ruby:例.html.erb

<%= form_with(url: search_tweets_path, local: true, method: :get, class: "search-form") do |form| %>
  <%= form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input" %>
  <%= form.submit "検索", class: "search-btn" %>
<% end %>
```

# モデルにseachメソッドを定義
※データの処理(ビジネスロジック)は、モデルに定義するため。

```ruby:tweet.rb
  #引数には検索フォームから送信されたパラメータが渡される
  def self.search(search)
    #検索フォームが空でない場合
    if search != ""
      Tweet.where('text LIKE(?)', "%#{search}%")
    else
      Tweet.all
    end
  end
```

##### whereメソッド
条件に一致したレコードのインスタンスを配列で取得できる。
条件式には　__'カラム名 > 5'__　やキーバリューの形で　__カラム名: 値__　などの記述が可能。
また、whereメソッドを連続して記述することで、複数の条件に一致したレコードを取得することもできる。

    モデル名.where('検索対象となるカラムを含む条件式')

##### LIKE句
whereメソッドと併用する。あいまい検索が可能。
| 記述例　| 実行結果|
|:-----:|:-----:|
|where('title LIKE(?)', "a%")|	aから始まるタイトル|
|where('title LIKE(?)', "%b")|	bで終わるタイトル|
|where('title LIKE(?)', "%c%")|	cが含まれるタイトル|
|where('title LIKE(?)', "d_")|	dで始まる2文字のタイトル|
|where('title LIKE(?)', "_e")|	eで終わる2文字のタイトル|


# コントローラーにseachアクションを定義する

```diff_ruby:tweets_controller.rb
class TweetsController < ApplicationController
+  before_action :move_to_index, except: [:index, :show, :search]


    #中略


+ def search
+    @tweets = Tweet.search(params[:keyword])
+ end

  private

  def move_to_index
    unless user_signed_in?
      redirect_to action: :index
    end
  end
end
Web APIのエンドポイントやレスポンスにIDを使用してはいけないか考える

# はじめに
皆様、こんにちは！
佐久間まゆちゃんのプロデューサーの[@hiroki_tanaka](https://note.com/hiroki_tanaka)です。

私は現在、RailsシステムのAPIリプレイス活動に携わっています。
その際にエンドポイントにIDを使用するかどうかやレスポンスにIDフィールドを含めるか含めないかといったID問題があったので、考えたこと・調べたことをまとめたいと思います。

# 結論
**エンドポイントやレスポンスにIDを使用しないほうが良い。**

# 理由
Railsにおいて、IDカラムは基本的にDBでAuto Incrementされて発行された連番のサロゲートキーに当たります。
そのため、サロゲートキーであるIDカラムが露出してしまうことで以下のような問題が発生します。

### IDの値の大小によって、サービス規模が推測出来てしまう。
例えば、`Get /api/users/:id`といったIDに紐づくユーザ情報を取得するAPIが存在した場合、ユーザは`:id`に好きな値を入れることができます。
そのため`Get /api/users/10000`まではユーザ情報が取得出来ていたが、`Get /api/users/10001`以降の値では全くユーザ情報が返ってこなくなった場合、そのサービスのユーザ数は1万人前後ということが推測出来てしまいます。
エンドポイントだけでなく、レスポンスに含まれている場合でも推測可能です。
自社のサービス規模は企業にとって重要な情報の1つです。それが簡単に第三者にわかってしまう状況は害ことあっても利がありません。
(虚偽広告をするのは以ての外ですが、もし「会員登録者数10万人突破！」を宣伝で謳っていたのに、IDを調べてみたら実際は1万人前後しかいなければ確実に炎上してしまいます。)

また、IDの大小とは直接関係ないですがユーザIDのような個人情報に紐付いているIDが推測可能になってしまうのはセキュリティの観点でもNGです。

### IDはインクリメントする値のため、スクレイピングやアタックが容易になってしまう。
例えば、書評サイトを運営していて`/api/books/:id`をいうエンドポイントで様々な本の書評を取得している場合、下記のように`:id`を連番にするだけで簡単にスクレイピングでき、情報を抜き取る事ができます。

`Get /api/books/100`
`Get /api/books/101`
`Get /api/books/102`
・
・
・
`Get /api/books/999`

urlが予測しやすくスクレイピングが容易な状態だと攻撃者や競合相手に情報を簡単に渡すリスクが非常に大きいだけでなく、攻撃によるセキュリティリスクも高いです。
上記の例だと仮に`/api/books/100`で攻撃に成功した場合、他のurlにも攻撃を繰り返すには簡単なfor文やwhile文で実現することが出来てしまうので、リスクが大きいです。

### 処理によってはIDにintegerの最大値を使用した場合、次のデータを作成する際にAuto Incrementでエラーとなってしまう可能性がある。
例えば、Getで連携されたIDが存在しない場合はそのIDのデータを作成して、後続処理を続けるという処理があったとします。
(`find_or_initialize_by`や`find_or_create_by`が使用されるイメージです。)
その際に、いたずら心を持ったユーザがMySQLのintegerの最大値である2147483647を使用して`Get /api/hoge/2147483647`を行った場合、ID:2147483647のデータが作成されます。
IDはAuto Incrementで発番されるので、次にこのテーブルのデータを作成しようとした時にIDはintegerの最大値+1となってしまい、MySQLでエラーが発生します。
このように開発者の予期せぬ所でエラーの発生原因を作ってしまいます。

# では、どうするべきなのか
下記のようにIDではなく、システム内でランダム文字列として生成するkeyやcodeをエンドポイントやレスポンスに使用します。
IDの露出を極力抑えることでシステムの安全性を高める事ができます。
`Get /api/piyo/abcd12345`

もしくは、セキュアな[uuid](https://docs.ruby-lang.org/ja/latest/method/SecureRandom/s/uuid.html)を使用する形でも問題ありません。
```ruby
require 'securerandom'
p SecureRandom.uuid
#=> ad54c1ed-0ac7-47c4-8a4a-7f63fbbf9e6e
# Get /api/piyo/ad54c1ed-0ac7-47c4-8a4a-7f63fbbf9e6e
```

# おわりに
これまで何気なくエンドポイントにIDを使用し、レスポンスにIDカラムを含めていましたがこれを機に見直していきたいです。
GCPのWorkbenchにgoを入れる

# はじめに
GCPのWorkbench(JupyterLab)にgoを入れたので備忘録として残します
Jupyter環境であれば同様の手順で入れられるかと思います。
goをgcpのワークベンチでインタラクティブに実行したいというニーズはほぼない気はしますが、そんなニッチな誰かの役に立てれば

# goをインストール

go**インストール**

```
cd /usr/local
wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.14.2.linux-amd64.tar.gz
rm -rf go1.14.2.linux-amd64.tar.gz
```

パッケージインストール先のディレクトリ作成

```
sudo mkdir /var/www
sudo mkdir /var/www/go
sudo chown -R jupyter /var/www/go
```

パスを通す

```
vim ~/.bash_profile

以下を追加
export PATH=$PATH:/usr/local/go/bin
export GOPATH=/var/www/go
export PATH=$PATH:$GOPATH/bin
```

### 動作確認

ワークベンチリセット後ノートブックでgoのcliが使えることを確認

```
!go version
```

以下のコードを作成

```
package main

import "fmt"

func main() {
    fmt.Printf("hello, world\n")
}
```

実行

```
!go run hello.go
```

# ****カーネル追加****

以下を使います

[https://github.com/gopherdata/gophernotes](https://github.com/gopherdata/gophernotes)

ソースを取得します

```
go get -u github.com/gopherdata/gophernotes
```

カーネルの設定をコピーします

```
mkdir -p ~/.local/share/jupyter/kernels/gophernotes
!cp $GOPATH/src/github.com/gopherdata/gophernotes/kernel/* ~/.local/share/jupyter/kernels/gophernotes
```

再起動後, goカーネルが選べることを確認

![5c9b672fcd4f25ffc8deb8a7f0fd3e5f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315124/7738f505-1a71-e005-2e9d-da987ba5c41b.png)

# Hello World!!

![57de2481d51ea628112e86c907379eae.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315124/32f4be86-7b72-f079-b9dd-160572c9392d.png)





https://www.wantedly.com/companies/sweeep/projects
【Ruby】電話番号をハイフンなしの半角数字に成形する方法

## 環境
Rails 6.0.1
Ruby 2.6.3
PostgreSQL 11.16

## ハイフンなしの半角数字に成形する方法

```ruby
phone_number = '０９０ー１２３４ー５６７８'
phone_number.tr('０-９', '0-9').gsub(/[^0-9]+/, '')

# => "09012345678"
```

```tr```で全角数字だったら半角数字に成形。
```gsub```でハイフンなどの```integer```以外の文字列が入っていたとき削除（空文字に変換）。


> @scivola さんのコメントより
> ```gsub```よりシンプルで高速な```delete```もあるとのこと。
> ```ruby
> phone_number.delete("^0-9")
> ```

## 成形するメソッド

下記記事の内容を組み合わせて、電話番号をきれいに成形するメソッドにしてもいいかも。

```ruby
def format!(phone_number)
  return nil if phone_number.blank?
  return phone_number if phone_number.match?(/\A[0-9]+\z/)

  phone_number.tr('０-９', '0-9').gsub(/[^0-9]+/, '')
end
```

https://qiita.com/kat0/items/5e73273f169904e4d499
【Rails】ActiveStorageで、保存する前に画像を縮小する方法

大阪でRailsを中心に学習しているヨマ(@yoma_2003)です！
「ActiveStorageで、保存する前に画像を縮小する方法」をまとめます。

※おことわり※
断定口調でまとめますが、初学者であるため間違い等あればご指摘頂けると嬉しいです。

# はじめに

### やりたいこと
**ActieStorageでAmazon S3等に画像を保存する場合に、指定のサイズ以下に画像を縮小してから保存したい。**

### 必要環境
画像処理のためのツール、Gemの導入。

- ImageMagick：画像加工ツール（本番環境ではサーバーにもインストールする）
- Minimagick：ImageMagickをRubyから使えるようにするGem
- ImageProcessing：画像サイズを調整するGem

https://qiita.com/TerToEer_sho/items/7f8f42503e3100c652d5

# 結論
コントローラーに渡されたパラメーター内の画像ファイル（`ActionDispatch::Http::UploadedFile`の`tempfile`）を、`Imageprocessing::MiniMagick`を利用して縮小処理して置き換えてからインスタンスを作成する。

##### モデル

```ruby: Post.rb
class Post < ApplicationRecord
  has_one_attached :image
end
```

##### ビュー

```erb: new.html.erb / edit.html.erb
<%= form_with model: @post, local: true do |f| %>
  <%= f.text_field :name %>
  <%= f.file_field :image %>
  <%= f.submit "投稿する" %>
<% end %>
```

##### コントローラー

```ruby: posts_controller.rb
class PostsController < ApplicationController
  # indexアクション、newアクション、editアクションは省略  

  def create
    @post = Post.new(image_resize(post_params))
    if @post_comment.save
      redirect_to root_path
    else
      render :new
    end
  end

  def update
    @post = Post.find(params[:id])
    if @post.update(image_resize(post_params))
      redirect_to root_path
    else
      render :edit
    end
  end

  private

  def post_params
    params.require(:post).permit(:name, :image)
  end

  def image_resize(params)
    if params[:image]
      params[:image].tempfile = ImageProcessing::MiniMagick.source(params[:image].tempfile).resize_to_limit(500, 500).call
    end
    params
  end
end

```

# 解説

### パラメーター内の画像ファイルを縮小して置換するメソッドを定義


「パラメーターの内容自体を置換する」という処理がRailsのセオリー的にどうなのか不明ですが、アクション内の記述をほとんど変えずにそのまま代入できるので、以下の様にしました。

```ruby: posts_controller.rb
  def image_resize(params)
    if params[:image]
      params[:image].tempfile = ImageProcessing::MiniMagick.source(params[:image].tempfile).resize_to_limit(500, 500).call
    end
    params
  end
```

##### 画像ファイルの場所
アップロードされた画像ファイルは、パラメーター内のimageカラムで、`ActionDispatch::Http::UploadedFile`の`tempfile`にバイナリファイルとして格納されている。

```:post_paramsで受け取ったパラメーター
pry(#<PostsController>)> post_params
=> <ActionController::Parameters {
     "name"=>"a",
     "image"=>
       #<ActionDispatch::Http::UploadedFile:0x00007faf175307c8 
         @tempfile=#<Tempfile:/var/folders/mf/abcde1234500000/T/RackMultipart20220831-21205-pnm0r4.jpg>,
         @original_filename="test.jpg",
         @content_type="image/jpeg",
         @headers="Content-Disposition: form-data; name=\"post[image]\"; filename=\"test.jpg\"\r\nContent-Type: image/jpeg\r\n">
   } permitted: true>
```

##### 縮小する処理
`ImageProcessing::MiniMagick`モジュールの機能を使用して画像ファイルを縮小する。

```ruby
ImageProcessing::MiniMagick.source(params[:image].tempfile).resize_to_limit(500, 500).call
```


# おわりに
ImageProcessing::MiniMagickモジュールでは他にも簡単に画像処理ができるメソッドがいくつか用意されているのでこの形の用途はいろいろとありそうです。

https://github.com/janko/image_processing/blob/master/doc/minimagick.md

# 参考

https://qiita.com/chappy_30313331/items/ac0a320c899f9fe1d23a

https://qiita.com/selmertsx/items/2beb0d7ec0774cbbf050
iOS開発で作成された不要なキャッシュを削除しディスク容量を増やす

## 前提
前提条件として、以下の実行環境での動作を確認しています。

- Apple M1 
- macOS Monterey バージョン 12.0.1
- Xcode Version 13.4.1

以前のバージョンや新しいバージョンでも動作するかは未検証です。

## シェルスクリプト
以下のスクリプトを実行すると不要なディレクトリ・ファイルが削除されます。
筆者の環境では数十GBのディスク容量を空けることができました。

```sh
# DerivedData
# 中間生成ファイル。アプリ単位でビルド時に作成され
# ビルドが突然できなくなった場合などこれを消すと解消する場合がある。
# 削除すると次回のビルドが実質クリーンビルドになる。
rm -rf ~/Library/Developer/Xcode/DerivedData/*

# iOS DeviceSupport
# Xcode が iOS 実機端末との接続を認識したタイミングで作成される。
# iOS バージョンをアップデートする度に新しいディレクリが増えていく。
# 全削除して問題なし。
rm -rf ~/Library/Developer/Xcode/iOS\ DeviceSupport/*

# watchOS DeviceSupport
# watchOS 用。
# Xcode が Apple Watch とペアリングした iPhone との接続を認識したタイミングで作成される。
# watchOS バージョンをアップデートする度に新しいディレクリが増えていく。
rm -rf ~/Library/Developer/Xcode/watchOS\ DeviceSupport/*

# Archives
# ipa 作成時に作成される。
rm -rf ~/Library/Developer/Xcode/Archives/*

# CoreSimulator
# シミュレータのキャッシュ
rm -rf ~/Library/Developer/CoreSimulator/Caches/dyld/*

# この中の== Devices ==にUnavailableとなっているものがあれば使えなくなった過去のデバイスイメージなので削除してOK。
# 個別に削除するのは面倒なので、一括で削除できるコマンドがあるのでそれを使用する。
xcrun simctl delete unavailable
```
Chromeのバージョンが105になったのでCSSの:has()とContainer queriesが使えるようになった

## この記事の概要

https://developer.chrome.com/blog/new-in-chrome-105/

Google Chromeのバージョンが105になりました。
変更内容はいくつかありますが、私が興味を持っているのはCSSにおける`:has()`とContainer queriesが使用可能になったことです。

それぞれの機能について軽く触れつつ、今後の適用を考えてみます。

## CodePen

両方をチェックできるものをCodePenで作成しました。

上段が`:has()`について、下段がContainer queriesについてです。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="YzamNjO" data-user="xrxoxcxox" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/xrxoxcxox/pen/YzamNjO">
  Chrome 105 check</a> by Keisuke Watanuki (<a href="https://codepen.io/xrxoxcxox">@xrxoxcxox</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## :has()

CSSを書いていて「特定のクラスが付いた要素を子に持つ要素だけスタイルを変えたい」という場面はそれなりにあると思います。
先ほどのCodePenでは、`img`要素を子に持つクラスだけ背景色と文字色を変えていました。[^1]

[^1]: 見本のためにこういう実装をしましたが、あまりよろしくないので真似はしないでください。

ある種、`if-else`的な考えでスタイルを切り替えられるので今後よく使われていくと思います。

ただ、現状はChromeとSafariしか対応していません。
FirefoxとEdgeでの実装が待たれますが、ポリフィルがあるので今のうちに慣れておくのも手ではないでしょうか。
ポリフィルを試してみた記事は以下です。

https://qiita.com/xrxoxcxox/items/74c2443026de8b10a92c

## Contaienr queries

レスポンシブ実装などにおいて、Media queriesでスタイルを実現するのって大変ではありませんか？
画面幅がどうというより、描画されている要素の幅がいくつなのかをトリガーにしてレイアウトを変えたいですよね。

それを叶えてくれるのがContainer queriesです。

先ほどのCodePenでは要素の幅が800px以下になったら背景色が変わるようにしています。
こういった書き方ができるおかげで、コンポーネントにレイアウト違いのスタイルを持たせるのも現実的になると思います。

こちらは更に対応ブラウザが限られているので、利用は先になってしまいそうですが、ポリフィルはあります。
試してみた記事は以下です。

https://qiita.com/xrxoxcxox/items/959105606fe876148115

---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox
【エラー】pushした時に出た「remote: Repository not found.」 に対処してみた

# gitでpushしようとしたら<font color="red">**エラー発生。**</font>
下記エラーコマンドが出現。
```
remote: Repository not found.
```


https://mykii.blog/git%E3%81%A7push%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%ABremote-repository-not-found-%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC/

上記記事によると、「リモートリポジトリをgit@〜のsshのほうで登録し直すと大丈夫」とのことで、**下記コマンドを実行。**
```
git remote add origin git@github.com:ユーザー名/アプリ名.git
```
**「これでおけ！」と思ったら、、、**

##  補足資料（知ってたら飛ばしてください）: 登録するSSHの確認方法
1. 緑色の「Code」ボタンをクリック
1. 「SSH」タブをクリック
![SSHの確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1584967/8a9c2df5-d0d9-da40-947b-50233fe81510.png)



# <font color="red">**また次のエラー。。**</font>
下記エラーコマンドが出現。
```
error: remote origin already exists.
```

**「なんでやねん...」**

https://qiita.com/yu-ki0718/items/3c8aae2c81ca3f82f522

上記記事によると、「一度originを削除し、再度originを登録すればよい。」とのことで、**下記コマンドを実行。**


```
git remote rm origin
git remote add origin https://github.com/ユーザー名/アプリ名.git
git push origin -u master
```

**これでpush完了！！**
Googole Chromeのインストーラーの直リンク

# Google Chromeのインストーラーを直接ダウンロードする

Google Chromeのインストーラーの直リンクの調べ方が記載されているページを発見しました。

https://oucrc.net/articles/stg4mc1x8gin/

これを基に、各種インストーラーの直リンクを調べましたので、ここに記載します。

調べ方は[リンク先](https://oucrc.net/articles/stg4mc1x8gin/)に記載がありますが、簡潔に書きますと、
* ブラウザのデベロッパーツールのNetworkタブにて実際にダウンロードしたときに生成されるURLを取得
* GUIDなどの不要な箇所を削除

となります。


|  種類  |  URL  |
| ---- | ---- |
| オンライン32Bit | https://dl.google.com/tag/s/app=stable-arch_x86-statsdef_1/update2/installers/ChromeSetup.exe |
| オンライン64Bit | https://dl.google.com/tag/s/app=x64-stable-statsdef_1/update2/installers/ChromeSetup.exe |
| スタンドアローン32Bit(exe) | https://dl.google.com/tag/s/app=stable-arch_x86-statsdef_1/chrome/install/ChromeStandaloneSetup.exe |
| スタンドアローン64Bit(exe) | https://dl.google.com/tag/s/app=x64-stable-statsdef_1/chrome/install/ChromeStandaloneSetup64.exe |
| EnterPriseバンドル版32Bit | https://dl.google.com/tag/s/app=stable-arch_x86-statsdef_0/dl/chrome/install/GoogleChromeEnterpriseBundle.zip |
| EnterPriseバンドル版64Bit | https://dl.google.com/tag/s/app=x64-stable-statsdef_0/dl/chrome/install/GoogleChromeEnterpriseBundle64.zip |
| EnterPriseスタンドアローン32Bit(MSI) | https://dl.google.com/tag/s/app=stable-arch_x86-statsdef_0/dl/chrome/install/googlechromestandaloneenterprise.msi |
| EnterPriseスタンドアローン64Bit(MSI) | https://dl.google.com/tag/s/app=x64-stable-statsdef_0/dl/chrome/install/googlechromestandaloneenterprise64.msi |
| EnterPriseスタンドアローン32Bitベータ版(MSI) | https://dl.google.com/tag/s/app=arch_x86-statsdef_0/dl/chrome/install/beta/googlechromebetastandaloneenterprise.msi |
| EnterPriseスタンドアローン64Bitベータ版(MSI) | https://dl.google.com/tag/s/app=arch_x64-statsdef_0/dl/chrome/install/beta/googlechromebetastandaloneenterprise64.msi |
| MAC版| https://dl.google.com/chrome/mac/universal/stable/GGRO/googlechrome.dmg |
| Linux版（Debian/Ubuntu 用） | https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb |
| Linux版（Fedora/openSUSE 用）| https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm |

最新版のインストールを自動化したいとかの場合に有効かと思います。
array_columnまとめ

# はじめに
業務でarray_columnを使用し、めちゃくちゃ便利な関数で今後も多く使用するだろうと思いまとめてみました。
自分の振り返りのため、皆さんの参考になれば何よりです。


## 第一引数に配列、第二引数に取り出す要素のキー名を指定するパターン
下記の例だと、idだけの配列が作成されます。
```php
<?php
$arr = [
    ['id' => 1, 'name' => 'joy', 'hoby' => 'soccer'],
    ['id' => 2, 'name' => 'mike', 'hoby' => 'baseball'],
    ['id' => 3, 'name' => 'taro', 'hoby' => 'tennis'],
    ['id' => 4, 'name' => 'hana', 'hoby' => 'tabletennis'],
    ['id' => 5, 'name' => 'kim', 'hoby' => 'basketball']
];

var_export(array_column($arr, 'id'));

// 結果
// array (
// 0 => 1,
//  1 => 2,
//  2 => 3,
//  3 => 4,
//  4 => 5,
// )
```

下記の例だと、nameだけの配列が作成されます。
```php
$arr = [
    ['id' => 1, 'name' => 'joy', 'hoby' => 'soccer'],
    ['id' => 2, 'name' => 'mike', 'hoby' => 'baseball'],
    ['id' => 3, 'name' => 'taro', 'hoby' => 'tennis'],
    ['id' => 4, 'name' => 'hana', 'hoby' => 'tabletennis'],
    ['id' => 5, 'name' => 'kim', 'hoby' => 'basketball']
];

var_export(array_column($arr, 'name'));

// 結果
// array (
//  0 => 'joy',
//  1 => 'mike',
//  2 => 'taro',
//  3 => 'hana',
//  4 => 'kim',
// )
```

## 第三引数を指定したパターン
第三引数を指定にすると、その要素を結果の連想配列のキーにできます。
```php
$arr = [
    ['id' => 1, 'name' => 'joy', 'hoby' => 'soccer'],
    ['id' => 2, 'name' => 'mike', 'hoby' => 'baseball'],
    ['id' => 3, 'name' => 'taro', 'hoby' => 'tennis'],
    ['id' => 4, 'name' => 'hana', 'hoby' => 'tabletennis'],
    ['id' => 5, 'name' => 'kim', 'hoby' => 'basketball']
];

var_export(array_column($arr, 'name', 'id'));

// 結果
// array (
//  1 => 'joy',
//  2 => 'mike',
//  3 => 'taro',
//  4 => 'hana',
//  5 => 'kim',
// )
```

## 第二引数にnullを指定したパターン
第二引数にnullを指定すると、配列をそのまま返します。それだけだと意味がありませんが、第3引数でキー名を指定すれば、その値を各要素のキー名として設定できます。
```php
$arr = [
    ['id' => 1, 'name' => 'joy', 'hoby' => 'soccer'],
    ['id' => 2, 'name' => 'mike', 'hoby' => 'baseball'],
    ['id' => 3, 'name' => 'taro', 'hoby' => 'tennis'],
    ['id' => 4, 'name' => 'hana', 'hoby' => 'tabletennis'],
    ['id' => 5, 'name' => 'kim', 'hoby' => 'basketball']
];

var_export(array_column($arr, null, 'id'));

// 結果
// array (
//  1 => 
//  array (
//    'id' => 1,
//    'name' => 'joy',
//    'hoby' => 'soccer',
//  ),
//  2 => 
//  array (
//    'id' => 2,
//    'name' => 'mike',
//    'hoby' => 'baseball',
//  ),
//  3 => 
//  array (
//    'id' => 3,
//    'name' => 'taro',
//    'hoby' => 'tennis',
//  ),
//  4 => 
//  array (
//    'id' => 4,
//    'name' => 'hana',
//    'hoby' => 'tabletennis',
//  ),
//  5 => 
//  array (
//    'id' => 5,
//    'name' => 'kim',
//    'hoby' => 'basketball',
//  ),
// )
```
【クエリビルダ：拡張表現】IncludeTotalRows文を使ってみる

今回は、[Sharperlight](https://sharperlight.jp/)の数ある拡張表現関数の中から、**IncludeTotalRows**文を使ってみます。
この関数を使用すると合計行にも拡張表現を適用することができます。
### 元となるクエリの準備 ###
[Sharperlight](https://sharperlight.jp/)アプリケーションメニューから`クエリビルダ`を起動します。
SAP Business Oneデータモデルを使用して元のクエリを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/af420198-6b9a-f031-c264-9e9251715fbc.png)
クエリ結果はこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/abc9dfb7-1f76-56b2-39a1-ce0fe4f7e546.png)
### IncludeTotalRows文の追加 ###
出力領域の右クリックから**拡張表現を追加**を選択します。
`一般`タブで**出力参照名**と**説明**を記入し、一度`OK`ボタンで確定します。
この時、`拡張表現`タブの構文エディタが空白だと確定できないので、とりあえず**0**を入力し確定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a8504fe5-f1fe-676e-b2d9-eefeb6eb363c.png)
再度、確定した拡張表現を開きます。拡張表現タブの関数一覧より**IncludeTotalRows**文を探し、ダブルクリックで上部エディタ領域にテンプレートを転送します。
あまり意味はないですが今回は**IncludeTotalRows**文の動作説明ということで、売上伝票総額の値が0000以上の場合は上向き三角アイコン、それ未満の場合は下向き三角アイコンを表示してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/31a6cbcf-b953-3f36-503c-7c12221da744.png)
出力列の定義はこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/05417276-0e9f-4792-b609-05f64d395869.png)
### 結果 ###
アイコンが合計行にも表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b38177c5-6562-9896-91e9-0f7d88fffc19.png)
レポートのデザイン上、ご利用の必要性が発生した場合は是非試してみてくださいね。

では、失礼します。
【laravel】改行コードを含む文字列をDBから取得しbladeで表示させる方法

### 環境
- laravel 6.17.1
- PostgreSQL

### 内容
DB上に登録されているテキストデータに\<br>が含まれている。
Bladeで表示する際に改行された状態で表示させたい。

### 結論
```
表示させたい箇所で以下のように記載する
{!! nl2br($変数名) !!}
```
【Google Cloudテクニカルブロク投稿キャンペーン】買い物難民問題の解決案アーキテクチャ

# はじめに
テクニカルブログ投稿キャンペーンのアプリケーションモダナイゼーション集中月間の8月の記事になります。

# 対策テーマ
サーバレス技術を活用した社会課題の解決策
- 空き家問題
- 買い物難民問題
- 東京一極集中
- フードロス問題

## テーマの選択について
4テーマから「買い物難民問題」の解決策について記載します。

## サービス概要
買い物難民のケースとしては、やはり高齢化に伴い買い物にいけない、地方の交通機関の衰退に伴い買い物にいけない、といったものが上げられます。
それに対して、複数の事業社と提携し、その提携事業社のメニュー内から注文したものをドローンで配達するアプリを想定しています。
なお、事業社登録用には別途Webサイトを設けて、提供元の事業所や在庫情報はそこで管理します。
一見高齢者ではこのような機能を使いこなすのが難しいかもしれませんが、ご家族などの代理での注文も可能とし、
ドローンに設置されているカメラで、配達先の動画などを残すことで、その配達先での様子も見ることが可能とします。
※仮に受け取れない場合、高齢者の異常を検知し、受け取れない旨のアラートをあげるような機能もいいかなと思いました。
また、利用回数を重ねたり、年齢や食事の嗜好、栄養バランスに応じて、レコメンド機能も付与し、似たようなサービスとの差別化、利用率上昇を考えました。
その後の傾向分析も行えるような仕組みも併設し、継続利用してもらえるようなサービスを目指します。

![Untitled-2022-08-31-1037.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1720034/8681be5a-1781-2dcc-476c-cac9367b399b.png)



## アーキテクチャ概要
- Cloud Run で開発者でも簡易的に構築できる環境とする
    - 事業社登録用と利用者用で分ける
- Cloud Armor で脆弱性対策を行う
- 静的コンテンツはCloud Storageを使う
- Spannerほどの可用性は必要ではないと考えてほどほどの負荷を意識しAlloyDBを選択
    - 管理サイト側も在庫情報をもつので同様の理由でAlloyDBを選択
- 利用者情報はidentity platformを使って認証する
- 検索やレコメンドでRecomended AI を使って利用率や注文率の上昇を狙う
- GoogleAnalyticsを利用したBQと連携し、Lookerも使ってデータ分析をできる基盤を作る
- 動画を撮影し顔検出はCloud Visionを使って実際に配達されたことを確認する
    - 顔認証はできないので、顔検出のみでいいか、は悩ましいところ(課題)
    - 顔検出できない場合はアラートなどを出して、高齢者の見守りも兼ねている
- レコメンドや検索の情報はサービス影響与えないよう、BQと連携しそこからデータをすい上げる
    - BQへ保存したデータはLookerなどで分析も可能な状態とする
- Firebase App Distributionでテストアプリ配信、管理し開発効率をあげる

# 所感
正直インフラ関連の業務を主にしているため、開発的な視点で難しいところなどあるかもしれません。
ただ経験の中から利用するGoogle Cloudのサービスを想定し、可能な限りサーバレス化できたかなと思っています。
初めてこういったものに投稿するのですが、色々発想を鍛えるためにもいい経験になったかな、と思っています。
サービス内容的にどこかで聞いたことのあるものになってしまって、もう少し面白い発想ができればよかったな、と思いました。

## 補足
利用サービスが図にしかないので、改めてここに掲載します。
- コンピューティング
    - Cloud Run
    - Cloud Functions
- データベース
    - Alloy DB
    - Cloud Firestore
- NW
    - Cloud Armor
- ストレージ
    - Cloud Storage
- 認証
    - Identity Platform
- 顔認証
    - Cloud Vision
- アプリ管理
    - Firebase App Distribution
- レコメンド、検索
    - Recommendation AI
- 分析
    - BigQuery
    - Google Analytics for Firebase
    - Looker
自然言語処理の前処理 ベクトル化について

# はじめに

自然言語処理では単語をアルゴリズムで扱える数字に変換する前処理が必要です。
ここでは、単語のベクトル化と称します。
単語のベクトルにも主に2つのアプローチがあります。

ここではそれらのアプローチの概要と軽く実装を紹介しようと思います。
以下の自然言語処理処理の流れの中でベクトル化についての話です。

1. 前処理
    1. 形態素解析
    2. **ベクトル化**
2. アルゴリズム
3. 後処理して出力

# ベクトル化のアプローチ

## ワンホットベクトル

単語をベクトルで表現する方法として、簡単に思いつく方法は、01のみのエンコードするケースです.
例とえば、文字0~9を表現する場合は、次元数は10の以下のようなベクトルで表現できます.

```
010000000

```

ただし、この方法にはいろいろな課題があります.

- 単語同士の計算ができない
- 単語間の関連性がわからない
- 次元数が単語数に比例する
    - 例えば広辞苑にある24万語を表現すると24万の次元数になる
    - データ量が非常に多くなってしまう

## 分散ベクトル

分散ベクトルとは、単語の意味をベクトルで表現したものです.
ベクトルで表現することで単語同士の演算ができ、類似度を測れたりと色々とメリットがあります.

例えば以下みたいな表現にすれば単語同士で計算でき、関連性が測れたりするのでは?

```
0.443 0.854 0.133, ...

```

分散表現がわかると、色々な嬉しいことがあります.

- 単語同士の計算ができる
- 単語間の関連性がわかる
- 少ない次元数で多様な単語を表現できる
    
    **nwjc2vec**
    
    - 大規模な日本語コーパスNWJC（258億語)で学習
    - 次元数は200
    - [https://www.jstage.jst.go.jp/article/jnlp/24/5/24_705/_pdf](https://www.jstage.jst.go.jp/article/jnlp/24/5/24_705/_pdf)

# 分散ベクトルのアルゴリズム

## Word2Vec

- Word2Vecは、単語の分散表現を得るためほ手法(2013年 トマス・ミコロフらによる)
- 分散表現を得る際にニューラルネットを使用
- 飛躍的な精度向上
- **分布仮説**をもとにしている

### Word2Vecの手法

以下２つの方法があります。

**Skip-gram**

- 中心の単語から周辺語を予測する

**CBOW**

- 周辺語から中心の単語を予測する

### 分布仮説とは

**単語の意味は周辺の単語によって決まる**とい分布仮説というものがあります.
単語の分散表現を得る手法はWord2Vec以外にもありますが、基本がこの仮説をもとにしています.

例) eatとくれば大体次は食べ物の単語がくることが予想できます.

```
I eat 食べ物の単語.
```

# genismで分散ベクトルを取得

genismを用いて単語の分散ベクトルを取得してみます。
genismはLDA(トピック分析)で使われるものですが、今回はLDAについては割愛します。
ベクトル化のAPIを使ってちょっと遊んでみます。
[Gensim: topic modelling for humans](https://radimrehurek.com/gensim/models/word2vec.html)

学習済の単語ベクトルを取得

```python
import gensim.downloader as api
wv = api.load('word2vec-google-news-300')
```

出力してみる

```python
wv["Tokyo"]
```

```python
array([-2.16064453e-02,  1.79687500e-01,  1.98242188e-01, -1.62109375e-01,
       -1.34765625e-01,  1.25732422e-02, -1.99218750e-01, -2.68554688e-02,
       -3.78417969e-02,  1.66992188e-01, -3.26171875e-01,  4.66796875e-01,
        8.74023438e-02, -2.63671875e-01, -8.69140625e-02, -2.55859375e-01,
        1.67846680e-03,  2.61718750e-01, -3.58886719e-02, -4.83398438e-02,
        6.17675781e-02, -1.97265625e-01, -8.30078125e-02, -6.49414062e-02,
       -2.35595703e-02,  2.47070312e-01, -1.05468750e-01,  3.36914062e-02,
       ...
```

単語の次元数は300でした

```python
wv["Toyko"].shape
```

```python
(300,)
```


色々計算してみます。

ロンドン - イギリス + 日本　＝東京

```
wv.similar_by_vector(wv["London"] - wv["England"] + wv["Japan"], 1)
```

```python
[('Tokyo', 0.7490742206573486)]
```

東京 - 日本 + イギリス　＝ロンドン

```python
wv.similar_by_vector(wv["Tokyo"] - wv["Japan"] + wv["England"] , 1)
```

```python
[('England', 0.708386242389679)]
```

なるほど。。

# おわりに

自然言語処理の単語のベクトル化について軽くまとめてみました。
ベクトル化をどう応用して実際の課題とアルゴリズムに適用するかはまた後ほど。

https://www.wantedly.com/companies/sweeep/projects
[Vue.js] スコープ付きslotの記述方法

## 子コンポーネント側

子コンポーネント側では、`<slot>`タグに対してv-bindを行います。

```vue
<template>
  <div>
    <slot :hoge="hoge">
  </div>
</template>

<script>
export default {
  name: 'Child',
  data () {
    return {
      hoge: 'hoge',
    }
  }
}
</script>
```

## 親コンポーネント側

親コンポーネント側では`<v-slot:default>`で受け取ることで、子コンポーネントのの値をとることができます。
slotPropsは任意ですので重複がなければ、どんな文字列でも構いません。

```vue
<template>
  <div>
    <Child v-slot:default="slotProps">
      {{ slotProps.hoge }}
    </Child>
  </div>
</template>

<script>
import MyCom from '../components/Child.vue'
export default {
  name: 'parent',
  components: {
    Child
  }
}
</script>
【クエリビルダ：拡張表現】RowSkipAllButLast文を使ってみる

今回は、[Sharperlight](https://sharperlight.jp/)の数ある拡張表現関数の中から、**RowSkipAllButLast**文を使ってみます。
この関数は、最後の行を除くすべての行をスキップし、合計行を非表示にします。 最後の行の値が、前の全行の累積合計である場合などに、最後の計算結果のみ出力した場合があります。そのような場面に使用します。**RowSkipAllButLast**を使用すると、最後の行だけが返され、すべての行が表示されなくなります。 非表示の行は、最後の行の計算に引き続き使用されます。
### 元となるクエリの準備 ###
SAP Business Oneを使用して作成してみます。
売上伝票の金額を年単位で集計する簡単なクエリを以下のように作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/e4cc77bc-7e43-5fe2-b200-9c549b1fcd46.png)
クエリ結果はこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/767608a5-6d93-bd98-d7e8-c3f081c80a9c.png)
### 売上伝票総額累計を計算する拡張表現の追加 ###
出力領域の右クリックから**拡張表現を追加**を選択します。
`一般`タブで列の**出力参照名**と**説明**を記入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d6c74b2e-d448-fef8-cf64-cd9c75b01536.png)
一度`OK`ボタンで確定後、もう一度同じ拡張表現を開きます。そうすることで入力した**出力参照名**が正しく使用できるようになります。
`拡張表現`タブでは、以下のような式を作成します。
累計なので売上伝票総額をどんどん加算していくといった具合になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/8861916e-a5a3-b5c8-a54c-8d1ed0588a06.png)
クエリ結果はこうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/cac48794-ddab-a089-6309-adddfb897d3f.png)
累計列の金額のフォーマットを揃えます。
その拡張表現を開き、`通貨接頭辞`を円記号にします。`小数点以下の桁数`は0にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/69145833-00df-b99e-b26e-10b299baf72b.png)
もう一度クエリ結果を確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/4e9b17a3-3fc9-6688-ca88-da5ae8144104.png)
### RowSkipAllButLast文の使用 ###
では準備したクエリに**RowSkipAllButLast**文を追加してみます。
この行だけが表示されるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/2ca98e6e-4840-7d21-2ea4-d469a6a24586.png)
出力領域の右クリックから**拡張表現を追加**を選択します。出力オプションダイアログが開いたら、関数一覧より**RowSkipAllButLast**文を探し、ダブルクリックで上部エディタ領域にテンプレートを転送します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/889ed7d4-824b-ef29-f493-8cbd5c42189c.png)
`一般`タブでは、以下のような設定を行います。この拡張表現自体の表示は必要ないので**非表示**にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/ba981fb9-dd36-00ff-8ed5-8ae0fa5edb6a.png)
### 結果 ###
クエリの出力定義はこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/929b8108-809d-f1b3-9347-e0a1ec393d3c.png)
では早速クエリ結果を見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/991860c2-806f-dae6-13ad-66b4bb344521.png)
`伝票集計年`列と`売上伝票総額`列が必要ない場合は、非表示にするとこのような結果となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/677c6282-6dd1-1aa8-55db-30a08eca2bca.png)

レポートのデザインで最後の行の値が欲しいケースが表れた場合は、是非試してみてくださいね。

では、失礼します。
Stripeでサブスクリプションの更新に失敗した時の、Customer Portalを使った決済手段の更新方法


サブスクリプションサービスを始める中で、サポートチームの負担・コストになりやすいのが「契約の更新失敗」です。

顧客への連絡、新しいカード情報の登録、カード情報とサブスクリプションの紐付け、UIでの警告表示etc...

これらの実装やワークフローの設計を、コア機能の開発と並行して行う必要があります。

## Stripe Customer Portalで、ノーコードなカード情報更新フローを作成

Stripeを利用いただいている場合、Customer Portalを使うことで、ほぼノーコードで実装できます。
![スクリーンショット 2022-08-29 11.53.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/c5541675-2a73-02c0-2255-e2fcd9e965cb.png)


このような契約管理ページを、以下の３行のコードで実現します。

```js
  const session = await stripe.billingPortal.sessions.create({
    customer: 'cus_xxxx',
  })
  res.redirect(session.url)
```

### 更新失敗時の、決済情報更新もノーコード

Customer Portalは、契約の更新に失敗した場合、ページに警告メッセージと更新のためのフローを用意します。

![スクリーンショット 2022-08-29 11.49.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/cb4be9c7-7344-1bde-b166-2af7e672d45c.png)

[決済手段の更新]を選択すると、登録済みの別カードへの切り替えや、新しいカードの登録と紐付けができます。

![スクリーンショット 2022-08-29 11.52.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/20f69ae6-38da-dd88-ae65-df08f862a1d0.png)

## 更新・キャンセルなどの設定範囲は、ダッシュボードから変更可能

「決済情報の更新はさせたいけども、キャンセルはしてほしくない」ケースなどでは、[ダッシュボード](https://dashboard.stripe.com/test/settings/billing/portal)からキャンセル機能をオフにできます。

![スクリーンショット 2022-08-29 11.54.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/db3b4056-8ef7-4c53-055b-407d3efe3c63.png)

Stripe側のアップデートで、ポータル上の機能を増やすことができます。

そのため、顧客の請求管理マイページの実装や運用工数・コストの最小化が期待できます。

## 関連リンク

https://stripe.com/docs/billing/subscriptions/integrating-customer-portal
Linux 基本的なネットワークコマンドについて（自分用メモ

●基本的なネットワークコマンド

・dig DNSサーバへ問い合わせ、DNSサーバへの登録情報を表示
・ifconfig インターフェイスの設定や表示
・ifup/ifdown インターフェイスを有効/無効
・netstat さまざまな項目を指定して、ローカルネットワークの情報を表示
・ping ICMPパケットを使って通信確認を行う
・route ルーティングテーブルの設定や表示
・traceroute ICMPを利用してリモートホストまでの経路情報を表示
・whois whoisサーバのデータベースに問い合わせを行い、ドメインの管理者や所有者情報を表示
・ip　iproute2ユーティリティに含まれている、IPアドレスやルーティングの設定を行うコマンド
・ping　エラーメッセージや制御メッセージを通知するICMPというプロトコルを使って、ネットワークの疎通確認を行うコマンド


※pingコマンド単体はCtrl+Cで停止


●ネットワークの疎通確認に使う代表的なコマンド
・ping/ping6 宛先アドレスに到達可能かを確認
・traceroute/traceroute6 宛先アドレスまでの経路を確認
・tracepath/tracepath6 宛先アドレスまでの経路と経路状の最大転送単位(PathMTU)を確認


●pingコマンド
ping [オプション] 宛先
ping6 [オプション] 宛先

オプション
・-c 疎通確認用パケットの送信回数
・-i 疎通確認用パケットの送信間隔
・-n 結果表示時の形式をホスト名ではなくアドレスで表示

▲※pingコマンド実行で発生する種類別エラー

・停止しているサーバに対してpingを実行
→応答が無い

・対象ホストの名前解決ができていない場合のエラー
→不明なホストというエラーが返ってくる

・コマンドを実行するマシンのインタフェースがdownしている時のエラー
→ネットワークに届かないというエラーが返ってくる

・存在しないIPアドレスに対して実行した場合のエラー
→ホストに届かないというエラーが返ってくる

●tracerouteコマンド
リモートホストまでの通信経路を表示。

traceroute [オプション] 宛先
traceroute6 [オプション] 宛先

オプション
・-n 結果表示時の形式をホスト名ではなくアドレスで表示
・-p 使用するポート番号を指定
・-g 使用するゲートウェイを指定
・-T TCPを使用
・-I ICMPを使用

●tracepathコマンド
tracepath [オプション] 宛先
tracepath6 [オプション] 宛先

オプション
・-n 結果表示時の形式をホスト名ではなくアドレスで表


●ifconfigコマンド
ネットワークインターフェースの情報の表示や設定を行う。

ifconfig [インターフェース名] [オプション]

オプション
・IPアドレス　IPアドレスを指定
・netmask サブネットマスク　サブネットマスクを指定
・up インターフェースを有効化
・down インターフェイスを無効化

※インターフェース名やオプションを指定せずに「ifconfig」コマンドのみを実行すると、有効化されている全てのインターフェースの情報が表示され、インターフェースのMACアドレスやIPアドレス、ブロードキャストアドレス、サブネットマスク、MTU（最大転送単位）などが確認できる。

※インターフェースを有効化するには「ifconfig インターフェース名 up」もしくは「ifup インターフェース名」を使用

例）
eth1インターフェースを停止（無効化）するには「ifconfig eth1 down」もしくは「ifdown eth1」を使用。

インターフェースを停止すると、接続するネットワークと通信できなくなり、接続するネットワークの情報がルーティングテーブルからも削除される。