OmniAICreator/Qiita-1.07M huggingface dataset:
We　found potential security vulnerabilities in your dependencies.


１
-

訳：![20210418-070611.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/1418bbaa-43a9-0968-55b6-ff0e9c42bacb.png)

We　found potential security vulnerabilities in your dependencies.
依存関係に潜在的なセキュリティの脆弱性が見つかりました。



2
-

![20210418-071102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/a75e8e1d-e167-8b8d-e20d-cf88e2dad96b.png)

をクリックすると


３
-

![20210418-071405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/8db960f6-3829-6f10-87de-c48ca16bd587.png)


Dependabot alerts surface known security vulnerabilities in some dependency manifest files. Dependabot security updates automatically keep your application up-to-date by updating dependencies in response to these alerts. Dependabot version updates can also help keep dependencies updated.

訳：Dependabotアラートは、一部の依存関係マニフェストファイルの既知のセキュリティ脆弱性を表面化します。 Dependabotのセキュリティ更新は、これらのアラートに応答して依存関係を更新することにより、アプリケーションを自動的に最新の状態に保ちます。 Dependabotのバージョン更新は、依存関係を最新の状態に保つのにも役立ちます。

４
-

さらに内容を確認

![20210418-071701.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/e5116f60-5b23-6bb4-a296-ea6011f92846.png)


Vulnerable versions: >= 2.1.0, < 4.2.2
Patched version: 4.2.2
The is-svg package 2.1.0 through 4.2.1 for Node.js uses a regular expression that is vulnerable to Regular Expression Denial of Service (ReDoS). If an attacker provides a malicious string, is-svg will get stuck processing the input for a very long time.

訳

脆弱なバージョン：> = 2.1.0、<4.2.2
パッチ適用バージョン：4.2.2
Node.js用のis-svgパッケージ2.1.0から4.2.1は、正規表現のサービス拒否（ReDoS）に対して脆弱な正規表現を使用します。攻撃者が悪意のある文字列を提供すると、is-svgは非常に長い間入力の処理でスタックします。
helperメソッド

###モジュール
モジュールとは、Rubyにおける「インスタンスを生成できないクラス」のようなもののことです。
下記のように定義します。


```rb
module モジュール名

end
```

また、モジュールの中にはクラスを定義することもできます。


```rb
module Sample
  class Test
  end
end
```

この「Testクラス」は下記のようにして呼び出すことができます。


Sample::Test
クラスとモジュールの使い分けとして、具体的なオブジェクトを生成したい場合（インスタンスを生成したい場合）はクラスを使用し、処理だけ（メソッドなど）が必要な場合はモジュールを使用するという認識で構いません。
またモジュールの中にクラスを定義するメリットは、Testクラスが複数ある場合に、下記のような記述でクラスごとに区別ができることです。

```rb
module Sample1
 class Test
 end
end
```

```rb
module Sample2
 class Test
 end
end
````
Sample1::Test
Sample2::Test
こうすることで、同じクラス名でも定義することができ、それぞれ区別して使用することができます。

###それでは、ヘルパーメソッドを作成するモジュールを見ていきます。

Helper
Helperとは、ヘルパーメソッドを作成できるモジュールです。
app/helpers配下に用意されており、application_helper.rbや、各コントローラーに対応したhelperのファイルに処理を記述することでヘルパーメソッドとして使用できます。実際には〇〇Helperという形で定義されます。

```application_helper.rb

module ApplicationHelper
  def sample
    # sampleというヘルパーメソッドです
  end
end
```

このようにApplicationHelper内へメソッドとして定義すると、下記のようにビューファイルで使用できます。

```rb:index.html.erb
<%= sample %>
```

ビューファイルへRubyの処理をたくさん記述してしまった場合や、繰り返し同じ処理を記述する場合は、可読性が落ちてしまうのでヘルパーメソッドとして切り出します。

ヘルパーメソッドを使用してみよう
-

###ヘルパーメソッドを定義しましょう

下記の6行目から始まるeachメソッドを使用してツイートを繰り返し表示する部分を、ヘルパーメソッドとして切り出します。

```rb:app/views/tweets/index.html.erb
<%= form_with(url: search_tweets_path, local: true, method: :get, class: "search-form") do |form| %>
  <%= form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input" %>
  <%= form.submit "検索", class: "search-btn" %>
<% end %>
<div class="contents row">
  <% @tweets.each do |tweet| %>
    <%= render partial: "tweet", locals: { tweet: tweet } %>
  <% end %>
</div>
```

###ヘルパーメソッドをtweets_helper.rbへ定義しましょう

app/helpers/tweets_helper.rbのファイルを開き、tweet_listsというメソッドを定義してください。このメソッドがヘルパーメソッドになります。


```app/helpers/tweets_helper.rb
module TweetsHelper
  def tweet_lists(tweets)
    html = ''
    tweets.each do |tweet|
      html += render(partial: 'tweet',locals: { tweet: tweet })
    end
    return raw(html)
  end
end
```

###処理を1つずつみていきましょう。

```app/helpers/tweets_helper.rb

  def tweet_lists(tweets)
    html = ''

# 省略

  end
```

まずは、2~3行目です。
2行目で「tweet_listsメソッド」を定義して、引数として「tweets」を持たせます。
3行目では、空の箱として「html = ''」を生成します。
この箱の中に、ツイート情報を代入します。

```app/helpers/tweets_helper.rb
    tweets.each do |tweet|
      html += render(partial: 'tweet',locals: { tweet: tweet })
    end
```


4~6行目では、tweetsに対してeachメソッドで繰り返し処理を行います。
そして、tweetに関する部分テンプレートを呼び出しています。この部分テンプレート内で扱うtweet情報は、「変数tweet」とます。
呼び出した部分テンプレートを、先程生成したhtmlに代入します。

```app/helpers/tweets_helper.rb
    return raw(html)
```

最後に7行目です。
raw()は、HTMLを正常に表示するためのメソッドと覚えていただいて問題ありません。具体的には、「<」「>」「&」などの、特殊文字と呼ばれる文字を意図するように扱うためのメソッドです。raw(文字列)とし、rawメソッドに引数で渡した文字をフォーマットするイメージです。これをしないと、文字化けしてしまうケースがあります。
そして、ここまでの処理を、tweet_listsメソッドの実行結果としてreturnで返します。

###ヘルパーメソッドを呼び出しましょう

次に、index.html.erbで先ほど定義したtweet_listsメソッドを呼び出します。index.html.erbを下記のようににします。

```rb:app/views/tweets/index.html.erb
<%= form_with(url: search_tweets_path, local: true, method: :get, class: "search-form") do |form| %>
  <%= form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input" %>
  <%= form.submit "検索", class: "search-btn" %>
<% end %>
<div class="contents row">
  <%= tweet_lists(@tweets) %>
</div>
```
herokuについて

# ClearDBアドオンとは
ClearDBというHerokuとは独立したデータベースサービスが提供している、MySQLを使うためのものであること
Railsはcredentials.yml.encで外部に漏らしたくない情報を暗号化すること
credentials.yml.encで暗号化された情報を復号するためには、master.keyを用いること,GITで管理されない仕組み.
# 環境変数　
OSが提供するデータ共有機能の1つで、「どのディレクトリ・ファイルからでも参照できる変数」を設けることができます。
master.keyの情報は、本番環境に環境変数として設置すること
RAILS_MASTER_KEYという環境変数（箱）を用意し、その中にmaster.keyの値を入れるという使い方をします。
【Spring Boot】ローカルではちゃんと動いてたのでVirtualBox上でjarを実行するとTemplateInputException

###現象
* ローカルではSpringBootプロジェクトを実行するとエラーが発生することなくページが表示される
* jarファイルを作ってVirtualBox上のContOSでjarを実行するとログにTemplateInputException（ページはWhiteLabel)

###原因
* ビューの戻り値がおかしかった
* ローカル環境ではなぜかSpringBootが解決してくれてるってこと？

###ソース

```
public String top(){
 ...
 return "/sample/top"; // ここの最初の/が必要ない
}
```

top.htmlがsampleフォルダに入っている。

最初の/があるのと無いのでは意味が変わってくるってことですね。

正しくは

```java
return "sample/top";
```

気をつけよう・・・
ActiveStorage のテストでnilと’’では’’で画像がないが通らない

 ActiveStorage のテストでnilと’’では’’で画像がないが通らない


とっても示唆的

別内容ですが、参考に

>【Rails】「テーブルのカラムに定義するNot Null制約」と「モデルに定義するバリデーション（presence: true）」の挙動の違い。
>@wonder_meet
>https://qiita.com/wonder_meet/items/fa804f0d436a29c97460
idはテーブル固有のものです。

![20210418-205807.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/4e024be3-64cc-452b-7e9c-3cbc21a8da83.png)


ActiveRecorrd::RecordNotFound「該当するレコードがみありません」

ここがキーです。CouldN't find them with 'id'=2「idの値が２のレコードが見当たりません」

どういうことか？
-

![20210418-210353.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/53d35946-3e69-4e17-f334-5f9c17a2da65.png)

先ほど１２行あったSequelProデータを消して新たにNo、１３のデータしかitemsテーブルにはありません。

この状態で

```ruby:app/controller/items_controller.rb
def show
   Item.find(params[:id])
