OmniAICreator/Qiita-1.07M huggingface dataset:
FreeBSD 13.0 + darkMate13 及び NAS中メディアファイルの再生　備忘録

###1. FreeBSD 13.0 がリリースされました。
継続的に使用することがなかったFreeBSD ですが、４月にバージョン13.0がリリースされました。当方の目的は、デスクトップ用途ですので、再評価も兼ねてインストールしてみました。

###2. ベースとなるシステム
昔からやり方も変わらず、５分程度でインストールできてしまいます。(省略)

###3. デスクトップ用ウィンドウマネージャー
さて、ここからです。デスクトップ用途には、desktop-installer というツールが、pkg install で利用可能です。ここから複数種類のデスクトップ環境がインストールができ、日本語フォント等も自動でインストールされるので、環境を日本語に変えても問題なく表示されます。しかし、デフォルトで用意されたアプリというか、設定は、帯に短し襷(たすき)に長し、といったところで、特にフォントですが、google系の日本語フォントは、きれいなのですが、どうしても違和感を感じる漢字フォントがありまして、ファイルサイズも大きいので、種類を絞りたい。ということで、別のスクリプトを探したところ、darkMate13.0 というスクリプトがあることを知りました。


https://github.com/broozar/installDesktopFreeBSD


試してみたところ、20分程度で終わります。
デフォルトで日本語フォントがインストールされず( ← これが良い)、自分の好みの日本語フォントのみインストールできスッキリした好みの顔になりました。インストールした日本語フォントパッケージは、下記の通り。多少、ノスタルジックな表情になります。

```
$ pkg info|grep ja-font
ja-font-ipa-uigothic-00203_5   IPA Japanese fonts, UIGothic
ja-font-ipaex-00401            IPAex Japanese fonts
```

日本語入力は、定番の fcitx-mozc がありましたので、それをインストール。インストール後は、こんな感じ。fcitx5 という新しいバージョンもありましたが、fcitx5-mozc というパッケージが、見当たらず、実績重視としました。

```
$ pkg info|grep fcitx
fcitx-qt5-1.2.6                Fcitx support for Qt5
ja-fcitx-mozc-2.23.2815.102.01_3 Mozc engine for Fcitx
zh-fcitx-4.2.9.7               Flexible Input Method Framework
$ pkg info|grep mozc
ja-fcitx-mozc-2.23.2815.102.01_3 Mozc engine for Fcitx
ja-mozc-server-2.23.2815.102.01_3 Mozc Japanese Input Method, Server
ja-mozc-tool-2.23.2815.102.01_3 Mozc tool for IBus, SCIM, and others
```

```
$ cat .xinitrc
export LANG=ja_JP.UTF-8
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
/usr/local/bin/mozc start
fcitx -r -d
exec mate-session
```

LibreOfficeも最新版の7.1.3.2 が日本語化され、日本語入力も可能になっています。

###4. NAS中のメディアファイル再生
我が家では、音楽CD等は全てデジタルデータをNAS中に保管し、PCあるいは、スマホからWi-Fi接続で楽しめるようにしています。SMB共有なのですが、FreeBSDでは、GUIで接続できません。NASのほうの設定に、ftpdサービスも追加し、Mateデスクトップのファイラーである、Cajaから、ftp クライアントとして接続するとつながります。

darkMate13.0 では、ホームディレクトリに ramdiskを作ってくれているので、そこにメディアファイルを一旦、コピーし、vlc で再生すると思惑通り、再生できました。まー、これでいいや。というところです。
上記の通り、ftp で接続できるので、表示されたftpサーバー内のメデイアファイルを直接、vlc で再生しても可能でした。

![Screenshot at 2021-06-10 18-55-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561584/e5ce8e8b-67ca-a488-3eaa-7e3562b4a46c.png)


以上
###
2Dアクションゲームを作りながらUnity学習　#１日目

# 環境
* MacBookAir(M1,2020)
* UnityHub 2.4.3
* Unity バージョン2020.3.10f1

# 本日の学習内容
* アニメーション設定
* キャラクターの移動設定(走る・ジャンプ)
* カメラの追従

# 苦労した点
* アニメーションを設定する為の絵を用意したこと
* 移動の設定方法が多く、絞るのが大変

# 感想
まだまだ先は長く、覚えるべきことも多いですが、楽しみながら頑張ります。
【Android】ダイアログのmatch_parentについて

ダイアログの幅・高さいっぱいに広げるのに手間取ったのでメモ。
あまり使う場面はないと思うが。

# AlertDialog

AlertDialogは比較的簡単に実装可能なため、これを使用していた。
ただ、これだと幅・高さいっぱいに広げられない。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/e254fb1f-8103-93d8-ae00-b723ae2a222b.png" width=30%>

```MainActivity.kt
val dialog = AlertDialog.Builder(this).apply {
	setTitle("タイトル")
	setMessage("メッセージ")
	setNegativeButton("閉じる") { dialog, _ -> dialog.cancel() }
}.create()

//このようにmatch_parentを使おうとしても意味がない
dialog.window?.setLayout(
	ViewGroup.LayoutParams.MATCH_PARENT,
	ViewGroup.LayoutParams.MATCH_PARENT
)

dialog.show()
```

# Dialog
通常のダイアログを使用すると、幅・高さいっぱいに広げることができる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/11971ad2-ef14-21e6-e666-e955c265d5ec.png" width=30%>


まずダイアログのレイアウト作成。

```test_dialog.xml
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:background="@color/white"
	android:gravity="center"
	android:orientation="vertical"
	android:paddingHorizontal="60dp"
	android:paddingVertical="20dp">

	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_gravity="start"
		android:text="タイトル"
		android:textSize="20sp" />

	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_gravity="start"
		android:text="メッセージ"
		android:textSize="18sp" />

	<Button
		android:id="@+id/button"
		style="?android:attr/borderlessButtonStyle"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_gravity="end"
		android:text="閉じる"
		android:textColor="@color/black" />
</LinearLayout>
```


次に処理部分の作成。ここでmatch_parent指定。

```TestDialogFragment.kt
class TestDialogFragment : DialogFragment() {

	override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
		return Dialog(requireContext()).apply {
			val binding = TestDialogBinding.inflate(LayoutInflater.from(context))

			binding.button.setOnClickListener {
				dismiss()
			}
			setContentView(binding.root)

			//ここで幅・高さをmatch_parentにする
			window?.setLayout(
				ViewGroup.LayoutParams.MATCH_PARENT,
				ViewGroup.LayoutParams.MATCH_PARENT
			)
		}
	}
}
```

最後にMainActivityでダイアログ表示

```MainActivity.kt
TestDialogFragment().show(supportFragmentManager, TestDialogFragment::class.java.simpleName)
```
「エンジニア人材の需給推移」から考えるこれからのキャリアについて

## はじめに

エンジニアとしてのキャリアを考える上で「どの技術を学ぶか」「どのような会社で働くか」「スペシャリストかマネジメントか」「フリーランスとして働くか」などなど色々な要素があると思います。個々それぞれのキャリアイメージを考えてみることはとても大事だと思いますが、今回はその1つとして**「エンジニア人材の需給推移」**という観点でエンジニアのキャリアを考えてみたいと思います。

## エンジニア人材の需給推移とは

こちらは、みずほ情報総研株式会社が経済産業省委託事業として2019年3月に調査公開している資料「IT人材需給に関する調査」からの抜粋です。

https://www.mizuho-ir.co.jp/publication/contribution/2018/zoom/mizuho-global1806-07_01.html

![スクリーンショット 2021-06-10 17.09.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502865/0fb425eb-a6c8-347a-5a05-59ad2fd98231.png)



この調査の通り、IT人材の国内人口は約100万人であり今後約10年間は微増傾向です。
一方でIT産業の発展により、人材の需要については大きく伸びる予測です。需給ギャップについては3パターンの予測推移があり高位シナリオでは約79万人、低位シナリオでも約16万人の供給不足が2030年に起こると予想されています。

この結果から

**今後国内IT人材について需要過多な状況が続く**

ということが予想されます。

なので、まずITエンジニアは基本的に「食いっぱぐれることは無い」キャリアを選択しているということです。もちろん個々の能力等で一概には言えませんが全体感としてはそうなると思います。

## 需要過多になるとどうなるか？

まず分かりやすいのが、**採用競争**です。各社が自社の魅力を伝えたり、より高い給与を提示して人材獲得競争が過熱します。ここ数年でも起こっていますが冒頭の予測でいくと今後も続くことが予想されます。

そうなるとエンジニアとしては

* 就職、転職の選択肢が広がる
* 全体として平均給与が底上げされる（多職種と相対的に）

