OmniAICreator/Qiita-1.07M huggingface dataset:
Rubocopを使ったLintチェックのやり方

## Rubocopとは

Rubocop（ルボコップ）とは、Railsアプリ開発において代表的なリンターです。

リンターとは、コードが一定の規則に従っているかをチェックし、従っていなければ違反警告を出してくれるツールです。

ここのコードは長すぎるね。とか、メソッド名変えようか。とか、インデント入れたほうがいいよ。とかをコマンド１つでターミナルに吐き出しててくれます。

これによりコードの書き方を統一できるため、テストと同様に現場では必須のツールです。

## Rubocopを導入するための2ステップ

Rubocopを導入する手順を解説します。

### 手順①：Gemをインストールする

Gemは、Airbnb社が公開しているカスタマイズ済みのrubocop-airbnbというGemを使用するのがおすすめです。

普通にデフォルトのRubocopを導入してもいいのですが、デフォルトに加えてたくさんルールを追加しなければならず手間だからです。

https://github.com/airbnb/ruby/tree/master/rubocop-airbnb

という訳でインストールします。

Gemfile　追記

```
group :development, :test do
 （省略）
 gem 'rubocop-airbnb'  # 追記
end
```

↓

$ bundle install

### 手順②：必要なファイルの作成

Rubocopの導入に必要なファイルを作成します。

.rubocop_airbnb.yml　新規

```
require:
 - rubocop-airbnb
.rubocop.yml　新規

inherit_from:
 - .rubocop_airbnb.yml

Rails:
 Enabled: true
```

以上でRubocopの導入は完了です。

## Rubocopの実行方法

準備は整ったので、Rubocopを実行してみましょう。

Rubocopの実行には「bundle exec rubocop」というコマンドを使います。

```
$ bundle exec rubocop
Inspecting 80 files
.....C...CC.....C...CCC...C...CC...CC.....C...CC....CC.C....
Offenses:
app/helpers/application_helper.rb:2:18: C: Airbnb/OptArgParameters: Do not use default positional arguments. Use keyword arguments or an options hash instead.
def full_title(page_title = '')
               ^^^^^^^^^^^^^^^
（省略）
65 files inspected, 35 offenses detected
```

コマンドを実行することで、ディレクトリ内のコードを全てチェックし、見つかった違反（Offenses）を書き出してくれます。

今回の場合、80ファイルを調べた結果35の違反が見つかったことがわかります。



Rubocopで見つかった違反の対処方法
見つかった違反に対しては、3つのアクションを取ることができます。

【1】ルールに従い、指摘箇所を修正する
【2】「このルールには従わない」という設定を追加する
【3】「このディレクトリはチェックしない」という設定を追加する
【1】は一番素直なパターンです。違反であると指摘されたものに対し、素直に修正します。

ただ、「違反と指摘されたものの、この書き方は変えたくない」というときもあると思います。そういう場合は【2】です。「このRailsプロジェクトではこのルールは無視します」と明示的に設定します。

また、特定のディレクトリはそもそもRubocopチェックをかけたくないという場合もあります。例えば中身が設定ファイルで、厳密に文法をチェックする必要がないときです。その場合は【3】です。

【2】と【3】の場合、rubocop.ymlというファイルに設定を書きます。

.rubocop.yml　追記（下記はあくまで例です）

```
（省略）
AllCops:
 Exclude:
   - 'bin/**'
   - 'config/**/*'
   - 'db/**/*'
   - 'vendor/**/**/*'
   - 'spec/*'
Style/TrailingCommaInHashLiteral:
 Enabled: false
Style/BlockDelimiters:
 Enabled: false
Layout/FirstHashElementLineBreak:
 Enabled: false
Airbnb/OptArgParameters:
 Enabled: false
Style/ColonMethodCall:
 Enabled: false
Layout/IndentationConsistency:
 Enabled: false
Layout/IndentationWidth:
 Enabled: false
Style/MixinUsage:
 Enabled: false
Style/MutableConstant:
 Enabled: false
```

違反の修正が完了したら、もう一度「bundle exec rubocop」を実行して、エラーがなくなったかどうかチェックします。

```
$ bundle exec rubocop
Inspecting 80 files
............................................................
65 files inspected, no offenses detected
```

上記のように「no offenses detected」と表示されたらOKです。


これでRubocopの導入から初期修正は完了です。



## まとめ

Rubocopの導入から初期修正が完了したら、その後は

```
$ bundle exec rubocop
```

上記のコマンドをこまめに実行して、適宜、違反を修正しましょう。

Rubocopは便利ですが実行し忘れで警告がたまってしまいがちです。

のちのち大量の警告を一度に修正するのは面倒なので、「git commitする前は必ずLintチェックする」という習慣をつけると良いと思います。

https://muranakablog.biz/
bundler: failed to load command: fastlane

以下のようなエラーが表示され、bundle exec fastlane xxxが動かなくなりました。

```
[14:28:48]: ▸ bundler: failed to load command: fastlane (/Users/takashi/.rbenv/versions/2.6.0/bin/fastlane)
[14:28:48]: ▸ NoMethodError: undefined method `require_exact=' for #<OptionParser:0x00007ffeda96d3c8>
```

エラーになるコマンドは `sh("bundle", "exec", "fastlane", "子のFastfileにあるlane" )` です。

原因は親Fastfile側のGemfile.lockのbundlerのバージョンと、インポートしている側のGemfile.lockのbundlerのバージョンが異なっていることでした。
Gemfile.lockをすべて削除し改めて、各ディレクトリで bundle installしたら正常に動作するようになりました。
ログデータ処理でBigQueryを試したときの話

## 試した理由

ユーザが過去ログを見る時に、データが多くてもDBの負荷を気にせず処理できて良いのではないか？と、思ったため。

また、料金的にも安くなるのでは？という期待感もあった。

## 試した結果

試したり試算した結果、クエリ課金が結構高くつくので不採用となった。

データ分析などの処理で実行時の料金なども含め、色々と把握してクエリを実行するのであればトータル安くなるのだろうが、ユーザが自由に検索した結果をページングで表示したりする用途には向かないという結論。

ここから下は調べた内容となる。

## 課金ポイント

* データ保持料金
* クエリ実行時料金
* steaming insert
  * 数分単位でのバッチ処理でOKなど、リアルタイム性が不要であれば課金されない

ざっくりと算出したい場合は、下記で入力すれば出る。

[GoogleCloudの料金計算ツール](https://cloud.google.com/products/calculator?hl=ja)

## データ保持料金について

Activeストレージと、LongTermストレージに分かれる。

90日間以上参照されているだけのテーブル or パーティションは自動的にそちらに移動となる。

料金が半額となるため、パーティション分割などで積極的に狙っていきたい。

こちらは恐れるほど高くはならない。

## クエリ実行時料金について

おそらくこちらが高くなることが多いと思われる。

limit句、where句などで絞り込んだとしても、見に行った先にデータがあれば課金対象なので、

テーブル分割や、パーティション分割で絞り込んでおかないと料金が跳ね上がる。

クエリを書いたときは、`dry run` が出来るので、先に捜査されるデータ量を把握すると良いと思う。

* `select * from ... where id=1`
  * 上記の場合、全カラムのバイト数 * 全レコード数
* `select name from ... where id=1`
  * (nameカラムとidカラムのバイト数) * 全レコード数

day1回しか行わないなどでは問題ないが、検索などでクエリを連発すると厳しいことになる。

キャッシュヒットの場合は課金されないので、出来る限りキャッシュヒットする使い方を検討すると多少は費用を削減できる。

[BigQuery におけるコスト最適化の ベスト プラクティス](https://cloud.google.com/blog/ja/products/data-analytics/cost-optimization-best-practices-for-bigquery)

## Node.jsでのコード

### index.ts

```ts
import * as bigquery from '@google-cloud/bigquery'

const datasetId = 'test_db'
const tableId = 'test_table'

async function main (): Promise<void> {
  await uploadData()
  await selectData()
}
main().catch(console.error)

function getClient (): bigquery.BigQuery {
  return new bigquery.BigQuery({ location: 'us-central1', autoRetry: false })
}