end
```

上記のようにItemテーブルからパラメーターid=2のデータを探しにいっています。

###ないナンバーデータを探すのは無理です。
備忘録 input要素のname属性



**input 要素 では， フォームのデータが送信されるときに，name 属性 の値が付加されており，対象とする要素のデータに簡単にアクセスできます。**
また，input 要素 では， name="_charset_" と name="isindex" という指定は特別な意味を持ちます。
書庫アプリケーション作成

課題
-

以下の仕様を満たすアプリケーションを作成。実装の際、注意の下に記載されている雛形を使用してください。

仕様
-
プログラムの実行を行うと、
・ [0]を選択した場合は、本の著者、タイトル、価格を入力させ、保存する。
・ [1]を選択した場合は、保存された本の番号とタイトルを出力、選択できるようにする。 表示した番号を選択された場合は、選択された本の著者、タイトル、価格を出力する。
・ [2]を選択した場合は、アプリケーションを終了する。

必要な知識
-

gets と chomp
to_i
ハッシュ
配列と配列演算子(<<)
実引数と仮引数
eachメソッド

雛形
-

```rb
def register_book
  # 本の著者、タイトル、価格をユーザーに入力させ、保存する
  puts '著者を入力してください'
  puts 'タイトルを入力してください'
  puts '価格を入力してください'

  book = { author: author, title: title, price: price }

end

def show_books(books)
  puts "見たい番号を入力してください"
  # 保存された本の一覧を出力する
end

def show_detail
  # 選択された本の詳細な情報（著者、タイトル、価格）を出力する
  puts "著者 #{book[:author]}"
  puts "タイトル #{book[:title]}"
  puts "価格 #{book[:price]}円"
end


while true do
  puts "番号を入力してください"
  puts "0: 本を登録する"
  puts "1: 本の一覧を見る"
  puts "2: 終了する"
  case gets.to_i
  when 0
    # 本の登録を行う
  when 1
    # 保存された本の一覧を出力する
  when 2
    exit
  else
    puts '無効な値です'
  end
end
```


```rb:追加修正プログラム
def register_book(books)　#1
  puts '著者を入力してください'
  author = gets.chomp
  puts 'タイトルを入力してください'
  title = gets.chomp
  puts '価格を入力してください'
  price = gets.to_i
  book = { author: author, title: title, price: price }
  books << book
end

def show_books(books)　#2
  puts "見たい番号を入力してください"
  index = 1
  books.each do |book|
    puts "#{index}: #{book[:title]}"
    index += 1
  end
  input = gets.to_i
  show_detail(books[input - 1])
end

def show_detail(book) #3
  puts "著者 #{book[:author]}"
  puts "タイトル #{book[:title]}"
  puts "価格 #{book[:price]}円"
end

books = []
while true do
  puts "番号を入力してください"
  puts "0: 本を登録する"
  puts "1: 本の一覧を見る"
  puts "2: 終了する"
  case gets.to_i
  when 0
   register_book(books)
  when 1
    show_books(books)
  when 2
    exit
  else
    puts '無効な値です'
  end
end
```

コードの内容
-

register_bookメソッド
このメソッドで処理したい内容は下記の通りです。

・本の著者、タイトル、価格をユーザーに入力させ、指定の変数に保存する
・保存した値をハッシュとして変数bookに格納する
・仮引数であり、配列であるbooksにbookの値を追加する

```rb:コード１
def register_book(books)
  puts '著者を入力してください'
  author = gets.chomp
  puts 'タイトルを入力してください'
  title = gets.chomp
  puts '価格を入力してください'
  price = gets.to_i
  book = { author: author, title: title, price: price }
  books << book
end
```

show_books メソッド
-

このメソッドで処理したい内容は下記の通りです。
・booksに保存されている情報のタイトルを表示する（ユーザーが選択できるように、本の一覧番号も一緒に表示させる）
・ユーザーが選択した番号の情報を出力する

```rb:コード２
def show_books(books)
  puts "見たい番号を入力してください"
  index = 1
  books.each do |book|
    puts "#{index}: #{book[:title]}"
    index += 1
  end
  input = gets.to_i
  show_detail(books[input - 1])
end
```

show_detail メソッド
-

このメソッドで処理したい内容は下記の通りです。
著者、タイトル、価格をハッシュから取り出し表示する

```rb:コード３
def show_detail(book)
  puts "著者 #{book[:author]}"
  puts "タイトル #{book[:title]}"
  puts "価格 #{book[:price]}円"
end
```
はじめてC++で画面を作ろう! (4) getOpenFileName編

#12.「ファイルを開く」を作ろう!!

__[1] actionOpenに処理を書く__
アクションエディタ画面より、__「actionOpen」__をクリック、続けてマウスの右ボタンをクリックすると、ポップアップ メニューが表示されるので、__「スロットへ移動」__をクリックします。

QAction trggered()をタプルクリックすると、自動的にC++のエディタに移動します。

```mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
  ...中略...

void MainWindow::on_actionOpen_triggered()
{

}
```

on_actionOpen_triggered()関数にカーソルが移動しています。

__[2] QFileDialogをインクルード!__
今回は、「ファイルを開く」の画面を呼び出すので、準備作業として、
Qt5の__QFileDialog__を先に__#Inculude__しておきます。

```mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QFileDialog> /* これを追加 */

MainWindow::MainWindow(QWidget *parent)
  ...中略...

void MainWindow::on_actionOpen_triggered()
{

}
```
__[3] ファイル名の変数を用意__
次にファイル名を入れる変数を用意します。
Qt5の文字列型の変数 (変数名:__fileName__)

※注意: Qt5用の__QString型__は、C++の標準 __String型__を拡張したモノ

```mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent)
  ...中略...

void MainWindow::on_actionOpen_triggered()
{
  QString fileName; /* これを追加 */
}
```
__[4] 「ファイルを開く」画面を呼び出す__
次に用意した変数に「ファイルを開く」画面の戻り値を入れます。

```mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent)
  ...中略...

void MainWindow::on_actionOpen_triggered()
{
  QString fileName = QFileDialog::getOpenFileName(this, tr("Open"), "", tr("Text File(*.txt);;All Files(*.*)"));
}
```

__[5] ステータスバーに表示する__
せっかく、戻り値で、ファイル名を取得したので、とりあえずステータスバーに表示しましょう!!

```mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent)
  ...中略...

