OmniAICreator/Qiita-1.07M huggingface dataset:
Networkタブの情報（ajax通信の内容）をスクレイピングする方法

# 概要
多くの場合、サイトを表示した場合にそのサイト内で（クライアントサイド）外部サーバへリクエストを行い、レスポンスされたデータを非同期で埋め込みながらページがレンダリングされますが、この時のクライアントサイドでリクエストした情報をスクレイピングしたくなったため、まとめます。

# 簡潔に方法をまとめると
1. selenium + 無理やりスクリプトでごにゃって情報取得
2. selenium + browsermob-proxyでproxy経由するようにして情報取得

の2パターンが存在します。
1番目の方法は手頃に実現できますが、全ての情報が取得できるわけではなく、その場合は2番目のproxy経由での方法を使用すると自由度があがります。

# 手順
## seleniumを導入
これはいろいろなサイトで説明があるため省略しますが、macの方はbrewで導入可能です。

```sh
$ brew install chromedriver
```

```
$ pip install selenium
```

### スクリプトでごにゃる方法
以下のスクリプトを実行します。
※自分の場合、「"chromedriver"は開発元を検証できないため開けません。」と表示されたため、「キャンセル」ボタンを押して「システム環境設定」をクリックし、「セキュリティとプライバシー」を選択して許可しました。

```py
import json
from selenium import webdriver

driver = webdriver.Chrome("/hoge/hoge/chromedriver") 
driver.get("{スクレイピングしたい先のサイトのURL}")
scriptToExecute = "var performance = window.performance || window.mozPerformance || window.msPerformance || window.webkitPerformance || {}; var network = performance.getEntries() || {}; return JSON.stringify(network);"
data = driver.execute_script(scriptToExecute)
json = json.loads(str(data))
```
あとはjsonの中にobjectが配列で入っているためいい感じに取り出します。

### proxy経由する場合
流れとしては以下です。
1. http://bmp.lightbody.net/ にアクセスし、zipをダウンロード
2. 解凍し、chmod 755 などで実行権限を渡す
3. pip install browsermob-proxy する
4. 以下のスクリプトを書く

```py
from browsermobproxy import Server
from selenium import webdriver

# このdictの中に"User-Agent":"hogehoge"や"referer":"hoge"などを追記することでヘッダー変更可能です。
proxy_ooptions = {'port': 50000}
# pathは、解答したフォルダのpath/bin/browsermob-proxy を設定します
path = "hoge/bin/browsermob-proxy"

server = Server(path, options=proxy_ooptions)
server.start()
proxy = server.create_proxy()

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--proxy-server={0}".format(proxy.proxy))
browser = webdriver.Chrome(options = chrome_options)

#optionは必要に合わせて変更すればよいですが、この場合はヘッダーとレスポンスのcontentが返ってくるようになります。
proxy.new_har("hogehoge", options={'captureHeaders': True, 'captureContent': True})

browser.get("http://www.google.co.in")

print(proxy.har)

# 終了時はproxyも終了すること
server.stop()
browser.quit()
```

この時、jdkが入ってない場合はエラーが出ます。
（java -version　で確認したら入っていないか確認できます。）
その場合は、https://www.oracle.com/java/technologies/javase-downloads.html からjdkを入れて再チャレンジしてください。

また、SSL通信が必要な場合は、さっき解凍したフォルダ内にあるssl-support/ca-certificate-rsa.cer をキーチェーンアクセスのシステム欄の証明書の中にぶちこむとうまくいくはずです。
（やり方はこちらを参考に ： https://qiita.com/suin/items/be87a7a581f30b38c5f7）

proxy.har["log"]["entries"]配下の"request"や"response"あたりに欲しい値が入りますので、あとはharの内容を焼いたり煮たりぐつぐつして終わりです。(ちなみにHARはjsonで書かれたHTTP通信ログのことです。)

## ちょっとした蛇足
いろいろな事情でUser-Agentを偽装する必要がありました。
当たり前ですが、上に書いたようにproxy経由時にheaderを書き換えても、クライアントサイドでリクエストを送る場合には当然そのブラウザのUser-Agent情報が上書きされるため、場合に合わせて以下の設定を入れて「selenium側で」書き換える必要があります。

```py
options.add_argument('--user-agent=hogehoge')
```
【GAS】プルダウンの連動



# コード作成後の動き

![2021-02-26_19h06_37.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/7c2a5f87-1e38-a87b-5b00-0d782bab1645.gif)




# コード

```javascript:GASコード
function onEdit(e) {

  // リストと一致しなかったら終了
  const value = e.value;
  const list = ['あ行', 'か行', 'さ行', 'た行', 'な行', 'は行', 'ま行', 'や行以降'];
  if (!list.includes(value)) return;


  const range = e.range;
  const sht = range.getSheet();

  // シート名が違ったら終了
  if(sht.getName() !== 'data') return;

  const row = range.getRow();
  const col = range.getColumn() + 1; //入力箇所からズラす列数

  // 入力規則の範囲取得
  const shtName = 'プルダウン';
  const pulldownSht = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(shtName);

  // 項目名取得
  const items = pulldownSht.getRange('1:1').getValues().flat().filter(val => val);

  // rangeの取得
  const pulldownCol = items.indexOf(value) + 1;
  const pulldownLastRow = pulldownSht.getMaxRows() - 1;
  const pulldownRange = pulldownSht.getRange(2, pulldownCol, pulldownLastRow, 1);

  // rule作成
  const rule = SpreadsheetApp.newDataValidation();
  rule.requireValueInRange(pulldownRange);

  sht.getRange(row, col).setDataValidation(rule);
}
```

こちらのシートではプルダウンのRangeを取得してプルダウンを範囲で指定しているので、
プルダウンシートに追加項目があった際にそれも対象となる汎用的な書き方にしています。

もし固定でよいということであれば、こちらの方がおすすめです。
シートAPIを叩かない分、動きが早くなります。


```javascript:コード2
function onEdit(e) {


  // リストと一致しなかったら終了
  const value = e.value;
  const list = ['あ行', 'か行', 'さ行', 'た行', 'な行', 'は行', 'ま行', 'や行以降'];
  if (!list.includes(value)) return;


  const range = e.range;
  const sht = range.getSheet();

  // シート名が違ったら終了
  if(sht.getName() !== 'data') return;

  const row = range.getRow();
  const col = range.getColumn() + 1; //入力箇所からズラす列数


  const obj = {
    'あ行': ['あ', 'い', 'う', 'え', 'お', ],
    'か行': ['か', 'き', 'く', 'け', 'こ', ],
    'さ行': ['さ', 'し', 'す', 'せ', 'そ', ],
    'た行': ['た', 'ち', 'つ', 'て', 'と', ],
    'な行': ['な', 'に', 'ぬ', 'ね', 'の', ],
    'は行': ['は', 'ひ', 'ふ', 'へ', 'ほ', ],
    'ま行': ['ま', 'み', 'む', 'め', 'も', ],
    'や行以降': ['や', 'ゆ', 'よ', 'わ', 'を', 'ん', ],
  }

  // rule作成
  const rule = SpreadsheetApp.newDataValidation();
  rule.requireValueInList(obj[value]);

  sht.getRange(row, col).setDataValidation(rule);
}
```

違いはrurleの`requireValueInRange` か `requireValueInList`です。


# 補足

スプレッドシートの入力規則のみで実装も可能ですが、
行数が多くなると重くなって運用的にNGでした。
GASで違ったらすぐ処理を止めるやり方の方が実用的でした。

範囲特定する場合は列の〇列より前でのみ動かすとかの設定も加えても
よいのかなと思いつつ、プルダウンの内容を誤記入することも少ないかなとも思っています。
DjangoでreCHAPTCHAを導入する

djangoでreCAPTCHAを導入しました。

参考になる記事が限定的だったので、書き残しておきます。