と基本的には良い事しか無いです。
一定水準以上のエンジニアという条件はありますが全体としての底上げが起きるはずです。

一方でこのように企業側が競争過多になった際には、エンジニアとしてはミスマッチを防ぐことが大切になってきます。企業側の状況によっては、とにかく人手が足りないため採用人数を確保すること自体が目的になってしまうこともあるかもしれません。そのような際に「自分に合った企業かどうか」を判断するように注意が必要です。

そして、**フリーランスとしての働き方**が増えてくると思います。これも既に起こっていますね。
人材の供給不足を解消するためには、案件ベース、プロジェクトベースで発注をしたい企業が今後より増えてくると予想されます。その中で普通のエンジニアの3倍、5倍のアウトプットが出せるフリーランスエンジニアには仕事が集まり、高い収入が得られるようになります。高いスキルに加えて、高いコミュニケーション能力も求められますがその分高いリターンを望めるキャリアです。

最後に**副業、複業**という選択肢があります。
これはまさに需要過多に対して、企業側にもエンジニア側にも良い概念であると思います。

https://www.freee.co.jp/kb/kb-fukugyou/sidejob_work_style/

この記事にあるように就業規則のガイドラインなども整備されてきており、今後導入する企業も増えてくるでしょう。

うまく活用することで企業にとっては無駄なく必要な能力（リソース）を確保しやすくなりますし、エンジニアにとっては複数の仕事をすることでのスキルアップ、多様な働き方の選択による自己実現などが得られます。
ただし、こちらもフリーランス同様に様々な調整や交渉なども含めてコミュニケーション能力が求められます。

## さいごに

今回の記事では需給のギャップが起こる前提で記載をしました。
全体感として今後起こることを客観的に意識をしながら、それぞれのキャリアを考えるヒントに少しでもなれば幸いです。

一方で今回の話と矛盾しますが、エンジニア人口自体を健全に増やしていくことも大切だなと感じています。そのような取り組みの一旦に自分なりに貢献出来ればと考えています。

## （補足）エンジニアキャリアについて

より具体的なお話はこちらの素晴らしい記事がありますのでぜひ気になる方はご一読ください。

https://qiita.com/hukusuke1007/items/1f3843a9f044a8affeee

https://qiita.com/miyashiiii/items/ec19a1b50308133e528e

https://qiita.com/kotar0/items/4f022889c4f049902367

https://qiita.com/spaces/items/482a91d85d6f9731bfcf
Webサービスのパフォーマンステスト、負荷テストツール紹介

# 概要
Webサービスのパフォーマンステスト（性能テスト）や負荷テスト（ストレステスト、ロードテスト）で大量トランザクションを流して、そのベンチマークをとったりするツールが世の中には多くあります。
最初に思いつくのはabですが、他のツールと比較検討して使いたいですよね。
ここで紹介するツールの詳細な特徴や比較検討はしませんが、他のツールを知るための足がかりとして利用いただければ幸いです。

# ツール一覧

- ab
  - https://httpd.apache.org/docs/2.4/programs/ab.html
  - It is designed to give you an impression of how your current Apache installation performs
  - MacやLinuxに最初から入ってる
  - コマンドラインのオプションで手軽に指定して使える基本中の基本のツール
- Jmeter
  - https://jmeter.apache.org/
  - 100% pure Java application designed to load test functional behavior and measure performance
  - JREが必要
  - GUI、CLI共にあり
  - abよりも非常にリッチなシナリオ実行が可能
- Siege
  - https://www.joedog.org/siege-home/ or https://github.com/JoeDog/siege
  - It was designed to let web developers measure their code under duress, to see how it will stand up to load on the internet.
  - 他より若干見劣り
