OmniAICreator/Qiita-1.07M huggingface dataset:
グラデーションを作成してみた[Xcode/Storyboard]

グラデーションを作ってみたので、忘れないように記事に書いてアウトプットしようと思います。

#環境
・Mac Book Pro(macOS:BigSur)
・Xcode(ver:12.5)

#作成したグラデーション
縦方向
![Unknown.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864623/0a4c19a2-9d63-e0e5-79e2-e328a47b1d42.gif)

横方向
![Unknown-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864623/3371c96b-98e8-aac8-6046-2584cc3bc298.gif)

#コード例
```ruby:ChangeColorModel.swift
class ChangeColorModel{
    
    func changeColor(topR:CGFloat, topG:CGFloat, topB:CGFloat, topAlpha:CGFloat, bottomR:CGFloat, bottomG:CGFloat, bottomB:CGFloat, bottomAlpha:CGFloat) -> CAGradientLayer{
        let topColor = UIColor(red: topR, green: topG, blue: topB, alpha: topAlpha)
        let bottomColor = UIColor(red: bottomR, green: bottomG, blue: bottomB, alpha: bottomAlpha)
        
        let gradientColor = [topColor.withAlphaComponent(1.0).cgColor, bottomColor.withAlphaComponent(1.0).cgColor]
        
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = gradientColor
        
        return gradientLayer
    }
```
```ruby:ViewController.swift
class ViewController: UIViewController,UITextFieldDelegate {
    
    @IBOutlet weak var btn: UIButton!
    var changeModel = ChangeColorModel()
    var gradientColor = CAGradientLayer()

    override func viewDidLoad() {
        
    }
    
    @IBAction func changeColorAction(_ sender: Any) {
        "色をランダムに設定するためのコード"
        let topRandomR    = CGFloat.random(in: 0.0...1.0)
        let topRandomG    = CGFloat.random(in: 0.0...1.0)
        let topRandomB    = CGFloat.random(in: 0.0...1.0)
        let bottomRandomR = CGFloat.random(in: 0.0...1.0)
        let bottomRandomG = CGFloat.random(in: 0.0...1.0)
        let bottomRandomB = CGFloat.random(in: 0.0...1.0)
    
        gradientColor =  changeModel.changeColor(topR: topRandomR, topG: topRandomG, topB: topRandomB, topAlpha: 1.0, bottomR: bottomRandomR, bottomG: bottomRandomG, bottomB: bottomRandomB, bottomAlpha: 1.0)
        
　　　　　"下記の2行を加えると横方向のグラデーションになる"
        gradientColor.startPoint = CGPoint.init(x: 0.0, y: 0.0)
        gradientColor.endPoint = CGPoint.init(x: 1.0, y: 0.0)
        
        gradientColor.frame = self.view.bounds
        self.view.layer.addSublayer(gradientColor)
        btn.layer.zPosition = 1
        
    }
    
}
```
How to Update Android Apps

I'll explain how to update Android Apps. I am using Android Studio.

```
[Steps]
1. Open "build.gradle" file on the Android Studio.
2. Update Version. We must set the versionCode as an Integer.
    (ex.) You must write the versionCode and version name in the file like this.
    versionCode 4 to 5
    versionName "1.0.4" to "1.0.5"
3. Click "Sync Now" on the upper right.
4. After the sync, Click Build on the menu. And then, choose Generate Signed APK...
5. Choose "Android App Bundle" on another pop-up window and click next.
6. Set your Key store path and fill in the Key store password, Key alias, and Key password. After that, click next.
7. Choose your Build Variants, debug or release and click finish.
8. After executing tasks, the android studio generates the signed bundle apps.
9. Login Google Play Developer Console.
10. Pick the app up and click the production of the Release
11. Open the Releases Tab, and then you click "Create new release."
12. Upload the app bundle (.aab) file.
13. Fill in the release notes.
14. Click the save on the bottom.
15. After saving, click the review release.
16. Click "Start rollout to production" after checking the detail.
```

Android アプリ更新の際の自分用のメモです。
Forgot Passwordのまとめ

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)



# 設定

+ [エクスペリエンスサイトからSiteクラスのforgotPassword実行時にリセットメールが送信されない事象が発生して](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000V7E7)

:::note
以下に同じようにメールを送信できないという質問がありますが、解決してないみたいです。 
https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T4E3NSAV

こちらにはSite.forgotPasswordを使ったコードのサンプルがあります。 
https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T4XkoSAF
:::



# コミュニティーのログインページにあるForgot Password?の色を変える

色々と、応用が利きそうだったので、ここに書いておきます。


```
body.comm-page-login-home a.inverseTextColor {color:#000000 !important;} 
```


https://trailblazers.salesforce.com/answers?id=9064S000000kFXc
to_symメソッド

ハッシュの形

hash1 = { "anime" => "呪術廻戦"}   ※キー文字列パターン

hash2 = { :anime=> "呪術廻戦"}   ※キーシンボルパターン

hash3 = { anime: "呪術廻戦"}   ※キーシンボルシンプルパターン


```ruby
#hash1のパターン例
def movie_info(movie, data)
  puts movie[data]
end
movie = {"title" => "ハリーポッター", "genre" => "ファンタジー", "year" => "2001年"}
puts "以下から一つを選んで入力してください。
  ・title
  ・genre
  ・year"
info = gets.chomp   #CHECK!!
movie_info(movie, info)

```
入力を文字列でうけ、キーも文字列



```ruby
#hash3のパターン例
def movie_info(movie, data)
  puts movie[data]
end
movie = {title: "ハリーポッター", genre: "ファンタジー",  year: "2001年"}
puts "以下から一つを選んで入力してください。
  ・title
  ・genre
  ・year"
info = gets.chomp.to_sym   def movie_info(movie, data)
  puts movie[data]
end
movie = {title: "ハリーポッター", genre: "ファンタジー",  year: "2001年"}
puts "以下から一つを選んで入力してください。
  ・title
  ・genre
  ・year"
info = gets.chomp.to_sym   #CHECK!!
movie_info(movie, info)  
```

入力を文字列でうけ、キーはシンボルのため、シンボルにへんこうしなければならない！

そんな時はコレ！　”to_symメソッド”
【Css】filterを試してみた

# 背景
Photoshopやinkscapeなどの画像編集ソフトを使わずに、cssで簡単に画像のグラフィック作業ができる方法が見つかったので学習した内容を記事にしました。

※内容に間違いなどがある場合はご指摘をよろしくお願いします。

#filterプロパティとは
要素をぼかしたり色を変化させたりすることができるプロパティ。背景はもちろん、urlを指定して画像を呼び出してその画像にグラフィック効果を適用することもできます。

#使い方
構文は「filter: 適用する効果」でとてもシンプル。試しに使ってみることに。
効果を適用しない要素はクラス名をnoneにしました。filterの対象になる要素はクラス名をtargetにします。

```html
<body>
  <div class="none"></div>
  <div class="target"></div>
</body>
```
①要素をぼかす

```css
body {
  display: flex;
}

.none {
  width: 300px;
  height: 300px;
  margin: 100px auto;
  background-color: orange;
}

.target {
  width: 300px;
  height: 300px;
  margin: 100px auto;
  background-color: orange;
  filter: blur(5px);
}
```
![スクリーンショット 2021-05-13 7.45.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/29d2ec0c-7c4e-a016-b33a-7274d6a88175.png)
②明るくする

```css
.target {
  width: 300px;
  height: 300px;
  margin: 100px auto;
  background-color: orange;
  filter: brightness(130%);
}
```
![スクリーンショット 2021-05-13 7.48.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/688f5c29-e945-22f5-d7c0-f2a0f1d7f62b.png)

③影

```css
.target {
  width: 300px;
  height: 300px;
  margin: 100px auto;
  background-color: orange;
  filter: brightness(130%);
}
```
![スクリーンショット 2021-05-13 7.49.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/9bafe74b-1b70-bbe7-1035-f356714668fb.png)

④色相を回転

```css
.target {
  width: 300px;
  height: 300px;
  margin: 100px auto;
  background-color: orange;
  filter: hue-rotate(180deg);
}
```
![スクリーンショット 2021-05-13 7.53.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/3aaff3ec-7f2d-7a5c-4f97-ce0305831813.png)