[django-recapcha](https://pypi.org/project/django-recaptcha/)があるのですが、日本語解説記事もないので今回は使ってません。

#環境
- Django(3.1.5)
- [reCAPTCHA v2](https://www.google.com/recaptcha/about/)
- python(3.6.5)

# 参考資料
- [How to Add reCAPTCHA to a Django Site](https://simpleisbetterthancomplex.com/tutorial/2017/02/21/how-to-add-recaptcha-to-django-site.html)
- [django-recaptcha](https://pypi.org/project/django-recaptcha/)
- [Django - 迷惑メール対策 - フォームに画像認証の reCAPTCHA を導入する](https://qiita.com/narupo/items/f779f85054759a594a50)

#1.API-KEYを発行
[reCAPTCHA](https://www.google.com/recaptcha/about/)にアクセスして、``SECRET_KEY``と``SITE_KEY``を発行します。

参考動画は[こちら](https://learnwagtail.com/tutorials/adding-recaptcha-to-your-contact-forms/)
本編は、wagtailの話なので冒頭のみ参考に。

#2.settings.pyに反映
``settings.py``に``SECRET_KEY``を反映させます。

```python:settings.py
GOOGLE_RECAPTCHA_SECRET_KEY = *******************************
```
#3.htmlファイルに反映

下記を追加します

```html
<script src='https://www.google.com/recaptcha/api.js'></script>
<div class="g-recaptcha" data-sitekey="6LffvWgaAAAAAEwCrsrcNLJr8DyjgnUx4p5JMLed"></div>
```

#4.views.pyに反映

下記を追加します。
大体、``if form.is_valid():``の下に書きますよね。

```python:views.py
from django.conf import settings
from django.contrib import messages
import requests

recaptcha_response = request.POST.get('g-recaptcha-response') #POSTされたデータを受けとる
data = {
　　　'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
     'response': recaptcha_response
}
r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data)
result = r.json()
```


完了です。

django-rechapchaが用意されてるので、本当は使うべきですね。
上手くできなければ、コメントください。

# 変更履歴
- 2021.08.01 追記・修正
DateFrameを2つのkeyで昇順にソートする方法

#1 この記事は何？

DateFarme型を2つのkeyで昇順に並べ替える方法を節毎します。

下記は、行名Aを第1keyで昇順に並べ替え、行名Dateを第2Keyで昇順に並べ替えをしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/1b95d711-1bb4-6a2e-584d-530a8a234b35.png)


#2 どうやってやるの？

下記のコードの通り実施してみてください。

```python:example
import pandas as pd
import numpy as np
import scipy.stats
idx = pd.IndexSlice

#dataを定義する。
dat = [
    [1,'2019-07-01',2],
    [1,'2019-09-02',4],
    [1,'2019-06-01',8],
    [3,'2018-07-02',16],    
    [3,'2019-07-03',100],
    [3,'2016-07-01',200],
    [2,'2020-07-01',400],
    [2,'2019-07-01',200],    
]

#datをDataFrame型変数dfに格納する。
df = pd.DataFrame(dat,columns=["A","Date","C"])
print("df",df)

print("第1keyを「A」、第2keyを「Date」で並べ替える。")
df1 = df.sort_values(['A', 'Date'],ascending = True)
df1
```

実行結果

```console:example
df    A        Date    C
0  1  2019-07-01    2
1  1  2019-09-02    4
2  1  2019-06-01    8
3  3  2018-07-02   16
4  3  2019-07-03  100
5  3  2016-07-01  200
6  2  2020-07-01  400
7  2  2019-07-01  200

第1keyを「A」、第2keyを「Date」で並べ替える。
        A	Date	C
0	1	2019-06-01	8
1	1	2019-07-01	2
2	1	2019-09-02	4
3	2	2019-07-01	200
4	2	2020-07-01	400
5	3	2016-07-01	200
6	3	2018-07-02	16
7	3	2019-07-03	100
```
zipの中のフォルダ名一覧をCSVで取得



# 環境

OS: Windows10
ツール: Google Colaboratory
Python ver: 3.7.10
※Colabのバージョン

特にOSが違う場合はでコード部分の引数は変わると思うので気を付けてください。

# コード


```python:コード
import zipfile
import pandas as pd
from google.colab import files
uploaded = files.upload()

file_name = list(uploaded)[0]
ary = []
with zipfile.ZipFile(file_name) as z:
  for info in z.infolist():
    info.filename = info.filename.encode('cp437').decode('cp932')
    ary.append([info])
    

df = pd.DataFrame(ary)

file_name = file_name.replace('zip', 'csv')
df.to_csv(file_name, encoding = 'utf-8-sig')

files.download(file_name)
```

わざわざDataFrameにする必要はないと思いますが、
慣れている方法で書きました。
ローカル環境でTwitterリンクシェア機能実装しようとしたらgoogleに怒られた

#概要
現在ローカル環境で作成している投稿型webアプリケーションでTwitterのシェア機能を実装しようと思って、以下のQiita記事を参考に実装していました。
[[HowTo]Twitterへのリンクシェア機能をお手軽に実装する！](https://qiita.com/Tatsu88/items/e8de26f214d392a3c6f9)

とても簡単そうだったのですが、何故かページが表示されなくなってしまいました。

#原因
google consoleを開いてissueを確認すると以下のメッセージがきておりました。

>
Indicate whether to send a cookie in a cross-site request by specifying its SameSite attribute
Because a cookie’s SameSite attribute was not set or is invalid, it defaults to SameSite=Lax, which prevents the cookie from being sent in a cross-site request. This behavior protects user data from accidentally leaking to third parties and cross-site request forgery.
Resolve this issue by updating the attributes of the cookie:
Specify SameSite=None and Secure if the cookie should be sent in cross-site requests. This enables third-party use.
Specify SameSite=Strict or SameSite=Lax if the cookie should not be sent in cross-site requests.


読めないので翻訳

>SameSite属性を指定して、クロスサイトリクエストでCookieを送信するかどうかを示します。CookieのSameSite属性が設定されていないか無効であるため、デフォルトでSameSite = Laxに設定され、クロスサイトリクエストでCookieが送信されなくなります。この動作により、ユーザーデータが誤ってサードパーティに漏洩したり、クロスサイトリクエストフォージェリが発生したりするのを防ぎます。 Cookieの属性を更新して、この問題を解決します。クロスサイトリクエストでCookieを送信する必要がある場合は、SameSite = NoneおよびSecureを指定します。これにより、サードパーティによる使用が可能になります。クロスサイトリクエストでCookieを送信しない場合は、SameSite = StrictまたはSameSite = Laxを指定します。

SameSiteがわからなかったのでググってみると、
`cookie設定の属性でCSRFへのセキュアレベルの設定`ができるようになるみたいです。
設定値はStrict,Lax,Noneで、StrictとLaxを指定するとCSRFをブラウザレベルで防げるようになります。

そんなん設定してたっけ？とさらにググっていくとLaravel8.12では初期設定されていたみたいです。

`config/session.php`を開いてみると

```config/sessiton.php
<?php

use Illuminate\Support\Str;

return [
    /*
    |--------------------------------------------------------------------------
    | Same-Site Cookies
    |--------------------------------------------------------------------------
    |
    | This option determines how your cookies behave when cross-site requests
    | take place, and can be used to mitigate CSRF attacks. By default, we
    | will set this value to "lax" since this is a secure default value.
    |
    | Supported: "lax", "strict", "none", null
    |
    */

    'same_site' => 'lax',

];
```
laxになっていました。

Noneに変更する場合は、`secure属性を有効にする`必要があるみたいですが、ローカル環境なのでhttps化をしておりません。

つまりサーバにアップしてから実装しろってことなんだと思います。




#まとめ
サーバに公開してから実装することにします！

#参考文献
[Chrome 80が密かに呼び寄せる地獄 ～ SameSite属性のデフォルト変更を調べてみた](https://qiita.com/ahera/items/0c8276da6b0bed2b580c)
[LaravelでCookieのSameSite属性を設定する](https://qiita.com/kusano00/items/e5861af3eb7221a006c3)
[vscode]リモート環境のjupyterにワンクリックでホストのブラウザからアクセスする

# はじめに

vscodeのpython extensionはjupyter notebook形式に対応していて、vscodeのタブをjupyter notebook風に利用することができます。
参考：[VS CodeのPython拡張がJupyterをネイティブサポートしたそうなので早速使ってみた。](https://qiita.com/simonritchie/items/5d865e72dba47cf8f6c0)

しかし2021年2月現在、

* 複数ペインでnotebookを開いた場合にフォーカスが安定しない
* 読み込みに時間がかかる
* 黒背景が見づらい

などパフォーマンス面でいくつかの課題があります。今のところ、ブラウザでjupyter-labを開いた時ほど安定感はないかなと思います。

ストレスフリーに使いたければブラウザからアクセスしたいところですが、ブラウザからリモート環境にアクセスするにはサーバのポートの設定などを変更しなければならず面倒だとされています。また作業ディレクトリを毎回変更して起動しなければならないのもやや面倒です。

できれば１クリックで実現したいところです→できます！


# 方法

1. VS Codeでリモート環境のフォルダーを開く
2. タブから"ターミナル(T)"→"新しいターミナル"を選択
3. ターミナルで`jupyter lab`を起動

4. ターミナル上に出力されたurlを**ctrl+クリック**
![jupyter_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246736/42a05a8c-b5b6-69fa-dc86-0c8f757b7194.png)


以上で、使い慣れたブラウザ版jupyterをワンクリックで利用することができました。
Formオブジェクトと複数画像投稿機能を使う時のストロングパラメータ

FormオブジェクトとActiveStorageで複数画像投稿機能を使う時のストロングパラメータの設定

今回imagesデータだけが.requireで別の名前で出力さた問題を起こしていました
本来ストロングパラメーターの記述は

```Ruby
params.require(:キー(モデル名)).permit(:カラム名１,：カラム名２,：カラム名3,~).marge(カラム名: 入力データ,~~)
```
のようにするのですが

formで指定したモデル外のものはfieldのname属性を入力する事で取り出すことができます

```ruby
f.file_field :images, id:"item-file_0", class: 'item-file', name:'item[images][]' 
```

のような記述であれば

```ruby
params.require(:item).permit(:images[])
```

と記述する事で解決する事ができました

これによりコントローラーで設定したモデル名と名前を合わせることで
同じ.require(:モデル名)内へデータをまとめる事ができました
STM32G031のArduinoでのHT16K33でナイトライダー


1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり

```c++

#include <Wire.h> //I2C library

//STM32G031J6M6
#define sdaPin PA12    // ArduinoA4
#define sclPin PA11    // ArduinoA5

// I2C address. 
#define HT16K33_add 0x70
#define I2Cadr      0x3e  // 固定


char    data_read[2]; //i2cバッファー
int     ii;           //ループカウンター

//レジスターの初期値
char INIT_com[] = {
  0x21,0x81,0xef
};

//表示器への書き込み
void i2c_HT16K33(char *buff1,int n){
  Wire.beginTransmission(HT16K33_add);
  Wire.write(buff1[0]);
  if(n == 2){
    Wire.write(buff1[1]);
  }
  Wire.endTransmission();
  delay(1);
}//i2c_HT16K33

void setup()
{  
  delay(3000); //not delete

  //Wire.begin(); // initialise the connection //767
  Wire.begin(sdaPin,sclPin); //STM32G031J6M6

  //レジスターの初期化 
  for(ii=0;ii<3;ii++){
    i2c_HT16K33(&INIT_com[ii],1);
  } //for

  //表示データの初期化
  for(ii=0;ii<16;ii++){
    data_read[0]=ii;
    data_read[1]=0x00;
    i2c_HT16K33(data_read,2);
  } //for
} //end setup

void loop()
{
  //ビットシフトでナイトライダー
  for(ii=0;ii<8;ii++){
    data_read[0]=0;       //アドレス
    data_read[1]=(1<<ii); //データ
    i2c_HT16K33(data_read,2);
    delay(1000);
  } //for
}//loop


```

![i2c_HT16K33_031_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/efeb5a47-04e4-7131-bb01-ff6715766821.jpeg)

![i2c_HT16K33_031_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/95626994-639f-1c1e-d0aa-ac20b2c98d70.jpeg)

![i2c_HT16K33_031_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/ef581939-284a-eb42-9178-ad63a37d4ba9.jpeg)

![i2c_HT16K33_031_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/090b1e9f-f7b2-9051-3674-a5e5e88ee382.jpeg)

![i2c_HT16K33_031_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c8c733bc-c408-0a8a-6c55-3720ad872f6a.jpeg)
MacbookにRubyをインストール

# 環境

MacOS:Catalina
`MacbookPro`初期の状態から`Ruby`、`Rails`、`MySQL`をインストールします。

手順は以下です。
・Zshをデフォルトに
・Command line tools導入
・Homebrew導入
・Rubyインストール
・MySQLを導入
・Railsを導入
・Node.jsの導入
・yarnの導入


# Zshをデフォルトに

 ```
# zshをデフォルトに設定
% chsh -s /bin/zsh

# ログインシェルを表示
% echo $SHELL
# 以下のように表示されれば成功
/bin/zsh
```
パスワード求められたらPCのパスワードを入力します。

# Command line tools導入
以下をターミナルで

```
% xcode-select --install
```
インストールをクリックして進める。

# Homebrew導入

Homebrewというソフトウェア管理ツールを導入します。
以下をターミナルで。

```
% cd  # ホームディレクトリに移動
% pwd  # ホームディレクトリにいるかどうか確認
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" # コマンドを実行
```
PCパスワードを求められます。
途中エンターキー入力あります。

以下でインストールできたか確認。

```
% brew -v
```
最新の状態にします。

```
% brew update
```
Homebrewの権限変更

```
%  sudo chown -R `whoami`:admin /usr/local/bin
```

# Rubyインストール
Rubyの土台となるrbenvとruby-buildを、Homebrewを用いてインストール

```
% brew install rbenv ruby-build
```
rbenvをどこからも使用できるようにする。

```
% echo 'eval "$(rbenv init -)"' >> ~/.zshrc
```
zshrcの変更を反映

```
% source ~/.zshrc
```

ターミナルのirb上で日本語入力を可能にする設定を行うために、以下のコマンドでインストール

```
% brew install readline
```
すでにインストール済と出る場合あります。

readlineをどこからも使用できるようにします。

```
% brew link readline --force
```
rbenvを利用してRubyをインストール。

```
% RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)"
% rbenv install 2.6.5
```
時間がかかるコマンドです。

rbenvを読み込んで変更を反映。

```
% rbenv rehash
```
Rubyのバーションを確認。

```
% ruby -v
```

# MySQLを導入

```
% brew install mysql@5.6
```

MySQLの自動起動設定。
MySQLは本来であればPC再起動のたびに起動し直す必要がありますが、それは面倒であるため、自動で起動するように。

```
% mkdir ~/Library/LaunchAgents 
% ln -sfv /usr/local/opt/mysql\@5.6/*.plist ~/Library/LaunchAgents
% launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql\@5.6.plist 
```

mysqlコマンドをどこからでも実行できるように。

```
% echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.zshrc # mysqlのコマンドを実行できるようにする設定
% source ~/.zshrc #  設定を読み込むコマンド
% which mysql # mysqlのコマンドが打てるか確認する

# 以下のように表示されれば成功
/usr/local/opt/mysql@5.6/bin/mysql
```

MySQLの起動を確認。

```
% mysql.server status # MySQLの状態を確認するコマンド

# 以下のように表示されれば成功
 SUCCESS! MySQL running
```

# Railsを導入

Rubyの拡張機能（gem）を管理するためのbundler（バンドラー）をインストールします。

```
% gem install bundler --version='2.1.4'
```

Railsをインストール。

```
% gem install rails --version='6.0.0'
```
処理に時間かかります。

rbenvを再読み込み。

```
% rbenv rehash
```

Railsが導入できたか確認。

```
% rails -v
Rails 6.0.0  # 「Rails」のあとに続く数字は変わる可能性があります
```

# Node.jsの導入

Railsを動かすためにはNode.jsが必要となり、それをHomebrewを用いてインストールします。

```
% brew install node@14
```

Warningでても問題ないです。

Node.jsへのパスを設定。

```
% echo 'export PATH="/usr/local/opt/node@14/bin:$PATH"' >> ~/.zshrc
% source ~/.zshrc
```

Node.jsが導入できたか確認。

```
% node -v
v14.15.3 # 数値は異なる場合があります
```

# yarnの導入

yarnのインストール。

```
% brew install yarn
```

yarnが導入できたか確認。

```
% yarn -v
```

以上で、Railsでアプリ作成ができる環境が整いました。
分析クエリ関連のリンク

分析クエリ(Analytic Query)に関する記事やリンクを集めました。

## 分析系CDS View全般

| タイトル | 作者 |概要        |
|:-----------|:------------|:------------|
| [Analytics on Universal Journal, the heart of SAP S/4HANA] (https://blogs.sap.com/2020/09/24/analytics-on-universal-journal-the-heart-of-sap-s-4hana/)        |[Masaaki Arai](https://people.sap.com/masaaki.arai)|会計系の標準VDMがたくさん載っている。標準VDMの上にカスタムクエリを作る方法についても紹介|
|[How to deal with “Not released” predefined VDM in S/4HANA](https://blogs.sap.com/2019/05/23/how-to-deal-with-not-released-predefined-vdm-in-s4hana/)       |[Masaaki Arai](https://people.sap.com/masaaki.arai)|未リリースのVDMを使いたい場合、どうするか|
|[Date Function for dynamic date filtering in Fiori apps](https://blogs.sap.com/2018/09/27/date-function-for-dynamic-date-filtering-in-fiori-apps/)|[Masaaki Arai](https://people.sap.com/masaaki.arai)|Date Functionを使って日付項目の初期値を設定する方法、ユーザのデフォルト値をパラメータ初期値に設定する方法|
|[Cardinality of Association in CDS View](https://blogs.sap.com/2018/08/20/cardinality-of-association-in-cds-view/)|[Masaaki Arai](https://people.sap.com/masaaki.arai)|Associationでのカーディナリティの指定方法によってアクセスされるデータにどのような違いがあるか|
|[Illustrate how Analytical Queries are executed and controlled by analytical engine and DCL on ABAP layer](https://blogs.sap.com/2021/01/19/illustrate-how-analytical-queries-are-executed-and-controlled-by-analytical-engine-and-dcl-on-abap-layer/)|[Yuto Sugita](https://people.sap.com/yuto.sugita)|分析クエリとODataサービスではSELECT先のデータソースが異なるので、パフォーマンストレースやアクセスコントロールで見るビューについて留意が必要|
|[Using Hierarchy in CDS](https://wiki.scn.sap.com/wiki/display/BI/Using+Hierarchy+in+CDS)|Community Wiki|階層つきCDS Viewの作り方|

## パフォーマンス関連
| タイトル | 作者 |概要        |
|:-----------|:------------|:------------|
|[CDS view performance Annotation for CDS view performance](https://blogs.sap.com/2020/02/06/cds-view-performance-annotation-for-cds-view-performance/)|[Abhimanyu Sharma](https://people.sap.com/abhimanyu.sharma)|アノテーション@ObjectModel.usageTypeの使い方|

## 権限のトラブルシューティング
| タイトル | 作者 |概要        |
|:-----------|:------------|:------------|
|[Tcode SACM(Access Control Management) to check authorization issues of CDS Views](https://blogs.sap.com/2016/03/11/tcode-sacmaccess-control-management-to-check-authorization-issues-of-cds-views/)|Former Member|Tr-cd:SACMの使い方|

## タイルの作成方法
| タイトル | 作者 |概要        |
|:-----------|:------------|:------------|
|[How to create custom Fiori Multidimensional Reporting Application in S/4HANA on-premise](https://blogs.sap.com/2018/07/11/how-to-create-custom-fiori-multidimensional-reporting-application-in-s4hana-on-premise/)|[Masaaki Arai](https://people.sap.com/masaaki.arai)|分析クエリからDesign Studio、またはWeb Dynproのタイルを作成する方法|

##標準のCDS Viewを探せるところ

- [SAP API Business Hub](https://api.sap.com/): S/4HANA CloudのCDS Viewが検索できる
- [SAP S/4HANA Cloudのヘルプ](https://help.sap.com/viewer/0f69f8fb28ac4bf48d2b57b9637e81fa/2102.500/en-US/5418de55938d1d22e10000000a44147b.html)
- [SAP S/4HANA On-Premiseのヘルプ](https://help.sap.com/viewer/8308e6d301d54584a33cd04a9861bc52/2020.001/en-US/5418de55938d1d22e10000000a44147b.html?q=cds): 対象システムのバージョンを選んで検索する

## トランザクション

- `RSRT`: クエリ実行
- `RSRTS_ODP_DIS`: Interface View実行
- `SDDLAR`: DDLソースの検索
[Drupal] Viewsの上にカスタムブロックを表示する方法

今回は画像のようにビューのヘッダー部分にカスタムブロックを追加する方法についてシェアしたいと思います。

![view_header.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/3ce3cac4-eb6e-0a66-8557-79bab8274acb.png)

## カスタムブロックを作成
まずは通常通り`/block/add`からカスタムブロックを作成します。

![スクリーンショット 2021-02-26 19.50.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/2247b689-6400-bb4d-c1d0-79e406b9a755.png)

## カスタムブロックを配置
次に、`admin/structure/block`から先程作成したブロックを配置します。

パスを限定しないとすべてのページで表示されてしまうので、**閲覧の制限**で表示したいビューのパスに限定します。

**システム内部名称**は後ほどビューの設定で使うのでわかりやすい名称を付けましょう。

リージョンはどこでもいいのですが、今回はとりあえずContentにしました。

![スクリーンショット 2021-02-26 20.04.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/28750248-e240-919c-7c59-586995d85c8e.png)

## ビューのヘッダー設定
仕上げにビューの設定を行います。

カスタムブロックを配置したいビューの**ヘッダー**の「追加」ボタンをクリックします。

![view_settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/871f6e4d-951b-d73c-53d1-6ff64a0dba6a.png)

**レンダリング済みエンティティ - Block**にチェックを入れ、保存します。(「レンダリング済みエンティティ - カスタムブロック」というのもあるのですが、なぜかブロックがレンダリングされないのでご注意を...)

![スクリーンショット 2021-02-26 20.08.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/8e2b57a5-a4e6-0d5d-a5fe-374cdcad2093.png)

**Block ID**にさきほどブロックレイアウトで設定したブロックのシステム内部名称を入力して保存します。

![スクリーンショット 2021-02-26 20.10.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/748c3759-205f-143e-bc67-7d20298f5110.png)

出来上がり！

![スクリーンショット 2021-02-26 19.54.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/25dfc05f-2e75-d5e6-ed69-7cafdffe653e.png)
配列から指定した属性を持つ要素の削除、更新

javascript使っていて、配列内の要素を属性を指定した上で**削除、更新**することが多いかったので個人的な備忘録も兼ねて投稿（マークダウンの練習、物書きの練習も兼ねて）。
<br>
こんな感じの3レコードある配列の中から対象を**削除、更新**していきたいとします。


```test.js
    let list = [{'id':1,'username':'hiro'},
                {'id':2,'username':'maro'},
                {'id':3,'username':'maro'}];

    console.log(JSON.stringify(list));
```
まずはconsole.logで表示してみます。

```
[{"id":1,"username":"hiro"},{"id":2,"username":"maro"},{"id":3,"username":"maro"}]
```


##削除
username = maroの2件をfilterを使って削除します。

```test.js
    list = Array.from(list.filter( (obj) => { return obj['username'] != 'maro'; } ) );
```

⇧listをfilterしdeep copy。
console.logで表示したところ。

```
    [{"id":1,"username":"hiro"}]
```

削除されていました。
対象が複数の場合でも1件でも変わりません。

##更新(1件)
更新対象が1件であればfindを使います。
id=2のレコードのusernameをheloに更新したいと思います。

```test.js
    let oneOfList = list.find( (obj) => { return  obj['id'] == 2; } );
    oneOfList['username'] = 'helo';
```
console.logで表示したところ。

```
    [{"id":1,"username":"hiro"},{"id":2,"username":"helo"},{"id":3,"username":"maro"}]
```

##更新(複数)
対象をまとめて更新しても良い場合
filterとforEachを使います。
maroのレコード2件をjaroに更新したいと思います。

```test.js
    let someOfList = list.filter( (obj) => { return  obj['username'] == 'maro'; } );
    someOfList = someOfList.forEach( (obj) => { obj['username'] = 'jaro'; } );
```
console.logで表示したところ。jaroに更新されています。

```
    [{"id":1,"username":"hiro"},{"id":2,"username":"jaro"},{"id":3,"username":"jaro"}]
```

##最後に
ご拝読ありがとうございました。
if文なしでじゃんけん - JS版

[if文なしでじゃんけん - Qiita](https://qiita.com/tadsan/items/65d91ba6b50535fc8815) を読んでJSで組んでみました。

# 解答

```js
const gu = "gu";
const choki = "choki";
const pa = "pa";

const createResult = (winHand, loseHand, drawHand) => ({[winHand]: "勝ち", [loseHand]: "負け", [drawHand]: "あいこ"})
const hands = Object.freeze({
    [gu] : {view: "✊", judgeTable: createResult(choki, pa, gu)},
    [choki] :{view: "✌ ", judgeTable: createResult(pa, gu, choki)},
    [pa] : {view: "✋", judgeTable: createResult(gu, choki, pa)},
});

const getView = (hand) => hands[hand]?.view;
const battle = (my, your) => judge(hands[my]?.judgeTable, your);
const judge = (judgeTable, your) => judgeTable[your];

Object.keys(hands).forEach(myHand => {
    Object.keys(hands).forEach(yourHand => {
        console.log(`[${getView(myHand)} vs ${getView(yourHand)}] ${battle(myHand, yourHand)}`);
    });
});
```
動作結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78708/86aae1db-4869-1d38-67f8-afb9a39b5746.png)

# 作ってみて
単純だからこそ考え甲斐があって楽しいですね。
本来であれば自分の手をSymbolで作るべきなのかなと思っていたのですが、出力部分が面倒なことになるので今回は定数という形で実装しました。

三項演算子、Null合体演算子も使うか迷ったのですが使いませんでした。
そのためjudgeで定義している関数で配列かどうかのチェックがありません。でも今回の要件に外からの入力は無いのでヨシとしました。
TypeScriptで実装していればこういった心配が少なくなるのが良いですよね。

今回は文字を出力するだけの要件なので、直接「勝ち」「負け」「あいこ」を書きましたが、関数を持たせるようにすれば勝利ポイントなども扱えるようになりそうです。

もっと短く書けるぞ！って方は是非挑戦してみてください。
OCI の Outbound Data Transfer の現在値を確認してみる。(Oracle Cloud Infrastructure)

OCI(Oracle Cloud Infrastructure) の Outbound Data Transfer、OCI内から外部へのデータ転送で
発生する料金は月毎に 10TB まで無償なんですが、現在値がどの程度かは気になりますよね。

> Oracle Networking Cloudの価格
> https://www.oracle.com/jp/cloud/networking/networking-pricing.html
> ：
> アウトバウンドデータ転送 - 最初の10 TB（1か月あたり）- 無償
> 
> OCI 課金にまつわるエトセトラ
> https://speakerdeck.com/mmarukaw/oci-ke-jin-nimatuwaruetosetora

この Outbound Data Transfer の現在値を確認する方法がちょっと解り難かったので、まとめてみましたやで。
彡(ﾟ)(ﾟ)

# 1. OCI Console から Service User Console を開く。

![Outbound001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/b17a76e6-9029-1641-0d4d-200ea42e645a.jpeg)

OCI Console画面右上の人のアイコンをクリックして、プルダウンメニューから「Service User Console」を開きます。

# 2. Service User Console から My Admin Accounts を開く。

![Outbound002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/d8048720-236b-7f2c-3d24-48b9e13c1b58.jpeg)

Service User Console画面右上の人のアイコンをクリックして、プルダウンメニューから「My Admin Accounts」を開きます。

# 3. My Admin Accounts の Usageタブをクリックする。

![Outbound003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/12e4fe20-9a9b-4543-2499-577f40e41783.jpeg)

My Admin Accounts の Usageタブをクリックします。

# 4. Usage Summary の Compute を展開する。

![Outbound004.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/deaf238f-b703-9d6b-700e-735df25033b5.jpeg)

Usage Summary の Description に表示されている Compute の三角マークをクリックして展開します。

# 5. Outbound Data Transfer の確認

![Outbound005.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/71e97ef6-bf45-ce5f-9eba-9b7f2e68c594.jpeg)

Description の Compute が展開されると、Outbound Data Transfer の現在値が確認できます。
Usage Quantity の単位は、おそらく課金単位の GB のはず……。彡(ﾟ)(ﾟ)

# 6. まとめ
Outbound Data Transfer の現在値はちょっと解り難い場所にひっそりと佇んでますね……。
とまれ転送量が 10TB を超えることはそうそう無いはず。OCI をどんどん活用して下さいね。彡(^)(^)

# 追記. Cost Analysis での同メトリックの取得
![Outbound006.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/5c236595-51e8-c805-ebeb-cafe507f0679.jpeg)

コメントにも有る通り Cost Analysis でも同メトリックが取得できました。
@sugimount さん、ありがとうございます！彡(^)(^) また逢い見えましょう。
【AWS】ECRでレポジトリを作成し、イメージをプッシュする手順



##1. レポジトリの作成

オレンジ色の「レポジトリを作成」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/010314dc-a2f7-dc67-9632-10ed2af08938.png)



###設定内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/b464ba31-42e8-5962-02f3-4576cca49f06.png)

(1) リポジトリ名


<br>
**▼以下はデフォルトのまま**

(2) プライベート　（イメージを公開したい場合はパブリックにする）
(3) タグのイミュータビリティ：　無効
(4) イメージスキャンの設定：　無効
(5) 暗号化設定：　無効


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/fad3293f-5c01-cefb-2330-60ffc49dfd49.png)

右下のオレンジ枠の「リポジトリを作成」をクリックすれば完成。たったこれだけ。


###タグのイミュータビリティとは？
イメージの上書き防止機能。

dockerでイメージを作成する時は、`イメージ名:タグ名`で、名前をつける。タグ名にはバージョンを指定することが一般的。

タグのイミュータビリティ機能を有効にすると、タグ名が同じ場合に上書きを防いでくれる。

レポジトリ作成後は変更できない。



###イメージスキャンの設定とは？
脆弱性を確認する機能。

イメージスキャンを有効にすると、イメージがECRレポジトリにプッシュされた時に、イメージの中身をスキャンし、欠陥がないか確認してくれる。

イメージスキャンの結果はAmazon EventBridgeに保存される。

無効にしている場合は、手動でスキャンを実行できる。



###暗号化設定とは？
暗号化方式の指定。

デフォルトではAES-256で暗号化されているが、KMS暗号化を有効にすると、AWS Key Management Service (KMS)で指定した方法で暗号化することができる。

2020/7/29から使えるようになった比較的新しい機能。

https://aws.amazon.com/jp/about-aws/whats-new/2020/07/ecr-supports-encryption-images-aws-kms-keys/



<br>
##2. イメージのビルド
docker-compose.ymlファイルとDockerfileを用意して、buildコマンドを実行する。

・`docker-compose build サービス名`

ECRにプッシュする前にイメージ名を変更する必要があるため、イメージ名は識別できるものにしておく。

docker-compose.ymlの中にimageディレクティブを記述する。

・`image: <イメージ名>:<タグ名>`


<br>
###デバッグしてからビルドする関数定義
本番環境のイメージ作成など、注意が必要な場合は、

(1)ローカルに未コミットがないか、(2)リモートレポジトリとローカルレポジトリのブランチの間に差分がないかを確認してから、イメージを作成するとうっかりミスを減らせる。

詳細は[gitのハッシュ値を使ってイメージビルド前のデバッグ処理を作成する方法](https://qiita.com/yuta-38/items/9194f5b89470821d320e)を参照。



<br>
##3. イメージをプッシュする
作成したレポジトリにイメージをプッシュするには、`docker push`コマンドを使う。

ECRへのイメージプッシュの処理手順は以下になる。

1. docker経由でawsへのログイン
2. docker tagでイメージ名を変更
3. docker pushでイメージを送信
4. ECR上でイメージが追加されたか確認


詳細は、[ECRにログインし、レポジトリにイメージをプッシュするエイリアスコマンドの作成方法](https://qiita.com/yuta-38/items/98227a7e9498d62f280e)を参照。


###ポイント１
`docker push`する際に、**プッシュ先のレポジトリはイメージ名で指定**する。

イメージ名は以下のようにする必要がある。

・`<ホスト名>/<レポジトリ名>:<タグ名>`

イメージ名を変更するために、`docker tag`コマンドを使う。



###ポイント２
イメージは新たにビルドする必要がある。

**元々あるイメージを再度プッシュしようとしても、変更がない場合はプッシュは行われない**。

プッシュ後にECRに行って、イメージタグが追加されているか確認すること。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/2eff2662-1f88-3366-f538-0d3d9d623047.png)


<br>
ECR上でプッシュした日時でイメージが確認できればOK。
#ターミナルをかっこよくする

#プロンプト
```:.bashrc
PS1='\[\e[30;47m\] \u \[\e[37;46m\] \W \[\e[0m\]\$'
```

```
$ source ~/.bashrc
```


説明
\[\e[ 0x;3x;4x m\]]の中身の文法

書体，文字色，背景色の順位に；で区切る

```:エスケープシーケンス
00　普通
01　ボールド
02　細字
03　イタリック
04　アンダーライン
05　点滅

3x　文字色
4x　背景色

x0　黒
x1　赤
x2　緑
x3　黄
x4　青
x5　紫
x6　水
x7　灰
```

変数の説明

```
\h　ホスト名　パソコンの名前
\u　ユーザ名
\w　カレントディレクトリ絶対パス
\W　カレントディレクトリ相対パス
\t　時間 24h
\T　時間 12h
\@　時刻PM  AM
\d　日付
\D　タイプスタンプ　\D{}として%y,%m,%d,%H,%M,%Sの引数をとれる
\#　コマンド番号
\n　改行する
\$　$ or #の表示　末尾に入れるべき
```


ひとまずここまで


#参考

https://qiita.com/hmmrjn/items/60d2a64c9e5bf7c0fe60
【Rails6】簡単ログイン・ゲストログイン機能のuser情報にActive Storageを用いている場合

#はじめに
簡単ログイン機能は以下の記事を参考にして、実装しました。
かなりわかりやすい記事なので、簡単ログインを実装する際にはぜひご参考ください。

https://qiita.com/take18k_tech/items/35f9b5883f5be4c6e104

本記事は上の記事の追加情報となります。

user情報にActive Storageを用いて、画像登録の設定をしているという記事を見たことがなかったので、作成してみました。

#バージョン
rubyのバージョン　ruby-2.6.5
Railsのバージョン Rails:6.0.0

#概要
上記の記事に加えて、新規登録情報にActive Storageを用いて画像の登録を行っている場合に、実装に必要な記述についてご紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/68644624-7b12-d536-25b7-97708a61b535.png)

#結論

コントローラー内に以下のimage.attachの記述を行う。

```app/controllers/homes_controller.rb

# 〜省略〜

def new_guest
    user = User.find_or_create_by!(nickname:'guest', email: 'guest@example.com', occupation: 'guest', position: 'guest', birth_day: '1990-10-10', sex_id: 2) do |user|
      user.password = SecureRandom.urlsafe_base64
      user.image.attach(io: File.open(Rails.root.join("app/assets/images/homekatajiten.png")), filename: "homekatajiten.png") # ←こちらです！
    end
    sign_in user
    redirect_to root_path, notice: 'ゲストユーザーとしてログインしました。'
  end

# 〜省略〜

```

#補足説明
Active Storageでimageカラムを取り込んでいるので、usersテーブルにimageカラムをattachします。

imageカラムをfind_or_create_byメソッドの引数に含めるとエラーが起こります。
というのもuserテーブルにimageカラムがないからです。

以上です。
【jquery,js】自作マークダウンエディタ、正規表現　[replace,html] [js08_20210226]

####  <font color='orange'>処理の概要</font>
入力されたマークダウン形式のテキストをhtmlに変換。これをhtmlタグコードと、htmlで表示する

##### 処理のフロー：
　(1)マークダウン形式のテキストを取得
　(2)関数にて置換
　(3)htmlタグ形式でテキストエリアに出力
　(4)htmlにて表示

####  <font color='orange'>画面イメージ</font>

#####画像１
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/db7a14c6-270e-1b4e-886f-4e64d6b1f575.png" width="500px">

#####画像２
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/c2ede0d9-9051-9cd8-075a-910b5b7ba9f2.png" width="500px">

####  <font color='orange'>ソースコード</font>
```html:index.html
<head>
<link rel="stylesheet" href="./css/default.css">
</head>
<body>
<textarea id="userText">
#タイトル1
本文本文本文本文*本文*本文

##タイトル2
本文本文本文本文*本文*本文
</textarea><br>
<input type="button" id="execButton" value="実行"><br>
<textarea id="output"></textarea><br>
<div id="output2"></div>
</body>
```

```javascript:main.js
// DOMの準備後に実行する内容
$(function() {
    $("#execButton").click(function(){
        var markDownText = $("#userText").val();
        htmlText = markDown(markDownText);

        $("#output").val(htmlText);
        $("#output2").html(htmlText);

        function markDown(argText){
            argText = argText.replace(/\*(.+?)\*/g, "<b>$1</b>");
            argText = argText.replace(/^## *(.+?)$/gm, "<h2>$1</h2>");
            argText = argText.replace(/^# *(.+?)$/gm, "<h1>$1</h1>");
            argText = argText.replace(/\n/gm, "<br>\n");

            return argText;
        }
    });
});
```

```default.css
textarea {
	height: 8em;
	width: 40em;
}

.input-style {
	color:blue;
	width: 400px;
}

b {color: red;}

```

####  <font color='orange'>ポイント</font>
html：
(1)なし
js：
(1)正規表現について
①*〜*で挟まれた部分を、`/\*(.+?)\*/g`で表現します。replaceなので、ステークホルダーを使い、`<b>$1</b>`で置換します。
`\`は\*(アスタリスク)をエスケープしています。下の参考資料の通り、\*は0回以上繰り返しの特殊記号なので。この記事を書いている時も、エスケープしています（笑）
`(.+?)`は、任意の一文字を示しています。

②行頭は`^`。行末は`$`です


####  <font color='orange'>参考資料</font>
JavaScript(仕事の現場でサッと使える！デザイン教科書)　p150
正規表現はこちら↓
JavaScript(仕事の現場でサッと使える！デザイン教科書)　p91


####  <font color='blue'>正規表現-参考資料1</font>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/17f3708f-4304-debd-36b2-a5cdde1316f3.png" width="200px">

####  <font color='blue'>正規表現-参考資料2</font>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/787e446f-1c5f-2fde-f718-8b7f3b9ea705.png" width="200px">

####  <font color='blue'>正規表現-参考資料3</font>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/4dff3bed-9b69-44c8-32fe-2d0a8a7cd6fc.png" width="200px">
M1 マックのXcode12でシミュレータでRunした時にbut linking in object file built for iOS, ... file for architecture arm64エラーの解決方法

##環境
- M1チップのMacBook air
- xcode12.3
- プロジェクトないで自作frameworkを利用している

## 症状
Xcode12でシミュレータでRunしようとすると、

```
in /Users/hoge/develop/fuga/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics(CLSInternalReport.o), building for iOS Simulator, but linking in object file built for iOS, file '/Users/tilda/develop/fuga/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics' for architecture arm64
```

のようなエラーがでて実行できない。
なお、実機では実行できる。

解決策としては
[Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64](https://stackoverflow.com/questions/63607158/xcode-12-building-for-ios-simulator-but-linking-in-object-file-built-for-ios)
や
[[iOS] Xcode12.0で「building for iOS Simulator, but linking in object file ... for architecture arm64」エラーの対処法](http://blog.be-style.jpn.com/article/187942746.html)
がヒットするが、それをしても自作frameworkでエラーが発生する。

## 解決策

1. 自作frameworkを`rosettaを利用`したXcodeでビルドする　←これ重要
2. `Build Settings`に以下を追記する　←これは上記で紹介した解決策の通り
![スクリーンショット 2021-02-26 19.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268579/cf5313d6-3e97-a541-666a-38f6be1869c9.png)

## 後書き
おそらくarm版のXcodeで自作frameworkをbuildすると今度はx86_64アーキテクチャに必要なものが足りなくなっていたみたい。

しばらくはXcodeはrosettaで使った方がよさげ・・・
Unreal Engineで音量調整


## やったこと

- Adjust Volumeを使ったら音量が下がった
    - AdustVolume Levelを0.1とかに設定
    - Durationは0のままだけど大丈夫みたい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142423/fd309e84-a6ac-eec5-6d6f-3888a267890f.png)

## 参考

[UE4 サウンドキュー（Audio Component）の音量を変更する（Adjust Volume） 凛(kagring)のUE4とUnityとQt勉強中ブログ](http://kagring.blog.fc2.com/blog-entry-332.html)
herokuへのデプロイ後エラー（We're sorry, but something went wrong.） の対応

#エラー概要



herkuへのデプロイ後　viewを押すと


![https___qiita-image-store.s3.amazonaws.com_0_270456_362496d9-176c-ba4f-50ff-9cb2802040b9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754290/cee4eb23-c9dd-0ebe-2c66-e0d4556513b6.png)

との表示

#デバッグ方法

まず、　

```
$ heroku logs --tail 
```
を実行し、
現在の状況を確かめる。

私の場合は

```
zsh: command not found: heroku
```
とのエラーが出たため、

```
$ brew tap heroku/brew && brew install heroku
```
にて、heroku CLIをインストール

インストール後は

```
$ heroku -v
```
にてバージョンを確認しました。

再度現状確認してみると

```
$ heroku logs --tail
 ›   Error: Missing required flag:
 ›     -a, --app APP  app to run command against
 ›   See more help with --help
```
とのエラーが表示

```
$ git remote -v
```
にてherokuに紐付けされているか確認

紐付けされていない場合は、

```
$  heroku git:remote -a アプリ名
```
を実行し紐付ける


最後に

```
$ heroku run rake db:migrate
```
を実行し、
heroku上のデータベースをリセットしたことにより
問題なく動きました。

#最後に
ご視聴いただきありがとうございます。
こちらの記事が皆様の役に立てば幸いです。
Failed to destroy the recordというエラーの原因



# 概要


今回は、Todoアプリ作成において、
taskのdelete機能を実装した際、

Failed to destroy the record

というエラーが出たので、原因を探りました。

rails console には下記の表示

```
Completed 500 Internal Server Error


ActiveRecord::RecordNotDestroyed - Failed to destroy the record:
```

# 原因

binding.pryにて

task.destroy!までは動いていることを確認した。

controllerとview側ではないと考え、
task.rbのコードをチェックすると、、、、


```
belongs_to :board, dependent: :destroy
```

ここが原因でした。

boardの下にtaskを位置付けているため、
board.rb側においては、dependent: :destroyの記述は必要ですが、
task側においては必要のない記述でした、、、

かなり初歩的なミスですが、
controller周りに異常がない場合は、
確認するようにします。


##　最後に

閲覧ありがとうございました。

何か間違いがあればご指摘いただけると幸いです。
【Git】サブモジュール をコミットした後の親プロジェクトの対応方法

個人メモです。
サブモジュールで更新した後に、親のプロジェクトでどう対応したらいいか迷うので、まとめとして。

サブモジュールのあるプロジェクトで、サブモジュールを更新すると、親のプロジェクトでステータスを見ると、

・`ディレクトリ名(new commits)`

が表示される。この後の処理方法などについて。

```
$git status

modified:   submodule名 (new commits)
```

または、

```
$git status

modified:   submodule名 (modified content)
```




##1. submoduleで変更をコミットする。
submoduleで変更を加えたら、`git add`, `git commit`する。


##2. submoduleのmasterにマージする
親のプロジェクトに反映する前に、submoduleの変更内容をmasterにマージする。

submoduleのディレクトリで、

`$ git push origin master`

または、個人のブランチにpushし、プルリクを出す。




##3. 親のプロジェクトディレクトリでコミットの確認
サブモジュールの変更内容を親のプロジェクトに反映させるため、ルートのプロジェクトディレクトリに移動する。

```:git-status
#submoduleが直下にあった場合
$ cd ..   

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)
        modified:   submodule名 (modified content)

no changes added to commit (use "git add" and/or "git commit -a")
```

commit or discard the untracked or modified content in submodulesとあり、サブモジュールで変更があったことを伝えてくれる。




<br>
##3. git diffで詳細を確認

```
$ git diff
diff --git a/sbmodule名 b/sbmodule名
--- a/sbmodule名
+++ b/sbmodule名
@@ -1 +1 @@
-Subproject commit 8f71500980389a8cdd5522545d352df5fa7b4faf
+Subproject commit 8f71500980389a8cdd5522545d352df5fa7b4faf-dirty
```

**Subprojectでコミットの変更があったことだけが表示**される。

サブモジュールのファイルの変更内容は見えない。中身を確認するためには、サブモジュールのディレクトリに移動する必要がある。



<br>
##4. サブモジュールの変更をコミット
サブモジュールの変更内容を確認し問題がなければ、

親プロジェクトで、サブモジュールの変更があったことをステージ＆コミットする。 

・`$ git commit -m "update submodule"`

コミット名は細かく記述してもいいが、サブモジュールで変更が頻繁にある場合は「update submodule」で簡略化してもいい。（コミット履歴はサブモジュールに行けば見れるため）

```
$ git add submodule名

$ git commit -m "update submodule"
[master 734fec6] update submodule
 1 file changed, 1 insertion(+), 1 deletion(-)


#クリーンになったか確認
$ git status
On branch master
nothing to commit, working tree clean
```
IEだとHTMLCollection.item()の挙動が異なる

# 問題のコード
```HTML:sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sample</title>
</head>
<body>
    <p id="one">1</p>
    <p id="two">2</p>
    <p id="three">3</p>

    <div id="hoge"></div>
</body>
<script>
    let pElements = document.getElementsByTagName("p");
    let value = pElements.item("two").innerText;

    document.getElementById("hoge").innerText = value;
</script>
</html>
```

pタグの内、「id=two」の要素のテキストを取得し、「id=hoge」の要素に追加するコード。

MDNを参照するとHTMLCollection.item()の引数には、indexを指定しなければならず、上記コードは期待通りの動作をしないはず。
[MDN Web Docs : HTMLCollection](https://developer.mozilla.org/ja/docs/Web/API/HTMLCollection)

## Chromeでの表示
>1
>2
>3
>1

Chromeでは想定通り「id=two」の要素が取得できていない。

## IEでの表示
>1
>2
>3
>2

IEでは「id=two」の要素が取得できている。

## まとめ
IEでは引数に文字列を渡した場合、HTMLCollection.namedItem()と同じ挙動をする模様。
IEと他ブラウザで同じ挙動をさせたい場合は、.namedItem()か.getElementBy○○()を使用するのが良さそう。

妙にハマったので備忘録として残しておく。
NameErrorの意外な原因

# 概要

Nameerror in api::sessionscontroller#create
(uninitialized constant Jwt::TokenProvider::JWT):
というエラーが発生し、なかなか解決できず。

# 試したこと
NameErrorの多くの原因が、
ファイル名に問題があるため、
controllerの名前は複数形になっているか、
modelの名前は単数系になっているか 
といったファイル名のチェックをし続けたが原因がわからず。。。

# 原因
jwt の　gem をインストール後
サーバーの再起動をしていなかったため、
jwt が反映されていなかった。

#　まとめ
必要なgem がしっかりインストールされているか、
また、念の為、サーバーの再起動をしてみる。

今後気をつけます。。。
文系の非エンジニアがiPadだけでpythonと機械学習の勉強をする②環境構築編 Google Colaboratoryの場合

# はじめに
前回はAzure Notebookを使ってpythonの学習環境を作ってみましたが、残念なことにAzure Notebookのサービスが終了してしまったので別の環境が必要になりました。
前回の記事の作成後、会社で受講したe-learningでGoogle Colaboratoryの存在を知ったので、こちらで改めて環境を構築したいと思います。

#準備するもの
- Googleアカウント

#勉強する人のスペック
- G検定合格（2020.3）
- コードは10年以上書いてない
- VB6.0,PL/SQL,COBOL
- 大学時代は作者の気持ちを考えていました
- e-learningでpythonを受講（2020.8）

# Google Colaboratryとは？
以下はGoogle Colaboratoryにアクセスして最初に表示される説明文です。

Colaboratory（略称: Colab）は、ブラウザから Python を記述、実行できるサービスです。次の特長を備えています。
環境構築が不要
GPU への無料アクセス
簡単に共有
Colab は、学生からデータ サイエンティスト、AI リサーチャーまで、皆さんの作業を効率化します。

#手順
##Googleアカウントにサインインする
Googleアカウントがあれば特に問題はありません。
普通にサインインしましょう

##Google Colaboratryにアクセスする
Google Colaboratryにアクセスするとこのような画面が表示されます。
↑で書いたので説明文は、［キャンセル］を選択した時に表示されるものですね。
ここでは[ノートブックを新規作成]を選択します。
![9B407CF2-4D80-4C09-A34F-3F9FA729835C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625163/5649b10c-f8f0-2ce0-09ee-21f2eac1cfc9.jpeg)


作成されたノートブックは[Untitled0.ipynb]という名前になります。

今回は学習用ということで、[pythonlearning.ipynb]に名称を変更します。
これでノートブック作成完了。pythonのコードを学習する環境が整いました。

##コードを書いてみる
ノートブックを開いた初期状態はこのような感じです。
![D2596845-B6E5-4050-AF4D-9C30E78B3EE8.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625163/b2da0eed-d77d-711e-87dc-3c2ac0f08938.jpeg)

[+コード]を選択すると、コード編集用の領域が追加されます。
例によってあれを書いてみましょう

    print("Hellow")

# コードを実行する
コードがかけたら実行します。
コード編集領域の左端の矢印をタップするか、shift+enterで実行できます。
iPadなのでタップでも操作できますね。忘れていました。

    print("Hellow")
    Hellow

# ここまでのまとめ
今回はAzure Notebookの代わりにGoogle Colaboratryを使って
- Notebookの作成
- コードの編集と実行
の方法を確認しました。

研修を受けてから少し時間が空いてしまったので、基礎的なコードを復習しながら学んでいきたいと思います。
今回は学習環境の再作成ということであまり複雑なことはしませんでしたが、無料で学習できる環境に不自由しないということには愕きました。
それだけ機械学習の分野には関心が集まり、人もお金も集中している、ということだと思います。
Xcodeを使ってipaをiPhoneにインストールする

## 対象
以下に当てはまる人

- adhoc用などで書き出したipaファイルを配布するまえに実機で確認したい
- ipaインストールのために余計なソフトを導入したくない
- 以前はiTunesでできたらしいが今はできなくなって困っている

## 手順
Xcodeを開き、メニューバーから`Window > Devices and Simulators`を開く
![スクリーンショット 2021-02-26 9.58.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268579/37257c8e-8dd5-abd5-30c7-b182614b25dd.png)

`INSTALLED APPS`の下にある`+`をクリックする
![スクリーンショット 2021-02-26 9.57.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268579/bd7194c8-79c8-5d8b-3f74-63a488d60a56.png)

インストールしたいipaファイルを選択肢して`open`をクリック
![スクリーンショット 2021-02-26 9.57.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268579/d85af37f-0c29-21e3-7956-d085da1d051c.png)

インストールが始まります。

## 後書き
普通に初歩的なことだと思うけど、調べてもこれに関する情報が見つからなかった。
appleの純正ソフトだと[Apple Configurator2](https://apps.apple.com/jp/app/apple-configurator-2/id1037126344?mt=12)というのを使えばできるらしい。

それ以外だと有料ソフトを使うとか、脱獄するとかスマートではない方法ばかりヒットした。

Twitterもやってるので、よければフォローお願いします。
→https://twitter.com/ObataGenta
*.js.erbファイルは読み込めているのに表示されないときの対処方法

- 「Completed 200 OK」となっているのに*.js.erbに書いたjavascriptのコードが動かないとき。
- javascriptのエラーも発生していないとき。

## 原因
https://github.com/rails/rails/issues/33115
どうやらrails-ujsが求めているContent-Typeが一致しないことが原因っぽいです。

## 対策
### 【対策1】レイアウトファイル名を変更する

`views/layouts/*.erb`
↓
`views/layouts/*.html.erb`

###【対策2】render時に`layout: false`を指定する
```ruby:*_controller.rb
  def create
    @sending_user = User.find(current_user.id)
    @receiving_user = User.find(params[:user_id])
    new_like_balance = @sending_user.like_balance - 1
    @sending_user.update(like_balance: new_like_balance)
    @like = Like.create(sender_id: @sending_user.id, receiver_id: @receiving_user.id)
    # ここ
    render formats: :js, layout: false
  end
```

どちらの方法でも解決できました。
Qiita Daily Survey memo 2021.02.26

# Qiita Daily Survey memo 2021.02.26
Qiita の記事を可能な限り毎日読むために、読んだmemoを公開することでモチベーションを維持しようという試み。

## [AWS認定クラウドプラクティショナー(CLF)を受験してみた](https://qiita.com/HiroyaEnd/items/7f0cbcf68d83d2cb1603)
Hiroya Endo(HiroyaEnd) さんの記事。
タイトルの通り AWS認定試験のうちクラウドプラクティショナーを受験された、という記事になります。
AWS認定試験系の記事を見て、3月からAWS系のお仕事なのでドキッとしてしまいました。
内容は勉強に使用された教材と、その内容・使い方と感想を教えてくださっています。
時代が変わってきて、勉強もいろんなアプローチ（動画など）があるなーと感じました。
また、いくつかの媒体で勉強され、それぞれの感想を教えてくださっているので参考になりました。

AWS認定試験関係では、過去に下記の記事を見て本を何冊か購入しました。
[AWS認定11冠制覇したのでオススメの勉強法などをまとめてみる](https://qiita.com/nakazax/items/20458e146d3d9f2aa615)

私みたいな三日坊主先延ばしプロフェッショナルは、まず受験の申し込みから始めるのがよいかもですね…。


## [業界未経験者が初めての共同開発を終えて](https://qiita.com/jojojo0501/items/17357d46e3ed1281001c)
かねこ(jojojo0501)さんの記事。
業界未経験の方が共同開発を実施され、その振り返りを紹介してくださっている記事になります。
成果物もアップしてくださっていて、ページ内をあちこち見てしまいました。
近代的なデザインで、「おー…すごい…！本当に未経験…？」という感想でした。
作業フローと各フェーズごとに実施内容と所感を記載してくださっています。
Trelloでガントチャートを作れるんだー…など、新しい発見もありとても参考になりました。
Composerを1系から2系にアップデートする

# はじめに
作業PCにインストールしているComposerを1系から2系にアップデートしたので、その備忘録です

# 現在のバージョン
```
$ composer -V
Composer version 1.10.10 2020-08-03 11:35:19
```

# アップデートする
`composer self-update` だと、1系の最新バージョンになるので、後述するコマンドでアップデートする

```
$ composer self-update
A new stable major version of Composer is available (2.0.11), run "composer self-update --2" to update to it. See also https://github.com/composer/composer/releases for changelogs.
Updating to version 1.10.20 (1 channel).
   Downloading (100%)         
Use composer self-update --rollback to return to version 1.10.10
```

```
$ composer -V
Composer version 1.10.20 2021-01-27 15:41:06
```

`composer self-update --2` で2系にアップデートする

```
$ composer self-update --2
Updating to version 2.0.11 (2.x channel).
   Downloading (100%)         
Use composer self-update --rollback to return to version 1.10.20
```

```
$ composer -V
Composer version 2.0.11 2021-02-24 14:57:23
```

# 2系から1系に戻す
```
$ composer self-update --rollback
Rolling back to version 2021-01-27_15-41-06-1.10.20.
```

```
$ composer -V
Composer version 1.10.20 2021-01-27 15:41:06
```


# まとめ
Composer2系になったことで変わったことは[こちら](https://qiita.com/ucan-lab/items/289009ffe5bb417c808e)でまとまっているので参考にしてみてください
自然に会話できるAIの福祉分野への活用について

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

今回はAIの福祉分野への応用について自然言語処理を用いたコミュニケーションAIに限定して書きたいと思います。
知識が足りていない部分や、考えが甘い部分があると思いますので、コメントどしどしお願いします。

###人間の話し相手となるAIについて
人はどんな時に幸せを感じるでしょうか。この問いの答えは人によって様々でしょうが、その最たるものとして**誰かと会話すること**があるのではないでしょうか？
人は人とコミュニケーションをとることによって幸福感を得ます。
今よりも自然言語処理、感情分析、音声合成、音声処理、3DCGなどの技術が発展し、よりAIが人間らしくなれば、我々はAIと日常的に会話する世の中がきます。AIが唯一無二の親友、あるいは家族として悩みを相談したり特別な感情を向ける相手になるでしょう。
とすれば、我々はAIとコミュニケーションをとることで幸福感を得られるのではないでしょうか？

しかしこういうことを言うと、**AIには感情がないから本当の意味でコミュニケーションをとることはできない**や**挙動や言動の不自然さが気持ち悪い**という意見を言う人がいます。

けれど僕はAIに本物の感情なんて必要ないと思っています（そもそも我々の持っている感情とはなんでしょうか）。AIに感情が芽生えてしまったら産業利用なんて不可能でしょう。我々がやりたくないと思う作業をAIにさせるわけですから。
**会話AIに感情は必要ありません。感情があるように見せられれば十分です**
我々はそもそも他人の感情自体を見たことはありません。相手の言動をもとに自分の頭の中で相手の感情を予測し人格を構築します。
物語の登場人物は実在する人間より魅力的に感じ、二次元のキャラクターを嫁として愛し、言葉が通じない犬猫に毎日語りかけます。神を創り出すことだってできます。
感情とは受け取る側が自身の脳内で創り出すものです。感情が本物かどうかなど関係ないのです。

挙動や言動の不自然さについても個性だと割り切ってしまえば問題ありません。彼、彼女らは少しだけ変わっていて面白い友人なのです。

###介護現場への活用
近年福祉分野へのAIの活用の話をちょこちょこ聞くようになってきました。ただAIと一口に言っても様々な技術があり、その応用方法も様々です。
その中で今回取り上げたいのは、要介護者の話し相手となるAIについてです。

介護の現場は慢性的な人手不足であり大変な業務をこなしながら一人一人に向き合いコミュニケーションをとる時間をしっかり確保するのは難しいのではないかと思われます。そこで要介護者一人一人に話し相手となるAIがいるといいのではないでしょうか？要介護者とコミュニケーションをとる業務をAIが補助できるのではないかということです。
ただ、作業的な業務の方にもAIやロボティクスなどのテクノロジーが活用されればスタッフがより人と向き合う業務に集中できることにもなると思いますので、どちらの業務にもAIが活用されることが必要だと考えます。これによりスタッフの方たちの働き方も広がり、やりたい業務により集中できるのではないかと思います。

要介護者にとっても、**気の向いた時にいつでも話せる相手**がいるというのはとても幸せなことなのではないでしょうか？

さらにデバイスさえあれば、会話だけでなく囲碁や将棋などのゲームを一緒に行うことができますし、体調管理や精神状態を確認することもできます。

**このようなAIは要介護者にとってはよき友であり主治医に、現場のスタッフにとっては頼れる仲間になるのではないでしょうか？**


社会を知らない一学生が書いた文です。厳しい意見も大歓迎ですので、コメントよろしくお願いいたします。