void MainWindow::on_actionOpen_triggered()
{
  QString fileName = QFileDialog::getOpenFileName(this, tr("Open"), "", tr("Text File(*.txt);;All Files(*.*)"));
  ui->statusbar->showMessage(fileName); /* これを追加 */
}
```

#13.動作確認!!
画面の左下にある、右三角マークの__「実行」__ボタンをクリックすると、何やら右下側にビルドしている状況が表示され、「MainWindow」が出てくる!

作ったアプリのメニューで、__[File | Open]__で、「ファイルを開く」画面が動く事をを確認しましょう!!

「ファイルを開く」画面で、「キャンセル」ボタンをクリックすると、__fileName = ""__となる。

#14.getOpenFileName関数の引数の説明
[1] __this__ :ここは、親オブジェクトの設定
[2] __tr("Open")__ :ここは、「ファイルを開く」のタイトル
[3] __""__ :ここは、画面を呼び出した時のファイルパス
「マイ ドキュメント」などを設定できる。
[4] __tr("Text File( *.txt );;All Files( * . * )")__ :ここは、拡張子のフィルター
フィルターは、セミコロン(;)を二つで区切りする
__Text File( *.txt *.xml *.json )__のように複数にもできる。
画像の場合は、__Image File( *.jpg *.png *.gif *.tiff )__のように設定できる。

今回は、ここまで次回は、「名前を付けて保存」を作ろう!!です。
就活生に贈る、レガシー ソフトウェア廃止イベントによる企業の踏み絵

# Internet Explorerの終焉に踊らされて、リテラシーの低さの露呈がする。
これはまるで踏み絵の様。

とても観察時で、注意が必要。

# 解説
Mirosoftはレガシーな ``Internet Explorer`` から ``モダン ブラウザー`` へ移行してもらうために、様々なアプローチを行ってきた。そして何年も前から、移行してくれと言っていた。そしてようやっと今回、いよいよデスクトップ版の終了の告知となったわけだが。

**こともあろうか、未だにそれ踊らされる、愚かな現場が存在していると言う事実がある。**
(えぇ、、、私の目の前にも。。。)

Microsoftが互換モードを提供し、``マルチ エンジン`` 状態で移行しやすくしても、無視し。
Microsoftがセキュリティのために最新のIEにアップデートするよう促し、それでも互換性のために用意したら ``エンタープライズ モード`` には定着し。
再三移行してくれと勧告しても無視をする。

Microsoftが恐らく10年以上のロングスパンで猶予をくれていたのにも関わらず、無視をし続けいっこうに ``モダン ブラウザ`` 対応を行ってこなかったのが、 今 ``踊らされている現場`` である。


ぶっちゃけこんだけの期間があって、対応できなかった **正当な理由** があると思います？
ぶっちゃけこんだけの期間があって、対応できなかった **正当な理由** があると思います？
ぶっちゃけこんだけの期間があって、対応できなかった **正当な理由** があると思います？
ぶっちゃけこんだけの期間があって、対応できなかった **正当な理由** があると思います？
ぶっちゃけこんだけの期間があって、対応できなかった **正当な理由** があると思います？
ぶっちゃけこんだけの期間があって、対応できなかった **正当な理由** があると思います？
(大事なことなので繰り返しました。)

まぁそれらの現場にも、もしかすると声を上げていた人が多少は居たのかもしれない。しかし、その現場の多数派ではなく意見が通らなかったのだろう。

就職活動や転職活動を行っている人にはぜひ、それらの状況を観察してみてもらいたい。

* その企業がまだIEを使っていたら
* その企業がIE対応の話をしていたら

その企業は

* 現場の声が通りづらい可能性が高い。
* その企業のIT系の部門のITリテラシーが著しく低い。
* 正常なIT意識を持った人が少ない。
* WEBに弱い (クソ雑魚級)。
 
といった **地雷企業** の可能性が高いです。更にこんなご時世なので **「ITに力を入れている」** なんてことも言っていたら、吃驚 **ダブル スタンダード** ですね。``FLASH`` をまだ使っていたらほんと目も当てられません。 (世の中には在るところには在る。)

レガシー技術で新機能を作って導入した後「○年後は俺居ねぇからそのあとのことは知らねぇ」って、保守性を放棄する現場なんかもある様ですね。

IT系での就職・転職には大変注意が必要です。

(若しくは ``俺がそげぶ！`` っていう強い意気込みのある方には、ぜひ改革をして欲しいものです。)



# さておき、Internet Explorer、お疲れ様！
晩年はゾンビの様な状態で延命させられてたけど。ようやく終わりが見えてきたね。
IEモードなんて選択する往生際の悪い企業が1社でも少ないことを願いたい。

## 技術は人を幸せにしかない。 
``Internet Explorer`` も沢山の楽しみと未来を与えて、大変大きな礎を築いてくれた。本当にありがとう。


## 人を不幸にするのはいつだって人の行い。
``Internet Explorer`` による不幸は、けして ``Internet Explorer`` のせいじゃなかった。賞味期限が切れているのにも関わらずそれを無視して使い続けた人間どもです。

ITに関わる人間はこの ``Internet Explorer`` の件を参考に、ソフトウェアの賞味期限にアンテナを貼り、``捨てるまで`` を想定した業務を心がける必要があります。悪いのは、ソフトウェアでも、サポートを打ち切る企業でもないです。

# さようなら、すべてのTrident、Chakra
おめでとう
:clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap::clap:
【php】３つの整数の比較

0-2の範囲の乱数を変数 $a, $b, $c にそれぞれ代入し、どの変数が最大であるかを表示してください。

１・0-2の範囲の乱数 $a, $b, $c をそれぞれ代入しておく。
２・変数のうち一つが最大値である場合、「変数○が最も大きい」と出力する
３・変数のうち2つが同じ値で最大である場合、「変数○と○が最も大きい」と出力する
４・3つの変数が全て同じ値の場合、「全て同じ値です」と出力する。

```PHP
<?php
$a = mt_rand(0, 2);

$b = mt_rand(0, 2);

$c = mt_rand(0, 2);
?>
```

```PHP
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>最も大きい変数</title>
</head>
<body>
  <h1>最も大きい変数</h1>
  <p>$a: <?php echo $a; ?></p>
  <p>$b: <?php echo $b; ?></p>
  <p>$c: <?php echo $c; ?></p>
 <?php  if($a === $b && $a === $c){ ?>
<p>  <?php  echo "全て同じ値です";?> </p>
 <?php  }elseif($a === $b &&  $a > $c ){ ?>
  <p>  <?php  echo "変数aとbが最も大きい";?>  </p>
 <?php  }elseif($a === $c &&  $a > $b ){ ?>
  <p>  <?php echo "変数aとcが最も大きい"; ?>  </p>
 <?php  }elseif($b === $c &&  $b > $a ){ ?>
  <p>  <?php  echo "変数bとcが最も大きい";?>  </p>
  <?php  }elseif($a > $c &&  $a > $b ){ ?>
  <p>  <?php  echo "変数aが最も大きい";?>  </p>
  <?php  }elseif($b > $c &&  $b > $a ){ ?>
  <p>  <?php  echo "変数bが最も大きい";?>  </p>
  <?php  }elseif($c > $a &&  $c > $b ){ ?>
  <p>  <?php  echo "変数cが最も大きい";?>  </p>
 <?php  }  ?>

</body>
</html>
```
Rails　Session と cookies

2種類のセッション（一時セッションと永続セッション）について


◆一時セッション　←　rails tutorial8章
　・sessionメソッドにより、ユーザーIDを一時cookiesに保存すること(ハッシュとして扱える)
　　　```session[:user_id] = user.id``` 
　・ブラウザを閉じるorログアウトで一時cookies(session)は破棄される。　　

　【流れ】
　　IDとPWでログイン
　　↓
　　ユーザーIDでDBから検索
　　↓
　　PWを検証する
　　↓
　　ユーザーが存在してPWも一致していればtrueを返す
　　↓
　　ブラウザの一時cookiesにユーザーIDを格納 ＆ ユーザーのプロフィールページにリダイレクト
　　↓
　　ブラウザを閉じるorログアウトで一時cookiesを破棄する

◆永続セッション　←　rails tutorial9章
　・cookiesメソッドにより、ユーザーIDと記憶トークンを永続cookiesに保存すること(ハッシュとして扱える)
　　　```cookies.permanent.signed[:user_id] = user.id```
　　　```cookies.permanent[:remember_token] = user.remember_token```
　・ブラウザを閉じても永続cookiesは破棄されない
　・ユーザーがログアウトしたら永続cookiesは破棄される
　・セキュリティ対策として、user_idは暗号化する
　

　【流れ】
　　Remember meのチェックボックスをオンにしてログインする
　　↓
　　urlsafe_base64 でランダムな記憶トークンを作成
　　↓
　　DBに記憶トークンをハッシュ化（記憶ダイジェスト）して保存
　　↓
　　暗号化されたユーザーIDと作成した記憶トークンが永続cookiesに保存される（デフォルトで期限20年）　
　　↓
　　ユーザーのプロフィールページにリダイレクト
　　↓
　　セッションが切れたとすると、、
　　↓
　　永続cookiesからユーザーIDと記憶トークンを取り出し、DBに保存されている記憶ダイジェストと比較
　　↓
　　一致してたら、ログインする
　　↓
　　ログアウト時は記憶ダイジェストにnilを入れ、永続cookiesのユーザーIDと記憶トークンを削除する
GCPとAWSのVPC・サブネットの違い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/5d00d612-43be-2452-73f9-3d959bffb13b.png)

- GCP
    - VPC
        - Regionを超えて**グローバルな存在**
        - VPCの中で複数のRegionを使える
        - IPレンジの定義が**ない**
    - サブネット
        - Regionの中に作成
        - サブネットの中で複数のZoneを使える
        - IPレンジを定義
- AWS
    - VPC
        - Regionの中に作成
        - VPCの中で複数のAZを使える
        - IPレンジを定義
    - サブネット
        - AZの中に作成
        - IPレンジを定義
AnsibleからOCIモジュールでcloud-initを操作する

# OCI上にインスタンスを作成する時にユーザを作成したい
AnsibleでOCI上にインスタンスを作る時に初回設定として、新しいユーザを作成しておきたい。
※AnsibleのOCIモジュール/CLIはインストール/設定済み

# OCIモジュールでデプロイする
モジュールの詳細は以下
https://github.com/oracle/oci-ansible-collection/blob/master/docs/collections/oracle/oci/oci_compute_instance_module.rst

### ファイル構造
```
.
|--files
|  `--cloud-init_user-data.yml
`--tasks
   `--main.yml
```