- wrk, wrk2
  - https://github.com/wg/wrk and https://github.com/giltene/wrk2
  - wrk is a modern HTTP benchmarking tool capable of generating significant load when run on a single multi-core CPU
  - wrk2 is wrk modifed to produce a constant throughput load, and accurate latency details to the high 9s (i.e. can produce accurate 99.9999%'ile when run long enough)
  - Cで書かれたOSSで軽くて速い。Luaによって拡張することが可能。
  - 使い方はabに似てるが、Luaを使って拡張しやすいことが特徴的で、Luaになれたチームなら適しているかも。
- Gatling
  - https://gatling.io/
  - It is designed for ease of use, maintainability and high performance.
  - JDKとScalaが必要、でもIntelliJ IDEAとEclipseからシミュレーション内容を編集可能とのこと
  - シナリオはScalaベースで書く必要があるので、Scala言語で書いたリポジトリに一緒にコミットしておけるのはいいかも
- LOCUST
  - https://locust.io/
  - Locust is an easy to use, scriptable and scalable performance testing tool.
  - Pythonで記述する
- Vegeta
  - https://github.com/tsenart/vegeta
  - Vegeta is a versatile HTTP load testing tool built out of a need to drill HTTP services with a constant request rate.
  - Macでbrew installか、go getでインストール
  - コマンドと豊富なコマンドラインオプションで、コンスタントなリクエストを送信するのに向いてそう。Goプログラムに組み込み可能。
- k6
  - https://k6.io/
  - k6 is a developer-centric, free and open-source load testing tool built for making performance testing a productive and enjoyable experience.
  - JavaScriptでテストスクリプトが書ける
  - abやJmeterのような古き良きロードテストツールとは違い、SREの活動の中で使われるようなツールとして開発されているのが特徴
- Artillery
  - https://artillery.io/
  - Artillery is a modern load testing and smoke testing solution designed for cross-functional teams that run microservice-based systems on AWS and rely on CI/CD to ship at high velocity
  - 主にAPIサーバなどのバックエンドサービス向けのツールで、フロントエンドサービス向けではないのが特徴的
  - k6同様、DevOpsやSRE文脈で利用されることを目指すツールです
  - 設定とシナリオだけの単純な構成でYAMLで記述できる
- WBench
  - https://github.com/desktoppr/wbench
  - WBench is a tool that uses the HTML5 performance timing API to benchmark end user load times for websites. It simulates users visiting your website for the first time, with nothing of your site cached.
  - Ruby gemとして導入する
  - 実際にGoogle Chromeを使うなどして、例えばDOMContentLoadedイベントまでの時間など、主にターンアラウンドタイム測定に適したツール。軽い検証ならば、Google ChromeのNetworkタブ等で済むかもしれないが、、、
- 自作
  - HTTPリクエスト送信自体は取り扱いが容易なので、自作されるケースも有るかと思います。ただ、その際はツールが動くクライアント側がボトルネックになる可能性があるので要注意です。
  - スケールフリーで自作するには、AWS LambdaやGCP Cloud Functionを使ってシステムをつくってしまうパターンもあるかも知れません
PHP データベースに接続


#　Mac MAMP データベースに接続
```
PDO = PHP Data Object
try = エラーの場合に動作し内容の確認ができる
----------------------------------------------------------------------
例　　
<?php
  try {
    $db = new PDO('mysql:dbname=データベース名;host=localhost;port=8889;charset=utf8','root','root');
  } catch(PDOException $e){
    echo 'DB接続エラー：'.$e->getMessage();
  }
?>

```

#エラーの内容を確認を行うには
```
下記を記述することでエラーの中身を確認可能！！！

var_dump(＄要素->errorInfo());
exit();
```
LaTeXのtabularでcolsを列数で指定する

無限に忘れるので書いておきます

```latex
\begin{tabular}{cccccccccc}
あ & い & う & え & お & か & き & く & け & こ
\end{tabular}
```

上記のソースだとパット見て列数がわからないです．

# 結論
```latex
\begin{tabular}{*{10}{c}}
あ & い & う & え & お & か & き & く & け & こ
\end{tabular}
```

列を線で区切ることもできます．

```latex
\begin{tabular}{|*{10}{c|}}
あ & い & う & え & お & か & き & く & け & こ
\end{tabular}
```
バリデーションの種類について Rails

多分よく使うであろうバリデーション

```ruby
#入力必須
presence: true

#一意性（被ったらエラー）
uniqueness: true

#最小文字数
length: { minimum: n }

#最大文字数
length: { maximum: n }

#パスワードは英数字を含める
PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i.freeze
validates_format_of :password

#email @を含める
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
format: { with: VALID_EMAIL_REGEX }

#全角カタカナ
format: { with: /\A[ァ-ヶー－]+\z/, message: '全角カタカナで入力して下さい' }

#全角カタカナ、ひらがな、漢字
format: { with: /\A[ぁ-んァ-ン一-龥々]+\z/, message: '全角ひらがな、全角カタカナ、漢字で入力して下さい' }
```

参考文献
https://qiita.com/h1kita/items/772b81a1cc066e67930e
https://qiita.com/necojackarc/items/cad2d4eb80f0629ad196

Railsガイドもわかりやすいです。
https://railsguides.jp/active_record_validations.html
メソッドの命名について考えてみた(Swift)

## はじめに

Twitterで気になったツイートを引用RTしたら、リプでいろいろ意見を頂きました。

https://twitter.com/the_uhooi/status/1402784145944711172?s=20

非常に興味深かったので、まとめてみることにします。

## updateAge(_ age: Int) vs update(age: Int)

`updateAge(_ age: Int)` と `update(age: Int)` メソッド、どちらの名前のほうがいいと思いますか？
少しだけ考えてみてください。

正解は…

.
.
.
.
.
.
.
.
.
.

__メソッドの処理によって異なる__ だと思います。

### updateAge(_ age: Int)

`updateAge(_ age: Int)` というメソッドを見て、どのような処理を想像するでしょうか？

私は「 __年齢のプロパティを更新する__ 」ことを想像しました。

コードに落とし込むとこんな感じです。

```swift:FooCollectionViewCell.swift
final class FooCollectionViewCell: UICollectionViewCell {
    private var age: Int = 0

    func updateAge(_ age: Int) {
        self.age = age
    }
}
```

呼び出しはこのようになります。

```swift
cell.updateAge(31) // `cell.age` が `31` に更新される
```

同じ処理を想像した人が多いと思っています。

余談ですがSwiftは引数にラベルを付けることができるので、 `updateAge(_ age: Int)` より `updateAge(to age: Int)` のほうが英語で意味が読み下せて、より処理を想像しやすくなります。

```swift
cell.updateAge(to: 31) // 「update age to 31」で意味が通る
```

ただ今回のようにプロパティにセットするだけなら `setAge(_ age: Int)` が最も処理を想像しやすいと思います。

```swift
cell.setAge(31) // ほとんどの人が `age` というプロパティに値をセットするとわかると思う
```

### update(age: Int)

続いて `update(age: Int)` です。

`updateAge(to age: Int)` よりも短く、意味も同じように捉えられそうですが、どうでしょうか。

実はよく考えると意味が異なることに気づきます。

先に呼び出し側のコードから見てみましょう。

```swift
cell.update(age: 31)
```

`age` はセルを更新するために使う要素のひとつに過ぎず「 __年齢を使ってセルを更新する__ 」ことが想像できると思います。

コードに落とし込むとこんな感じです。

```swift:FooCollectionViewCell.swift
final class FooCollectionViewCell: UICollectionViewCell {
    @IBOutlet private weak var birthYearLabel: UILabel!

    func update(age: Int) {
        birthYearLabel.text = convertAgetoBirthYearString(31)
    }

    private func convertAgetoBirthYearString(_ age: Int) -> String {
        // ...
    }
}
```

あくまで例ですが、 `age` というプロパティを持たず、年齢から生まれた年を算出してラベルに表示する、というような処理が想像できます。

余談ですが、私はセルを初期化するメソッドは `setup()` という名前にしています。

```swift
cell.setup(age: 31)
```

参考: https://github.com/uhooi/UhooiPicBook/blob/v1.4.0/UhooiPicBook/Modules/MonsterList/Views/MonsterCollectionViewCell.swift#L38

どこかで見たのをマネしたと思うのですが、どこで見たかは覚えていません。

## おわりに

他にも「 `updateAge(_ age: Int)` はObjective-C感がある」「API Design Guidelinesに従っていればこだわらない」などの意見がありました。

他にも意見があればコメントなどで教えていただけると嬉しいです :relaxed: 

## 参考リンク

- https://twitter.com/___freddi___/status/1402784455899578372?s=20
- https://twitter.com/terrypy6/status/1402834977771855872?s=20
- https://twitter.com/macneko_ayu/status/1402800940084711430?s=20https://twitter.com/_take_hito_/status/1402810071835238402?s=20
- [Swift.org - API Design Guidelines](https://swift.org/documentation/api-design-guidelines/)
how to stop groutine with channel

# overview
バックグラウンド等で動かすgoroutineを使ったforループプログラムで、シグナルを受け取った際に終了させる処理例

# example1
ここではシグナルの代わりに適当なチャンネルを使う。

```
package main

import (
	"fmt"
	"time"
)

func main() {
	c := make(chan string, 1)
	sig := make(chan string, 1)
	go func(){
		for{
			fmt.Println("Hello")
			
			select{
			case s := <-c:
				fmt.Println(s)
				sig<-"FINISH"
				return
			default:
			}
			time.Sleep(1 * time.Second) //
		}
	}()
	
	time.Sleep(10 * time.Second)
	c<-"done"
	s:= <-sig
	fmt.Println(s)
}
```

# example2
実際にシグナルを使った例

```
package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func Loop(c chan os.Signal, done chan int) {
	go func() {
		for {
			fmt.Println("do something....")
			select {
			case s := <-c:
				fmt.Println("Got signal:", s)
				close(c)
				done <- 0
				return
			default:
			}
			time.Sleep(1 * time.Second)
		}
	}()
}
func main() {
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT)

	done := make(chan int)
	defer close(done)

	Loop(sig, done)

	<-done
	fmt.Println("Exit")
	os.Exit(0)
}
```

## 実行結果
- `main`ではdoneチャンネル受信待ちにする。
- シグナルを送るとチャンネルに送信される。
- 所定の処理が終わったあとにチャネルを受信する。シグナルが来ていなければ処理を継続。シグナルが来ている場合は`done`チャンネルに送信する、mainで`done`チャンネルを受信し処理を終了する。

```
$ go run signal.go
do something....
do something....
do something....
do something....
do something....
do something....
do something....
do something....
do something....
do something....
do something....
^Cdo something....
Got signal: interrupt
Exit
```
Object.values() が便利だから(？) Javascript では配列よりハッシュを積極的に使おう

まぁ表題のままなので、あまり書くような事もないんですが。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/values

つまり

```javascript
const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.values(object1));
// expected output: Array ["somestring", 42, false]
```

こういう事なんですが、具体的にどういう場面で使えるのか、というところについて書きたいと思います。

----

6/12追記 : コメントで「この例ならMAPの方がいい」という指摘をいただきました。
MAPはキーに `Object` も使えるし `forEach` も `values` も実装されているので、MAPの方がよさそうです。
なのでまぁ、 `Object.values()` はそれはそれで便利だよという感じで見ていただければと思います。

----

## 配列管理

```javascript
const user = {
  id: 123456,
  name: 'Alice',
  mail: 'alice@example.com'
}
```
こういうデータがあったとして

* `id` はいわゆる主キーとして機能する
* `id` は規則的ではない
* `id` 以外の情報は書き換えが存在する

このデータを沢山管理する必要があった時に素朴に思いつくのは配列だと思います。

```javascript
const users = [
  {
    id: 123456,
    name: 'Alice',
    mail: 'alice@example.com'
  },
  {
    id: 573940,
    name: 'Bob',
    mail: 'bobie@example.com'
  },
  ....
]
```

こうすると「 `id: 999` のデータを探したい」ってなった時にこうなると思います

```javascript
const userThreeNine = users.find(u => u.id === 999)
```

情報を更新したいってなったらこうなりますね。実際はもっと多くのプロパティ持ってるでしょうし、ロジック分けるのもめんどうなので「情報を全部貰ってリプレイスする」方がいいと思うので、こうなる事の方が多いと思います。

```javascript
Object.assign(users.find(u => u.id === 999), newData)
```

一番面倒なのはこの配列からデータを削除したい場合です。多分こうなると思います。

```javascript
users.splice(users.findIndex(u => u.id === 999), 1)
```

配列使ってるんだからこうだよね、という感じのごくごくあたりまえのコードに見えますが、パッと見でこのコードを理解できますか？

あとは、たとえば大量のデータを処理しようとした時にかかるオーダーは全体数を $n$、更新数を $m$ とした場合に $ O(n,m) = log(n)*m $ です。 別に目を顰めるオーダーではないですが、減らせるんなら減らしたいですよね。

## ハッシュ管理

なので、こうしてしまいましょう。

```javascript
const userThreeNine = {
  id: 999,
  name: 'Three Nine',
  mail: 'three.nine@example.com'
} 
users[hogeUser.id] = hogeUser
```

検索も存在確認も削除も以下の通りです。

```javascript
const id = 999
const userThreeNine = users[id] // 検索

const hogeUserNewData = {...}
users[hogeUserNewData.id] = hogeUserNewData // 更新

const deleteUserId = 666
delete users[deleteUserId] // 削除
```

コードも直感的になったし、勿論検索コストは $ O(n, m) = m $ です。
これで万事解決！といいたいところですが……

### 配列だからこそできたこと

* 各要素でのソート
* 主キー以外での検索/フィルタリング

とかとか、「配列でできた事ができなくなったじゃないか！」と思っているでしょう。
素朴に書くなら、例えば検索なら `for...in` を使えばできそうです。

```javascript
const hasHogeIsHuga (user) {
  return user.hoge === 'huga'
}
const findSomtehing (users, hasHogeIsHuga) {
  const result = []
  for(const p in users){
    if( hasHogeIsHuga(users[p]) ){
      result.push(users[p])
    }
  }
  return result
}
```

:thinking: :thinking: :thinking: :thinking: :thinking: 
なんじゃこれ。ってなりますね。

### そこで `Object.values()`

一番最初に書いたように、この関数はオブジェクトを配列の形に開いてくれます。
なので例えば

```javascript
// フィルタリング
const hasHogeHugaUsers = Object.values(users).filter(hasHogeIsHuga)

// ソート
const usersSortedByPoint = Object.values(users).sort((a,b) => a.point - b.point)
```

のように書けるわけです。便利！

## という訳で

* ハッシュ管理は見やすいよ
* `Object.values()` は便利だよ

という話でした。
見やすいコードに貢献してくれると思います。
Amazon CloudWatch Logsの使い方について簡単にまとめてみた

#ログの調査の流れ
よく業務でCloudWatchでログ調査することがあって、効率的にログが出せるように使い方を調べたのでまとめてみました。
こんな感じで調査しています。

エラー発覚。発生時間や現象等を教えてもらう。
↓
エラーが発生したと思われるサービスのロググループを開く。
↓
ログイベントの中から、時間、and検索、除外検索でエラーログを特定していく。
↓
エラーログを発見。前後のログ見たり、共有したり。

その方法を以下にまとめてみたので、興味のある方は読んでみてください。

#ロググループの検索
まず該当のロググループを検索したいのだが、そのフィルタールールが使いにくいので挙動をまとめました。
具体例で示すと、

```
検索ワード: abc

abc.def  ○
ab.c  ○
a.b.c  ○
cba ×
cba.bc ○
```

このようにロググループの検索は、
「１文字ずつのor検索に加えて、文字の順番(？)が考慮されてるフィルター」のようです。

###完全一致にチェックを入れた場合
完全一致にチェックを入れる項目がありあますが、検索ワードをひとかたまりとして検索をかけれるようです。(googleの""を使った完全一致検索と同じ)

```
完全一致にチェックを入れた場合
検索ワード: abc

abc.def  ○
ab.c  ×
a.b.c  ×
cba.bc ×
```

※スペースは検索対象文字として扱われるので、and検索とかはできない

#ログイベントの検索
ロググループを選択したらログストリームで該当のものを選択。
該当のものがわからないときは「Search all」を選択した方が早い。

ログの検索については[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html)に全てが載っている。
簡単にまとめるとこうなる。

* スペース区切りでand検索
* 「?」を前につけるとor検索
* 「-」を前につけると除外
* 「_」以外の記号を使う場合は「""(ダブルクォーテーション)」で囲う
* 「[]」「{}」はスペース区切りフィルター、JSONフィルターという検索方法があるらしく検索ワードに含めない方が良い。使い方は[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html)を参照してください。

例

```
and検索:    abc def
or検索:     ?abc ?def
除外:       -abc
記号を含む:  "/abc/def"
```

#ログストリームの表示
エラーの原因のログを見つけたら、前後の処理を見たかったり、共有したいことありますよね。
そういうときは「ログストリーム名」を表示させておきます。

該当のログを探して、そのログストリーム名のリンクを開きます。
そうすると、該当のログを基準にフィルターがかかってない状態で前後を見ることができます。
また、そのリンクを共有することでログの共有が簡単にできます。

#まとめ
最初は検索の仕方に癖があるなと思って使いづらいと思っていたが、規則を理解したら効率良く調査できるようになった。
コンソールを完全に使いこなせているとは思えないので、もっと便利な機能があれば使ってみたい。
インサイトも便利なのでまとめようと思う。
rake db:create で ActiveRecord::NoDatabaseError

Rails 環境の構築中に、`rake db:create` で以下のエラーが発生。

```
ActiveRecord::NoDatabaseError: could not connect to server: No such file or directory
	Is the server running locally and accepting
	connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
```

ググると `.pid` ファイル消すといいとかって記事が色々ヒットするけど、全然なおらない。

2h くらい引っかかっていた時、さっきまで動いてた別のブランチで、同じ手順で構築し直して `rake db:create` するとなぜか動く。

作業していたファイルの差分を見ると・・・、

```diff
 default: &default
   adapter: postgresql
   encoding: unicode
-  host: db
-  username: postgres
-  password: password
-  pool: 5
```

そりゃ動かないよね。凡ミス。

おしまい。
【ブログ運営】SEO時代の終焉は先のお話

![reference-image-of-the-number-of-readers-who-are-visiting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1629151/ef3123ab-cc09-b530-b4e9-77589703bf20.png)
タイトルが大げさかもしれませんが、昔も今もSEO主体によるブログ運営で流入を増やしていく根本的なところはあまり変わっていません。

そしてそれは、今のところはこれからもです。（たぶん。）

##2020年も2021年も、新規に開設したサイトは成長を続けています。

僕が運営しているブログサイトの1つ、2020年01月に開設した<a href="https://unicorn-blog.jp" target="_blank" rel="noopener">ユニコブログ&reg;</a>は、変動は大きめですが、20万PV〜40万PVくらいまでサイトを成長させる事ができています。

![reference-image-of-the-number-of-readers-who-are-visiting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1629151/126af14c-20ed-6b22-dde3-a185fd8da563.png)

<a href="https://www.similarweb.com/ja/" target="_blank" rel="noopener">Similarweb</a>で、ユニコブログ&reg;の直近6ヶ月間くらいのアクセスが確認できるのでそこでもアクセス数の推移を見ることができます。
（<a href="https://www.similarweb.com/ja/" target="_blank" rel="noopener">Similarweb</a>は、<b>無料</b>で他のサイトが実際どれくらいのアクセスなのか見ることができるので便利です。）

##多くのSEOアフィリエイトサイトを構築して検証中

そして現在、ユニコブログ&reg;以外に、SEOアフィリエイト主体の15サイトを越えるテーマ特化型ブログを運営しています。

色んなレンタルサーバーやWordPressテーマを使いつつ、サイト構成や記事数、文字量などはなるべく一緒にして、どんな風に成長していくかずっと検証を続けています。

■テーマ特化型によるSEOアフィリエイトの構成

1. 記事総数は約50記事
1. 標準記事は文字量が2,000文字〜3,000文字
1. サイト内のまとめ記事は5,000文字くらいで標準記事と内部リンクで繋げておく

やっているのはこれくらいです。

ちなみに、上記の条件で作成したブログサイトは、6ヵ月〜9ヵ月で収益が5~10万/月になってきました。

##少しずつでも積み上げていくことで大きな収入に繋がるきっかけになります

上記条件の特化ブログを作るには、ゆっくりでも下記の感じで作って行くことが可能なので、何とか時間を作ってやっておいたほうが良いと思います。


■テーマ特化型によるSEOアフィリエイトサイト構成の総文字数
└大体150,000文字（1サイト）

1日400文字を書く × 365日 = 150,000文字

ちょっと極端な結論になりますが、<b>１日400文字</b>書いていけば<b>１年</b>で月5~10万/月になる特化ブログサイトを構築できることになります。

SEOも重要なのですが、それは書いていきながら学びつつ、<a href="https://unicorn-blog.jp/archives/15741" target="_blank" rel="noopener">リライト</a>をして記事タイトルや文章の見出し構成などを見直していけば大丈夫です。

##SNSなどの拡散で疲れる必要なし
ブログサポートをしていると、SNSの同時進行についてもよく聞かれますが、正直、SEOアフィリエイトサイトであれば、あまり気にする必要ありません。

実際、僕の場合なんかツイートすればするほどフォロワーが減るような感じですが、ブログサイトは検索流入で成長しています。

なので、同時にやってみて「SNSは疲れるな...」みたいな感じだったら、無理に一緒にやる必要はないです。

といいつつ、自己紹介忘れていました。申し訳ありません。
僕の実績は<a href="https://unicorn-blog.jp/profile" target="_blank" rel="noopener">プロフィールページ</a>で公開しています。

書きながら考えるタイプなので、紹介が遅れましたこと大変恐縮です。

##これからも変わらないSEOとは？
実際には色々細かい部分で色々あるのですが、初心者向けにも超シンプルにすると

1. 読者が読みやすいこと
1. リライトをしていくこと
1. 被リンクを増やすこと（自然と）
1. 不必要なインデックスページを作らないこと
1. 検索エンジンが読みやすいコードにすること（シンプルに正確に）

に帰結していくと思います。

昨今は、コアウェブバイタルの改善も必要ですが、、、。
ちょっと緩めになっていっているし。

また、「良質なコンテンツ」、「長文SEOはまだまだ健在」など、いろいろな事がありますが、これについても突き詰めていくと

<b>検索意図にたいするトピックを徹底的にカバーしているページか？</b>

に集約されていきます。

したがって、<b>ページタイトル「H1」</b>の検索意図に当たる範囲に気をつけながら新規記事を書いていけば良いと考えます。

なので、長文書けなくても大丈夫です。

それではまた^ ^


■ブログを始めるなら？
<a href="https://unicorn-blog.jp/archives/5516/" target="_blank" rel="noopener">● レンタルサーバー徹底比較！WordPressおすすめサーバー10選</a>

<a href="https://unicorn-blog.jp/archives/15616" target="_blank" rel="noopener">● 初心者向けに最適化されたレンタルサーバーでブログ運営を始める方法</a>

<a href="https://unicorn-blog.jp/archives/14903" target="_blank" rel="noopener">● レンタルサーバーとWordPressのテーマ選びに困ったらConoHa WINGとTHE SONIC</a>
MySQL The server quit without updating PID file 

# 内容
MySQLを立ち上げようと思ったら以下に遭遇

```
$ mysql.server start --skip-grant-tables
Starting MySQL
.. ERROR! The server quit without updating PID file (/opt/homebrew/var/mysql/*****.local.pid).
```

# 対処法
/opt/homebrew/var/mysql/*****.local.pidを追加する方法
grepで検索して動いているプロセスをkillする方法

上記では上手く行かず、
幸い、MySQLにデータをとくに入れていなかったため、
`/opt/homebrew/var/mysql`のフォルダを削除し再インストールを実行すると問題解決

```
$ mysql.server start --skip-grant-tables
Starting MySQL
. SUCCESS! 

$ mysql -uroot
Welcome to the MySQL monitor.  Commands end with ; or \g.
```
Lightning Knowledge の設定とカスタマイズ ⇒ 記事を使用したケースのクローズ

１．サポートスペシャリストのケースページにナレッジコンポーネントが表示されない場合、Maria は何ができますか?
２．メールに記事を挿入するときに、不要な情報を削除する (そして顧客満足度を高める) 一番手っ取り早い方法は何ですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/9e395bf9-a819-b05f-76b1-dfbb6dbccfcd.png)
VanillaなCentOS7への AWS Session Manager (SSM) 関連インストール

事前準備: CentOS7.x
======================================

パッケージのアップデート
--------------------------------------------------

```bash:command
yum update -y
```

Session Managerのインストール
======================================


インストール
--------------------------------------------------

```bash:command
REGION="ap-northeast-1"
sudo yum install -y https://s3.${REGION}.amazonaws.com/amazon-ssm-${REGION}/latest/linux_amd64/amazon-ssm-agent.rpm
```


systemdによるssmのデーモンの有効化/再起動/確認
--------------------------------------------------

systemdによるssmのデーモンの有効化/再起動/確認
3行目のレスポンスとして、`Active (running)` になっていることを確認する。

```bash:command
sudo systemctl enable amazon-ssm-agent
sudo systemctl restart amazon-ssm-agent
sudo systemctl status amazon-ssm-agent
```

Session Manager によるインスタンス接続確認
--------------------------------------------------

対象となるインスタンスの`インスタンスに接続`画面右下の接続ボタンがクリック可能なことを確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73207/cacb9aa0-da83-53d9-f185-b1d2f2315ffc.png)

クリック後、ブラウザにターミナルが開くことを確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73207/acdf2999-34df-7d43-bc2c-e37314300778.png)


AWS CLI 用の Session Manager plugin のインストール (接続元、必要に応じて)
============================================================================

下記はLINUXの場合です。

AWS CLIのインストール
--------------------------------------------------

```bash:command
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
```

pluginのインストール
--------------------------------------------------

```bash:command
curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/linux_64bit/session-manager-plugin.rpm" -o "session-manager-plugin.rpm"
sudo yum install -y session-manager-plugin.rpm
```

インストールの確認
--------------------------------------------------

以下のコマンドを実行

```bash:command
session-manager-plugin
```

以下のようなメッセージが得られていればインストール成功

```text:response
The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.
```
SwiftUI: 簡単にフォント名を指定する方法！

#SwiftUIのフォント

SwiftUIにおいて文字のフォントを指定したいときは、以下のようにフォント名を文字列として入力します。

```swift:SampleText.swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello,World!")
            .font(.custom("AcademyEngravedLetPlain", size: 100))
    }
}
```

ただ、毎回コピペしたり正しい名前になっているか確認するのは面倒ですし、名前を間違えてしまう可能性もあります。
また、デザインに合うフォントを色々試してみたいときにも切り替えが早い方が効率的です。


#改善策

以下のような`extension`を用いると比較的ラクにフォント名の指定ができるようになります。例のように「タイトル用」などとコメントを残しておくと後で使うときに迷わずに済みます。

```swift:FontExtension.swift
extension Font {
    
    enum Keys: String {
        case AcademyEngravedLetPlain
        case AlNile

        ///タイトル用
        case Damascus
    }
    
    static func namedFont(_ name: Keys, size: CGFloat) -> Font {
        return Font.custom(name.rawValue, size: size)
    }
}

```

###使用例
```swift:SampleText.swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello,World!")
            .font(.namedFont(.AcademyEngravedLetPlain, size: 100))
    }
}
```
コードの見た目や長さはほとんど同じですが、Xcodeならコード補完で正確にフォント名を指定できるようになります。

#余談

同様の意図で実装の仕方を調べるとカスタムModifierを用いたものが紹介されていることが多いです。
そちらでも問題はないのですが、今回紹介した`extension`を用いる方法だとフォントに対して変更を加えたことが明示的になるので、多人数開発のときには少しだけ便利かな...と思います。
Cloud9がバーストして開けなくなった時の対処法

~/.ssh以下のファイルを書き換えてしまった為に、Cloud9がバーストしてアクセスできなくなってしまった。
エラー文は下記の通り。

```
This is taking longer than expected. The delay may be caused by high CPU usage in your environment, or your T2 or T3 instance is running out of burstable CPU capacity credits, or there are VPC configuration issues. Please check documentation.
これには予想以上に時間がかかっています。遅延の原因としては、環境内の CPU 使用率が高いか、T2 または T3 インスタンスでバースト可能な CPU 容量クレジットが不足しているか、VPC 構成に問題があることが考えられます。ドキュメントを確認してください。

```

何時間待っても
インスタンスタイプを変更しても、開くことは出来なかった。
その時の解決方法を備忘録として残しておく。
（結論から言うと、そのCloud9はもう二度とアクセス出来ない）

参考にした記事など
[https://qiita.com/ataru_mix/items/757dadc453a8d399b470](https://qiita.com/ataru_mix/items/757dadc453a8d399b470)

解決手順

1. AMIイメージの作成
2. 作成したAMIからEC2インスタンスを作成（この時にキーペアを新規か既存かを選ぶ）
3. Cloud9作成時にssh接続で作成を選択する
4. ２で作成した作成したキーペアを元にEC2にgitbashなどでSSH接続し、.ssh以下にあるauthorized_keyの中身に今回出てきたキーペアを追記する

参考↓
[https://qiita.com/rockhopper-penguin/items/d5042b71230eb94955d0](https://qiita.com/rockhopper-penguin/items/d5042b71230eb94955d0)

要は開発の中身のデータが消えてしまったら困るので、どうしてもCloud9を復活させたかったわけ。
metabase + mysqlでRSA public key is not available client side

version v0.39.3

metabaseでmysqlを使おうとすると以下のエラーが出る場合がある。

```java
java.sql.SQLException: Could not connect to address=(host=metabase-db)(port=3306)(type=master) : RSA public key is not available client side (option serverRsaPublicKeyFile not set)
	at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:262)
	at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1241)
```

原因と解決策は以下のとおり。

https://github.com/metabase/metabase/issues/12545

上記にあるとおり環境に応じてjdbc-urlを修正する。ローカル環境などとりあえず接続出来れば良いだけなら「追加のJDBC接続文字列オプション」に```allowPublicKeyRetrieval=true```を追加すればよい。
deviseを使用した時のログインページのビューについてRails

## 注意点1 form withの中身

```ruby
<%= form_with model: @user, url: user_session_path,class: 'registration-main', local: true do |f| %>

#省略

<% end %>
```

まずmodel名を記述する。
今回は@userというインスタンス変数を使用しています。
更にurlにrails routeで確認したsession pathを記述します。

要はモデル名とpathがないと、仮にログインボタンを押しても、どのモデルを参照にするのか、その際のルーティングは？というところが不明なので、ログインできません。

## 注意点2 各入力欄の中身

```ruby
<%= f.email_field :email, class:"input-default", id:"email", placeholder:"PC・携帯どちらでも可", autofocus: true %>
```

例えば、これはemailの欄ですが、fieldの記述の後に、カラム名を記述します。
それを元にUsersテーブルのカラム名と合致するかどうか、参照します。
placeholderは入力前に表示される文字列です。
metabaseのデータ保存先をh2からmysqlに変更

version v0.39.3

公式の https://www.metabase.com/docs/latest/operations-guide/running-metabase-on-docker.html#using-postgres-as-the-metabase-application-database や https://www.metabase.com/docs/latest/operations-guide/configuring-application-database.html#mysql-or-mariadb に書いてあるとおり環境変数で制御する。

例えばjdbc-urlで指定する場合は以下のとおり。

```
MB_DB_CONNECTION_URI: mysql://db:3306/metabase?user=dbuser&password=userpass&allowPublicKeyRetrieval=true
```

接続先のmysqlにmetabase用のdatabaseが必要。以下のSQLは[公式ガイド](https://www.metabase.com/docs/latest/operations-guide/configuring-application-database.html#mysql-or-mariadb)からコピペしたもの。

```sql
CREATE DATABASE metabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

mysqlも一緒に起動するとしてそこに接続する場合のdocker-compose.ymlの例は下記の通り。

```yaml:docker-compose.yml
version: "3.7"

services:
  db:
    image: mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_USER: dbuser
      MYSQL_PASSWORD: userpass
      MYSQL_DATABASE: metabase
    networks:
      - metabase-net

  metabase:
    image: metabase/metabase:latest
    ports:
      - "3000:3000"
    volumes:
      - ./plugins:/plugins
    environment:
      MB_DB_TYPE: mysql
      MB_DB_CONNECTION_URI: mysql://db:3306/metabase?user=dbuser&password=userpass&allowPublicKeyRetrieval=true
    networks:
      - metabase-net

networks:
  metabase-net:

```
activeadminの基礎的なコードを理解したい

#はじめに
activeadminを使った際に、基礎的なコードだが何をしているものかわからなかったので、分からなかった箇所をまとめてみた。

分からなかった下記のコード

```app/admin/texts.rb
ActiveAdmin.register Text do
  permit_params :genre, :title, :content

  index do
    selectable_column
    id_column
    column :genre, :text, &:genre_i18n
    column :created_at
    column :updated_at
    actions
  end

  show do
    attributes_table do
      row :id
      row :genre, :text, &:genre_i18n
      row :content
      row :created_at
      row :updated_at
    end
    active_admin_comments
  end

  form do |f|
    f.semantic_errors
    f.inputs do
      input :genre, as: :select, collection: Text.genres_i18n.invert
      input :title
      input :content
    end
    f.actions
  end

  filter :genre, as: :select, collection: Text.genres_i18n.invert.transform_values { |v| Text.genres[v] }
  filter :title
  filter :content
  filter :created_at
  filter :updated_at
end

```

#ActiveAdmin.register

```rb
ActiveAdmin.register Text do
#処理
end
```
app/admin/配下に、管理画面を追加するコマンドで自動生成されるファイルに標準で記述されている構文。この中に処理を記述していく。


# permit_params
```.rb
  permit_params :genre, :title, :content

```
`permit_params`はデータモデルの有効なパラメータの設定。明示したフィールドのアクセスを許可する。

# filter
```.rb
  filter :genre, as: :select, collection: Text.genres_i18n.invert.transform_values { |v| Text.genres[v] }
  filter :title
  filter :content
  filter :created_at
  filter :updated_at
```
`filter`は管理者画面の右側（検索ボックス）のカスタマイズを指定する。
`as:`は指定した形式にオーバーライドする。
`collection:`は渡すデータを指定する。

#index
```rb
index do
    selectable_column
    id_column
    column :genre, :text, &:genre_i18n
    column :created_at
    column :updated_at
    actions
end

```
アクションに対応した処理を記述。
`selectable_column`はチェックボックスの配置を指定。
`id_column`はそのまま表示するコンテンツ。
`column`はモデルのフィールドに対応したコンテンツを表示。
`actions`は`permit_params`の値に応じて閲覧編集削除のリンクを表示。

ちなみに対応するカラムのenumはこちら

```enums.ja.yml
ja:
  genre: &genre
    invisible: '非表示'
    basic: 'Basic'
    git: 'Git'
    ruby: 'Ruby'
    rails: 'Ruby on Rails'
    php: 'PHP'

  enums:
    text:
      genre: *genre
    movie:
      genre: *genre
```

#show
```.rb
  show do
    attributes_table do
      row :id
      row :genre, :text, &:genre_i18n
      row :content
      row :created_at
      row :updated_at
    end
    active_admin_comments
  end
```
`attributes_table`はデフォルトの外観を維持する。
`row`はモデルのフィールドに対応したコンテンツの表示。
`active_admin_comments`はコメントフォームの表示。

# from
```
  form do |f|
    f.semantic_errors
    f.inputs do
      input :genre, as: :select, collection: Text.genres_i18n.invert
      input :title
      input :content
    end
    f.actions
  end
```
`form`はフォームのカスタマイズを指定。
`f.semantic_errors`はエラーメッセージの表示。　　
`f.inputs`は入力フィールドを表示。
`f.input`はモデルのフィールドに対応した入力フィールドを表示。
`f.actions`はsubmit/cancelボタンの表示。

# 最後に
`rails g active_admin:resource モデル名`を実行した際に作成されるリソースをベースに、上記のコードでカスタマイズするという内容だった。

# 参考元
[Active/Admin公式ドキュメント](https://activeadmin.info/index.html)
GCSのファイルを、BigQueryへ前日分を自動的に取込

#SQLの機能を利用して定期取込み自動化

##1 特に下記新機能を使ってみたい
<dd>1. CREATE OR REPLACE EXTERNAL TABLE　（外部ストレージの読み取りと書き込み）</dd>
<dd>2. EXECUTE IMMEDIATE　（スクリプティングと SQL の改善）</dd>
<dd>↓半年前っぽいが最近気づいた、他にも参考になりました</dd>
https://cloud.google.com/blog/ja/products/bigquery/smile-new-user-friendly-sql-capabilities-bigquery
##2 やりたい事
<dd>毎日スケジュールでGCSのtable_yyyymmdd.csvを、BQに取込みtable_yyyymmddテーブルを作成したい</dd>
##3 利用データ
<dd>GCS：table_20200609.csv  日付はyyyymmdd形式　/ 前日日付で、毎日作成される</dd>
<dd> テーブル構成</dd>

|列名|型|
|:-----------|------------:|
|TABLE_SCHEMA |STRING|
|TABLE_NAME |STRING|
|TABLE_ROWS |INT64|
|TABLE_COMMENT |STRING|
###4 実行SQL
```sql:transfer.sql
/*1 日付変数を定義*/
DECLARE yyyymmdd INT64 DEFAULT 20210601;
SET yyyymmdd = (SELECT CAST(FORMAT_DATE("%G%m%d",CURRENT_DATE() -1) as INT64)) ;
/*2 GCSとの外部接続テーブル作成*/
EXECUTE IMMEDIATE format("""
    CREATE OR REPLACE EXTERNAL TABLE <外部接続テーブル名>(TABLE_SCHEMA STRING,TABLE_NAME STRING,TABLE_ROWS INT64,TABLE_COMMENT STRING) 
    OPTIONS 
        (uris=["gs://<パケット名>/<フォルダ名>/table_%d.csv"], skip_leading_rows=1,format=CSV)
""", yyyymmdd);
/*3 外部接続テーブルから、実テーブル作成*/
EXECUTE IMMEDIATE format("""
    CREATE OR REPLACE TABLE `<project名>`.test.table_%d
    as (select * from ＜外部接続テーブル名＞)
""", yyyymmdd);
```
<dd>1.SETで前日日付をセット</dd>
<dd>2.EXECUTE IMMEDIATE でtable_yyyymmdd.csvとの外部接続テーブル（EXTERNAL TABLE）を作成</dd>
<dd>　(列名はskip_leading_rowsで指定)</dd>
<dd>3.EXECUTE IMMEDIATE でtable_yyyymmddを作成</dd>
###5 スケジュールに登録し、実行![rapture_20210610154042.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483729/88acb522-2547-2db1-57d2-7d43e279ece2.jpeg)
<dd>テーブルも出来ているようです。</dd>
###6 まとめ
<dd>１日１回取込みぐらいだとSQL機能のみで簡単便利かと</dd>
アコーディオンの開くアニメーションをCSSで表現する


久しぶりにフロントエンド周りです。
ボタンを押すとアコーディオンが開く、というよくある実装をCSSアニメーションを用いて実装します。

## これが結末

```sass
.foo
  max-height: 0
  padding: 0 20px
  transition: max-height 0.3s, padding 0.3s 
  overflow: hidden
  &.is-open
    max-height: 100vh 
    padding: 20px
```


## つまずきやいポイント1: heightとtransition
最初に思いつきそうなのが、heightの高さを可変にして、`transition`を使おう、というものだと思います。

```sass
.foo
  height: 0
  transition: height 0.2s
  &.is-open
    height: auto
```

![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/5ebee42c-9435-2115-b128-ac24a8724181.gif)

全くうまくいっていないのがわかるかと思います。
これは、*transitionがheightをサポートしていないからです。*

ではどうすれば良いかと言いますと、いくつかの方法がありますが今回は`max-height`を使用する方向で実装します。
`max-height`であればtransitionが効きます。

```sass
.foo
  max-height: 0
  transition: max-height 0.2s
  overflow: hidden;
  &.is-open
    max-height:100vh // ここは適宜変更ください
```


## つまづきやすいポイント2: display: none
`display:none` から `display: block`への変化などは、途中推移がないため当然transitionが効きません。
上記のように`max-height`で指定してもうまくいかないので気をつけましょう。
max-hegihtとoverflowでコントロールしていれば、概ねdispalyでコントロールする必要はないパターンが多いかと思います。
どうしても非表示を行いたいケースでは`opacity`を使います。
この場合、伸び縮みだけではなく「ふわっとでる」ようになることに注意してください。


```sass
// ダメな例
.foo
  display: none
  max-height: 0
  transition: max-height 0.2s
  &.is-open
   display: block
   max-height: 100vh 
```



```sass
// これならいける
.foo
  display: none
  transition: max-height 0.2s
  max-height: 0
  opacity: 0
  &.is-open
   display: block
   max-height: 100vh 
   opacity: 1
```

![ezgif.com-gif-maker (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/cf74e141-4c51-9427-4737-56960ad84642.gif)


## つまづきやすいポイント2: padding
max-heightを調整したのに、開いていない状態でも高さが残ってしまう...なんて場合は、paddingを考慮し忘れているかもしれません。

```sass
.foo
  max-height: 0
  padding: 20px
  transition: max-height 0.2s
  overflow: hidden
  &.is-open
    max-height:100vh

```

↓閉じた状態にもかかわらずpaddingが残っているとこうなる
![スクリーンショット 2021-06-10 15.27.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/1e8416f8-4fd0-fb40-2957-4ae986bed595.png)

ではpaddingを全部消せば良いのかというと、左右paddingをショートハンドなどで巻き込んでしまっていると、
徐々に左右のpaddingが出てしまうという変な動きになってしまいます。

```sass
// 左右のpadding変な動き
.foo
  max-height: 0
  padding: 0
  transition: max-height 0.2s, padding 0.2s // ここにpadding-left・padding-rightも入っている
  overflow: hidden
  &.is-open
    max-height:100vh 
    padding: 20px

```

![ezgif.com-gif-maker (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/40a21b8a-4377-b3b9-6afb-9cb43a9a8a81.gif)

解決方法としては、

- transitionでの指定を律儀に`padding-top: ..``padding-bottom: ..`とする
- 開いていない状態の上下paddingだけを削る

の二つがありますが、今回は後者で行きます。


```sass
.foo
  max-height: 0
  padding: 0 20px
  transition: max-height 0.3s, padding 0.3s 
  overflow: hidden
  &.is-open
    max-height: 100vh 
    padding: 20px
```

![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/bb15462d-2aa0-bd60-fdee-7d3244225582.gif)


これで実現したい動きを実装できました🎉
Lightning Knowledge の設定とカスタマイズ ⇒ 記事と項目の表示設定

１．表示設定を使用して、記事を参照できるユーザを制御する理由は何ですか?
２．Maria がページレイアウトから表示設定を削除するにはどうしたらよいですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/debccb02-f662-c2a7-c898-646757bbcb9f.png)
dockerのmetabaseにoracleのjdbcドライバを追加

version v0.39.3

[metabase](https://www.metabase.com/) はライセンスの関係でoracleのjdbcドライバをデフォルトでは含めていない。なのでoracleを使いたい場合は自分で追加の必要がある。jarで起動する場合は```plugins```ディレクトリにjdbcドライバを配置で良い。https://www.metabase.com/docs/latest/administration-guide/databases/oracle.html や https://qiita.com/mkyz08/items/376895d64897181b18e9 を参照。

dockerの場合は https://www.metabase.com/docs/latest/operations-guide/running-metabase-on-docker.html#adding-external-dependencies-or-plugins のように、ホスト側のjdbcドライバをvolumeでマウントすればよい。

たとえば、下記のようなディレクトリを作成して、

```
docker-compose.yml
plugins
+-ojdbc8.jar
```

<code>volumes</code>でマウントする。

```yaml:docker-compose.yml
version: "3.7"

services:
  metabase:
    image: metabase/metabase:latest
    ports:
      - "3000:3000"
    volumes:
      - ./plugins:/plugins
```

成功すればそれっぽいログが出るし、データベース追加画面でoracleが選択可能になる。

```
metabase_1  | 2021-06-10 06:24:09,521 INFO plugins.classloader :: Added URL file:/plugins/ojdbc8.jar to classpath
```

# ハマった点
## FileSystemException
```/plugins``` ディレクトリは実行時に書き込み権限が必要。以下のエラーログから分かるように、JDBCドライバのファイルをコピーして配置する、みたいな処理を行うため。WSLで実行してると特にこのハマり方しやすいんじゃないかな、という気がする。

```
metabaseoracle-metabase-1  | 2024-07-02 05:22:02,484 ERROR util.files :: Failed to copy file
metabaseoracle-metabase-1  | java.nio.file.FileSystemException: /plugins/oracle.metabase-driver.jar: Operation not permitted
```

解決方法としては、以下のようにディレクトリではなく特定ファイルだけをマウントするよう変更する。

```
      - ./plugins/ojdbc8.jar:/plugins/ojdbc8.jar
```
コピペでできるログイン状況に応じて、ログインを表示するのか、ログアウトを表示するのか Rails

```ruby
<% if user_signed_in? %>
  <li><%= link_to 'マイページ', "/users/#{current_user.id}" ,class: "***"%></li>
  <li><%= link_to 'ログアウト', destroy_user_session_path, method: :delete, class: "***"%> </li> 
 <% else %>
  <li><%= link_to 'ログイン', new_user_session_path, class: "***" %></li>
  <li><%= link_to '新規登録', new_user_registration_path, class: "***" %></li>
<% end %>
```

マイページのところはユーザー名を表示させることもできます。

ユーザー名を表示させたいときは

```ruby
<%= link_to current_user.name, "/users/#{current_user.id}",class: "***" %>
```
にすればOKです。

## 解説

いくらコピペでOKとは言いましたが、モデル名には気をつけてください。
（ほとんどの場合はuserだと思いますが）

```ruby
<% if user_signed_in? %>
```
でユーザーがログインしている時の処理を記述します。
各種pathは

```ruby
rails routes
```
で確認してください。

ログアウトの時はメソッドを追記する必要があります。

この辺はログイン機能があるアプリではほぼデフォルトの表示だと思うので。
Ransackで孫のモデルの検索をしたいときの書き方

## 概要
Ransackを使っていると子のモデルのさらに子が持つフィールドで検索したくなることが結構あるのではないかと思います。
公式のREADMEを軽く読んでもそのような方法を実現するコード例が見当たらなかったので、記事にしてみようと思います。

## 方法
例として特定のタグを持つ記事を書いたユーザーを検索したい場合などを例にしてみようと思います。
モデル構造は下記のような形です。

```ruby:models/user.rb
class User
  has_many :posts, dependent: :destroy
end
```

```ruby:models/post.rb
class Post
  has_many :post_categories, dependent: :destroy
  has_many :categories, through: :post_categories
end
```

```ruby:models/category.rb
class Category
  has_many :post_categories, dependent: :destroy
  has_many :posts, through: :post_categories
end
```

```ruby:models/post_category.rb
class PostCategory
  belongs_to :post
  belongs_to :category
end
```

この時ユーザー一覧ページで特定のカテゴリの記事を書いたユーザーを検索するには下記のように記述します。
なお`Category`はnameというカラムをカテゴリ名として持っているとします。

```ruby:views/users/index.html.slim
form
  = search_form_for @q, url: users_path do |f|
    .form-group
      = f.label :posts_categories_id_eq, "記事カテゴリで検索"
      = f.collection_select :posts_categories_id_eq, Category.all, :id, :name, {include_blank: true}, class: 'form__field'
    .form-group
      = f.submit "検索", class: 'button button--primary mr-2'
```

フィールド名を`子テーブル名_孫テーブル名_孫テーブルのフィールド名_検索方法(eq, contなど)`とすれば検索できるかと思うので、試してみてください。
[Rails]もっと見るボタンで全文を表示させる

## はじめに
自作のRailsアプリケーションでもっと見るボタンを実装したのでメモ。以下のようなイメージで投稿した記事を最初に折りたたんだ状態で「もっと見る」ボタンを押すと全文を表示させるというものです。

![スクリーンショット 2021-06-09 18.48.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/9fc330a1-bce6-4372-c57e-f9a5262a837a.png)

![スクリーンショット 2021-06-09 18.48.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/7ed5b6ce-c09c-1bfd-6d06-0a7962646aa8.png)


## 実装方法
※筆者はindexページで実装しています。
また今回はJQueryでAjaxを使わずに行います。

まず手を加える前のコードは以下のようになっています。

```:index.html.erb
<% @posts.each do |post| %>
   <%= post.body%>
<% end %>
```

今回は200文字以上の場合にもっと見るボタンを付け足すと想定します。

```:index.html.erb
<div class="content-body">
  <% @posts.each do |post| %>
    <%if post.body.length > 200 %>
      <p><%= post.body.truncate(200)%></p>
      <p>&lt;もっと見る&gt;</p>
    <%else%>
      <p><%= post.body %></p>
    <%end%>
  <% end %>
</div>
```
上記のようにif文で200文字以上の時は文字を`truncate`で省略し200文字未満の場合はそのまま表示します

次にJQueryを使うための追記をします。
以下のように追記をします。

```
<div class="content-body">
  <% @posts.each do |post| %>
    <%if post.body.length > 200 %>
      <!--追記-->
      <div class="truncated">
        <p><%= post.body.truncate(200)%></p>

        <!--class="see-more"を追記-->
        <p class="see-more">&lt;もっと見る&gt;</p>
      </div>

      <!-- 追記 style= "display: noneで 通常時は見えなくする-->
      <div class="untruncated" style="display: none">
        <p><%= post.body %></p>
      </div>
    <% else %>
      <p><%= post.body %></p>
    <% end %>
  <% end %>
</div>
```

追記した部分はコメントを追加しています。

最後にjsを設定します

```:jsファイル
$('.see-more').click(function(){
  $(this).closest(".content-body").find(".truncated").hide();
  $(this).closest(".content-body").find(".untruncated").show();
})
```
以上を設定すると実装完了です。
説明すると`see-more`をクリックした時に(1行目)その１番近い親要素である`content-body`の中の`truncated`を隠す(2行目)。そのあと`content-body`の中の`untruncated`を表示させる(3行目)

以上になります。
たった3ヶ月のプログラミング経験のみを引っ下げてセブ島オフショア開発拠点に乗り込んだ話(後編)

この記事は、プログラミングほぼ未経験だった私が数年前にフィリピンのセブ島にあるオフショア開発現場にてブリッジSEとしてのキャリアをスタートした頃の経験についてです。前編ではブリッジSEとして入社するまでの経緯について書きました。この後編では入社前の手続き関係から入社後の経験について書いていきます。

ブリッジSEに挑戦したい方、海外就職に興味がある方に向けて、少しでも参考になれば幸いです。

前編はこちら↓

https://qiita.com/kaaazz018/items/8124d83e697f7a743e7a

#内定承諾の後、フィリピンへの渡航

９月上旬の採用イベントにて内定が出た後、そこからが時間掛かりました。当時通っていたプログラミングの学校の卒業予定が１０月末。最終的に給与交渉その他諸々がまとまったのは帰国後の11月前半。

フィリピン特有のスローさに加え、今まで日本人を採用したことがなかった（日本語がペラペラのハーフは２人いましたが、フィリピンのパスポートを持っていたので特別な手続きは必要無かった）ため、ビザの取得方法とかでかなり時間が掛かってしまったみたいです。

そして話を聞くと、ビザの取得にはフィリピンに入国してから２ヶ月程度掛かる可能性があるから１日でも早く入国してほしいとのこと。そして１１月下旬に入国し、そこから2ヶ月に及ぶ暇な日々が始まりました。笑

入国直後は住む部屋もないので日本人が経営するゲストハウスに滞在し、部屋が見つかるまで３週間ほどお世話になりました。そこでの生活は色々な人との出会いもあり充実していましたがとにかくやることがない。笑

遠出して島とかに行きのんびり過ごしたかったのですが、人事からはビザの手続きが急に必要になる可能性があるため、市内にいてくれと言われていました。

なので年末に帰国することも国内旅行に行くこともできず、ひたすら市内でビザを待つという日々でした。幸いなことに年末年始を挟んでいたのでイベント事に多く参加出来たのはせめてもの救いでした。

#そして迎えた入社日

２ヶ月に及ぶ異国でのニート生活を経て、２０１８年１月下旬にようやく仮の労働ビザが取得でき、入社日を迎えました。

その日は他にも入社する人が計８名ほどいました。もちろん私以外は全員フィリピン人エンジニアです。向こうもまさか日本人がいるなんて想像もしてなかったでしょう。特に初日の午前中は距離を感じました。

入社の手続きやオリエンテーションなど、最初の数日は実際の業務に就くことは無かったのですが、数日経ってチームのメンバーを紹介してもらい、本格的に仕事が始まる、、かと思われました。

#入社直後に出張で開発現場に送り込まれる

入社前の段階でマネージャーからは出張で日本に行ってもらうことはできるか、と聞かれていたので、短期ならむしろ行きたいですと答えていたため、いつかは出張で日本に行くことがあるんだろうと準備はしていました。

が、まさか入社して３週間後に３人のチームのブリッジSEとして東京に送り込まれるとは想像していませんでした。その当時たった２ヶ月PHPを触っただけの、素人に毛が生えたどころか、産毛しか生えていない状態で某大手通信会社のエリート達が集まる日本のオフィスに乗り込むこととなったのです。

#緊張の東京出張

入社してからの３週間はほぼ出張の準備であっという間に過ぎていき、ブリッジSEとはなんぞやということもよく分からないまま出張の日を迎えました。

当時のチームは私を含めて３人。チームリーダーはマニラオフィスからだったため、メールでのやりとりはあったものの対面で会うのは出張初日の朝、出勤前でした。

セブからのもう一人はミドルクラスのメンバーではあったものの、彼もまた入社直後でした。不安しかない中、当日オフィスに行き、受け入れ先の担当の方と会ってそこから合計７ヶ月に及ぶ地獄の日々が始まりました。ストレスしか無かったこの７ヶ月の話はまたいずれシェアします。

そんなこんなでブリッジSE経験ゼロ、プログラミング経験3ヶ月（PHP2ヶ月、IllustratorやPhotoshopなど１ヶ月）のみを引っ下げてセブ島のオフショア開発拠点に乗り込んだ話でした。

#最後に

この経験で言えることは、やはり人は現場で揉まれることによって成長すること、人生なんでもなんとかなるということです。

今考えると、ITのことなんてほぼ分からない状態でよくあの会社の採用イベントに参加し、よくあんなドヤ顔で面接受けたなと自分でも感心します。今なら絶対にできない。。笑

経験がない、スキルがない。そんな状態でブリッジSEとしてのキャリアをスタートさせ、その状態のまま現場に送り込まれ、最初はかなり苦労しました。日本側の担当者の言ってる意味が分からず、通訳なのに通訳できない。さらに日本側の担当者とフィリピン人エンジニアは言葉が通じないはずなのに自分を介さずに会話した方が話が通じる、という状況も多々経験しました。

ただ、その経験がモチベーションとなり成長に繋がりました。現在でも技術的な知識やプロジェクトマネジメントのスキルに関してはまだまだ勉強中の身ですが、あの時の経験があるので怖いもの無しで取り組めています。

現在はコロナの影響もあり渡航が難しく、海外で挑戦するのは難しい状況ではありますが、日本以上に責任感を感じられて成長できる環境が海外にはあります。

コロナが落ち着き再び渡航が自由にできるようになった際は、海外で挑戦したい気持ちがある方は是非挑戦することをお薦めします。