// データアップロード
async function uploadData (): Promise<void> {
  const bgClient = getClient()
  const metadata: bigquery.JobLoadMetadata = {
    sourceFormat: 'NEWLINE_DELIMITED_JSON',
    autodetect: false // autodetectがtrueだと、テーブルが無ければ勝手に作られる。
  }
  const result = await bgClient
    .dataset(datasetId)
    .table(tableId)
    .load('aaa.json', metadata) // 中身：{ "name": "nnn", "age": 25 }
  console.log(result[0].status)
}

// データ取得
async function selectData (): Promise<void> {
  const bgClient = getClient()
  const query = `SELECT *
                   FROM \`${datasetId}.${tableId}\`
                  LIMIT 100`

  // 基本0番目のやつしか使わないのに、なぜか配列でJobを返してくる。
  const jobs = await bgClient.createQueryJob({ query })

  const rows = await jobs[0].getQueryResults()

  rows.forEach((row) => console.log(row))
}
```

サンドボックスだとストリーミングインサートはエラーとなるので上記のloadを使った転送方式となっている。

### 前準備と実行

```bash
echo '{"name":"nnn","age":25}' > aaa.json
export GOOGLE_APPLICATION_CREDENTIALS="app-name-12345678.json"
ts-node --transpile-only index.ts
```

## 所感

今回の要件では採用を見送ったが、ドキュメントも日本語で揃っており、使いやすいなぁと思った。

触ってみてRDBMSを使ったことあるなら、サーバ実装などがあっても同じ感覚で作れるなぁという印象。

実際にDDLなんかも使えるようになっていて、SQLも標準SQLのほとんどが使用できるようになっているらしい。

Googleでの改良の方向性もRDBMSに使い勝手を寄せていく方向なんだろうなぁと思った次第です。
[JavaScript] var, let, constの違い

## var, let, const とは
JavaScriptでは、変数や定数を使うときに、変数名を宣言することが推奨されています。
<font color="Red">var</font>、<font color="Red">let</font>、<font color="Red">const</font>は変数を宣言する際に使うキーワードです。

```javascript
var x = 'Hello';
let y = 'Hello';
const z = 'Hello';  // constは初期値省略不可
```
# var, let, const の違い
###1. 再代入、再宣言ができるか
・**再代入**：一度宣言した変数に対して、値を再び代入すること
　再代入可能　⇒　<font color="Red">var</font>、<font color="Red">let</font>
・**再宣言**：一度宣言した変数を同じ変数名で宣言し直すこと
　再宣言可能　⇒　<font color="Red">var</font>
###2.スコープの違い
・<font color="Red">var</font>は**関数スコープ**
　関数内で<font color="Red">var</font>を使って宣言した変数は、関数内のどこからでも呼び出すことが可能。
・<font color="Red">let</font>、<font color="Red">const</font>は**ブロックスコープ**
　同じ関数内であっても、{}で括られたブロックの外側から呼び出すことが不可能。

以上をまとめると以下の表になる

|     |再代入|再宣言| スコープ|
|---  |---   |---  |---     |     
|var  |　〇  |　〇  | 　関数　　|
|let  |　〇  |　× 　| ブロック|
|const|　×   |　×   | ブロック|

#　まとめ
・基本的には、<font color="Red">const</font>を使うのが望ましい。
　<font color="Red">const</font>は、制約が多いため意図しない実装を防ぐことができる。
・変数の中身を更新する必要がある場合は<font color="Red">let</font>を使用。
1が連続しない2進数の数とフィボナッチ数列の関係

以下のような例題を解くことを考えます。
> **例題. $n\leqq2^{20}$で、2進数表記したとき１が連続しない自然数nの数を答えよ**

2進数表記したとき１が連続しないということは、1ビットシフト（2倍）して論理積(&)を取ると0になるということなので。4桁まで求めると以下のように7個になります。

```python
for n in range(1,2**4):
  if n&(2*n) == 0:
    print(f"{n:3} | {n: >10b}")
#  1 |          1
#  2 |         10
#  4 |        100
#  5 |        101
#  8 |       1000
#  9 |       1001
# 10 |       1010
```
さらに5桁目まで求めて各桁ごとの数を見てみると、1,1,2,3,5,...となりこれはフィボナッチ数列？と思わせます。そこでよく見てみると5桁の最初の3つは4桁の数から、後の2つは3桁の数から作られています。

```
  n |  桁数|   2進数
-----------------------
  1 |    1 |         1
-----------------------
  2 |    2 |        10
-----------------------
  4 |    3 |       100 |--------------------+
  5 |    3 |       101 |                    |
-----------------------                     | 左に
  8 |    4 |      1000 |                    | 10をつける
  9 |    4 |      1001 | --+                |
 10 |    4 |      1010 |   |                |
-----------------------    | 左の1を取って  |
 16 |    5 |     10000 +   | 10をつける     |
 17 |    5 |     10001 |<--+　              | 
 18 |    5 |     10010 +                    |
 20 |    5 |     10100 +<-------------------+
 21 |    5 |     10101 |
```

元の例題にもどって、最初のループで$2^{20}$まで走らせてカウントすると$17710$となり、
フィボナッチ数列の$2^{20}$までの和は以下の公式によりK=20のとき$F(22)-1=17710$と一致します。最終的な答えは$2^{20}$自身を加えて$17711$となります。

> $\large \sum_{k=1}^{n}F(k) = F(n+2)-1$

$n=2^{20}$程度では時間にあまり差はでませんが$2^{30}$くらいを超えてくると以下のリンクで紹介した方法等でフィボナッチ数列を計算した方が格段に速くなります。

> [フィボナッチ数列を行列を使ってO(log(n))で計算する](https://qiita.com/masa0599/items/5d412daa96695dea74bf)

この考え方はProuect Euler: Problem 301等を考えるときに役に立つかもしれません。

（開発環境：Google Colab）
Ruby on Rails ~rescue_from~ 

RailsをAPIモードで使用していた時に４００などのエラーリスポンスを書く必要が出てきた。複数のアクション内で同じようなエラー処理になってしまうだろうなあと思ったのでこのような処理を共通化する方法はないだろうかと調べた時に`rescue_from`メソッドに出会った。
[Github](https://github.com/rails/rails/blob/18707ab17fa492eb25ad2e8f9818a320dc20b823/activesupport/lib/active_support/rescuable.rb#L51)

# メソッドの仕組み
Githubの処理を見ていくと、３つの引数をとっている。

## klasses
特定のエラーに対応するクラス名を受け取る。。クラス名そのままでもいいし（クラスとして定義されている定数？）、文字列でも良い。

## with
エラーを補足した際に行うための処理を渡す。メソッドかprocオブジェクト。

## &block
エラーを補足した際に行うためのブロック。
with引数がnilだった場合にこのブロックがwithに代入される。



最後に`rescue_handlers`にクラス名とエラー処理の２つを要素とした２次元配列を代入している。

# 使い方
```ruby
class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

  private

    def record_not_found
      render plain: "404 Not Found", status: 404
    end
end
```

以下のようにカスタム例外クラスも補足できる。

```ruby
class ApplicationController < ActionController::Base
  rescue_from User::NotAuthorized, with: :user_not_authorized

  private

    def user_not_authorized
      flash[:error] = "You don't have access to this section."
      redirect_back(fallback_location: root_path)
    end
end

class ClientsController < ApplicationController
  # ユーザーがクライアントにアクセスする権限を持っているかどうかをチェックする
  before_action :check_authorization

  # このアクション内で認証周りを心配する必要がない
  def edit
    @client = Client.find(params[:id])
  end

  private

    # ユーザーが認証されていない場合は単に例外をスローする
    def check_authorization
      raise User::NotAuthorized unless current_user.admin?
    end
end
```


特定のコントローラだけで行いたい場合はモジュール化してそれを必要とするコントローラ内でインクルードさせるとよい。


```ruby
module ErrorRenderable
  extend ActiveSupport::Concern

  included do
    rescue_from ActiveRecord::RecordNotFound do |e|
      render json: { errors: { title: 'レコードが見つかりません', detail: 'IDと一致するレコードが見つかりません' } }, status: :not_found }
    end
  end
end
```

```ruby
class UsersController < ApplicationController
  include ErrorRenderable

  def show
    @user = User.find(params[:id])
  end