### tasks/main.yml
```
---
- name: Create instance
  oracle.oci.oci_compute_instance:
    display_name: "myinstance1"
    availability_domain: "Uocm:PHX-AD-1"
    compartment_id: "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...vm62xq"
    shape: "VM.Standard2.1"
    metadata:
      ssh_authorized_keys: "ssh-rsa BBBB.....==" # <公開鍵> → opcの公開鍵設定
      user_data: "{{ lookup('file','cloud-init_user-data.yml') | b64encode }}" #ここがポイント
      # user_dataはcloud-init_user-data.ymlに記載しておく。
```
https://github.com/oracle/oci-ansible-modules/issues/127

### files/cloud-init_user-data.yml
```
#cloud-config       # お約束 無いと動かない
groups:
  - opegrp          # groupを追加する場合は追記(※gidの指定が出来ない。。)

users:
  - default         # お約束 無いとユーザが追加出来ない
  - name: operator  # 追加するuser名(※uidの指定は出来ない。。)
    primary_group: opegrp
    sudo: [ "ALL=(ALL) NOPASSWD:ALL" ]
    ssh_authorized_keys:
      - "ssh-rsa BBBB.....=="  # <公開鍵> → operatorユーザの公開鍵

runcmd:
  - 'usermod -u 1200 operator' # uidの指定が出来ない為、runcmdから変更する
  - 'groupmod -g 2000 opegrp'  # gidの指定が出来ない為、runcmdから変更する
```
https://cloudinit.readthedocs.io/en/latest/topics/modules.html#users-and-groups

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_cloud-init_for_rhel_8/configuring-cloud-init_cloud-content

# インスタンス上のuser-data
cloud-initのuser-dataは以下に格納されている。
実行した後、うまく動いてない場合などはこちらにきちんと想定どおりのデータが連携されているか確認する。

/var/lib/cloud/instances/**OCIインスタンスのID**/user-data.txt

# cloud-initの参考
https://qiita.com/yamada-hakase/items/40fa2cbb5ed669aaa85b
【Dockerとは】

6月からエンジニアとして働き始める素人の身としてDockerの勉強を始めたので備忘録として残す。
間違いがあればご指摘いただけますと幸いです。

<h1>Dockerとは</h1>
##### 仮想環境を構築するためのプラットフォーム、またはオープンソースウェアのこと。
Dockerという船（仮想環境）に適宜必要なアイテム（OS、言語、フレームワーク、サーバー類など）を積んだり降ろしたりして使用する。
実際Dockerのアイコンを見たらわかるが、クジラ？の上にたくさんの箱が乗せられている。

<b>★仮想環境とは？</b>
自身のPC上に環境を構築するのではなく、バーチャル上に環境を構築するイメージ。

<b>★環境構築とは？</b>
開発に必要な材料を揃えるイメージ。

・OSは何を使う？　　　　　　　→　例）Linux
・言語は何を使う？　　　　　　→　例）PHP
・フレームワークは何を使う？ 　→　例）Laravel
・webサーバーは何を使う？　　→　例）Apache
・DBサーバーは何を使う？　　　→　例）MySql

これらを開発する環境（自身のPCだったり仮想環境だったり）にインストールすること。

<h1>なぜ仮想環境を作るの？</h1>
##### ◎プロジェクトごとに開発環境を構築できるから
プロジェクトAではOSはWindows、プロジェクトBはLinuxというようなことになっても、わざわざそのOSに対応したPCを用意する必要がなくなる。

例えば、Linux OSのPCの仮想環境にWindows OSの環境を構築したり、同じWindows OSでも別バージョンのWindows OSの環境を構築できる。

また、自身のPCには最新バージョンのPHPがインストールされているが、開発環境では1つ前のバージョンを使うとなると、わざわざグレードダウンしなくてはならない、、、といった問題も解消できる。

<h1>なぜDockerを使うの？</h1>
<b>①開発環境・本番環境ごとの設定が不要で、一度Dockerで環境を作れば開発環境だろうと本番環境だろうと関係なく使用できる</b>
<b>「Dockerfile」</b>というファイルにDockerの利用に関する手順を記述することで、そのファイルを共有すれば誰でもどこでも同じ環境を構築できる。

<b>②環境構築の材料集めが容易</b>
<b>「Docker Hub」</b>というクラウド上のリポジトリにプログラミング言語からサーバー類など一通りの材料が揃っており、コマンド1つで取得することができる。

<h1>Dockerで環境構築するまでの一連の流れ</h1>
<b>Docker Hub</b>上にある材料（プログラミング言語やサーバー類など）の雛形のことを<b>「イメージ」</b>という。
<b>イメージ</b>とは設計図のようなもので、この設計図を元に<b>「コンテナ」</b>を作成する。
実際に使用するのはこの<b>コンテナ</b>で、Dockerという仮想環境に積んだり不要になったら降ろしたりすることで開発環境を整える。

前述の<b>Dockerfile</b>とは<b>コンテナ</b>を自動生成できる手順書のことで、コマンドによって<b>Dockerfile</b>を読み込む。
ファイルの中にはどのイメージからコンテナを作成するのかなどの情報が記載されている。
このファイルを共有すれば誰でも同じ環境を構築できるというのはそういうこと。

この記事の作成途中に知ったがどうやら会社ではDocker使わないみたいなのでこれくらいで。。。
<br>

以上
スプレッドシートからメールを送る際にマークダウンっぽいのを使えるようにしたい

毎日スプレッドシートで日報の内容を書いてそれを元に下書きを作成し送信しているのですが、
せっかくなら簡単なマークダウンを使えたら便利だなと思い作りました。


## 対応したマークダウンっぽいもの

\### ->フォントサイズ3になりQuitaの#を使った時と同じような下線が入ります。
\##　->フォントサイズ4で上記に同じです
\#   ->フォントサイズ3で上記に同じです

\*hogehoge\* -> *イタリック*になります。
\*\*hogehoge\*\* -> **太字**になります
\~~hogehoge~~ -> ~~取り消し線~~が引かれます。

## 実装

```js:gas

function myFunction() {
  const values = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
  const to = values[1][1];
  const subject = values[2][1];
  let body = '';

  body = values[3][1]
  html = transformMarkdownToHtml(body)

  GmailApp.createDraft('mike@example.com', 'test',body,{htmlBody:html});
}

function transformMarkdownToHtml(body) {

  // １行ごと取り出す
  htmllist = body.split(/\n/g)
  Logger.log(htmllist)

  var returnHtmlList = []
  for (var row of htmllist){

    //マークダウンのタグの処理
    tag = row.split(' ')[0]

    // #の処理
    if (tag==='###'){ //標準の大きさ
      row = '<font size=3 style="border-bottom: 1px solid #ddd; display: block; margin-bottom:0.2em;">'+row+'</font>'
    }
    else if (tag==='##'){ //中の大きさ
      row = '<font size=4 style="border-bottom: 1px solid #ddd; display: block; margin-bottom:0.2em;">'+row+'</font>'
    }　
    else if (tag==='#'){ //大の大きさ
      row = '<font size=5 style="border-bottom: 1px solid #ddd; display: block; margin-bottom:0.2em;">'+row+'</font>'
    }
    else if (row==='***'){//水平線
      row = '<hr>'
    }

    var flag = true
    //１行に複数のタグがあるかもなので、elseに流れるまでは繰り返します。
    while (flag){
      //イタリック
      if (row.search(/\*\*.*\*\*/) != -1){
        row = row.replace(/\*\*/,'<i>')
        row = row.replace(/\*\*/,'</i>')
      }
      //太字
      else if (row.search(/.\**\*./) != -1){
        row = row.replace(/\*/,'<b>')
        row = row.replace(/\*/,'</b>')
      }
      //打ち消し線
      else if (row.search(/.~~.*~~./) != -1){
        row = row.replace(/~~/,'
')
        row = row.replace(/~~/,'
')
      }
      else{
        row += '<br>'
        flag = false
      }
    }
    returnHtmlList.push(row)
  }

  // リストの結合
  strhtml = returnHtmlList.join(',').replace(/,/g,'');

  return strhtml
}

```

## こんなかんじ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107518/6a6afc86-1a3f-ad1d-f55d-3608012147da.png)

とりえあず使いそうなもの、使いたいものは実装しました。
イタリックや太字などのrow.searchの部分で正規表現に少し苦労しました。
もっといい感じにすることができたらコメント欄で教えてもらえたらうれしいです。
【php】1-100の範囲の乱数が奇数か偶数かを判定するプログラムを作成せよ