⑤反転

```css
.target {
  width: 300px;
  height: 300px;
  margin: 100px auto;
  background-color: orange;
  filter: invert(80%);
}
```
![スクリーンショット 2021-05-13 7.54.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/bac29c7d-bb6f-2c8e-97b2-4ec52db10d21.png)

# 感想
画像ソフトを使わずに簡単に要素にグラフィック効果を適用できるので、javascriptなどを合わせて使うと動的に変化する背景やイメージなどができそうなので今度試してみたいと思いました。

https://code-kitchen.dev/css/filter/
https://developer.mozilla.org/ja/docs/Web/CSS/filter
https://developer.mozilla.org/ja/docs/Web/CSS/backdrop-filter
Denoでpuppeteerを使う (windows)

puppeteerはNode.js向けのブラウザ自動操作ライブラリですが、Denoからも使用することができます。

[deno-puppeteer](https://deno.land/x/puppeteer)

作者はDenoメンテナの一人であるLuca Casonato氏です。

# 使い方

環境はWindows10でやっていきます。
実行方法はReadMeページに書いてある通りです。

```js
import puppeteer from "https://deno.land/x/puppeteer@9.0.0/mod.ts";
```

ただし、このまま実行するとエラーが出る可能性があります。私は出ました。

```js
error: Uncaught (in promise) Error: Could not find browser revision 869685. Run "PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@9.0.0/install.ts" to download a supported browser binary.
      if (missingText) throw new Error(missingText);
                             ^
    at ChromeLauncher.launch (https://deno.land/x/puppeteer@9.0.0/src/deno/Launcher.ts:99:30)
```

このエラーが出た場合は以下の手順を実行する必要があります。と書いてあります。

1. 環境変数`PUPPETEER_PRODUCT`を設定

    windowsの設定（もしくはコマンドライン）から環境変数`PUPPETEER_PRODUCT`を`chrome`に設定します。

2. 初期インストールスクリプトを実行

    `deno run -A --unstable https://deno.land/x/puppeteer@<バージョン番号>/install.ts`をコマンドラインで実行します。

    ```
C:\Users\...>deno run -A --unstable https://deno.land/x/puppeteer@9.0.0/install.ts
Download https://deno.land/x/puppeteer@9.0.0/install.ts
Download https://deno.land/x/progress@v1.1.4/mod.ts
Download https://deno.land/std@0.74.0/fmt/colors.ts
Check https://deno.land/x/puppeteer@9.0.0/install.ts
 100.00%                                                    62.7s 174152394/174152394
Downloaded chrome 869685 to C:\Users\...\AppData\Local\deno\deno_puppeteer\chromium\win64-869685\chrome-win\chrome.exe from https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/869685/chrome-win.zip
```

    これで初期設定が完了です。`~\AppData\Local\deno\deno_puppeteer`以下に必要なものがインストールされます。
    余談ですが`deno run`で直接http://～やdata://～のスクリプトが実行できるの便利ですよね…

これで、以下のようなコードが実行できるようになっているはずです。

```js
import puppeteer from "https://deno.land/x/puppeteer@9.0.0/mod.ts";

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://www.yahoo.co.jp/");
await browser.close();
```

基本的なAPIは[Node.js版](https://github.com/puppeteer/puppeteer)と同じです。
top-level-awaitがデフォルトで使えるのでシンプルにかけていい感じです。
flutterを独学で確実に習得する方法

こんにちは

flutterを学び始めて4か月がたち１つアプリをリリースし、ある程度どのように学べばいいのかを把握し始めたので私が思う最も確実なflutterの学習方法を書きます。これはもちろんほかの言語でも使えると思います。

１．flutterのインストールをする（数時間～1週間ほどかかっても根気強くやりましょう）
２．公式のチュートリアルを行う
３．New flutter projectで作られる初期の数字を数えるアプリを色々書き換えてみる

４．作りたいアプリをAPI、Widgetを調べながら作る（めちゃくちゃ簡単な方がいい）
５．YouTubeやブログ等を見てアプリを作る、またはコードを書く
　　　（ここで新たな知識を得る）
６．５で作ったアプリを色々書き換えてみる
７．今知ってる範囲の知識で作れるアプリを作る（もちろんエラー祭りになるのでたくさん調べます）

８．4～7を繰り返す

９．結構自在にアプリが作れるようになったらfirebaseやMySQLなどについて学びを深める


以上のステップを踏めば作りたいと思うスマホアプリはだいたい作れるようになると思います。ポイントは背伸びせず自分ができる範囲で4～7を繰り返すこと、それを続けることです。

私も最初はflutterを使えるようになるぞ！と一か月くらい毎日やっていたのですが、そのあとはエラーが多すぎて自分が作りたいアプリが完成する気がせず完全にやる気を失いました。そして、週に1度少し触るだけという時期が2か月ほど続き、また先月から4～7の工程を意識してアプリを作り始めて4個ほどアプリを作り、1つはリリースまですることができました。

プログラミングは最初の1年は地獄と言われることもあります。とにかく1年続けることが大切です。そのためにもある程度楽しくなくてはなりません。紹介した4～7のステップは「挑戦する➡素材を集める➡経験値をためる➡挑戦する」とゲームのようになっているので「自分ができる範囲で楽しみながら勉強を進める」ことができます。

また、アプリ開発をしていく中でリリースの方法、DB（データを保存する場所）としてfirebase MySQL等の知識、APIやDocumentの使い方、見方もこの間に理解していくとさらに実力が身に着くと思います。

このステップを繰り返すように記事を書いていくので、また他の記事も見てみてください。
PostgreSQLで親子テーブルを1回のSELECTで取得する。子はJSONの配列で返し、子がいない場合を考慮する。

# 目的
親子テーブルを取得する時に1回のSELECTで取得したいです。子のデータはJSONの配列として取得します。

# JSONで集約して返すSQL
```sql
SELECT
  t1.id
  ,t1.name
  ,jsonb_agg(
    jsonb_build_object(
      'id'
      ,t2.id
      ,'name'
      ,t2.name
    )
    ORDER BY t2.id ASC
  ) AS children_json
FROM
  parents AS t1
  LEFT OUTER JOIN children AS t2 ON (
    t1.id = t2.parent_id
  )
GROUP BY
  t1.id
  ,t1.name
```

子がいる場合はこれでうまくいきます。しかし子がいない場合children_jsonは以下のように返します。

```json
[{"id": null, "name": null}]
```

期待としては[]になってほしいです。そこで集約関数に対してFILTERを使います。

# 子がいなくても問題無いSQL
```sql
SELECT
  t1.id
  ,t1.name
  ,COALESCE(
    jsonb_agg(
      jsonb_build_object(
        'id'
        ,t2.id
        ,'name'
        ,t2.name
      )
      ORDER BY t2.id ASC
    ) FILTER (WHERE t2.id IS NOT NULL)
    , '[]'::JSONB
  ) AS children_json
FROM
  parents AS t1
  LEFT OUTER JOIN children AS t2 ON (
    t1.id = t2.parent_id
  )
GROUP BY
  t1.id
  ,t1.name
```
FILTERを使ってNULLの場合を取り除きます。もし1行も無くなると集約した結果がNULLになります。そこでNULLの場合はCOALESCEで空配列のJSONに変換しています。
温度/湿度センサー (DHT22) も Raspbery Pi で使ってってみた (メモ)

adafuit が DHT22 の [Python モジュール](https://github.com/adafruit/Adafruit_CircuitPython_DHT) も作っています。最新版は以下に説明があります。モジュールの詳しい使い方は[ここ](https://readthedocs.org/projects/adafruit-circuitpython-dht/downloads/pdf/latest/)にあるようです。

https://learn.adafruit.com/dht-humidity-sensing-on-raspberry-pi-with-gdocs-logging/python-setup

ただ理由は不明ですが Raspberry Pi Zero WH では結果が全て "A full buffer was not returned. Try again." のエラーで動きませんでした。Rasrpberry Pi 3 では[ここ](https://forums.adafruit.com/viewtopic.php?f=19&t=160892#p799195)みたいな結果となり動いたのでなにか環境依存があるのかもしれません。

似たレポートが以下でも報告されています。

https://github.com/adafruit/Adafruit_CircuitPython_DHT/issues/33

既に非推奨となっていますが以下が[古いバージョン](https://github.com/adafruit/Adafruit_Python_DHT)が存在します。

https://github.com/adafruit/Adafruit_Python_DHT

上記を使うと以下のように問題なく動きました。

```
pi@test:~ $ python3 ./simpletest.py
Temp=21.3*C  Humidity=61.0%
```

[pigpio-dht 0.3.6](https://pypi.org/project/pigpio-dht/) など他の Python モジュールもあるようです。[pigpio](https://decafish.blog.ss-blog.jp/2016-10-15) というモジュールを使っているようで面白そうですが adafruit の古いバージョンで動いているのでとりあえず上記の古いバージョン (Adafruit_Python_DHT) で使うことにします。。
【Rails】カラムの設定を変更する方法

# 目的
適用済みのマイグレーションファイルに記載されたカラムの型を変更すること

# 手順
■ 実行予定の手順

1.既存のマイグレーションファイルをロールバックする

2.変更したいマイグレーションファイルのステータスを確認

3.対象のマイグレーションファイルを書き換える

4.マイグレーションコマンドの実行

5.マイグレーションファイルのステータスがupになっているか確認

## 1.既存のマイグレーションファイルをロールバックする
前提として適用済みのマイグレーションを編集してはいけません。
必ずロールバックをしてから編集する必要があります。

```:ターミナル
rails db:rollback
```

## 2.変更したいマイグレーションファイルのステータスを確認
変更したいマイグレーションファイルのステータスがdownになっているか確認します。

```:ターミナル
rails db:migrate:status
```

実行すると以下のようにターミナルにマイグレーションファイルのステータスが表示されます。

```:ターミナル
Status   Migration ID    Migration Name
--------------------------------------------------
   up       222222222222  Devise create users
   down     222222222222  Create items
```

rails db:rollbackコマンドでは直近のマイグレーションのみロールバックがされます。
変更したいマイグレーションファイルをdownにしたい場合は、複数回rails db:rollbackコマンドを実行してください。

マイグレーションファイルを一度に複数ロールバックする方法は[こちらの記事](https://railsguides.jp/active_record_migrations.html#%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)をご参考ください。


## 3.対象のマイグレーションファイルを書き換える
対象のマイグレーションファイルのステータスがdownになっていることが確認できましたら、マイグレーションファイルのカラムの型を変更していきます。
例： integer → float に変更

元の記述

```ruby
t.integer :time, null: false
```

変更後の記述

```ruby
t.float :time, null: false
```

## 4.マイグレーションコマンドの実行
変更したいカラムの型を書き換えたらマイグレーションコマンドを実行します。

```ruby:ターミナル
rails db:migrate
```

マイグレーションコマンドはdownになっているマイグレーションファイルをすべてupにしてくれます。


## 5.マイグレーションファイルのステータスがupになっているか確認
念の為マイグレーションファイルのステータスを確認します。

```:ターミナル
rails db:migrate:status
```

ステータスがupになっていることが確認できたら終了です。
laravel new で Laravelを始めるまでの記録

# はじめに

この資料は、 `laravel new` コマンドを使うために行った設定諸々のメモです。

参考になればと思います。

## 特記事項

全てのコマンドはやった結果であり、「なぜ」については「こうやった結果うまくいっている」（必要な物を入れていった結果のまとめ）と捉えていただけたらと思います。

## 環境
- MacOS 11.2.3

# 入ってるもの一覧
- brew
- phpbrew (過去に入れたことがあるやつが入ってた)

# やったこと

## 事前準備的なもの

### phpbrew 更新

とりあえず最新化で。

```
phpbrew self-update
```

## 必要なパッケージのインストール

brew でインストール。

```
brew install 
```

## phpbrew でPHPインストール

```
phpbrew i 7.4.19 +bz2="$(brew --prefix bzip2)" +zlib="$(brew --prefix zlib)"
phpbrew switch 7.4.19
```

`phpbrew known --update` で有効なバージョンを確認できます。

確認
```
$ php -v
PHP 7.4.19 (cli) (built: May 10 2021 21:09:33) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
$
```

## 拡張モジュールをインストール

```
phpbrew ext install iconv mbstring json curl filter openssl fileinfo
```

次の `laravel new` でモジュールエラーになった場合に、このコマンドで入れます。（エラーになって入れてを繰り返した結果がこちらです）

## Laravel インストール

```
laravel new api
```

`api` は、任意の名前です。

成功したら `/api` 以下にLaravel モジュールが出来上がります。

## 確認

```
php artisan serve
```

で、ブラウザから http://localhost:8000 とアクセスし、Laravelのページが表示できたらOK。

以降、Laravel に必要な個別設定を行ってください！！
Windows Virtual Desktop (WVD)でCPUが100%になって大変だった話

##Windows UpdateでCPUが100%に（先月）

先月のWindows Updateの日、午後くらいからWVDのホストのいくつかのCPUが100%に。
Windows Updateで再起動待ち状態だったので次の月は業務開始前にアップデートを完了させることを決意


##Windows Updateが終わっていたのにCPUが100%に（今月）

今月はWindows Updateを業務開始前に完了、再起動も実施。さあ、これでバッチリだ！
と思いきや、午後くらいからWVDのホストのいくつかのCPUが100%に。（泣）

プロセスの状況を見ると **Windows Search** が怪しい。
サービスから Windows Search を無効にすると（ただ止めるだけだとすぐにまた実行中になる）CPU使用率は落ち着いた。
ああ、よかった。


##これからの検討事項

とはいえ、Windows Searchもそれなりに使用する機能なのでどうすればCPUをできるだけ使わずに検索ができるようにするかは要検討である。
SwiftUI DatePickerについて

# DatePickerについて

## 環境
【Xcode】 12.4
【Swift】 5.3.2
【iOS】 14.5

## DatePickerとは
日付を入力するUIとしてDatePickerが用意されています。
はじめにDatePickerの使い方から

```swift

struct ContentView: View {
    @State var time: Date = Date()
    var body: some View {
        DatePicker(selection: $time, label: { Text("hoge") })
    }
}

```
selectionパラメータにはDatePickerで選択された値を受け渡すためのBindingを設定。
labelにはPickerとして表示したいTextビューを設定。

## Style
iOS14で新たに、GraphicalDatePickerStyleが追加されました。

```swift

struct GraphicalDatePickerStyle //iOS14で追加

```

もう少し書こうと思いましたが、
参考になる記事がありましたのでここまでにしておきます。


https://qiita.com/kj_trsm/items/774bd24f3b2723b9f7dc
【Rails6】1対多のアソシエーションが組まれている場合に子モデルが多い順にソートする

## 前提

以下のような1対多のアソシエーションを組んだモデルを使ってRailsアプリを実装しています。



###  booksテーブル

|Column|Type|Options|
|------|----|-------|
|isbn|string|null: false, unique: true|
|title|string|null: false|
|author|string|null: false|
|author_kana|string|null: false|
|publisher_name|string|null: false|
|sales_date|string|null: false|
|item_price|integer|null: false|
|item_url|text|null: false|
|image_url|text|null: false|



#### Associations

\- has_many :awarenesses



### awarenessesテーブル

|Column|Type|Options|
|------|----|-------|
|content|string|null: false|
|user|references|null: false, foreign_key: true|
|book|references|null: false, foreign_key: true|



#### Associations

\- belongs_to :book

Bookモデルが書籍情報で、Awarenessesモデルが書籍を読んでの気付きの情報を持っています。
カラムの中身を個別に解説することは今回はしません。
このような場合にBookモデルのデータをAwarenessesモデルのデータが紐付いている数が多い順にソートしたい。

## 結論

以下のコードでいけました。

```ruby
Book.left_joins(:awarenesses).group(:id).order('count(book_id) DESC')
```

## ポイント

ポイントはleft_joinsを使う点です。

left_joinsは関連するモデルデータを同時に引っ張ってくれるメソッドですが、joinsと異なり関連モデルのデータ存在しない
レコードも引っ張ってきてくれます。

joinsとleft_joinsの違いは以下の記事がわかりやすかったです。
僕が説明するよりこっちをみてもらったほうがわかりやすいと思います。(~解説がめんどくさい~)
https://pikawaka.com/rails/left_joins

## 感想

単純な一覧表示でしたが案外難しかったです。
SQLもっと勉強したいな〜と思いました。
私にコーヒーをおごってほしい - エンジニアと報酬・対価について考えた

表題に他意はなく、単に興味を持った「[Buy me a coffee](Buymeacoffee.com)」を日本語にしたらそういう感じなのかな、というところです。記事の結論を先に書くと「金銭」とまでは言わずとも、「お礼」や「応援」の気持ちは、普段から開発者同士もっと表明して送っていきたい。そういう気持ちを改めてもったという話。

Buy me a coffee、Qiita記事でも紹介されていた。以下。

https://qiita.com/whitphx/items/f37216ab2392ab359f11#buy-me-a-coffee

モノの試しに自分でもBuy me a coffeeアカウントを作ってみた。しかし何かを作ることとお金、もう少し話を広く表現すると「報酬」「対価」の話は各媒体、それぞれ戦略や考え方がある。


## 「お金を稼ぐ」ことにまつわる各コミュニティ等のお話

### 例: Qiita

https://qiita.com/HiromuMasuda0228/items/aa3729882cb59fda9838

https://qiita.com/tamappe/items/fc786333b0f97ba7738e

実際、そういえばとおもったのでQiita本営へ問合せた。Qiitaに投げ銭サービスリンクは貼れるのか。端的に以下回答を頂いた。

> アフィリエイトや欲しいものリスト、投げ銭を受け付けることの出来るURLやQRコードを掲載する、あるいは、掲載されている他サービスへのリンクを設置することは、利用規約( https://qiita.com/terms )第11条の「客観的には事実上、広告・宣伝や商用を目的とした勧誘と認められる行為（検索サイト最適化又はアフィリエイトを目的とする投稿行為を含むがこれに限らない）。」の客観的に広告・宣伝や商用を目的とした勧誘と認められる行為に該当

先の Buy me a coffee のようなサービスへのリンクを例えば添えるような行為は果たしてアリなのか？それはNGだという話である。これにかんして良いとも悪いとも思わないが、それがQiitaの現時点での戦略なのだなあという感想。私はQiitaという場をそれなりに楽しませていただいてもいる。


### 例: Zenn

一方のZenn。こんな記事を見る。またコミュニティ自体に説明がある。

https://zenn.dev/daichi_gamedev/articles/4ee023a1bc2d06#%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%EF%BC%88%E6%8A%95%E3%81%92%E9%8A%AD%EF%BC%89

https://zenn.dev/about

「情報を発信するエンジニアが対価を得られるように」。


### 例: note

こちらはエンジニアに限らないが、note。そのままなのでコメント割愛。

https://help.note.com/hc/ja/articles/360010430873-%E5%A3%B2%E4%B8%8A%E9%87%91%E3%82%92%E5%8F%97%E3%81%91%E5%8F%96%E3%82%8B



### 例: Buy me a coffee

で、GitHubでバナーをよく見ていたので興味を持った。

https://blog.nismit.me/post/2020/05/buy-me-a-coffee

一方こんなお話も見つける。

https://qiita.com/rana_kualu/items/db62ad8d7dc0a4cce9db


### 世間話: Babel 

トランスパイラ「Babel」の開発チーム、「何百万人にも使われているのに、なぜ私たちの資金は尽きようとしているのか？」。資金難により寄付を訴え

https://www.publickey1.jp/blog/21/babel.html

ちょうど読んだニュースです。

### 世間話: Wikipedia

同じく思い出す話題。

https://dime.jp/genre/493140/

https://jp.techcrunch.com/2019/01/23/2019-01-22-google-org-donates-2-million-to-wikipedias-parent-org/

### 世間話: Docker

鯨さんにはお世話になっている。

https://www.docker.com/blog/updating-product-subscriptions/

https://qiita.com/autotaker1984/items/284e28f82fc1828da44e

https://zenn.dev/koduki/articles/ba54daaba28f93

> Docker社にはDockerというかコンテナがここまで広まったのにビジネス的には成功出来てない不遇の位置にいるので、きちんとこういう方法で儲けて欲しい

この気持ちではある。


### 思い出話: 「夢だけじゃ腹はふくれない。」

小さい頃に藤子不二雄の「エスパー魔美」という漫画を読み、その話の一つで出てきた印象的な一節である。
[エスパー魔美　７ | 藤子・Ｆ・不二雄 | 【試し読みあり】 – 小学館コミック](https://shogakukan-comic.jp/book?isbn=9784091423238)
売れない小劇団に所属することをあきらめ辞めていく青年のセリフ。うーん、伝わりづらい気もしますが、「何かを作る」人間にとって、きれいごとではないのがお金でもある。


## 感想

儲けたいのではない、使ってもらいたいからこその無償提供、かたやそんなのは綺麗事であるからこその課金。以下、お金の話と比較しては飛躍しすぎているように聞こえてしまう部分もあるかもしれません。

しかし「人を応援する」という気持ちはもっと大切にして良いのかもしれないと反省します。実際に身銭を切ることをしないにせよ、面白い記事を見つけ役に立ったらLGTMを押す、は私にもできます。価値あるものに見返りを送れる仕組み、報酬、対価とは言い切れなくてもせめて応援する気持ちを送れる仕組みは、開発者の世界を盛り上げるアクションの一つとして普段のお仕事から意識していきたいなと感じます。それで「良いコミュニティ」が盛り上がるなら。

その点コーヒー１杯というちょうど良さを表現している Buy me a coffee はなるほどなと思ったし。

会社でもSlackのリアクションだとかから始めないとなあという気持ち。エンジニアと報酬・対価。いかが感じるところでしょうか。なにがしか参考になればさいわいです。
MinecraftでMODを開発したい#1

*MinecraftでMODの開発をします*
*試行錯誤を書いていくだけのものになります*

##概要
環境構築をする

##動作環境 2021/05/12
||Version|
|:-:|:-:|
|Mac OS Big Sur|11.1|
|IntelliJ IDEA|2021.1.1|
|AdoptOpenJDK (HotSpot)|1.8.0_282|
|Minecraft|1.16.5|
|Forge|36.1.0|


##目次
- IntelliJ IDEAのインストール
- Forgeのインストール
- Example Modの削除


##IntelliJ IDEAのインストール
ダウンロードページから「Community」をダウンロード
ダウンロードしたインストーラを実行し、デフォルト設定のまま画面に従ってインストール
IntelliJ IDEAを起動し、タイトル画面で「New Project」を選択
「Project SDK」から「Download JDK」を選択
「Version」に「1.8」、「Vendor」に「AdoptOpenJDK (HotSpot)」を指定し、「Download」
「Project SDK」に「adopt-openjdk-1.8」が選択されていることを確認する

##Forgeのインストール
ダウンロードページから1.16.5を選択し、「Download Recommended」の「Mdk」をダウンロード
ダウンロードしたzipファイルを解凍し、任意の場所に移動させておく
IntelliJ IDEAを起動して解凍したファイルを選択
自動で読み込みが始まるので、右下の進捗表示が完了するまで待つ

画面右側のTool Window Barにある「Gradle」を選択し、GradleのTool Windowを開く
Tasks > fg_runsと階層を下りて「genIntellijRuns」をダブルクリックすると、実行構成が自動で作成される
「BUILD SUCCESSFUL」の表示がでれば成功
Terminalから`$ ./gradlew genIntellijRuns`を実行でもできる

Gradle Tool Window左上の同期ボタン（Reload All Gradle Projects）を押す

画面右上の「TitaniumMod [genIntellijRuns]」などと表示されている実行構成選択ボタンを押して「runClient」を選択
実行ボタンを押して、Minecraftが起動すれば成功
起動しない場合、Terminalから`$ ./gradlew runClient`を実行すると起動できる場合がある


##Example Modの削除
src/main/java/にあるcom.example.examplemodを削除
com.exampleが残るので削除
src/main/javaを右クリックし、New > Packageからcom.ドメイン名.examplemodパッケージを作成
com.ドメイン名.examplemodを右クリックし、New > Java ClassからExampleModを作成
src/main/resources/META-INF/mods.tomlを開き、modId="examplemod"をmodId="examplemod"に変更(*今回はMOD名を変更しないため変更なしとする)
changelog.txt、CREDITS.txt、LICENSE.txt、README.txtを削除
 
######参考文献
https://www.tntmodders.com/tutorial/env-1165/
https://qiita.com/niwasawa/items/ca565091468abce48f53
理系の文章構成備忘録（更新中）

　論文を推敲する上で確認する用のメモが欲しかったので常に更新しながらまとめようと思う。

## 論文 編
- 第1文でどんな研究なのか概要が伝えられている。
    - 「本論文では，○○を解決するために△△を用いた××手法を提案する」
- 前の文章で定義されていない単語や文字式を用いず書けている。
    - 逆茂木型になっていないか。
-  概要から詳細の流れで文章が構成されている。
    -  物理的なシステムであれば空間に沿って説明すると良い。
    -  複雑なアルゴリズムであれば時間に沿って説明すると良い。
- 抽象的な単語を用いていない。
    - 手法を説明する場合「モデル」や「活用」といった結局何かわからない単語を用いると読み手が手法を想像できない。
- 過去研究と対比させる場合、何が対比となるのか明らかにすること。

###挿入する画像 編
- 画像内の文字フォントサイズは本文で用いているフォントサイズの7割以上にする。
- 画像の説明「図１：...」は簡潔にするか丁寧に説明するかは統一する。
- 画像は必ず本文で引用、説明されている。

###数式 編
- 数式の終りにカンマまたはピリオドをつける。

###言葉選び 編
- 直接的で意味が一意に決まる言葉を使う。
    - 「そして」→ 受け手によって印象が変わってしまう。
    - 「不自然」→ 何が不自然？
    - 「ぴったり」→ オノマトペ表現は論文を表す言葉として不適切である。
- 「○○的」は あまり使わない方が良い。
    - そもそも他の適切な言葉があるはず。
-  「まとめ」と「結論」の違い
    -  「まとめ」は今までの流れをすべて簡潔に説明する。「結論」はその研究で得られた成果を示す。
- ``recent''はここ2～3年といった最近のという意味だが、良い手法とは限らないという意味も含まれる場合がある。

###こまごまとした表記法 編
#### 英語表記
- 日本人名のローマ字表記は，姓名の順にして，間違えやすい時等には姓は全て大文字とする（国の方針らしい）。
- 初出時はフルスペルで書く。
    - SNS (Social Network Service) 
- ダブルクォーテーションは``(Shift+@)ではじまり''(Shift+7)で終わる。
    - ``Hogehuga algorithm''
- 連続した名詞の表記は``..., ..., ..., and ...''
    - 特に参考文献の研究者一覧表記で忘れがち。
- 略語の後にはピリオド。
    - Trans. Vis. Comput. Graph.  

#### 日本語表記
- カタカナ表記と英語表記が乱立していないか。

### 文献 編
- 文献情報がすべて同じ順番、同じ形式で統一されている（著者、タイトル、論文誌名、発行年）。
- 文献がすべて本文で引用されている。
- Webページを文献にした場合、アドレスの後ろに最終確認年月日が描かれている（20XX年XX月XX年確認）。


##発表スライド
- 適切な部分で改行されている。
    - ネットワ（改行）ークとなると読みづらい。
- 数式で用いた変数名は必ず注釈を入れる。
- 手法の流れを図で説明すると良い。
    - 全行程のうちどの部分を話しているか分かるようにするために各スライドで小さく手法の流れの図を載せると良い。
Vagrant up時にSSH auth method: private keyで止まってTimeoutしてしまう

最近仮想通貨の盛り上がりで様々なブロックチェーンのプラットフォームが出てきていますが、
その中でEthereumをフォークしたプラットフォームであるQuorumを個人的に使ってみる事にしました。

公式で提供されている[Quorum examples](https://github.com/ConsenSys/quorum-examples)を使ってQuorumを触ってみようとしたのですが、
一番初めのVagrantを立ち上げる**vagrant upをするとSSH auth method: private keyのタイミングで進まなくなり、Timeoutしてしまう問題**が発生してしまいました。

調べてみると結構よくある問題らしく、原因も色々考えられるため結構厄介らしい。

なんとか複数の解決策を試して解決できたのでメモしておきます。
#環境
・Windows 10 home
・VirtualBox(6.1.22)
・vagrant(2.2.16)
#よくある解決策
いくつか記事を読みましたが以下の方法で解決できる場合が多いようです。
**結果的にはHyper-Vの無効化(仮想マシンプラットフォームの無効化)で解決できました。**
###・BIOSの"Virtualization Technology"を有効にする
　BIOSを確認してみると私の場合は無効になっていたため有効にしました。
　ですがこれだけでは解決できず、、

###・Hyper-Vの無効化
**コントロールパネル->プログラム->Windowsの機能の有効化または無効化**
からHyper-Vのチェックをはずして無効にするらしいのですが、windows 10 homeなのでHyper-Vが入っていません。

ただこんな記事を見つけました。
[・WSL2とHyper-Vの関係](https://qiita.com/matarillo/items/ca1eecf8f9a3cd76f9ce)

ちゃんとは理解できてないですが、試しに仮想マシンプラットフォームのチェックを外してみる事にしました。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693048/3f9049a4-39d6-8f2c-6e51-72241325bbcf.jpeg)
これでPCを再起動してvagrant upしてみたらちゃんと立ち上がりました！！


#まとめ
vagrant upがprivate keyのタイミングで止まってしまう問題はよく起きるみたいですが、Dockerを入れた際にHyper-Vが有効になってしまってこの問題が起きている人が多い印象でした。
この方法で解決できた人がいれば嬉しいです。
Pythonスクリプトでrosbag record的な事をする

# やりたいこと
Pythonスクリプトで`rosbag record`を開始したり、止めたりしたい。
topic名を指定するだけで、recordしたい。

# 方法
```python
import rospy
from rqt_bag.recorder import Recorder

if __name__ == '__main__':
    rospy.init_node("sample")
    # すべてのトピックをrecordする場合
    rec_1 = Recorder("sample_1.bag")
    rec_1.start()
    rospy.sleep(10)
    rec_1.stop()

    # 特定のトピック(/hogeと/fuga)をrecordする場合
    rec_2 = Recorder("sample_2.bag", topics=['/hoge', '/fuga'], all=False)
    rec_2.start()
    rospy.sleep(10)
    rec_2.stop()

    # 特定のトピック(/hogeで始まるトピック)をrecordする場合
    rec_3 = Recorder("sample_3.bag", topics=['/hoge*'], regex=True, all=False)
    rec_3.start()
    rospy.sleep(10)
    rec_3.stop()

    # 各topicのメッセージを1つだけrecordする場合
    rec_4 = Recorder("sample_4.bag", topics=['/hoge', '/fuga'], all=False, limit=1)
    rec_4.start()
    rospy.sleep(10)
    rec_4.stop()
```

方法2~4は、オプション引数の`all`をFalseにしないと、全てのトピックがsubscribeされてしまうので注意が必要。
Google Maps で白地図を取得する（１）

こちらのページをクリック
https://mapstyle.withgoogle.com/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/b2b5917a-8112-c96b-1e99-a49ab97eff57.png)
この画面が出る場合はNo thanks, をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/88618311-440c-a8cb-3a02-2b9a8c519410.png)

Roads/Landmarks/Lavelsのスライダーをすべて左端にすると右側の地図が白地図になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/99338a3f-68c3-4d90-495d-93948648bb8c.png)

[FINISH]ボタンを押すとJSONとURLが出る。
・API_Keyを持っている場合はURLにAPI_Keyを含めるとそのURLで白地図の画像を取得できる（が、使用上限を超えると課金されるので公開しないこと）
Rspec factorybot 動作確認

#Rspec
Gemfileに以下のコードを追加

```Gemfile:Gemfile
group :development, :test do
  gem 'rspec-rails', '~> 4.0.1'
end
```
ターミナルで

```
bundle install
```

```
rails db:create
```

```
bin/rails generate rspec:install
```

下記のgem追加

```ruby:Gemfile
group :development do

...元から書いてあるgemは省略

下の1行を追加してください
  gem 'spring-commands-rspec'
end
```

bundle install実行

```
bundle install
```

binstubのgemがインストールできたので、以下のコマンドを実行して新しいbinstubを作成しましょう。

```
bundle exec spring binstub rspec
```

コマンドがうまく実行できていれば、アプリケーションのbinディレクトリ内にrspecという実行用ファイルが作成されているはずです。

ターミナルを開いて、以下のコマンドを実行してください。

```
bin/rspec
```
すると、以下のような結果が返ってきました。

```
Finished in 0.03718 seconds (files took 0.78572 seconds to load)
0 examples, 0 failures
```
まだテストを何も書いていないので、全て0ですが、RSpecはちゃんとインストールされているようです。

これから新しいモデルやコントローラーなどを作成する時に、一緒にRSpecのテストファイルも自動で作成してもらえるように設定しましょう。

config/application.rbを開き、以下のコードを追加します。

```ruby:config/application.rb
require_relative 'boot'

require 'rails/all'

Bundler.require(*Rails.groups)

module MiyachaApp
  class Application < Rails::Application
    config.load_defaults 6.0


#ここから  
    config.generators do |g|
     g.test_framework :rspec,
       fixtures: false,
       view_specs: false,
       helper_specs: false,
       routing_specs: false
    end
#ここまで

  end
end
```

#Factorybot

Gemfileを開いて、以下の記述を追加してください。

```ruby:Gemfile
group :development, :test do
#...他のgemは省略
  gem 'factory_bot_rails', '~> 4.10.0'
end
```
忘れずにbundle install
次にUserモデルを作成

次にターミナルを開いて、以下のコマンドを実行してください。

```
bin/rails g factory_bot:model user
```
このコマンドを実行すると、specフォルダ内にfactoriesというフォルダが作成されたはずです。

factoriesフォルダの中のuser.rbファイルを開いて見ましょう。

```ruby:user.rb
FactoryBot.define do
  factory :user do
    
  end
end
```
このfactories/user.rbファイルに、FactoryBotで作成するデータを定義していきます。

それではfactories/user.rbファイルを開いてください。

以下の内容にしてください。

```ruby:factories/user.rb
FactoryBot.define do
  factory :user do
    email { "test@test.com" } 
    password { "testpassword" }
  end
end
```

それでは実際にUserモデルを作成して見ましょう。

「spec/models/user_spec.rb」ファイルを開いてください。

このテストファイルでFactoryBotを使ってデータベースを作成しましょう。

user_spec.rbのファイルに以下のexampleを追加してください。

```ruby:user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
...他のexampleは省略

  it "factorybot test" do
    user = FactoryBot.create(:user)
    expect(user).to be_valid
  end
end

```

テスト用のテーブル作成

```
bin/rails db:migrate RAILS_ENV=test
```
テストの内容としては、

userという関数に、FactoryBotで作成したUserを格納しています。

そして、expectの行で、そのuserがbe_valid（有効である）となるはずであると記述しています。

それでは、テストを実行して見ましょう。

ターミナルを開いて以下のコマンドを実行してください。

```
bin/rspec spec/models/user_spec.rb
```
これで実行結果が返ってこれば成功です。
スクロール時にCSSでスナップを効かせる方法

***画面スクロールをした時にセクションごとにストップさせる方法を見つけたので備忘録***
---

親要素に以下
```scroll-snap-type: x mandatory;```

子要素に以下を追加することで実装できる
```scroll-snap-align: start;```

実際のCSSコードはいか
```.section {
  display: flex;
  overflow-x: auto;
  height:100vh;
  scroll-snap-type: x mandatory;
}

.section__item {
  height:100vh;
  scroll-snap-align: start;
}```
Salesforce リリース準備状況戦略 ⇒ 新機能の検索、有効化、コミュニケーション

１．組織に利益をもたらす、すべての新機能をすばやく特定する方法はどれですか?
２．関係者やユーザに新しいリリースについて伝えるときのベストプラクティスはどれですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/279cafa5-1a58-23e3-e047-94c06d707122.png)
M5Stackで日時を表示

M5Stackを使って簡単なプログラミングを実施しました。
M5StackをWiFiにつなげてNTPサーバから時刻を取得し、取得した時刻を画面に表示するものです。

![M5STACKで時刻表示.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483586/4a55246c-0423-e2d1-54fe-a5f0a8e2f117.png)

* 環境
    * M5Stack BASIC
    * Windows 10 (作業用PC)

* 事前準備
M5Stackでの作業は初めてのため、以下の事前準備作業をしました。
  1. 作業用PCに[Arduino IDE](https://www.arduino.cc/en/software)と[CP210X Driver](https://shop.m5stack.com/pages/download)をインストールします。  
詳細は[M5Stackの開発環境を構築する](https://qiita.com/Toshiaki0315/items/a16394e7e90271f420d1)参照してください。
  1. 作業用PCとM5STACKをUSBで接続します。
  1. 作業用PCでArduino IDEを起動します。

* ソースコード
ほぼ参考元のコピペで作成しました。
ssidとpasswordに自身のWiFi環境の情報を記載するとM5StackがWiFi接続可能になりました。

```
#include <M5Stack.h>
#include <WiFi.h>
#include "time.h"

const char* ssid       = "XXXXXXXXXXXXX";
const char* password   = "XXXXXXXXXXXXX";

const char* ntpServer = "ntp.nict.jp";
const long  gmtOffset_sec = 3600 * 9;
const int   daylightOffset_sec = 0;

void printLocalTime()
{
  struct tm timeinfo;

  if(!getLocalTime(&timeinfo)){
    M5.Lcd.println("Failed to obtain time");
    return;
  }
  // テキストサイズ指定
  M5.Lcd.setTextSize(2);
  // カーソル位置を設定
  M5.Lcd.setCursor(40,100);
  M5.Lcd.printf("%04d-%02d-%02d %02d:%02d:%02d" 
                ,timeinfo.tm_year + 1900
                ,timeinfo.tm_mon + 1
                ,timeinfo.tm_mday
                ,timeinfo.tm_hour
                ,timeinfo.tm_min
                ,timeinfo.tm_sec
                );
}

void setup()
{
  M5.begin();
  
  //connect to WiFi
  int cnt=0;
  M5.Lcd.print("Connecting to YOUR_SSID ");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    cnt++;
    delay(500);
    M5.Lcd.print(".");
  }
  M5.Lcd.println(" CONNECTED");
  
  //init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();

  //disconnect WiFi as it's no longer needed
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
}

void loop()
{
  delay(1000);
  printLocalTime();
}
```

Arduino IDEで上記ソースコードを保存します。
その後、コンパイルとマイコンボードへの書き込みを実施するとM5Stackの画面に日時が表示されました。

* 参考元  
今回の作業は以下のサイトを参考に実施しました。
    * [M5Stackの開発環境を構築する](https://qiita.com/Toshiaki0315/items/a16394e7e90271f420d1)
    * [時刻の表示 - m5stackで組込み！！](https://m5stack-build.hatenablog.com/entry/2019/09/18/074659)
    * [M5StickCでできること 〜LCD画面に現在時刻を表示する ](https://msr-r.net/m5stickc-ntp/)
redshift data api example


```
#!/bin/sh                                                                                                                       

/usr/local/bin/aws redshift-data execute-statement \
    --region us-east-1 \
    --secret arn:aws:secretsmanager:us-east-1:xxxxxxx:secret:dataapi-test-user-xxxxxxxxx \
    --cluster-identifier [cluster-identifier] \
    --sql "select * from [table name] limit 10" \
    --database [dbname]
```
Firebaseエミュレータ＆デプロイ環境導入時にハマった初歩的な所

1からFirebaseエミュレータを導入した時に詰まった落とし穴。
基本はGoogleさんの下記の手順でやれば良かったが、新しいMACなどで特に開発環境を整えていないケースでハマっちゃったポイントがあったので備忘録。

https://firebase.google.com/docs/functions/get-started?hl=ja

### 前提
* 既にFireBaseプロジェクトは作成済みで、新しくCloudFunctionsの開発及びデプロイ環境を揃えようとした
* npmとnodeは最新が入っていた


##1.npmのアクセス権で引っかかる
 
初っ端から。これに関してはgoogleさんからもお達し済。

>npm install -g firebase-tools
これにより、グローバルに使用できる firebase コマンドがインストールされます。コマンドが失敗した場合は、npm アクセス権の変更が必要になる場合があります。firebase-tools を最新バージョンに更新するには、同じコマンドを再実行します。


```
npm ERR! code EACCES
npm ERR! syscall access
npm ERR! path /usr/local/lib/node_modules
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!  [Error: EACCES: permission denied, access '/usr/local/lib/node_modules'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/local/lib/node_modules'
npm ERR! }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR! 
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.
```

下記の手順にて解決

https://qiita.com/rakuraku0615/items/4d47dc6315f01667027a

## 2.JAVAが入ってなかった

firebase emulators:start
で何故かFirebaseエミュレーターが起動しない・・・！　
エラーもそれらしいのが出ていなかったがJAVAのインストールで起動しました。これ実は書いてないかも？


## 3.functionsのデプロイができない！
エミュレーターも動き、一通りの動作を見終わっていざデプロイ。ここでもエラー発生。
設定時にESLintというJavaScript検証ツールを有効にしているとここでエラーになっちゃうらしく、それが記載されているfunctionsのpredeployを消す必要があるようでした。

https://qiita.com/pontarou194/items/55b53700082a59a148fb
Nginxでドメイン名によってアクセスを振り分けてみた

## はじめに
以下記事をほぼほぼ参考に試してみた備忘録です。
https://qiita.com/South_/items/7bdb1f373410cb1c907b

jwilder/nginx-proxy っていうimageのnginxをプロキシとして使うとヘッダーで設定したホスト名でアクセスを割り振ってくれる。

## ディレクトリ構成
```
$ tree
.
├── docker-compose.yml
├── web
│   └── index.html
├── web2
│   └── index.html
└── web3
    └── index.html
```

## docker-compose.yml

```
$ cat docker-compose.yml 
version: '3'

services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    ports:
      - 80:80
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro

  web:
    image: nginx
    environment:
      - VIRTUAL_HOST=web.localhost
    volumes:
      - ./web:/usr/share/nginx/html

  web2:
    image: nginx
    environment:
      - VIRTUAL_HOST=web2.localhost
    volumes:
      - ./web2:/usr/share/nginx/html

  web3:
    image: nginx
    environment:
      - VIRTUAL_HOST=web3.localhost
    volumes:
      - ./web3:/usr/share/nginx/html
```

## htmlファイルを用意

- webコンテナ

```
<html>
  <head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>webコンテナのページ</title>
  </head>
  <body>
    <h1>webコンテナのページ</h1>
  </body>
</html>
```

- web2コンテナ


```
<html>
  <head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>web2コンテナのページ</title>
  </head>
  <body>
    <h1>web2コンテナのページ</h1>
  </body>
</html>
```

- web3コンテナ


```
<html>
  <head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>web3コンテナのページ</title>
  </head>
  <body>
    <h1>web3コンテナのページ</h1>
  </body>
</html>
```

## docker-compose実行

```
$ docker-compose up -d
Creating nginx_reverse_proxy_as_multidomainserver_web_1         ... done
Creating nginx_reverse_proxy_as_multidomainserver_web3_1        ... done
Creating nginx_reverse_proxy_as_multidomainserver_web2_1        ... done
Creating nginx_reverse_proxy_as_multidomainserver_nginx-proxy_1 ... done
```

## 動作検証

```
$ curl -H 'Host:web.localhost' 0.0.0.0
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>webコンテナのページ</title>
  </head>
  <body>
    <h1>webコンテナのページ</h1>
  </body>
</html>

$ curl -H 'Host:web2.localhost' 0.0.0.0
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>web2コンテナのページ</title>
  </head>
  <body>
    <h1>web2コンテナのページ</h1>
  </body>
</html>

$ curl -H 'Host:web3.localhost' 0.0.0.0
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>web3コンテナのページ</title>
  </head>
  <body>
    <h1>web3コンテナのページ</h1>
  </body>
</html>
```
VitePressでRouterの変更を検知する


## したいこと
VitePressでGoogle AnalyticsをしたいけどSPAだからページ移動しても検知してくれない。
なのでVitePressでRouterの変更を検知して検知させたい。

### 2021年6月追記
VitePressはビルド時サーバー側でもレンダリングを行うので
gtagがないよと怒られてしまう。
解決策としてはglobalThisを使って判断する

## 結論
```JavaScript:.viteperss/theme/index.js
import DefaultTheme from 'vitepress/theme';
import { watch } from 'vue';

export default {
	...DefaultTheme,
	enhanceApp({ app, router }) {
		if (globalThis && globalThis.gtag) watch(router.route, () => {
			// 変更を検知したタイミングで呼んでくれる
		});
	}
}
```
## 解説
`router.route`は[reactiveなので](https://github.com/vuejs/vitepress/blob/master/src/client/app/router.ts#L41)Vue3の[watch](https://v3.vuejs.org/api/computed-watch-api.html#watch)を使って検知するだけです

## 【おまけ】Google Analyticsに対応させる
今回はgtagを利用します

```JavaScript:.viteperss/theme/index.js
import DefaultTheme from 'vitepress/theme';
import { watch } from 'vue';

export default {
	...DefaultTheme,
	enhanceApp({ app, router }) {
		if (globalThis && globalThis.gtag) watch(router.route, () => {
			gtag('config', window.GA_MEASUREMENT_ID, {'page_path': router.route.path });
		});
	}
}
```

```JavaScript:.viteperss/config.js
module.exports = {
	// 中略
	head: [
		// ここは各自scriptのURLに置きかえる
		[ 'script', { src: '', async: true } ],
		[ 'script', {}, `window.GA_MEASUREMENT_ID = 'Google analyticsに書いてあるIDを書く';window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());`]
	]
	// 中略
}
```

これでヨシ！
誤字などありましたら教えてください～
Selenium 画面外の要素を画面内に表示させる

#はじめに
本記事は「要素は存在するけど、クリック操作できない」という場合の対処法です。
↓こんな感じのエラーの時です。

```
unknown error: Element is not clickable at point
```



#要素が画面外にあるので、スクロールして表示させる
要素が画面表示外にあるため、操作できなくなっているはずです。
なので、画面内に表示するようスクロールしてあげます。

```python:要素を表示するようスクロール
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains

# クローム起動(カレントディレクトリにwebdriverを設置済)
driver = webdriver.Chrome()

# ページの表示
driver.get("https://==========================")

# クリックするとエラーになる要素の取得
element = driver.find_element_by_xpath("/html/body/div/div")

# 要素を表示するようスクロール
ActionChains(driver).move_to_element(element).perform()

# クリック
element.click()
```

画面下に指定した要素がひょこっと現れて操作できるようになります。
Laravel mimetypesでバリデーション設定したら突破するはずの値が弾かれる

# 目的

- mimetypesのバリデーションルールを設定後にバリデーションを通過するはずの値が弾かれる問題の原因をまとめる

# 原因

- Mimetypeの指定時にスペースを入れてしまっていた。

# 問題のソース

- 下記のようにバリデーションルールを記載した。

    ```アプリ名ディレクトリ/todos/app/Http/Requests/TaskRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Illuminate\Foundation\Http\FormRequest;
    
    class TaskRequest extends FormRequest
    {
        /**
         * Determine if the user is authorized to make this request.
         *
         * @return bool
         */
        public function authorize()
        {
            return true;
        }
    
        /**
         * Get the validation rules that apply to the request.
         *
         * @return array
         */
        public function rules()
        {
            return [
                'name' => ['required'],
                'limit_id' => ['required'],
                'file' => [
                    'required',
                    'file',
                    'image',
                    'mimetypes: image/jpeg, image/png',
                ],
            ];
        }
    }
    ```

- 注目いただきたいソースは`'mimetypes: image/jpeg, image/png',`の部分であり、Mimetype名の前に半角スペースが空いている。これが原因だった。

# 問題を解消したソース

- 下記のようにバリデーションルールを記載した。

    ```アプリ名ディレクトリ/todos/app/Http/Requests/TaskRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Illuminate\Foundation\Http\FormRequest;
    
    class TaskRequest extends FormRequest
    {
        /**
         * Determine if the user is authorized to make this request.
         *
         * @return bool
         */
        public function authorize()
        {
            return true;
        }
    
        /**
         * Get the validation rules that apply to the request.
         *
         * @return array
         */
        public function rules()
        {
            return [
                'name' => ['required'],
                'limit_id' => ['required'],
                'file' => [
                    'required',
                    'file',
                    'image',
                    'mimetypes:image/jpeg,image/png',
                ],
            ];
        }
    }
    ```

- 上記のように半角スペースを開けずに記載することでバリデーションを突破する事ができた。

# 参考文献

- [https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types](https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types)
Railsにおけるリクエストからレスポンスの流れ

#はじめに
&emsp;Webページを表示したり、タスクの新規作成をする際にrailsのなかでどのような処理が行われているのかをまとめました。

# ユーザーの一覧ページを表示する（GETメソッド）
- `/users`というパスに対してGETリクエストがWebサーバに送られる。<br>
（POSTではなくGETを使う理由は、一覧表示ではデータの書き換えは必要ではなく、データを取得したいだけなのでGETを使う)
- WebサーバがGETリクエストを受け取り`routes.rb`の`resources :users`により、それに対応するコントローラのアクションが呼び出される。
- コントローラのindexアクションで全ユーザーのデータを取得する。

```
def index
  @users = User.all
end
```
（この記述だけでデータベースからデータを取得できる理由は、RailsにはモデルにActiveRecordが継承されているので、Rubyを用いてデータベースからデータを探したり、持ってくることができる。）

- indexアクションに紐づくindex.html.erbを編集する<br>

@users.eachでuserオブジェクトを一つずつ取り出し、その情報がHTMLタグの中に動的に埋め込まれ、HTMLを組み立てる。

```
<% @users.each do |user| %>
    <li>
      <%= user.name, user %>
    </li>
  <% end %>
```

（データベースに検索されるタイミングはindexアクションでUser.allされたときではなく、検索結果が必要なタイミングで行われるので、今回の場合は@users.eachが呼ばれた時）

- Webサーバからindex.html.erbで組み立てたHTMLをHTTPのレスポンスボディにのせてレスポンスを返す。
- Webブラウザがレスポンスを受け取り、処理して画面にユーザー一覧が表示される。

# タスクを新規作成する（POSTメソッド）
### 新規作成ページを表示する
- `/tasks/new`というパスに対してGETリクエストがWebサーバに送られる。
- WebサーバがGETリクエストを受け取り`routes.rb`の`resources :tasks`により、それに対応するコントローラのアクションが呼び出される。
- コントローラのnewアクションで新しいオブジェクトを作成

```
def new
  @task = Task.new
end
```

### タスク名（name）を入力する
- 入力フォームのHTMLを生成するためnewアクションに紐づくnew.heml.slimを編集する。

 ```
= form_with model: @task, local: true do |f|
  .form-group
    = f.label :name
    = f.text_field :name, class: 'form-cotrol'
  = f.submit nil, class: 'btn btn-primary'
```
- form_withによってこのようなHTMLが生成される。

```
<form action="/tasks" accept-charset="UTF-8" method="post">
　　　　　<input name="utf8" type="hidden" value="✓">
　　　　　<input　type="hidden"name="authenticity_token"value="0/MwK3LxN24WXfQNV5cFYZkbRSoRsL9QEomdh2h+Hr2BpWQqeW95LO7MM4ZZGoz56y+mHx0hMETSwAW18fqKvw==">
     　　<div class="form-group">
       　　　　　<label for="task_name">Name</label>
            　　<input class="form-cotrol" type="text" name="task[name]" id="task_name">
         </div>
         <input type="submit" name="commit" value="登録" class="btn btn-primary" data-disable-with="登録"></form>
```
### 作成ボタンを押す
- form_withで生成されるmethod: postによって、フォーム内容を送信するときにPOSTメソッド指定される。/tasksに対してPOSTリクエストが送られると`routes.rb`の`resources :tasks`で対応する`tasks_controller`のcreateアクションが実行される。
- task_paramsで取得したデータをTask.newの引数にしてインスタンスを作成

```
 def create
    @task = Task.new(task_params)
    if @task.save
      redirect_to @task
    else
      render :new
    end
 end
 
 private
 
 def task_params
   # require(:task)は生成されたHTMLのname="task[name]"のtaskと関連している。
   # permit(:name)で指定したカラムのみ取得する。
   # リクエストボディの「入力されたタスク名」がRailsによりparamsオブジェクトの中にハッシュのような構造で入る
   params.require(:task).permit(:name)
 end

```


### タスク詳細ページに遷移する
- データベースへの保存が成功した場合、リダイレクト先を@taskとすることで詳細ページに遷移する（redirect_to @taskはredirect_to task_url(task.id)と同じ意味を持つ）
Windows Terminalのプロファイル設定

# はじめに

## やりたいこと

* PowerShell、Windows Terminalをインストールする
* Git・Python用のプロファイルを設定する

# 説明

## そもそも、ターミナル(Terminal) と シェル(Shell) とは?

* シェル
    * ユーザがOSを操作するためのインターフェース
    * cf) bash, zsh, powershell
* ターミナル
    * 標準出力を文字として表示したり、キーボード入力を取得したりするプログラム
    * cf) GNOME Terminal, xterm

* 主に、ターミナルを介して、シェルを操作する
* 本記事では、Windows Terminal(ターミナル) を介して、PowerShell、Git Bash(シェル) を操作する。

# 手順

## PowerShell をインストールする

1. Microsoft Store 経由で PowerShell をインストールする
    * ダウンロードサイト [PowerShell を入手 - Microsoft Store](https://www.microsoft.com/ja-jp/p/powershell/9mz1snwt0n5d)
    * デフォルトでインストールされている "Windows PowerShell" は開発が終わっているため、新しく開発が行われている "PowerShell Core" を利用したほうが良い

## Windows Terminalをインストールする

1. Microsoft Store 経由で Windows Terminal をインストールする
    * ダウンロードサイト [Windows Terminal を入手 - Microsoft Store](https://www.microsoft.com/ja-jp/p/windows-terminal/9n0dx20hk701) 

## Gitのインストール

* [Windows10にGitをインストール](https://qiita.com/k5_mot/items/895f2e5d6bcd7dcfea5d)

## Pythonのインストール

* [Windows10にPythonをインストール](https://qiita.com/k5_mot/items/d8264e75ffc2de0da5ec)

## Windows Terminal のプロファイルを設定

1. Windows Terminal を起動
2. 上部の "V" のようなマークをクリック。
3. 左の一番下にある "JSONファイルを開く" をクリック
4. "settings.json" を編集

```json
## ~~~ 省略 ~~~
"profiles": 
    {
        # デフォルトの設定
        "defaults": 
        {
            "acrylicOpacity": 0.9,           # 透過率
            "colorScheme": "One Half Dark",  # カラーテーマ
            "fontFace": "Cascadia Code",     # フォント
            "fontSize": 10,                  # フォントサイズ
            "fontWeight": "normal",          # フォントスタイル
            "padding": "0, 0, 0, 0",         # 余白の指定
            "useAcrylic": true               # 透過を行う
        },
        "list": 
        [
            ## ~~~ 省略 ~~~
            {
                ## Git Bash Profile
                "commandline": "C:\\Program Files\\Git\\bin\\bash.exe",
                "guid": "{ea627c79-2732-4aa7-84be-e6787190da28}",
                "hidden": false,
                "icon": "C:\\Program Files\\Git\\mingw64\\share\\git\\git-for-windows.ico",
                "name": "Git Bash"
            },
            {
                ## Interactive mode Python Profile
                "commandline" : "C:\\Program Files\\Python39\\python.exe",
                "guid" : "{1850e97f-16dc-4281-9ea9-0100c4e852c5}",
                "icon" : "C:\\Program Files\\Python39\\Lib\\test\\imghdrdata\\python.png",
                "name" : "Python",
                "startingDirectory" : "%USERPROFILE%"
            }
        ]
    },
## ~~~ 省略 ~~~
```

# 終わり

本記事は終了です。

# References

* [シェル、ターミナル、コンソール、コマンドライン](https://qiita.com/tadsan/items/441dcd910537d3f408e5)