end
```
Python3: MQTT クライアントのサンプル

こちらで定めた仕様を満たすクライアントです。
[IOT: MQTT クライアントのサンプル](https://qiita.com/ekzemplaro/items/949fea7247b90bf531aa)

Raspberry Pi で確認しました。
>GPIO16 に接続した LED を ON/OFF します。

環境設定
ユーザーを gpio グループに所属させます。

```bash
sudo gpasswd -a uchida gpio
```

ライブラリーのインストール

```bash
sudo apt install python3-rpi.gpio
```

プログラム

```py:subscribe_paho.py
#! /usr/bin/python3
#
#	subscribe_paho.py
#
#					Oct/05/2021
# ------------------------------------------------------------------
import paho.mqtt.client as mqtt
import ssl
import sys
import json
import RPi.GPIO as GPIO

broker = "example.com"
topic = "example/test01"

# ------------------------------------------------------------------
def report_proc(on_off):
	rvalue = {}
	rvalue["state"] = {}
	rvalue["state"]["reported"] = {}
	rvalue["state"]["reported"]["led"] = on_off
	str_json = json.dumps(rvalue)
	client.publish(topic, str_json)
# ------------------------------------------------------------------
def led_proc(on_off):
	sys.stderr.write("led_proc " + on_off + "\n")
	if on_off == "on":
		GPIO.output(16,1)
	elif on_off == "off":
		GPIO.output(16,0)
	report_proc(on_off)
# ------------------------------------------------------------------
def on_connect(client, userdata, flags, respons_code):
	print('status {0}'.format(respons_code))
	client.subscribe(topic)

# ------------------------------------------------------------------
def on_message(client, userdata, msg):
	print(msg.topic + ' ' + str(msg.payload))
	bb = msg.payload
	str_json = bb.decode()
	print(str_json)
	try:
		dict_aa = json.loads(str_json)
		state = dict_aa['state']
		if 'desired' in state:
			desired = state['desired']
			on_off = desired['led']
			print(on_off)
			led_proc(on_off)
	except Exception as ee:
		sys.stderr.write("*** error *** in json.loads ***\n")
		sys.stderr.write(str(ee) + "\n")
	print()

# ------------------------------------------------------------------
sys.stderr.write("*** subscribe_paho *** start ***\n")
GPIO.setmode (GPIO.BCM)
GPIO.setup (16,GPIO.OUT)

client = mqtt.Client(client_id= "python",protocol=mqtt.MQTTv311)

client.on_connect = on_connect
client.on_message = on_message

#client.connect(broker, port=port, keepalive=6)
client.connect(broker, keepalive=6)
client.loop_forever()
#
sys.stderr.write("*** subscribe_paho *** end ***\n")
# ------------------------------------------------------------------
```
[Rails] 言語切り替え機能

PFに言語切り替え機能を実装した時のメモ。
※日本語化対応は既に実装されていることを想定しています。
# 完成イメージ
![言語切り替え.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/974719/9dac2564-a262-86dc-c057-a72e1a3746a2.gif)



# 実装と解説
言語切り替えはURLにパラメーターをつけることで切り替えます。
例えば日本語なら`exapmle.com/?locale=ja`英語なら`exapmle.com/?locale=en`みたいな感じです。

### ① application_controller

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :set_locale

  def default_url_options
    { locale: I18n.locale }
  end

  private

  def set_locale
    I18n.locale = params[:locale] || I18n.default_locale
  end
end
```

### 解説
```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :set_locale

  private

  def set_locale
    I18n.locale = params[:locale] || I18n.default_locale
  end
end
```

`set_locale`にはURLにパラメーターをつける処理を書いています。
具体的には、`exapmle.com/?locale=ja`のようにURLにパラメータが付いているならそれを使い、なければデフォルトのパラメーターなしのURLを使うという処理です。
なぜ`application_controller.rb`の`before_action`に`set_locale`を指定しているのかというと、
`application_controller.rb`は全てのcontrollerに継承されている。つまり全てのcontrollerの実行前に`set_locale`が実行されるという仕組みです。

```ruby:app/controllers/application_controller.rb
  def default_url_options
    { locale: I18n.locale }
  end
```

`default_url_options`はデフォルトで必ず実行されるメソッドらしいので、
ここで書いているのは`exapmle.com/?locale=ja`のようなパラメータをデフォルトの状態、つまり最初にサイトにアクセスしたときから付けるという処理です。

### ② 言語の.ymlファイルの作成
今回は日本語と英語で言語を切り替えるのでconfig/localesにja.ymlとen.ymlファイルを作成し各言語を記述していきます。
※今回は完成イメージのように検索ページのタイトル部分を変更することを想定しています。

```ruby:config/locales/events.ja.yml
ja:
  events:
    search-title: "イベントを探す"
```

```ruby:config/locales/events.en.yml
en:
  events:
    search-title: "Search Event"
```

### ③ 該当箇所のHTMLを書き換え
今回言語切り替えがしたい**イベントを探す**の部分を書き換えていきます。

(変更前)

```ruby:app/views
.title
  %h2 イベントを探す
```

(変更後)

```ruby:app/views
.title
  %h2= I18n.t('events.search-title')
```

### 解説
```ruby
I18n.t('events.search-title')
```
ここで先ほど作成したlocalesのファイルにあるeventsのsearch-titleの部分を指定しています。

### 言語切り替えボタンの作成
あとは言語切り替えのためのボタンを作って完成です。
ボタンは全ページに設置したいので`app/views/layouts/aplication.html`の部分に記述します。

```ruby:app/views/layouts/aplication.html.haml
%lang.lang-container
  - if I18n.locale == :en
    = link_to '日本語', url_for(locale: :ja)
  - else
    = link_to 'English', url_for(locale: :en)
```

`link_to`の`url_for`を使うことでパラメーターのみの変更が可能です。

これで完成。
[Rails] jQueryで画像プレビュー機能を実装する

RailsのポートフォリオにjQueryを使って画像プレビュー機能を実装した時のメモ。
# 完成イメージ
![画像プレビュー.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/974719/d23d5533-21fb-d5bf-57e5-39a05e51756f.gif)


# 実装と解説

### ①HTMLにID付与
まずは画像プレビューを付けたい箇所にidを付与します。
idをつけることでjQueryを反映させる目印になります。

idをつけるのはイメージを反映する場所の`image_tag`と`file_field`
これから実装するjQueryのファイルを読み込むのも忘れずに！

```ruby:app/views
.form.text-center
  = image_tag event.eyecatch_image, id: 'preview', class: 'preview-image'
.form.text-center.mt-5
  = f.file_field :eyecatch, id: 'input-file'

= javascript_pack_tag 'image-preview'
```

### ②jQueryで画像プレビュー
jQueryで画像プレビューできるようにしていきます。


```javascript:app/javascript/packs/image-preview
import $ from 'jquery'

$('#input-file').on('change', function (e) {
  var reader = new FileReader();
  reader.onload = function (e) {
      $("#preview").attr('src', e.target.result);
  }
  reader.readAsDataURL(e.target.files[0]);
}); 
```

1行ずつ詳しく解説していきます。

`input-file`というidに変化があれば実行される関数を定義。

```javascript:
$('#input-file').on('change', function (e){

}
```

`FileReader`でファイルの読み込みができるように、それを`reader`として変数に格納。

```javascript:
var reader = new FileReader();
```

格納した`reader`に`onload`を使って、読み込みが可能になったら実行とする関数を定義。

```javascript:
reader.onload = function (e) {

}
```

読み込んだ画像ファイルの結果を`preview`というidを持つ部分に表示

```javascript:
$("#preview").attr('src', e.target.result);
```
最後にさっき読み込んだファイルを`readAsDataURL`で実際に読み込むことで反映。

```javascript:
reader.readAsDataURL(e.target.files[0]);
```

### ③スタイル調整
画像表示する部分のスタイルを設定して完成です。
これはお好みでどうぞ！

```ruby:app/assets/stylesheets
.preview-image {
  width: 40%;
  height: auto;
}
```
ruby 豆知識 ~klass~

railsのGithubを見ていたら、`klasses`,`klass`というキーワードに出会った。
これは何を意味しているんだろう、クラスのことかな？と思ったら本当にクラスのことだった。

rubyや他の言語では、`class`は予約語として定義されている。
そのため、変数名だったりとして　`class`を用いることはできない。
そこで、`klass`というキーワードを使ってその変数にはクラスが渡されることを示唆しているらしい。
xamppとLaravelで環境構築したらhello worldがうまく画面に表示できなかった件