１・1-100の範囲の乱数を取得し、変数 $rand に代入する
２・乱数の値を「$rand: [乱数]」と表示する
３・偶数が代入されていれば、「偶数です。」と表示する。
４・奇数が代入されていれば、「奇数です。」と表示する。


```php
<?php
$rand = mt_rand(1, 100);
 
if ($rand % 2 === 0) {
  # 入力値が偶数ならば
  $result = '偶数';
} else {
  # 入力値が偶数でないならば（奇数ならば）
  $result = '奇数';
}
?>
```
```Html
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>奇数・偶数の判定</title>
</head>
<body>
  <h1>奇数・偶数の判定</h1>
  <p>$rand: <?php echo $rand; ?></p>
  <p><?php echo $result; ?>です。</p>
</body>
</html>
```
CpawCTF Q7.[Reversing] Can you execute ? Writeup Using Ghidra

SECCON Beginners CTF 2021 の discord でCpawCTFの存在を知りました。
さっそく勉強開始。

# 問題

Q7.[Reversing] Can you execute ?
10pt

拡張子がないファイルを貰ってこのファイルを実行しろと言われたが、どうしたら実行出来るのだろうか。
この場合、UnixやLinuxのとあるコマンドを使ってファイルの種類を調べて、適切なOSで実行するのが一般的らしいが…
問題ファイル： exec_me

# Solution

こういう問題を見たら意地でも動かしたくない。
strings でダメだったので Ghidra で静的解析する。

初期デコンパイル結果

```c:main
undefined8 main(void)
{
  int local_7c;
  undefined4 local_78 [4];
  undefined4 local_68;
  undefined4 local_64;
  undefined4 local_60;
  undefined4 local_5c;
  undefined4 local_58;
  undefined4 local_54;
  undefined4 local_50;
  undefined4 local_4c;
  undefined4 local_48;
  undefined4 local_44;
  undefined4 local_40;
  undefined4 local_3c;
  undefined4 local_38;
  undefined4 local_34;
  undefined4 local_30;
  undefined4 local_2c;
  undefined4 local_28;
  undefined4 local_24;
  undefined4 local_20;
  undefined4 local_1c;
  undefined4 local_18;
  undefined4 local_14;
  undefined4 local_10;
  
  local_78[0] = 0x4d;
  local_78[1] = 0x5a;
  local_78[2] = 0x4b;
  local_78[3] = 0x61;
  local_68 = 0x65;
  local_64 = 0x2e;
  local_60 = 0x59;
  local_5c = 0x49;
  local_58 = 99;
  local_54 = 0x59;
  local_50 = 0x5f;
  local_4c = 0x49;
  local_48 = 0x55;
  local_44 = 0x58;
  local_40 = 0x59;
  local_3c = 0x61;
  local_38 = 0x49;
  local_34 = 0x2f;
  local_30 = 0x36;
  local_2c = 0x30;
  local_28 = 0x49;
  local_24 = 0x50;
  local_20 = 0x53;
  local_1c = 0x56;
  local_18 = 0x4f;
  local_14 = 0x29;
  local_10 = 0x67;
  local_7c = 0;
  while (local_7c < 0x1b) {
    putchar((int)(char)((char)local_78[local_7c] + '\x16'));
    local_7c = local_7c + 1;
  }
  putchar(10);
  return 0;
}
```

チューニング

変数名
local_7c  -->  i
local_78  --> flag

while (local_7c < 0x1b) {　から　local_78 の型を変更
undefined4 local_78 [4];  -->  byte flag [27];

```c:main改
undefined8 main(void)
{
  int i;
  byte flag [27];
  
  flag._0_4_ = 0x4d;
  flag._4_4_ = 0x5a;
  flag._8_4_ = 0x4b;
  flag._12_4_ = 0x61;
  flag._16_4_ = 0x65;
  flag._20_4_ = 0x2e;
  stack0xffffffffffffffa0 = 0x59;
  i = 0;
  while (i < 0x1b) {
    putchar((int)(char)((char)*(undefined4 *)(flag + (long)i * 4) + '\x16'));
    i = i + 1;
  }
  putchar(10);
  return 0;
}
```

んーん。直らねー。

ほっといて Ghidra Script 書いちゃう

```python:test_cpaw.py
ans=[]
inst = getInstructionAt(toAddr(0x00400535))
i = 0
while i < 0x1b:
    ans.append(inst.getOpObjects(1)[0].getValue()+0x16)
    inst = inst.getNext()
    i = i + 1
print(''.join(map(chr,ans)))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/ddaa838f-4948-5197-55b4-d31995278df1.png)

デコンパイル結果がいまいちで残念。
DockerでReact+Typescript環境を作る

## 前置き
学校の自由課題的な物でDockerを学ぶことにしたのでアウトプット

現状知識不足で細かいところを詳しく説明できないのでご了承ください(_ _ )

## 対象者
Dockerに対して多少知識のある方
[こちらの方の動画](https://youtu.be/yoBvz39X55w)を見て内容を実装できれば大丈夫だと思います

## 環境
- MacOS 11.2.3
- VisualStudioCode
- Docker for mac
    - [ダウンロードリンク(確かここ)](https://docs.docker.com/get-started/)


## ディレクトリ構造
```
Docker-ts
　├ dockerfile
　└ docker-compose.yml
```

## Dockerfile

```dockerfile
FROM node:14-alpine3.13
WORKDIR /usr/src/app

LABEL description = "Dockerfile test for Typescript and React"

RUN npm install --save prop-types
RUN npm install -g create-react-app 
```

## Docker-compose.yml

```yml
version: '3'
services:
    node:
        build:
            context: .
        tty: true
        environment:
            - NODE_ENV = production
        volumes:
        - ./:/usr/src/app
        command: sh -c "cd sample-project && yarn start"
        ports:
        - "3000:3000"
```

## コンテナ立ち上げの流れ

### ビルド
```
docker-compose build
```

#### ビルドでimageが作られたか確認
```
docker images
```

#### create-react-app Typescript

```
docker-compose run --rm node sh -c 'npx create-react-app sample-project --template typescript'
```

#### コンテナの立ち上げ

```
docker-compose up
```
ここで**localhost:3000**にアクセスすればReactのサンプルサイトが表示されていると思います

#### コンテナの停止

```
docker-compose down
```


## 最後に
チーム開発などでなければ実際にDockerを使って開発する機会は少ないのかなーと思いますが、実際に使う！ってなった時にすぐに馴染めるようにしたいなーと思います
CSSを使ったカミナリマークの作り方

#どうも7noteです。カミナリマークの作り方

cssを使って、カミナリマークを作ります。

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/1fa4ef54-cd93-a952-f518-fe3b947051ce.png)


## ソース

```index.html
<div class="thunder"></div>
```

```style.css
.thunder {
  position: relative; /* 基準位置とする */
  width: 15px;        /* 適当な幅を指定 */
  height: 35px;       /* 適当な高さを指定 */
}

.thunder::before,
.thunder::after {
  content: "";  /* 疑似要素に必須 */
  width: 10px;  /* 三角の幅を指定 */
  height: 20px; /* 三角の高さを指定 */
  display: inline-block; /* インラインブロック要素にする */
  position: absolute; /* 相対位置に指定 */
  transform: skewX(-10deg); /* マイナス10度傾ける */
}

.thunder::before {
  background: linear-gradient(to top left, rgba(255,255,255,0) 50%, #FADD7A 50.5%) no-repeat top left/100% 100%; /* 直角三角形を作る */
  bottom: 0; /* 下から0pxの位置に配置 */
  right: 0;  /* 右から0pxの位置に配置 */
}

.thunder::after {
  background: linear-gradient(to bottom right, rgba(255,255,255,0) 50%, #FADD7A 50.5%) no-repeat top left/100% 100%; /* 直角三角形を作る */
  top: 0;  /* 上から0pxの位置に配置 */
  left: 0; /* 左から0pxの位置に配置 */
}
```

## 解説

二つの三角形を作って再現します。
今回三角形は二つとも擬似要素を使って表現しています。

カミナリのサイズを決めれば、擬似要素で三角形を作っていきます。
borderではなく背景色を使った方法で三角形を作っています。

色をつけて配置を調整すれば完成。

## まとめ

比較的簡単に再現する事が可能です。
webサイトで使うことはあまり無いかもしれませんが、三角形を組み合わせた図形を作る方法は応用することで好きな形をつくることができると思います。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
お手軽Rubyスクリプト 馬連用の組み合わせ作成

## 概要 

Qiita初投稿です！
よろしくお願いします。

最近ウマ娘の影響で競馬を始めました。
馬連かワイドの馬券をよく買うのですが、
簡単に目星をつけた馬の組み合わせを作れないかな→Rubyのスクリプトで作れるかも
と思い立ち、作ってみました。

## 環境
スクリプトを作成した環境です。
OS：macOS Big Sur バージョン11.3
Ruby：ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin20]

## スクリプト
```generate_horse_combinations.rb
puts "\n名前を「、」で区切って入力してください（例 : グラスさん、すぺちゃん、エル）"

names_input = gets.chomp
names_array = names_input.split("、").uniq

puts "\n組み合わせは以下の通りです（2つの名前の組み合わせ、重複なし、順序なし）"

names_array.combination(2).with_index(1) do |name, index_number|
  puts "#{index_number}: #{name.join("、")}"
end
```

## 使い方

### スクリプトの保存
テキストエディタを開き、上のスクリプトをコピペしてください。
名前をつけて保存します。
ファイル名：```generate_horse_combinations.rb```

### スクリプトの実行

#### Mac, Linuxの場合
ターミナルを起動します。
cdコマンドでスクリプトを保存したディレクトリに移動後、
下のコマンドを入力してスクリプトを実行してください。
```shell
ruby generate_horse_combinations.rb
```

#### Windowsの場合
Progateさんのページを参考にRubyをインストールします。
参考：https://prog-8.com/docs/ruby-env-win

コマンドプロンプトを開きます。
cdコマンドでスクリプトを保存したフォルダに移動後、
下のコマンドを入力してスクリプトを実行してください。
```shell
ruby generate_horse_combinations.rb
```

### スクリプト実行後
馬の名前の入力を求められるので入力すると、
下のようにインデックス番号と馬の組み合わせが表示されます。
![スクリーンショット 2023-12-10 23.59.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610878/d302f83c-982f-f399-522d-53c25077b6ab.png)



## 感想
組み合わせを返してくれるツールがちょっと見当たらなくて、自分で作ってみることにしました。
Rubyのスクリプトを作ることができて勉強になりました。
週末のオークスは勝ったるでー！
vue.js で文字数を超えたら、警告文を表示する

```
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>算出プロパティ</title>
</head>
<body>
	<div id="app">
		<input type="text" v-model="inputCharactors">
		<p v-if="inputNumber < 10">必要な文字数は{{ needNumbers }}文字です</p>
		<p v-else style="color :rgb(255, 30, 30);">10文字以上入力されています</p>
	</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
  el: '#app',
  data: {
  	inputCharactors: ''	
  },
  computed:{
  	inputNumber : function (){
      //文字の数を取得する
  		return this.inputCharactors.length;
  	},
  	needNumbers : function(){
      //10文字までに必要な残りの文字数を表示する
  		return 10 - this.inputNumber;
  	}
  }

})
</script>	
</body>
</html>
```

conputedは値を監視するときに、ifバインドと合わせるいい感じになるっぽい。
関数として呼び出す必要がなくて、常に働いてくれてすごいです。

参考
https://reffect.co.jp/vue/vue-js-basic

本当にこのサイトはわかりやすい
Vue.js(Vue 3.x)でvue-routerを使って簡単SPA

####学習の備忘録です。Vue-routerを用いたSPAの実装を簡単に説明したものになります。
####間違えている箇所等ございましたらご指摘お願いします。

#**インストール方法** 
vue3のプロジェクトを作成後、vue-routerをnpmでインストールします。

```
npm install vue-router@next
```

vue-routerでSPAを実装するための各ファイルの記述は以下の通りです。

```vue:App.vue
<template>
  <div id="vue">
    <div>
      <router-link to="/" class="btn btn-primary mx-2">
        HelloWorld
      </router-link>
      <router-link to="/vue" class="btn btn-warning">
        HelloVue
      </router-link>
    </div>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'vue'
}
</script>