バージョン
xampp　3.3.0
laravel 8.62.0


##まず下記を参考に環境構築をする
https://snome.jp/framework/laravel-screen-display/

するとhello worldが表示されず下記エラーになる

```php
lluminate\Contracts\Container\BindingResolutionException
Target class [TestController] does not exist.
```

なぜか調べるとなんだかLaravelのバージョンが8になってルーティングの記載方法が変わったらしい。

ver7.x

```php:web.php
Route::get('test/func','TestController@func');
```
ver8.x

```php:web.php
Route::get('test/func', [TestController::class, 'func']);
```

~~しかしなぜかバージョン8の記法に変えてもエラーのまま。。。。~~
👆TestControllerをuseしていないことが原因(下記記載方法はフルパスだからuse無しでも大丈夫なのかな？)
そこで下記の記載もできるようなのでやってみると。。

```php:web.php
Route::get('test/func','App\Http\Controllers\TestController@func');
```

Hello　Worldが無事表示された！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544175/f5af1c2c-aa75-3d11-c700-7615a90e9f9a.png)

~~※なぜ新記法で表示されないのか知っていたら教えて下さいませ:disappointed:~~

参考

https://blog.capilano-fw.com/?p=7799#i-6

https://teratail.com/questions/292482#reply-413765
Windows 版 Microsoft Teams Desktop アプリ版のキャッシュをクリアする

# 背景
Teams を使用する際には、複数の方法が用意されています。これは、**可用性** 観点では良いのです。ですが、データがおかしい場合にはユーザーとしては大変困ります。

特に常駐が便利であるため Desktop 版を使う場合が多いのではないでしょうか?

その扱うデータ量が増える傾向にあるため、ローカルにキャッシュを持っています。 ここでは、**Windows** 版に限ってのキャッシュクリアの方法を示します。

# 注意事項

- **自己責任**でお願いします。私の所属企業とは一切関係がありません😅
- Teams のアプリケーションの**アンインストール** されます。
- Teams のカメラでの**背景の画像 [背景フィルター]** も消えます。

# 手順

## 1. Teams のアプリケーションの停止

アプリケーションを停止させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/158e5596-3333-ab5c-fca6-58afb5d7f12e.png)

Teams のアプリがまだ動いているかどうかは [タスクマネージャー] で確認できます。
こちらは、**動いている時** の様子です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/fe92b146-b1c5-6775-8c83-8622fa147e68.png)

停止していると **Teams.exe** は表示されません。

## 2. キャッシュファイルの削除

以下のコマンドで、ファイルを削除します。
Teams のプロセスが残っていると一部のファイルの削除が出来ない場合があります。その際には、再度コマンドを実行してください。

```cmd
rd /s /q %AppData%\Microsoft\teams
rd /s /q %LocalAppData%\Microsoft\teams
```

私は、**.bat ファイル** にしていつでも実行できるようにしています😎

## 3. Teams アプリケーションの再インストール

公式サイトからダウンロードして再インストールします。

https://www.microsoft.com/ja-jp/microsoft-teams/download-app#desktopAppDownloadregion

- 適時設定をし直す
    - [背景フィルター] - これは初回の Teams Meeting 時ですね😊
    - Teams 会議の背景を変更する
        - https://support.microsoft.com/ja-jp/office/teams-%E4%BC%9A%E8%AD%B0%E3%81%AE%E8%83%8C%E6%99%AF%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B-f77a2381-443a-499d-825e-509a140f4780

# まとめ

似た挙動の Outlook がそうでしたが、今後、キャッシュの扱いなどがこなれてくると、公式ドキュメントに手順として反映されたり、ツールが出てくるかもしれません。


Teams のトラブルシューティング:
https://docs.microsoft.com/ja-jp/MicrosoftTeams/troubleshoot/teams-welcome
cssを使って非表示にするテクニック

# カンマの使い方

カンマを置くたびに、マッチングが最初からやり直されるからです。カンマの前の前の式でターゲットを取得しません。

```
.comm-page-detail-500 .button, 
.comm-page-detail-500 [role="button"], 
.comm-page-detail-500 [title="Add Files"] 
{
display:none;
}
```

[Add Files button](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Bsa9nSAB)
メタタグについて

##

```html
<meta name = "keywords" content="メタキーワード">
<meta name = "keywords" content="メタキーワード1,メタキーワード2,メタキーワード3">
```


メタタグの1つで、そのページがどんなキーワードと関連したページなのかを示すタグのこと
キーワード数は2～3つ程度、多くても5つ以内が推進

今は効果が無くなってしまったことがGoogleから名言されている
昔は、メタキーワードはページ内の重要なキーワードを検索エンジンに伝える役割を担っていた

###なぜ？
検索エンジン自体がアップデートされた
ページの内容とメタキーワードが一致しない、メタキーワードを大量に詰め込むようなメタキーワードの悪用

だから現在のGoogleにおいてはメタキーワードを認識していない


##メタディスクリプション

```html
<meta name = "description"  content = "メタディスクリプション">
```

ユーザーがどんなページなのか判断できるよう、検索結果にページの要約文を表示させるもの

ページコンテンツを100文字程度の文章で表した「概要」や「要約」のようなもの
スマホ　90文字
PC　120文字

前半50文字に重要な文章

Googleのような検索エンジンの検索結果一覧ページで活用される

タイトルの下に表示される

現在、検索順位が上下することはそれほどない
ユーザに対してどう見えるかが大事
PHPで10文字以上の文章なら...をにする

##PHPで10文字以上の文章なら...をにする方法

```PHP

//整形したい文字列
 $textLimits = $val ["TITLE"];
//文字数の上限
$limit = 10;
                            
// 文字数10以上ならば、...に変換　
if(mb_strlen($textLimits) > $limit) { 
  $title = mb_substr($textLimits,0,$limit);
  echo $title. "..." ."</a>" ;
} else {
  echo $textLimits. "</a>";
}


//整形したい文字列
$textLimits = $val ["TITLE"];
//文字幅の上限
$limit = 10;
                            
// 文字幅が10以上ならば、...に変換　半角が1　全角が2
if(mb_strwidth($textLimits) > $limit) {
// 文字列を文字幅上限に丸める
$title = mb_strimwidth($textLimits,0,$limit);
  echo $title. "..." ."</a>" ;
} else {
  echo $textLimits. "</a>";
}
```
gitコマンド

コマンド忘れて毎回調べてるので箇条書きでまとめました。

#よく使うコマンド
```

git init　//既存のディレクトリをgitに登録
git remote add origin [リモートリポジトリのURL] //リモートリポジトリを追加
git remote -v　//現在のリモートリポジトリを確認
git add .　
git commit -m "first commit"
git branch -M main
git checkout -b main
git push -u origin master　//push
git push --set-upstream origin main //初期commitの時は上流ブランチがないとかでエラーがでるのでこっちを使うといいかも

```





```
git log
git reset --soft HEAD^ //commitを取り消せる
git reset --hard HEAD　//
git update-ref -d HEAD //first commit だけは上記のresetで消せないのでこのコマンドを使う

```

#Git Large File Storage
ファイルサイズが100 MBを超えるとgithubに上げられなくなるので以下を利用する必要がある。

https://git-lfs.github.com/
上記のサイトでダウンロードインストールを行った後以下のコマンド

```

git lfs install
 git lfs track "*.psd"　//追加した拡張子をlfsで管理するようになる。lfsで管理されたものは100mbを超えてもよくなる。

```

以下参考

https://vastworld.org/file-size/
RailsのAPI用のControllerをつくる

#RailsのAPI用のコントローラーをつくる
備忘録です。

- api/v1/mobile/以下に`dictionaries_controller.rb`を作成したい。
- jsやviewやhelperを作成したくない。

場合のコントローラーの生成方法です。

````
rails g controller api::v1::mobile::dictionaries --no-helper --no-assets --no-view-specs --skip-template-engine
````

またAPI用のコントローラーを生成したあとは、ApplicationControllerからActionController::APIを継承するように手動で設定し直すことを忘れずに。
AWS Systems Manager + Ansible 

## 概要

system managerからansibleをEC2インスタンスに対して実行することができます。ssh鍵不要である点がとても嬉しいです。

## 使い方

- ansibleのソースコードはs3またはgithubにおく
    - s3の場合はzipファイルをアップロードする
- system manager ⇒ Run Commandで設定をする
    - コマンド ドキュメント
        - AWS-ApplyAnsiblePlaybooksを選択
    - コマンドのパラメータ
        - イメージは以下
        
            ```
'{"Check":["False"],"PlaybookFile":["/playbook/ec2.yml"],"SourceType":["S3"],"SourceInfo":["{\"path\":\"{{S3のURL}}\"}"]]}'
```
        - Source TypeでS3を選択
        - Source InfoにS3のzipファイルurlを入力
        - install dependenciesをtrueにする
            - 依存関係の解決
        - Playbook Fileにてplaybookのyamlファイルのパスを指定する

    - ターゲット
        - 実行するEC2を選択
    - 実行する

## やってみた

実行したansibleは以下のもの

- nginxのインストールと実行をするansibleサンプル

[https://github.com/ryo-hagiwara-fate/ansible_nginx](https://github.com/ryo-hagiwara-fate/ansible_nginx)

- zipファイルにする

```bash
zip -r ファイル名.zip フォルダパス
```

- s3にアップロードする

```bash
aws s3 cp ファイル名.zip s3://バケット名/ --acl public-read
```

- System Managerで設定する
    - Source Infoの書き方は`{"path":s3にアップロードしたzipファイルのurl}`
    - Playbook Fileのパスに関して今回は「playbook/ec2.yml」となる
- 確認
    - EC2インスタンスのpublic IPまたはDNSにアクセスするとnginxの画面が現れる。

## 注意点

- EC2インスタンスのインスタンスプロファイルに「S3ReadOnlyAccess」権限を付与すること
- ansibleのhostsはallにする。

## レポート

- ssh鍵なしでansible実行できる。
- 今まではinventoryで実行するインスタンスのipアドレスを入力する必要があったがそれが不要。シェルスクリプトでいちいちやる必要がなくなった。
- 感覚的にはopsworksのansible版。opsworksはchefで、system managerはansibleでできる。

## 自動化できました
今回はAWSのコンソールでポチポチ設定するような形式でしたが、AWS CLIでも同じことができます。そのサンプル作成しました。

https://github.com/ryo-hagiwara-fate/phpMyAdmin_ansible

以下のようにしてAWS CLIで実行できます。プレイブックのzip化、s3アップロードなどもスクリプトにかけば全工程をコマンド一発で自動化できる。

```
# systems manageの設定
PARAMETER='{"ExtraVariables":["SSM=True"],"Check":["False"],"PlaybookFile":["/playbook/ec2.yml"],"SourceType":["S3"],"SourceInfo":["{\"path\":\"{{S3のURL}}\"}"],"ExtraVariables":["hostname='${RDSなどのホスト名}'"]}' && echo ${PARAMETER}

# SystemsManagerコマンド実行
aws ssm send-command --document-name "AWS-ApplyAnsiblePlaybooks" --instance-ids "${INSTANCE_ID}" --parameters ${PARAMETER} --profile ${PROFILE}
```

## 参考文献

[Ansible使いの人はちょっと見逃せない。AWS Systems Managerで複雑な構成のAnsible-Playbookの実行が可能になりました](https://dev.classmethod.jp/articles/systems-manager-to-execute-complex-ansible-playbooks/)
[Ansible プレイブックを実行する関連付けの作成](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-state-manager-ansible.html)
CloudFormation のメモ



https://dev.classmethod.jp/articles/cloudformation-tips-focused-on-refs/



https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html



https://qiita.com/namoshika/items/528d8a50f399b998b14b#ref



https://qiita.com/NaGym_t/items/8b4f4dcc489364313da3



https://awspolicygen.s3.amazonaws.com/policygen.html



https://1000ch.github.io/yaml-json/



https://adrianhesketh.com/2020/10/10/pen-test-passing-s3-bucket-cloudformation-config/




https://dev.classmethod.jp/articles/guardduty-export-s3/
【備忘録】MySQLデータ移行(Aurora Serverless)

## 概要
Aurora Serverlessから別のAurora Serverlessへのデータ移行を行う業務を担当した際ポイントに感じたことまとめ

### mysqldumpを使う

バックアップ及びデータの復元に使う。mysqlをインストールした時点で使える。以下のコマンドを実行することでDBのテーブル定義と既存のデータを取得してファイルに出力してくれる。

```bash
mysqldump -u #{ユーザー名} -p #{コピーしたいDB名} > ファイル名.sql
```

### Auroraで行う場合は -skip-column-statisticsオプションを追加する。

mysqldump8以降でそれ以前 (5.7とか) のMySQLサーバに対してダンプを実行したらこの問題が起こるらしい。Auroraは現在Mysql5.7(2020年12月)。

```bash
mysqldump -u #{ユーザー名} -h#{AuroraのEndpoint} -p #{DB名} > ファイル名.sql --skip-column-statistics
```

ちなみにAuroraは通常プライベートサブネットに配置されているため、外からこのコマンドを投げることはできない。Auroraが存在するVPCにVPN接続するか、踏み台サーバーを使う。セキュリティグループのインバウンド設定を忘れずに

### 出力されたファイルの中身

vimコマンドなどで開いてみる。テーブルを一回破棄してその後改めて新規作成し、その新規テーブルにinsertさせることで復元するというロジックみたい。


## データ復元

mysqlコマンドにmysqldumpで出力したsqlファイルを渡して実行させればOK。

```bash
mysql  #{移行先のAuroraのユーザー名} -h#{移行先のAuroraのEndpoint} -p #{DB名}  < mysqldumpで出力したsqlファイルを指定
```

### Access denied; you need (at least one of) the SUPER privilege(s) for this operationについて

下記のようなSuper権限でしか実行できないSQL文がmysqldumpの出力したファイルには入ってしまっている。エラー箇所はat lineに記載されているので消去していけば実行できる。

```sql
SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN;
```

### 参考文献

[【MySQL】DBをコピーする（mysqldump）](https://qiita.com/oden141/items/793a256696fd1d6622ae)
Scipyを用いた補間処理（線形補間、スプライン補間）

#Scipyを用いて補間処理を行う

「補間計算をPythonのScipyを用いてとりあえず実装してみたい！」という方向けです。
まずは、補間計算について。以下のコードを実行して、グラフを描画してみます。

```python
#ライブラリの読み込み
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt

# xとして、linspaceで、開始が0、終了が10、項目が11個の等間隔数列を生成
x = np.linspace(0, 10, num=11, endpoint=True)
# yの値を生成
y = np.cos(-x ** 2.0 / 10.0)
plt.plot(x, y, 'o')
plt.grid(True)
```
![スクリーンショット 2021-10-05 12.27.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1859982/89e2e089-5986-a5bc-08d7-c7e0209649d2.png)

左から順に点を見ていくと、何かの曲線を表しているようにも見えます（自身で作成した点ですが、とりあえず「点のデータのみ持っている」という前提で進めます）。
このようなグラフにおいて、「$x$が2.5のとき」など、点と点の間にある$x$に対応する$y$はどのような値をとるのだろうか？　これを考えるのが`補間計算`です。

## 線形補間
Scipyでは、データ間の補間は`interp1d`で計算できます。たとえば、以下では点と点の間を1次式でつないで補間（線形補間）しています。

```python
from scipy import interpolate

# 線形補間の場合、interp1dのパラメータとして「linear」を指定する
f = interpolate.interp1d(x, y, 'linear')
plt.plot(x, f(x), '-')
plt.grid(True)
```
![スクリーンショット 2021-10-05 12.37.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1859982/bfba2894-5850-03f9-5037-6a2626d3912c.png)

## 3次スプライン補間
次に、スプライン3次補間も加えて、グラフを描画します。スプライン3次補間は、点と点の間を3次の多項式で補間する手法です。

```python
# スプライン3次補間を計算してf2として追加する。パラメータは「cubic」を指定。
f2 = interpolate.interp1d(x, y, 'cubic')

#曲線を出すために、xの値を細かくします。
xnew = np.linspace(0, 10, num=30, endpoint=True)

# fを直線で描き、f2を点線で描きます。
plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')

# 凡例
plt.legend(['data', 'linear', 'cubic'], loc='best')
plt.grid(True)
```
![スクリーンショット 2021-10-05 12.42.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1859982/1d569b4e-ab2b-80b6-202e-4eedda613c2e.png)
上のグラフでは、スプライン３次補間の方が良い補完に見えます。
ただし、あくまでこの補間した曲線は現在のデータすべてを利用して曲線を引いており、これが新しい未知のデータに対して当てはまるとは限りません。

# まとめ
PythonのScipyを用いて、簡単な補間処理を行いました。補間処理は機械学習でも重要なので、様々な手法を知り、特徴を生かすことが大切に思われます。本記事がそのような目的の第一歩の手助けになれば幸いです。

参考記事
[数値補間手法の食べ比べ](yberagent.co.jp/careers/special/students/tech/)
[スプライン補間](http://www.yamamo10.jp/yamamoto/lecture/2006/5E/interpolation/interpolation_html/node3.html)
【Vue.js】単一ファイルコンポーネントの作成

#はじめに
こんにちは。
Vue.jsの単一ファイルコンポーネントを作成していきます！

##単一ファイルコンポーネントとは
HTML、CSS、JavaScriptを一つのファイルとして作成できる、拡張子が`.vue`のVue.jsコンポーネント。
<br>


##単一ファイルコンポーネントの利用
VueCLIをインストールしたフォルダに、`Hello`と表示させるコンポーネントを作成する。階層構造の一部は以下のようになります。

>src/
　├ App.vue
　├ components/
　│  ├ HelloWorld.vue
　│  └ Hello.vue（追加）
　└ views/
　　   ├ Home.vue
　  　└ About.vue


```javascript:Hello.vue
<template>
  <div>
    <h1>Hello!</h1>
  </div>
</template>

<script>
export default {
}
</script>

<style scoped>
</style>
```

新規追加したファイル`Hello.vue`に最低限の単一ファイルコンポーネントを作成します。

<br>

```javascript:Home.vue
<template>
  <div class="home">
    <Hello/>
  </div>
</template>

<script>
// @ is an alias to /src
import Hello from '@/components/Hello.vue'

export default {
  name: 'Home',
  components: {
    Hello
  }
}
</script>
```
VueCLIで生成された`Home.vue`のdivタグ内、import、componentsの記述を修正して、Helloコンポーネントが表示されるようにする。

<img width=“200” src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/af4eb743-17a0-cd84-bd01-e3616237a0d4.png">

#最後に
ここまで単一ファイルコンポーネントについてまとめました！
VSCodeサイドバーの「ソース管理」が2つに分かれてしまったときの直し方

VSCodeでGitlens使用時に発生し、それなりに困ったので共有します。
## 問題
本来なら1つにまとまっているサイドバーの「ソース管理」が2つにわかれてしまった。
未コミットの変更だけ別タブになっていて操作が手間。
![スクリーンショット 2021-10-05 11.59.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48189/f7fb76d0-058b-2118-f5e0-331e08271396.png)
![スクリーンショット 2021-10-05 11.59.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48189/4b2451a9-968f-0970-6412-368fc0ff9ec5.png)
　↑ソース管理を右クリックすると表示非表示する項目を選択できますが、わかれてしまった項目は表示されません。
## 解決法
サイドバーのソース管理を右クリック→どちらかに「場所のリセット」があるのでクリックする。
![スクリーンショット 2021-10-05 11.59.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48189/748e1ae4-e69f-8d11-d5c5-d5a6033a0383.png)
これで一つにまとまるはずです。
## 原因
何かの拍子に「ソース管理」をサイドバーにD&Dしていたらしい。
![スクリーンショット 2021-10-05 12.19.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48189/b779964f-9e0f-b284-5088-120b0d1afda1.png)
## Gitlensのレイアウトについて
Gitlensのレイアウトは2パターンあります。
![スクリーンショット 2021-10-05 12.24.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48189/cfee9e01-554e-a77a-5dc2-37e54a26ae91.png)
GitlensLayoutは少し前の仕様(おそらく)で、サイドバーのメニューはGitlensで独立します。
一方SourceControlLayoutは拡張機能を入れてない状態の「ソース管理」とGitlensを統合したレイアウトで、現在のデフォルトはこちらです。
SourceControlLayoutになっているにもかかわらず、Gitlensと「ソース管理」がわかれてしまった場合は、知らないうちにD&Dしてしまっている可能性があります。
[m1]asdfでバージョン管理を行なったterraformを使うまで[mac]

https://qiita.com/sugo/items/eb69fad41ffe753dd489

https://qiita.com/sugo/items/54b8e88e0d6a9656777d

この流れ

# 前提
- asdfインストール済み
    - 未インストールの場合、冒頭のnodejsの記事を参照してasdfを導入する

# 環境
- MacBook Air (M1, 2020)

# terraform

現状確認

```sh
% asdf plugin list
nodejs
python

% asdf list
nodejs
  14.17.4
  16.2.0
  16.3.0
python
  3.8.10
  3.9.5
```

プラグイン追加

```
% asdf plugin add terraform
```

プラグイン追加されたの確認

```
% asdf plugin list
nodejs
python
terraform
```

最新版確認

```
% asdf latest terraform
1.0.8
```

最新版インストール

```
% asdf install terraform latest
```

インストールされたの確認

```
% asdf list
nodejs
  14.17.4
  16.2.0
  16.3.0
python
  3.8.10
  3.9.5
terraform
  1.0.8
```

プライマリバージョン設定

```
% asdf global terraform 1.0.8
```

バージョンとかそれぞれ確認

```
% asdf current
nodejs          16.3.0          /Users/ユーザー名/.tool-versions
python          3.9.5           /Users/ユーザー名/.tool-versions
terraform       1.0.8           /Users/ユーザー名/.tool-versions

% asdf current terraform
terraform       1.0.8           /Users/ユーザー名/.tool-versions

% cat ~/.tool-versions
nodejs 16.3.0
python 3.9.5
terraform 1.0.8

% terraform -v
Terraform v1.0.8
on darwin_arm64
```

これでterraform入門できる
【iOS】RxSwiftを使ってMVVMなカウントダウンタイマーの作り方

# リアクティブなカウントダウンタイマーの作り方

手書きでQiita書いたので誤字脱字あったらお許しください...

### ViewController

```swift:ViewController.swift

class ViewController: UIViewController {

  @IBOutlet private weak var countLabel: UILabel!
  @IBOutlet private weak var startButton: UIButton!
  @IBOutlet private weak var stopButton: UIButton!

  private var viewModel: ViewModel!
  private let disposeBag = DisposeBag()

  override func viewDidLoad() {  
    super.viewDidLoad()
    setupViewModel()
  } 

  private func setupViewModel() {
    let input = ViewModel.Input(
      startButtonTapped: startButton.rx.tap.asObservable(),
      stopButtonTapped: stopButton.rx.tap.asObservable()
    )
    viewModel = ViewModel(trigger: input)
    // output
    viewModel.output().count
      .map { "あと：\($0)秒" }
      .bind(to: countLabel.rx.text)
      .disposed(by: disposeBag)
  }
}

```

### ViewModel

```swift:ViewModel.swift

class ViewModel {

  struct Input {
    var startButtonTapped: Observable<Void>
    var stopButtonTapped: Observable<Void>
  }

  struct Output {
    var count: Observable<Int>
  }
  
  private var input: ViewModel.Input!
  private var output: ViewModel.Output!
  
  private let isTimerActionSubject = PublishSubject<Bool>()
  private let countRelay = BehaviorRelay<Int>(value: 60) // 初期値: 60秒 (任意)

  private let disposeBag = DisposeBag()

  init(trigger: ViewModel.Input) {
    input = trigger
    output = ViewModel.Output(
      count: countRelay.asObservable()
    )

    bind()
    setupTimer()
  }


  // MARK: Actions
  private func bind() {
    // start button tapped
    input.startButtonTapped
      .map { true }
      .bind(to: isTimerActionSubject)
      .disposed(by: disposeBag)

    // stop button tapped
    input.stopButtonTapped
      .map { false }
      .bind(to: isTimerActionSubject)
      .disposed(by: disposeBag)
  }
  
  // MARK: Timer
  private func setupTimer() {
    isTimerActionSubject.asObservable()
            .flatMap { $0 ? Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance) : .empty() }
            .withLatestFrom(countRelay) { $1 - $0 }
            .bind(to: countRelay)
            .disposed(by: disposeBag)
  }

  // MARK: -- OUTPUT
  func output() -> ViewModel.Output {
    return output
  }
  
}

```

:::note info
こんな感じで動くかと！！
ぜひ試してみてください😁
:::

### 参考
[RxSwift | GitHub](https://github.com/ReactiveX/RxSwift)
[[iOS] RxSwiftのIntervalオペレータを使用して一定間隔で処理を行う](https://dev.classmethod.jp/articles/ios-periodic-processing-with-rxswift-interval/)
[【iOS】MVVMについて](https://qiita.com/s_emoto/items/b000a5c076f3d6076972)
【備忘録】LightGBMインポートでエラー 

### 結論
LightGBMをインストールする際はとりあえずpipではなく、ちゃんとLightGBMのリポジトリに記載されている手順に従うこと！

https://github.com/microsoft/LightGBM/blob/master/docs/Installation-Guide.rst#apple-clang

### エラー内容
環境はMacOS。LightGBMを使いたかったのでpipでインストール。インストールの際は特にエラーはなかった。

```
pip install lightgbm
```
しかしimportしようとするとOSError `(OSError: dlopen ~ Library not loaded ~ Reason: image not found)`が起こってしまった。

```python
#[IN]:
import lightgbm as lgb
```
エラーは以下のようなかんじ。

```
dlopen(/Users/*site-packages/lightgbm/lib_lightgbm.so, 6): Library not loaded: */libomp/lib/libomp.dylib Referenced from: /Users/*/opt/anaconda3/lib/python3.6/site-packages/lightgbm/lib_lightgbm.so Reason: image not found
```

このエラーをネットで検索するとそこそこヒットするため多くの人が遭遇している可能性あり。
### 解決方法
3ステップで解決。

1. `libomp` をインストール
2. `LightGBM`をアンインストール
3. `LightGBM`を再びインストール

#### 1. libompをインストール

```shell
brew install libomp
```

[LightGBMのリポジトリ](https://github.com/microsoft/LightGBM/tree/master/python-package)に以下の内容が記載されていた。

>For macOS (we provide wheels for 3 newest macOS versions) users:

>Starting from version 2.2.1, the library file in distribution wheels is built by the Apple Clang (Xcode_8.3.3 for versions 2.2.1 - 2.3.1, and Xcode_9.4.1 from version 2.3.2) compiler. This means that you don't need to install the gcc compiler anymore. Instead of that you need to install the OpenMP library, which is required for running LightGBM on the system with the Apple Clang compiler. You can install the OpenMP library by the following command: brew install libomp.
For version smaller than 2.2.1 and not smaller than 2.1.2, gcc-8 with OpenMP support must be installed first. Refer to Installation Guide for installation of gcc-8 with OpenMP support.
For version smaller than 2.1.2, gcc-7 with OpenMP is required.

どうやらLightGBMをMacで実行するためにはOpenMPライブラリをインストールする必要があるらしい。ということで書かれている通りにlibompをhomebrewでインストール。

#### 2. 一旦LightGBMをpipでアンインストール
LightGBMをアンインストールします。

```
pip uninstall lightgbm
```
#### 3. 再びLightGBMをインストール
libompがインストールされている状態でLightGBMをインストールします。これでエラーは解消しました！

```
pip uninstall lightgbm
```

### 参考
https://cocoinit23.com/mac-lightgbm-image-not-found/
https://aotamasaki.hatenablog.com/entry/2018/08/05/215612
画面遷移時にタスクを破棄する方法

## 使い所
何度かの画面線時に一つ前の画面にもどらず初期の画面に戻りたい場合にタスクを破棄してあげれば、初期画面に戻れます

```
startActivity(Intent(context, MainActivity::class.java).addFlags(FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK))
```
【R】データ集計(未編集)


h_num_list<-(1:100)

#start_MOR
start_MOR<-data.frame()

for (list_num in h_num_list) {
  
  h_num_data<-table[table$h_num==h_num,]
  h_num_data_start<-h_num_data[1,]$MOR
  start_tmp<-data.frame(list_num)
  colnames(start_tmp)<-c("start")
  start_MOR<-rbind(start_MOR,start_tmp)
}

#end_MOR
end_MOR<-data.frame()

for (list_num in h_num_list) {
  
  h_num_data<-table[table$h_num==h_num,]
  end_row<-nrow(h_num_data)
  h_num_data_start<-h_num_data[end_row,]$MOR
  end_tmp<-data.frame(list_num)
  colnames(end_tmp)<-c("end")
}

#start_O
start_O<-data.frame()

for (list_num in h_num_list) {
  
  h_num_data<-table[table$h_num==h_num,]
  h_num_data_start<-h_num_data[1,]$MOR
  start_tmp<-data.frame(list_num)
  colnames(start_tmp)<-c("start")
}

for (h_data in h_list) {
  
}

h_start<-
h_cp<-
h_cp_data<-rbind(h_start,h_cp)
row_num<-nrow(h_cp_data)


o_diff<-data.frame()

for(h_list in 1:(row_num-1){
  
  diff<-h_cp_data[(h_list+1),]$O-h_cp_data[h_list,]$O　
  
  data.frame(diff)
  cbind()

}
bind_rows()
【Python】仮想環境を構築

# Anacondaを使わずに、仮想環境を立ち上げましょう

実行したOS: MacOS (Macbook Air)
Pythonバージョン: 3.8

### 1.まずターミナルを開いて、pipでvirtualenvパッケージをダウンロードします

```zsh
$ pip install virtualenv
```

### 2. 好きな名前を付けます (my_env以外でも何でも)

```zsh
$ virtualenv my_env
```

### 3. 仮想環境を起動します

```zsh
$ source my_env/bin/activate
```

### 4. この仮想環境の下で、必要なパッケージ、モジュールなどをダウンロードしましょう

```zsh
$ pip install torch
```

以上です。
Nuxt.jsのプロジェクトをGithub Pagesに公開する手順

Nuxt.jsのサイトをGithub Pagesにあげようとして手間取ったので、手順をまとめておきます。

#手順
##1. 普通にNuxtを書く
書きましょう。

##2. npm run generateする
Nuxt.jsのプロジェクトをそのままGithubにあげてもGithub Pagesにdeployできません。
```npm run generate
```をすると、静的なアプリケーションが/dist以下に生成されます。

##3. 公開用のリポジトリを作成し、/distの中身を全てUploadする
以上です。[Githubのユーザー名].github.ioに接続すると、Nuxtのサイトが表示されているはずです。Readme.mdが表示されてしまう時は、Readme.mdを/.githubにぶちこむか削除するとおそらくうまくいきます。

#注意
[Githubのユーザー名].github.ioではないリポジトリをGithub Pagesに公開する際は
https://develop365.gitlab.io/nuxtjs-2.8.X-doc/ja/faq/github-pages/
を参考にbaseUrlを設定しましょう。

#参考資料・動画
https://develop365.gitlab.io/nuxtjs-2.8.X-doc/ja/faq/github-pages/

https://qiita.com/mogamoga1337/items/1752ec783d0fdc866a6a

https://www.youtube.com/watch?v=lG9y6WKcyeE&t=617s
Github Actionsの結果をSlackに通知

slackを触ったこともない初心者が簡単な通知をslackに飛ばせるようになったお話

<strong>始まりはgit action でcicdを実装したこと</strong>
ci/cdと呼べるほどの物ではない気もするけど、一応、pull_request時、masterに対して、pushまたはmergeされた時にrspecの実行と、herokuへのデプロイを行なってもらうようにしました。
それだけで充分かなと思っていたのですが、いろんな記事を見ていたらactionの結果をslackに通知している記事がありました！
これは面白そうと思ってざっと調べてみました。

__まずはgithubのマーケットプレイスから探します__

https://github.com/marketplace

キーワードにslackって打ったらいろいろ出てくるので試してみてください！

今回僕は「Slack Notify」を使います！
下記リンクに飛んで下にスクロールしていけばセットアップの方法が載っているのでそれを参考にしてください

https://github.com/marketplace/actions/slack-notify

github側で設定することはymlファイルを作成するくらい？
slack側では下記に対応する情報を取得します。

```
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
```

slackでアプリをしていしたら以下のリンクからslakc webhookを対象のアプリ、またはチャンネルにインストールします。

https://w1633071224-zxz341457.slack.com/apps/A0F7XDUAZ--incoming-webhook-?tab=more_info

そこでwebhook urlを新しく作って、その情報をgithubのsecretとして登録します。

```
github
↓
対象のリポジトリ
↓
Setting
↓
サイドバーのsecrets
↓
「New Repository Secret」をクリック
↓
NAMEとValueを設定

NAME : SLACK_WEBHOOK
Value : 先ほどコピーしたwebhookのurl
```

これで設定は完了です。

あとは通知を送信したいチャンネル、通知の内容などをymlファイルに記載することで通知が飛びます！

githubに詳しい設定が書いてあります

```
例)
    - name: Slack Notification
      uses: rtCamp/action-slack-notify@v2
      env:
        SLACK_CHANNEL: general  #チャンネルの名前
        SLACK_COLOR: ${{ job.status }} #成功は失敗かで色が変わる
        SLACK_ICON: https://github.com/rtCamp.png?size=48　#githubのアイコンリンク
        SLACK_MESSAGE: Post Content #送信されるメッセージ
        SLACK_TITLE: Post Title 
        SLACK_USERNAME: rtCamp #送信者の名前
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1541345/a21a405b-babf-4545-ef56-c85f7a13d2d4.png)



こんな感じでslackに通知が行きます！
結構デザインもいじれるみたいですし、マーケットプレイスにも種類がたくさんあるので試してみてはいかがでしょうか！
モンキーテストとは


モンキーテスト

実施者がその場の思いつきで操作してみる方式
猿に検証機を与えたかのようにテストの内容や操作手順をランダムに操作して検証するものです。

至る所にマウスカーソルを合わせてみる
何も無い空間を含め、さまざまな場所をクリックしてみる
テキストボックスなどの入力部分に出鱈目に入力してみる
ブラウザによるuserAgentでの表示変更方法

```html

<html>
    <head>
    </head>
    <body>
    <script>

      var isBrowser = navigator.userAgent.indexOf("edge") > 0 || 
                      navigator.userAgent.indexOf("chrome") > 0 || 
                      navigator.userAgent.indexOf("safari") > 0 || 
                      navigator.userAgent.indexOf("firefox") > 0;

        if(isBrowser) {
          // 対応ブラウザ外
          console.log('対応ブラウザではありません。');
        } else {
          // 対応ブラウザ
          console.log('対応ブラウザです。');
        };


      var isBrowser2 = navigator.userAgent.indexOf("edge") < 0 ||
                       navigator.userAgent.indexOf("chrome") < 0 || 
                       navigator.userAgent.indexOf("safari") < 0 || 
                       navigator.userAgent.indexOf("firefox") < 0;

        if(isBrowser2) {
          // 対応ブラウザ
          console.log('対応ブラウザです。');
        } else {
          // 対応ブラウザ外 
         console.log('対応ブラウザではありません。');
        };

      var isNotBrowser = navigator.userAgent.indexOf("edge") > 0 || 
                         navigator.userAgent.indexOf("chrome") > 0 || 
                         navigator.userAgent.indexOf("safari") > 0 || 
                         navigator.userAgent.indexOf("firefox") > 0;
        if(!(isNotBrowser)) {
          // 対応ブラウザ
          console.log('対応ブラウザです。');
        } else {
          // 対応ブラウザ外
          console.log('対応ブラウザではありません。');
        };

      var browserCheck = window.navigator.userAgent.toLowerCase();
        if(browserCheck.indexOf('msie') > 0 || browserCheck.indexOf('trident') > 0) {
          console.log('このブラウザはInternet Explorerです。');
        } else if(browserCheck.indexOf('edge') > 0) {
          console.log('このブラウザはEdgeです。');
        } else if(browserCheck.indexOf('chrome') > 0) {
          console.log('このブラウザはGoogle Chromeです。');
        } else if(browserCheck.indexOf('safari') > 0) {
          console.log('このブラウザはSafariです。');
        } else if(browserCheck.indexOf('firefox') > 0) {
          console.log('このブラウザはFireFoxです。');
        } else if(browserCheck.indexOf('opera') > 0) {
          console.log('このブラウザはOperaです。');
        } else {
          console.log('このブラウザは何かわかりません。');
        }

      var terminalCheck = navigator.userAgent.indexOf("iPhone") > 0 || 
                          navigator.userAgent.indexOf("iPad") > 0 || 
                          navigator.userAgent.indexOf("Android") > 0;
　　　　if(terminalCheck) {
		  // スマホ　タブレット
          console.log('スマホです。')
        } else {
		  // PC
          console.log('デスクトップです。')
	    }
    </script>
    </body>
</html>

```
M1 Mac で Cloud Run に デプロイする際の注意点

# はじめに
いつも使用しているIntel Mac の調子が悪い！
そうだ、この前買った M1 Mac でこれからは開発しよう！と思い立ったのが昨日の昼間...
特に docker 周りで辛い思いをたくさんしたがローカルでの開発環境は整った。いざデプロイしようと今まで通りのスクリプトを動かしてみたら動かず...

```
Failed to start and then listen on the port defined by the PORT environment variable. Logs for this revision might contain more information
```

エラーもポート関係のエラーのようで Dockerfile もスクリプトも読んでも何一つ問題が見当たらない...
普通にデプロイが成功している Intel Mac と比較をしながら調査をしているとどうやら M1 Mac のビルドに問題があるようだった。

# 前提

## デバイス環境
- MacBookAir (M1, 2020)
- Apple M1
- メモリ 16GB
- macOS Bug Sur

## システム環境
- Docker version 20.10.8
    - Use gRPC FUSE for file sharing OFF
    - Use Docker Compose V2 OFF
- rosetta2 インストール済み
- google-cloud-sdk インストール済み

# Rosseta の有効
お使いの terminal でまずは `情報を見る → Rosetta を使用して開く` を確認し、 Rosetta を有効にします。

![スクリーンショット 2021-10-05 2.21.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/85aff18d-83b2-0551-e142-26a447262b35.png)
![スクリーンショット 2021-10-05 11.24.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/e22d29e5-62d3-ef1d-05cf-be6e3a32cd06.png)

# M1 でのコンテナのビルド
次に GCR にあげるためのコンテナをビルドします。こちらの工程で従来の Intel Mac とは違ったコマンドが必要になります。

```
docker buildx build --platform linux/amd64 -t コンテナ名 .
```

buildx についての公式ドキュメントはこちら
https://matsuand.github.io/docs.docker.jp.onthefly/buildx/working-with-buildx/

どうやら マルチプラットフォームのイメージビルドを行う際に活躍してくれるみたいです。

# 残りの工程
ビルドができましたら後は従来通りの工程と同じです。tag つけて GCR に push してそれを CloudRun でデプロイするだけ。

## タグをつける
```
docker tag コンテナ名 gcr.io/プロジェクト名/コンテナ名
```
## GCR に Push
```
docker -- push gcr.io/プロジェクト名/コンテナ名
```
## CloudRun にてデプロイ
```
gcloud beta run deploy CloudRun 上のサービス名  --project プロジェクト名
...
```

無事にこれでデプロイできるはずです。
エラーがポート関係
おそらくビルドの際に注意するように心がければ AWS の ECS などの別サービスでもいけるはず。
【atom】autocomplete-pythonが動かないよ

0.事象
-
atomエディタで、autocomplete-pythonのパッケージがうまく動かない。
適当なファイル内にimport とうつと、atomウィンドウ右上に赤枠で下記のようなエラーが表示される。

<省略>~autocomplete-python\lib\completion.py", line 8, in <module>

1.環境
-
OS:windows10 home
python:3.10
atom:1.58
autocomplete-python:1.17.0

2.原因
-
python環境側で、jediというパッケージを持っていなかった。

3.対応
-
a)コマンドプロンプト開く。
b)下記コマンドを順番に実行。

```
python -m pip install --upgrade pip
pip install jedi==0.17.2
```

c)atomを再度開いて、適当なファイルでコーディングして補完を確認する。

4.まとめ
-
正しい対応なのかどうか不明だが動いたのでおけ。


5.参考
-
https://github.com/autocomplete-python/autocomplete-python/issues/453