```
router-link内のto=""にmain.jsで設定したpathを記入することで遷移先を設定することが出来ます。
router-linkをクリックすることでpathに設定されたファイルの内容がrouter-viewに表示されることになります。

```js:main.js
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
import { createRouter, createWebHistory } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
import HelloVue from './components/HelloVue.vue'


const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'index',
      component: HelloWorld,
    },
    {
      path: '/vue',
      name: 'vue',
      component: HelloVue,
    },
  ],
})

var app = createApp(App)
app.use(router)
app.mount('#app')　 
```
今回はmain.js にまとめて記述していますが、以下の記述を別のjsファイルを作成して
管理するほうが分かりやすいかもしれません。

```js:
import { createRouter, createWebHistory } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
import HelloVue from './components/HelloVue.vue'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'index',
      component: HelloWorld,
    },
    {
      path: '/vue',
      name: 'vue',
      component: HelloVue,
    },
  ],
})

```

```vue:HelloVue.vue
<template>
  <div class="alert alert-primary">
    <h1>Hello Vue</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloVue'
}
</script>
```
```vue:HelloWorld.vue
<template>
  <div class="alert alert-primary">
    <h1>Hello Vue</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloVue'
}
</script>

```

HelloVue.vueとHelloWorld.vueが今回のrouter-viewに出てくる表示内容となっています。
内容は適当なので何でも構いません。

今回の実装方法は一例ですのでもっと効率的で簡単な実装方法があるかと思いますが、
大目に見てやってください。
AWS コスト管理関連サービス概要

### AWS Cost Explorer
コストと使用量の経時的変化を可視化して、カスタムレポートを作成してコストと使用量のデータを分析する

### AWSのコストと使用状況レポート
コストと使用状況の詳細を確認するためのレポート

### AWS Billing and Cost Management
AWS の請求書の支払い、使用量のモニタリング、コストの分析と管理に使用する

### AWS Budgets
予算のしきい値を超えたときにアラートを発信するカスタム予算を設定

### AWS Cost Categories
自身の組織やプロジェクト構造にわけてコストをカテゴライズすることが可能な機能

### Trusted Advisor
コスト最適化とセキュリティと対障害性とパフォーマンス向上についてアドバイスを提供するサービス

### 簡易見積りツール
利用するAWSサービスに対する月額料金を見積ることができる

### TCO計算ツール
AWS利用した場合とオンプレミス環境やコロケーション環境との価格比較ができる

### Pricing Calculator
ビジネスや個人のニーズに沿った個別の予測コスト見積りを実施することができる
UiPathOrchestratorの社内用サーバ証明書を作るポイント

UiPath Orchestratorのバージョンは2020.10.x以降になりIISのバージョンも10になったことで、自己証明書の作成がより難しくなった。チャレンジはしたが、かなりハードルは高く覚えていられないレベルだった。

まず、前提条件：
UiPath Orchestratorサーバ用のADサーバがありDNSサーバも持っていること。
UiPath OrchestratorサーバはUniversalInstallerを起動する前までの設定が済んでいること。

それぞれの手順はググると出てくるからとりあえず省きUiPath Orchestrator用の証明書を作るポイントだけメモした。
１、ADサーバの機能を追加でAD CSのエンタープライズ＆ルートCAサーバを追加する
　　ポイント１：このAD CSで発行される証明書はWebサーバテンプレートのキーが1024bitなので2048bit以上のテンプレートを作らないといけない
　　ポイント２：このAD CSで発行される証明書はSAN属性が有効になっていないので有効にする

２、OrchestratorサーバのIISで証明書発行要求から完了までブラウザでAD CSへアクセスして証明書を発行する
　　ポイント１：WindowsServer2016ではhttpでcertsvrページにアクセス可能。（これは同じドメイン内限定）
　　ポイント２：2048bitキーのテンプレートを選ぶこと
　　ポイント３：SAN属性を追加する※属性のIPはAD CSで指定するとエラーになる。名称のみ。
　　ポイント４：ダウンロードファイルはcer属性のファイル以外は証明書発行の完了が出来ないので注意。

３、OrchestratorサーバでUniversalInstallerを起動する
　　ポイント１：2020.10.8からサーバ証明書が信頼できるかどうかのチェックが動く※この証明書だと警告も出ないで動く
　　ポイント２：証明書発行の完了が出来ていればバインド、80削除もインストーラーがやってくれる。
　　ポイント３：Identityなる設定画面が追加されている。ここでも証明書の確認がされる

４、SQLServerのスキーマは自作する必要がある。既存は無理でInsightとか入れるならSQLServer認証にする
　　ポイント１：あらかじめSQLServerにはUiPath社のインストール手順通りスキーマを空で作っておくとスムーズ


５、インストールが終わるとIISにバインドされているのでFullFQDNアクセスするとSSL警告も出ない
　　ポイント１：IE、Chrome、Edgeは警告が出なくなる。同じドメイン内のマシンは証明書も配布されるので警告は特に何もしなくとも出なくなる。
　　ポイント２：警告も出ないのでStudio、Robotも問題なく認証が行われる。

６、UiPath Orchestratorをクライアントが接続出来るようにライセンスを導入し設定変更する。
　　ポイント１：ドメイン外のクライアントは、Orchestratorが所属するドメインのDNSサーバを参照させるようにすると名前解決は出来る。DNSを向けるのが難しい場合は、hostsファイルにエントリを書くと解決出来る
　　ポイント２：証明書は自動で配布されないので、手動でインストールする。
　　ポイント３：インストールする証明書はサーバ上のブラウザで正常に表示される証明書をコピーすることで作成したものを使う。※これによりドメイン外はURLを知っていても繋がらないので必要な人にしか提供できないように出来る。

７、クライアント側の設定とStudio、AssistantをOrchestratorへ接続する
　　ポイント１：ここまで繋がればあとは認証するだけ。

UiPath社的にはおそらくCloudを使うようにしてもらいたいのであろう。滅茶苦茶構築のハードルが上がっている。お客様的には社内でしか使わない全く社外がら繋がれないOrchestratorシステムの証明書を10万円近く掛けて買わなければならないのは負担であるし当然のように自己証明書（いわゆる俺俺証明書）を使うと思われ、IISでSSLはIP使えないとかそういうのはやめて欲しいところなのですが、セキュリティ的には買うべき論が多いのか、これらのネタは一連では無かったので備忘の意味も込めて残す。
【備忘録】初めてのCakePHP② - Tips編

随時更新予定

| アクション名 | 意味 |
|:-:|:-:|
| 　\$this->set(['article' => \$article, 'user' => $user]))　　| Viewに変数を渡すときの書き方 ​|
| $this->set(compact(['article', 'user'])) | キーと変数名が同じ場合の省略記法 |
| $this->render('/Posts/show') | レンダリングするビューテンプレートを明示する記法。action名とtemplateのファイル名が異なる時に使う |


## Controller


```php:src/Controller/ArticlesController.php
  // Controllerに対応したViewファイルを自動で読み込むのをやめたいとき
  public $autoRender = false;

  public function initialize()
  {
    parent::initialize();
    // Template/Layoutの自動レンダリングをやめたい時
    $this->viewBuilder()->disableAutoLayout();
    // Template/Layout/default.ctpではなくTemplate/Layout/other.ctpを使ってほしい時（上の記述はコメントアウトする）
    $this->viewBuilder()->setLayout('other');
  }

  /**
   * Index method
   *
   * @return \Cake\Http\Response|null
   */
  public function index()
  {
    $articles = $this->paginate($this->Articles);
    // アクションごとに個別のレイアウトを使うときはここに書く
    $this->viewBuilder()->setLayout('only');
    $this->set(compact('articles'));
    // ↓$this->autoRenderをfalseにしているときは自分で指定する（ルートパスはsrc/Template）
    $this->render('Articles/customindex')
  }
```

## Template

```php:Template/Articles/index.ctp

<!-- /articlesにアクセスするとTemplate/Articles/index.ctpがレンダリングされる -->
<h1>Blog articles</h1>
<table>
  <tr>
    <th>Id</th>
    <th>Title</th>
    <th>Created</th>
    <th>edit</th>
    <th>delete</th>
  </tr>

  <!-- ここから、$articles のクエリーオブジェクトをループして、投稿記事の情報を表示 -->
  <?php foreach ($articles as $article): ?>
    <tr>
      <td><?= $article->id ?></td>
      <td>
        <!-- 詳細画面に遷移するリンクの書き方 -->
        <?= $this->Html->link($article->title, ['action' => 'show', $article->id]) ?>
      </td>
      <td>
        <?= $article->created->format(DATE_RFC850) ?>
      </td>
      <td>
        <!-- 編集画面に遷移するリンクの書き方 -->
        <?= $this->Html->link('編集', ['action' => 'edit', $article->id]) ?>
      </td>
      <td>
        <!-- Confirm付き削除フォームの書き方 -->
        <?= $this->Form->postLink('削除',
         ['action' => 'delete', $article->id],
         ['confirm' => '一度削除するともとに戻せません。削除してよろしいですか?']
        )
        ?>
      </td>
    </tr>
  <?php endforeach; ?>
</table>
```
## Htmlヘルパー
```php:src/Template/Layout/default.ctp
<li><?= $this->Html->link('ログアウト', ['controller' => 'users', 'action' => 'logout']); ?></li>
```

```php:src/Template/Articles/show.ctp
<div>
<!-- 記事の詳細画面から投稿者の詳細画面(="Template/Users/show.ctp")へ遷移する場合 -->
<?= $this->Html->link($article->author->username, [
  'controller' => 'users', 'action' => 'show', $article->author->id
]);
?>
</div>
```


## Formヘルパー

### 投稿時によく使うパターン
```php:Template/Articles/add.ctp
<!-- /articles/addにアクセスするとTemplate/Articles/add.ctpがレンダリングされる -->
<h1>Add Article</h1>
<?php
<!-- Formヘルパー -->
echo $this->Form->create($article);
echo $this->Form->control('title');
echo $this->Form->control('body', ['rows' => '3']);
echo $this->Form->button(__('Save Article'));
echo $this->Form->end();
?>
```

### サンプル：削除ボタン
```php:Template/Articles/add.ctp
<td>
<!-- Confirm付き削除フォームの書き方 -->
<?= $this->Form->postLink('削除',
  ['action' => 'delete', $article->id],
  ['confirm' => '一度削除するともとに戻せません。削除してよろしいですか?']
  )
?>
</td>
```
Nuxt.jsでGA4(Google Analytics 4)のUser-IDを設定する方法


Nuxt.jsでGA4(Google Analytics 4)のUser-IDを設定する方法になります。
タグマネージャーを使用して設定するので、[@nuxtjs/gtm](https://www.npmjs.com/package/@nuxtjs/gtm)を使用します。

## gtm-moduleをインストール
Nuxt.jsでタグマネージャーの設定をするために、@nuxtjs/gtmをインストールします。

```
yarn add @nuxtjs/gtm 
or 
npm install @nuxtjs/gtm
```
### nuxt.config.jsで設定する

```js:nuxt.config.js
export default {
  modules: [
    '@nuxtjs/gtm',
  ],
  gtm: {
    id: 'GTM-XXXXXXX' // タグマネージャーのid
  }
}
```
インストール後`nuxt.config.js`でタグマネージャーのidを設定します。

## タグマネージャーでUser-IDの設定をする

続いて、タグマネージャーでUser-IDの設定をします。

### 変数の設定
![nuxt3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/e6cb6a45-83fe-19fd-a2e6-b92bc2110ebf.jpeg)
データレイヤーの変数を`user_id`に設定します。

### トリガーにnuxtRouteのイベントを設定
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/8a9e40fb-d113-81c2-5a1a-2d57ac985064.png)
`nuxtRoute`は`@nuxtjs/gtm`がデフォルトで設定しているイベントです。ページ遷移時に呼び出されます。

### タグの設定
![nuxt2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/389a7126-8199-0b87-1278-250c697ff429.jpeg)

上記の画像のようにタグの設定をします。
設定フィールドは`user_id`として、値は先ほど作成したデータレイヤーの変数`user_id`を設定します。
トリガーには、先ほど作成した`nuxtRoute`を設定します。

## Nuxt.jsからUser-IDを送る
Nuxt.jsからタグマネージャーにUser-IDを送るために、イベントを設置します。

```js
const userId = 10
this.$gtm.push({ user_id: userId  })
```

上記のコードでタグマネージャーにUser-IDを送ることができます。
ログイン完了時など、会員番号を取得したタイミングで設定するのが良いかと思います。

![nuxt.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/2b54f640-f3f0-ec4b-4ddd-7ad8cb8e47f2.jpeg)
タグマネージャーのプレビュー画面でuser_idがセットされていれば、イベントを送信できています。

### middlewareでUser-IDを設定することも可能

```js
const userIdMiddleware = ({ store }) => {
  const userId = 10
  store.$gtm.push({ user_id: userId })
}

export default userIdMiddleware
```
Nuxt.jsのmiddlewareで設定することで、ページがレンダリングする前にUser-IDをセットすることができます。
Vuexと組み合わせて、User-IDを管理するのも良いかもしれません。


## Google Analytics 4でレポートを作成
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/8fdb68fd-200a-b7e3-b811-ade3b4f83f12.png)

GA4(Google Analytics 4)でレポートを作成することで、User-IDの情報を見ることができます。

## 参考
https://support.google.com/analytics/answer/9213390
ざっくり、フロントエンド開発のためのバックエンドサービスを整理する

ReactやVue.js、Angularなどフロントエンド開発フレームワークが注目を集めています。SPA(Single Page Application)なんて呼ばれていますね。Next.jsやNuxt.jsなど、必要となる機能を統合したライブラリも充実してきました。

こうしたフロントエンド開発について調べていると、ググって最初のほうで見つかったチュートリアルや実現例に引っ張られて、他の実現方法に目がいかないことが多々あります(私の場合)。

とくにバックエンドの構成です。

そこで、いろいろ調べる中で見つかったフロントエンド開発で利用できそうなバックエンドを整理しています。個人で利用できるものからエンタープライズ領域まで、ざっくり5つのカテゴリに整理してみました。

- Hexabase企業サイトに記事を移行しました。こちらをご覧ください。
 [**React・Vueのフロントエンドで利用できるバックエンドサービスを整理する** ](https://www.hexabase.com/column/backend-service-for-frontend/#qiita)


## 関連ページ

- [ざっくり、Webシステムの発展と最新状況 2021](https://qiita.com/y_catch/items/1597a9a2ac2f7c8c43bf)
- [ざっくり、オープンソースビジネスの最新事例2021](https://qiita.com/y_catch/items/2947121bedf86d4504fc)
- [アイコン素材ダウンロードサイト**icooon-mono**](https://icooon-mono.com/)
- [フロントエンド強化月間 - 開発する上で知っておくべき知見を共有しよう](https://qiita.com/official-events/b9ad63394fa2635dfca9)
Laradockでpython pipが実行できなくてsupervisorがインストールできないときの解決法

## はじめに
Laradockでsupervisorをインストールしようとして少しつまったので、
解決策をメモ代わりに記事にしておきます。
エラーの詳細やLaradockについては割愛します。

## 本文

Laradockのドキュメントにsupervisorのインストール方法が記載されています。

https://laradock.io/documentation/


ドキュメントには以下のように環境設定ファイルを編集してね、とあるので
そのとおりにします。

```:.env（該当箇所以外は省略）
WORKSPACE_INSTALL_PYTHON=true
WORKSPACE_INSTALL_SUPERVISOR=true
```

そして、コンテナを立ち上げます。

```
docker compose up -d workspace
```

すると、

```:ターミナル
 => ERROR [ 78/110] RUN if [ true = true ]; then   apt-get -y install python python-pip python-dev build-essential    && python -m pip in  1.8s
------
 > [ 78/110] RUN if [ true = true ]; then   apt-get -y install python python-pip python-dev build-essential    && python -m pip install --upgrade pip    && python -m pip install --upgrade virtualenv ;fi:
#82 0.412 Reading package lists...
#82 1.378 Building dependency tree...
#82 1.580 Reading state information...
#82 1.617 Package python-pip is not available, but is referred to by another package.
#82 1.617 This may mean that the package is missing, has been obsoleted, or
#82 1.617 is only available from another source
#82 1.617 However the following packages replace it:
#82 1.617   python3-pip
#82 1.617 
#82 1.733 E: Package 'python-pip' has no installation candidate
```
なぜかエラーが...。
よく詳しくはよく分かりませんが、python pipが使えないので
かわりにpython3 pipを使ってねって感じだと思います。

とりあえずsupervisorさえインストールできればいいので、おとなしくpython3を使うことにします。
.envファイルを下記のように修正します。

```:.env（該当箇所以外は省略）
WORKSPACE_INSTALL_PYTHON=false
WORKSPACE_INSTALL_PYTHON3=true
WORKSPACE_INSTALL_SUPERVISOR=true
```

また、laradock/workspace/Dockerfileを下記のように修正します。

```yml:laradock/workspace/Dockerfile（該当箇所以外は省略）
ARG INSTALL_SUPERVISOR=false

RUN if [ ${INSTALL_SUPERVISOR} = true ]; then \
    # INSTALL_PYTHONをINSTALL_PYTHON3に変更
    if [ ${INSTALL_PYTHON3} = true ]; then \
    # pythonからpython3に変更
    python3 -m pip install --upgrade supervisor && \
    echo_supervisord_conf > /etc/supervisord.conf && \
    sed -i 's/\;\[include\]/\[include\]/g' /etc/supervisord.conf && \
    sed -i 's/\;files\s.*/files = supervisord.d\/*.conf/g' /etc/supervisord.conf \
  ;fi \
;fi

USER laradock
```

もう一度コンテナを立ち上げます。

```
docker compose up --build -d workspace
```

これで無事コンテナが立ち上がるはずです。


めでたし、めでたし。
Automation 360上でJavaScriptを使ってUnix時間を取得する

APIを叩くときにちょっと必要になったので、自分のメモを兼ねて貼っておきます。
JavaScriptの部分は @keng0o さんの [JSでUNIXのタイムスタンプを取得する - Qiita](https://qiita.com/keng0o/items/b15e58401b10fb1892ac) を丸ごとお借りしています。

## Botの完成イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/f990ee42-27b9-793d-4051-aac2912f8358.png)

### 1. JavaScript: 開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/c757f0e2-c774-7521-3b12-7b5f749b2cb4.png)

#### コード部分
```
function getUnixTime(){
timeStamp = Math.round((new Date()).getTime() / 1000);
return timeStamp
} 
```

### 2. JavaScript を実行
出力する変数名は適宜変更してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/ae281358-2e99-fd93-9a06-501952968a75.png)

### 3. JavaScript: 閉じる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/ede8ee05-6449-c740-ceaf-c768ab62dd57.png)

### 4. メッセージボックス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/05db24c0-4e92-fe90-a6b7-13517a3cd8e9.png)

## 実行結果

こんな感じで取得できたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/09fbc3b8-c572-f88e-1fc1-ce5362f0109a.png)
Windows10 で CapsLock キーと Ctrl キー入れ替え + Google 日本語入力導入

# はじめに

最近仕事用の PC が異音を出すようになったため、新しい PC に交換してもらった。再度自分用に PC をセットアップするため、次回同じことが起きた時に何をすべきか思い出せるように備忘録として残す。
本記事では、CapsLock と Ctrl の入れ替えと Goocle 日本語入力の導入を行う。とくに前者は Emacs Keybingings 使いである自分は必ずしなければならない。[【Ctrl2cap】「Caps Lock」を「Ctrl」に入れ替えよう！（Windows10）](https://kitsune.blog/ctrl2cap)を参考にした。

# Ctrl2Cap のインストール

[Ctrl2cap](https://docs.microsoft.com/ja-jp/sysinternals/downloads/ctrl2cap) から Ctrl2Cap.zip をダウンロードして解凍する。コマンドプロンプトを「管理者として実行」し、以下コマンドを実行して Windows を再起動。

```
$ cd [ctrl2cap_path]
$ ctrl2cap /install   # アンインストール時は ctrl2cap /uninstall
```

# Google 日本語入力のインストール

[Google 日本語入力](https://www.google.co.jp/ime/)から GoogleJapaneseInputSetup.exe をダウンロードして、実行。
Inkbird IBS-TH1 MINI 温湿度計をラズパイから読む

　前回、Inkbird IBS-TH1 MINI 温湿度計をmatlabから読みました。ここではラズパイ4で読みます。
###ラズパイの準備

セントラルのプログラムを書くために、bluepyライブラリをインストールします。このBLEライブラリは、pythonでセントラルのプログラムだけが書けます。

　ラズパイ4は最新の状態にしておきます。次の2点をインストールします。

``$ sudo apt-get install python3-pip libglib2.0-dev
$ sudo pip3 install bluepy
``

　[GitHub](https://github.com/IanHarvey/bluepy)にあるサンプルblescan.pyをエディタに読み込み、scan.pyの名前で保存します。

``$ sudo python3 scan.py
``

で、アドバタイジングしているBLEペリフェラルを探します。見つけてきました。Device Addrをメモしておきます。
![sps201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/6baace12-c743-dd86-f215-af88bbcaef21.png)

###プログラム


```C
from bluepy import btle
import time

data_CharacteristicUUID    = "FFF2"
deviceAddr = "10:08:2c:1e:2e:ab"

print('connect to Inkbird\n')
peri = btle.Peripheral()

while 1:
    peri.connect(deviceAddr, btle.ADDR_TYPE_PUBLIC)
    # print('connect')
    dataInformation = peri.getCharacteristics(uuid=data_CharacteristicUUID)[0]
    readdata = dataInformation.read()

    # print(readdata[0],readdata[1],readdata[2],readdata[3])
    temp = (readdata[1] * 256 + readdata[0] ) / 100.0
    humi = (readdata[3] * 256 + readdata[2] ) / 100.0
    print("temperature={:.2f}`C humidity={:.1f}%".format(temp, humi))

    peri.disconnect()
    time.sleep(7)
```

実行します。
![sps202.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/5be49349-b897-2856-3175-b089e4c4d24b.png)

　残念ながら、十数回から30回ほどで止まってしまいます。