OmniAICreator/Qiita-1.07M huggingface dataset:
Let's Encryptで発行したSSL証明書をACMで使用してhttps化してみた

# 目標
Let's Encryptで発行したSSL証明書をACMで使用してサイトをhttps化させます。
SSLなう!を使用する事でブラウザ上でSSL証明書が簡単に取得出来ます。

# 環境
![lp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2088692/a8ee51cd-b0c5-f7d8-a1a8-e3ce249821ef.png)

EC2にACM証明書を設定する事は出来ません。
そのため今回はELBにACM証明書を設定します。
>Elastic Load Balancing (ELB) や Amazon CloudFront ディストリビューションなど、ACM と統合するサービスの背後に Amazon EC2 インスタンスを配置することで、通信に SSL/TLS 暗号化を使用できます。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/configure-acm-certificates-ec2/

# 1.ドメイン取得
今回は、[freenom](https://www.freenom.com/ja/index.html)でドメインを取得しました。

# 2.SSLなう!でSSL証明書発行
[SSLなう!](https://sslnow.ml/)でSSL証明書を発行する。
SSLなう!の手順詳細は「[Let's Encrypt の証明書をブラウザ上で簡単取得](https://qiita.com/tappie/items/76881fdf7996c57a105a)」を参照してください。
<details><summary>上記手順「[3.ドメイン名](https://qiita.com/tappie/items/76881fdf7996c57a105a#3-%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E5%90%8D%E3%81%AE%E6%89%80%E6%9C%89%E7%A2%BA%E8%AA%8D)」の補足説明</summary><div>
1.SSLなう!で「dns-01」を選択
2.freenomのドメイン編集画面を開く
ドメイン編集画面が分からない方は「[【Freenom】取得したドメインのDNS設定～Aレコードの登録手順～](https://pig-log.com/freenom-add-record/)」を参照してください。
3.Typeを「TXT」に変更
4.下記表を参照し、SSLなう!の値をfreenomに貼り付ける

|SSLなう!|freenom|
|:--|:--|
|FQDN|Name|
|TXTレコード(1行です)|Target|

5.下記画像の様に入力できたら「Save Changes」を押下
![image-20211002-054650.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2088692/b7837d8c-a132-9dd3-fdbf-7457095c8bc7.png)
6.freenom設定後反映5～10分待機し、SSLなう!の「確認」ボタンを押下
>レコードの設定を行ってから実際に権威 DNS サーバに反映されるまでにタイムラグがある場合があります。
</div></details>

# 3.ACMにSSL証明書をインポート
1.ACM画面の証明書のプロビジョニング下の「今すぐ始める」を押下
2.「証明書のインポート」を押下
3.下記表を参照し、SSLなう!の証明書、秘密鍵をACMに貼り付け「次へ」を押下

|SSLなう!|ACM|
|:--|:--|
|cert.pem (サーバ証明書)|証明書本文*|
|サーバで使用する SSL 秘密鍵|証明書のプライベートキー*|
|chain.pem (中間証明書)|証明書チェーン|

4.「タグ名」「値」を入力する。今回はNameとSSLで登録を行いました。
5.下記画面が表示されれば証明書、秘密鍵の整合性が取れているのでドメイン、有効期限等を確認し「インポート」を押下して下さい。
![2edit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2088692/b6f35427-6fac-125f-92fa-72aa4628b26a.png)
6.証明書を発行する事が出来ました。状況も発行済みとなっています。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2088692/d3bdf357-43b5-4e6c-f56b-63e6f26740e7.png)

# 4.ACM SSL/TLS証明書をLBに関連付ける
下記手順を参照し、ACM SSL/TLS証明書をLBに関連付けます。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/associate-acm-certificate-alb-nlb/

# 5.サイト確認
1.ELBのDNS名でサイトを開く
2.保護されていない通信 → 証明書 の順で押下
発行者がR3になっている(R3はLet's Encrypt)事を確認
3.有効期間が先程ACMの画面で確認した日付と一致しているので成功です。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2088692/61b1c727-6ab8-f96a-4cc8-03f2c1229054.png)
RuboCopの導入

学習のアウトプットとして投稿しています。
何かご指摘がございましたらお願いいたします。

# RuboCopとは
Rubyのコードを解析してくれる。コードに問題があるかどうかや、RuboCopで指定されているフォーマットに沿っているかなどを確認し、問題があった場合は指摘してくれる。直せる部分は自動修正してくれる機能がある。

## 実行環境
- macOS
- Ruby 2.6.7
- Rails 6.1.4.1
- RuboCop 1.22.0

## 設定
gemfileに以下を追加する。rubocopはターミナルから使用するので、`require: false`を加える。これによりRailsアプリには自動的に読み込まれなくなる。

```ruby:Gemfile
group :development do
  gem 'rubocop', require: false
  gem 'rubocop-rails', require: false
  gem 'rubocop-performance', require: false
end
```
### 拡張gem
■ rubocop-rails
rubocop単体だと規約が厳しく問題箇所が多くなりすぎるため、Rails用に調整してくれる。 　　

■ rubocop-performance
処理が遅くなるコードを指摘してくれる。
　　

拡張gemはRuboCopの設定ファイル(`.rubocop.yml`)を作成して、読み込む必要がある。
設定ファイルはRailsアプリと同じルートディレクトリに配置する。

```yaml:.rubocop.yml
require:
  - rubocop-performance
  - rubocop-rails
```

以上で設定は完了です。
あとは実際にコマンドラインで使っていきます。

```zsh
% bundle exec rubocop
略
test/test_helper.rb:7:7: C: [Correctable] Style/ClassAndModuleChildren: Use nested module/class definitions instead of compact style.
class ActiveSupport::TestCase
      ^^^^^^^^^^^^^^^^^^^^^^^

64 files inspected, 282 offenses detected, 245 offenses auto-correctable
```

64ファイルチェックして282箇所コードに問題があることを指摘してくれています。その中の245箇所は自動修正可能です。自動修正はrubocopに続けて`-a`オプションをつけて実行するとやってくれます。

# --auto-gen-configオプションを用いたRuboCopの導入
指摘箇所が多すぎる場合は一つひとつ確認してコードを直していくと大変なので、`--auto-gen-config`オプションを利用すると効率よくリファクタリングできる。
### ① rubocoop --auto-gen-configを実行する。

```zsh
% bundle exec rubocop --auto-gen-config
略
Rails/WhereNot: # new in 2.8
  Enabled: true
For more information: https://docs.rubocop.org/rubocop/versioning.html
Created .rubocop_todo.yml.
```

コマンド実行後は`.robocop_todo.yml`ファイルが作成され合わせて、`.rubocop.yml`に`inherit_from: .rubocop_todo.yml`が追記され、rubocop実行時に`.rubocop_todo.yml`ファイルも読み込まれるようになる。

```yml:.rubocop_todo.yml
#略

# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: nested, compact
Style/ClassAndModuleChildren:
  Exclude:
    - 'test/sign_in_helper.rb'
    - 'test/test_helper.rb'

# Offense count: 21
# Configuration parameters: AllowedConstants.
Style/Documentation:
  Enabled: false

#略
```

`.rubocop_todo.yml`にはエラーが起こっているファイルを除外したり、cop(検査する個々のルール)を無効にする設定が書かれている。そのため、いったんエラーを退避してくれるようになる。デフォルトではエラーが起こっているファイルが15より大きいとそのcopを無効にする設定となっている。`--exclude-limit`オプションでファイル数を変更できる。

### ② .rubocop_todo.ymlファイルを編集していく
チームのコードスタイルにあっている設定の場合は、`.rubocop_todo.yml`の設定を`.rubocop.yml`に移動させる。修正すべき部分はコードを編集し、`.rubocop_todo.yml`ファイルの設定項目を削除していく。
該当コードを修正後`rubocop --regenerate-todo`を実行して、`rubocop_todo.yml`ファイルを更新していく方法でも可能。

### ③ .rubocop_todo.ymlファイルの全ての設定項目を削除する
②を繰り返し、.rubocop_todo.ymlファイルの全ての設定項目が削除されたらRuboCopの導入が完了になります。

## 参考
[【Rails】RuboCopの基本的な使用方法と出力の見方](https://qiita.com/terufumi1122/items/ad55bf8713c0df053f58)
[Automatically Generated Configuration](https://docs.rubocop.org/rubocop/1.22/configuration.html#automatically-generated-configuration)
[パーフェクト Ruby on Rails 【増補改訂版】](https://www.amazon.co.jp/%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88-Ruby-Rails-%E3%80%90%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88%E3%80%91-Perfect/dp/4297114623)
【備忘録】IPTablesを使用したport開放

# IPTablesを使用してport開放を行う
ufwでのport開放ができなかったので、備忘録として書いておきます。
# 動作環境
・Ubuntu18.04LTS

#実際にやったコマンド
今回は8080を開ける場合とします。

```bash
#8080の開放
$ iptables -I INPUT -p tcp -m tcp --dport 8080 -j ACCEPT

#設定の保存
$ sudo iptables-save -c

#reboot
$ reboot
```
これで適当にnmapかなんかで、

```bash
$ sudo nmap -sS -sU -Pn -p 1-65535 <IP Address>
```
と実行し、自分が開けたいportが開いているかを確認できます。
[Poetry] [Windows10] "ValueError File .. pypoetry\ *.whl does not exist" を解決する

# Windows10環境でのPoetryの不具合
Windows10で，最新版のPoetry (筆者の環境では`1.1.10`)にて`poetry install`を行おうとすると，`ValueError File \C:\Users\user\AppData\Local\pypoetry\ *.whl does not exist ` と表示されてしまい詰まってしまったので，解決法をメモする．
# 解決法
`C:\Users\your_username\AppData\Local\pypoetry\Cache`を削除してキャッシュの削除を行い，もう一度`poetry install`を実行すればよい．
また今のところ，`poetry install`を行う際に毎度この手順を踏む必要がある．(他の解決法を知っている方，良ければコメントで教えて頂きたいです．)

# Reference
https://github.com/python-poetry/poetry/issues/4163

#追記

https://qiita.com/radiol/items/a27530fd33b7e4758e6d
こちらに同じの問題の，より根本的な解決法が示されていました．WindwosとLinuxのパスの指定方法の違いに起因する様です．
【Salesforce】特定の文字列を更新したときだけ処理する自動化の作り方

テキストの中に特定の文字が含まれていたとき（いないとき）にのみ特定の処理を行う自動化を作ってみました。

##今回の想定
* バッチなどを使用した外部連携で特定の項目が更新されたときにPardotのオプトアウトを自動化する

##特定の文字列を含む場合の自動化
こちらはプロセスビルダーの演算子で「次の文字列を含む」を選択することで簡単に実現できます。

###条件
* 指定した項目の値が変更されたとき
* 「メールを送信しない」が指定する項目の文字列に含まれる場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/ee857ffb-6f6a-0cde-9fa8-224fe4f05802.png)

###アクション
* 「メール送信除外」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/99fef9eb-3348-ef2b-ecb6-f84a5d807ab9.png)
文字列の中に特定の文字が含まれる場合はチェックが入るようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/4110b717-3860-0d2e-6b24-c96dc3c56937.png)

##特定の文字列を含まない場合の自動化
問題はこちらです。プロセスビルダーでは「次の文字列を含む」はあっても「次の文字列を含まない」はないので、自分で判定式を作らなければいけません。

###条件
* 指定した項目の値が変更されたとき
* 「メールを送信する」が指定する項目の文字列に含まれない場合（数式）

チェックボックス型の数式を作成し、下記のように含まない条件を記述する。
※ 今回はnullを考慮してないです

```
NOT(CONTAINS(判定する項目, "判定する文字列"))
```

文字列に「メールを送信する」が含まれない場合にチェックが入るようになったので、これを使って条件を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/ba352b2d-cbe3-8ba8-975d-b8984c6b85d6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/21ebe381-c96c-8c44-4297-b749754367f4.png)

作成した数式を選択し、「次の文字列と一致する」で「True」にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/e67c4d76-e4eb-6be6-4645-9aeef0ff3452.png)

###アクション
* 「メール送信除外」にチェックを入れる

文字列に「メールを送信する」が含まれない場合「メール送信除外」にチェックが入るようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/607b0d81-3acc-61f3-b0b0-01573c67a67a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/063d8879-64e0-4831-d9e1-5162f56dafa4.png)
next.jsでcssModuleのcamelCaseオプションを使う方法

## 経緯
next.js にて [react-transition-group](https://reactcommunity.org/react-transition-group/css-transition) を使用したアプリを作成を行っていたところ、　cssModule　の　camelCase　オプションを使いたくなった。

### cssMocule camelCase オプションについて
cssのケバブケースをキャメルケースに変更してくれるオプション
下記のようなクラスの指定が可能となる

```Foo.module.css
.item-container {
  background: red;
}
```

```Foo.js
import styles from './Foo.module.css'

export const Foo = () => {
  return (
    <div className={styles.itemContainer}>
      <h1>hello world</h1>
    </div>
  )
}
```

## 結論
next.config.js を下記のようにすればOK 

```next.config.js
const path = require('path')

module.exports = {
  reactStrictMode: true,
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    const rules = config.module.rules
      .find((rule) => typeof rule.oneOf === "object")
      .oneOf.filter((rule) => Array.isArray(rule.use));

    rules.forEach((rule) => {
      rule.use.forEach((moduleLoader) => {
        if (
          moduleLoader.loader.includes("css-loader", "dist") &&
          typeof moduleLoader.options.modules === "object"
        ) {
          moduleLoader.options = {
            ...moduleLoader.options,
            modules: {
              ...moduleLoader.options.modules,
              exportLocalsConvention: "camelCase",
            },
          };
        }
      });
    });

    return config;
  }
};
```

### 参考
<https://github.com/vercel/next.js/discussions/11267#discussioncomment-101154>
[Vue3] dataオブジェクトに後からプロパティを追加する時の注意点

すごい簡単だけど困ったのでメモしておきます。

# dataオブジェクトの初期値を外部APIから入れようとした

Vue.jsを用いたプロフィール入力画面で、Firestoreから既存のプロフィール情報を引っ張ってくるようにしています。
1つずつプロフィール情報をdataオブジェクトに割り当てていくのは面倒なので、ドキュメントオブジェクトを全部dataオブジェクトに全部つっこもうとして初期値が反映されず困っていました。
コードは以下の通り。

```js
//-- abbr --
  data () {
    return {
    }
  },
  mounted() {
    this.$data = { ...this.getProfile(getAuth().currentUser.uid)};
  },
  methods: {
    const getProfile = async (uid) => {
      const docRef = doc(getFirestore(), "users", uid);
      const docSnap = await getDoc(docRef);
      if(docSnap.exists()){
        return docSnap.data();
      }
    };
  },
//-- abbr --
```

こんなの。


# ルートのdataオブジェクトにリアクティブなプロパティの追加はできないらしい
参考：[Vue3 公式ドキュメント](https://v3.ja.vuejs.org/api/options-data.html#data-2)

>一度監視されると、ルートのデータオブジェクトにリアクティブなプロパティを追加することはできなくなります。そのため、インスタンスを作成する前に、すべてのルートレベルのリアクティブプロパティを前もって宣言しておくことをお勧めします。

この表現だけだとわからず、読み飛ばしていました。

# 解決：前もってプロパティを宣言しておく

```js
//-- abbr --
  data(){
    return {
      user: "",
    }
  },
  mounted() {
    this.user = { ...this.getProfile(getAuth().currentUser.uid)};
  },
  methods: {
    const getProfile = async (uid) => {
      const docRef = doc(getFirestore(), "users", uid);
      const docSnap = await getDoc(docRef);
      if(docSnap.exists()){
        return docSnap.data();
      }
    };
  },
//-- abbr --
```

dataオブジェクトの返り値のとこに、前もってuserプロパティを宣言しておき、そこにFirestoreから取得したドキュメントオブジェクトを突っ込むとよいらしい。

もしくは、こういう表記もありかもしれない。（試してない）

```js
//-- abbr --
  data(){
    this.user = { ...this.getProfile(getAuth().currentUser.uid)}; 
    return {
    }
  },
//-- abbr --
```


# ルートレベルのリアクティブプロパティはこれで正解？

>ルートレベルのリアクティブプロパティ

がこれで正解かは自信ないけど、こうすると確かに想定した通りの挙動になったので合ってそう。
Firestoreからドキュメントオブジェクトを入れたい時だけでなく、jsonから出力したい時とか使えそうです。
Dart/FlutterでGroup By

## groupListsBy

ListをあるKeyでGroup化するには`groupListsBy`が使えます。

### 環境

```
Dart SDK version: 2.14.2 (stable) (Wed Sep 15 12:32:06 2021 +0200) on "windows_x64"
```

### 実装

```dart
import "package:collection/collection.dart";

void main(List<String> args) {
  var list = [
    {'groupId': 1, 'label': 'レタス'},
    {'groupId': 2, 'label': 'カルビ'},
    {'groupId': 1, 'label': 'しいたけ'},
    {'groupId': 3, 'label': 'レモン'},
    {'groupId': 2, 'label': 'ロース'},
  ];

  print('original list:');
  list.asMap().forEach((key, value) => print("$key: $value"));

  print('\x0Agrouped list:');
  var listByGroupId = list.groupListsBy((obj) => obj['groupId']);
  listByGroupId.forEach((key, value) => print("$key: $value"));
}
```

### 実行結果

```
original list:
0: {groupId: 1, label: レタス}
1: {groupId: 2, label: カルビ}
2: {groupId: 1, label: しいたけ}
3: {groupId: 3, label: レモン}
4: {groupId: 2, label: ロース}

grouped list:
1: [{groupId: 1, label: レタス}, {groupId: 1, label: しいたけ}]
2: [{groupId: 2, label: カルビ}, {groupId: 2, label: ロース}]  
3: [{groupId: 3, label: レモン}]
```

## 補足

当初groupByを使おうとして以下を試したのですが構文エラーになりました。

```dart
groupBy(list, (obj) => obj['groupId']);
```

### エラー

```
The method '[]' can't be unconditionally invoked because the receiver can be 'null'.
Try making the call conditional (using '?.') or adding a null check to the target ('!').dartunchecked_use_of_nullable_value
```

以上
【初心者】Laravelのミドルウェアって

##はじめに
「Laravelのミドルウェアって何者?」というレベルの初学者が
ざっくり調べてざっくりまとめました。(Laravel6系です。)

##ミドルウェアって
Laravelにおけるミドルウェアは、コントローラークラスの処理前後に位置し、主にHTTPリクエストのフィルタリングやHTTPレスポンスの変更を担う。認証やCSRF保護などのミドルウェアが用意されていて`app/Http/Middleware`ディレクトリに設置されている。


![middleware.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/5132df31-b820-a7f3-be66-d9bb8e9dfab4.png)


そして、ミドルウェアは自作できる..!!
##作成手順 (Laravel6)
1.artisanコマンドでミドルウェアクラスを作成
2.ミドルウェアクラスの編集
3.ミドルウェアクラスの登録


### 1.artisanコマンドでミドルウェアクラスを作成

```.php
php artisan make:middleware HogeMiddleware
```
このコマンドを実行するとapp/Http/Middleware/HogeMiddleware.phpが生成される。

### 2.ミドルウェアクラスの編集
生成されたHogeMiddleware.phpは下記のようになっているので、
handle()の中に処理を書いていく。


```app/Http/Middleware/HogeMiddleware.php
<?php
namespace App\Http\Middleware;

use Closure;

class HogeMiddleware {

  public function handle($request, Closure $next)
  {
    //処理を記述

    return $next($request);
  }
}

```

### 3.ミドルウェアクラスの登録

作成したミドルウェアクラスを使うには、Kernel.phpに記述する必要がある。
一部省略しているがKernel.phpはデフォルトでは下記のようになっている。先ほど作成したHogeMiddlewareクラスを$middle内に追加した。

```app/Http/Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\HogeMiddleware::class,   //こんな感じに追加
        ...
    ];

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            ...
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ...
    ];

    protected $middlewarePriority = [
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\Authenticate::class,
        ...
    ];
}

```

####$middleware
全ての処理に対して必ず実行される。

####$middlewareGroups
配列として、グループ名とその配列の中にグループ化したいミドルウェアを登録していく。
デフォルトでwebとapiが設定されている。webミドルウェアグループは`route/web.php`内の処理に対して実行される。（RouteServiceProviderで設定できるらしい）

####$routeMiddleware
あらかじめキーを割り当てておくことで、RouteやControllerで簡単に使うことができる。

```.php
Route::get('admin/profile', function () {
  //処理
})->middleware('auth');
```
####$middlewarePriority
ミドルウェアの優先度を指定できる。

参考:
https://laravel.com/docs/6.x/middleware
https://qiita.com/kurikazu/items/0c57f050f5dfef02b23e

####これで、リクエスト時やレスポンス時にフィルタリングの機能を使うことができる..!!
【AWS】アカウント作成手順（2021年10月更新）

#はじめに
AWSのさまざまなサービスに触れています。是非[コチラ](https://qiita.com/onishi_820/items/92bc81c450f1c2021b09)から他の記事もご覧ください。
随時更新中ですのでお探しの内容に関する記事がない場合はコメントいただければ優先して記事にしようと思っています。

また、投稿日が古い記事に関しては、現在のマネコンのUIと異なる場合がございます。
内容が異なる場合はコメントいただけると幸いです。

本記事は、アカウント作成手順についてまとめた記事になります。

アカウント作成後に行う、セキュリティ対策の設定に関する記事も作成しました。
[コチラ](https://qiita.com/onishi_820/items/c732ac4b9afb6379f173)からぜひご覧ください。

# アカウント作成
[公式サイト](https://aws.amazon.com/jp/)にアクセスします。

画面右上から`コンソールにサインイン`をクリック
![スクリーンショット 2021-10-01 19.26.52.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/b8789c9c-3fe4-9011-fb6c-f959941ed2f4.jpeg)

`新しいAWSアカウントの作成`をクリック
![スクリーンショット 2021-10-01 19.29.34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/556a3c01-9858-ebd0-6695-2809dbc9c113.jpeg)

AWSアカウントを作成する際に、メールアドレスが必要になります。
AWS用のアカウントを持っていれば、通知を見逃すことがないのでオススメです。

私は、Googleアカウントを作成しGmailのアドレスで登録しました。
GoogleアカウントとGmailの登録は[コチラ](https://support.google.com/mail/answer/56256?hl=ja)から

4つの項目を入力して続行をクリックします。
AWSアカウント名はお好きなアカウント名で大丈夫です。

サポートに問い合わせしたりする可能性もあるので、
恥ずかしくないアカウント名にした方がいいとは思いますが。。
![スクリーンショット 2021-10-01 19.34.18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/7aa1bcf4-fa26-c3d7-915b-6b888b086bd3.jpeg)

画面に入り切っていませんが、次の画面でも各項目に個人の情報を入力してください。
住所は英語で入れるので[コチラ](https://kimini.jp/)で英語表記の住所に変換してコピペしてください。
![スクリーンショット 2021-10-01 19.38.01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/453ec252-e81e-f3e3-7f29-90682d231717.jpeg)

次の画面では、クレジットカードの情報を記載していきます。
悪用されるわけではないですし、セキュリティも安全なので気にせず入力しましょう。
![スクリーンショット 2021-10-01 19.41.29.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/9f4e3e9c-7ee9-c7fd-f137-a13512ea462d.jpeg)

本人確認を行います。

国コードを日本にして、電話番号を入力後、セキュリティチェックの内容を入力します。
コードが分かりにくかったら、コードの右にある🔄をクリックしましょう。
![スクリーンショット 2021-10-01 19.43.12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/e6f55994-b8f5-c64a-3f8f-4466650a9a22.jpeg)

続行をクリックすると、次の画面が表示されます。
コチラでは、先ほどの電話番号に送信される４桁のコードを入力します。
![スクリーンショット 2021-10-01 19.43.32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/4a92c365-3b71-2ab8-f860-d868bb562c82.jpeg)

続いてサポートプランですが、ベーシックで大丈夫です。

推奨されるシステムの構成などについて教えてもらいたい場合は、
上のサポートなどにしないと教えてくれないと思いますが、
始めたばかりの頃はベーシックでいいと思います。
![スクリーンショット 2021-10-01 19.45.50.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/6bc58cd6-8014-8c80-4318-972dda8bd13f.jpeg)

マネジメントコンソールへ進みましょう。

最初の画面に戻り、ルートユーザにチェックを入れてログインします。
メールアドレスは先ほど登録したアドレスです。
![スクリーンショット 2021-10-01 19.48.24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/066adaff-902c-2be4-ddef-c5fd71c48489.jpeg)

その後、セキュリティチェックとパスワードを聞かれるので、
入力してログインします。

以下の画面がコンソール画面になります。
アカウント作成はこれでOKです。
![スクリーンショット 2021-10-01 19.49.59.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/322e1981-0b76-fb50-c220-24b61bcf950c.jpeg)

#さいごに
最後までご覧いただきありがとうございました！

他にも様々なサービスに触れています。是非[コチラ](https://qiita.com/onishi_820/items/92bc81c450f1c2021b09)から他の記事もご覧ください。
テスト47


```vb
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hwndParent As Long, ByVal hwndChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal MSG As Long, ByVal wParam As Long, ByVal lParam As Any) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const BM_CLICK As Long = &HF5
Private Const WM_ACTIVATE As Long = &H6
Private Const WM_SETTEXT As Long = &HC

Sub PDF_Print()
'(^ω^)
'Windows Script Host Object Modelを参照設定
Dim wsh As IWshRuntimeLibrary.WshShell
Dim strShell As String
Dim printName As String
Dim pw As String
Dim objWSH As Object
Dim hwnd As Long
Dim edt_hwnd As Long
Dim btn_hwnd As Long
'(･ω:;.:…ｻﾗｻﾗ
pw = "111111"
Set wsh = New IWshRuntimeLibrary.WshShell

'Const filePath = "C:\Users\User\Desktop\VBA練習\PDF\test.pdf"
Const filePath = "C:\Users\User\Desktop\VBA練習\PDF\test4.pdf"
'------------------------------------------------
printName = "Microsoft Print to PDF"
'以下のようにポート番号を入れて実行しようとすると正しく動作しない
'   printName = "Microsoft Print to PDF on Ne01:"
'------------------------------------------------

strShell = "AcroRd32.exe /t " & filePath & " " & printName
wsh.Run (strShell)

If pw <> "" Then

    Do Until hwnd <> 0
    
        hwnd = FindWindow("#32770", "パスワード")
        
        Sleep (50)
        DoEvents
    
    Loop

    hwnd = FindWindowEx(hwnd, 0&, "GroupBox", vbNullString)

    If hwnd <> 0 Then
    
        edt_hwnd = FindWindowEx(hwnd, 0&, "RICHEDIT50W", vbNullString)

        btn_hwnd = FindWindowEx(hwnd, 0&, "Button", "OK")
        
        If (edt_hwnd <> 0) And (btn_hwnd <> 0) Then

            Call SendMessage(edt_hwnd, WM_SETTEXT, 0&, pw)
            Call SendMessage(btn_hwnd, WM_ACTIVATE, 1, 0&)
            Call SendMessage(btn_hwnd, BM_CLICK, 0, 0&)
        
        End If

    End If

Set wsh = Nothing

End Sub

'Acessメモ
'画面左側
'「すべてのACCESSオブジェクト」で右クリック
'↓
'ナビゲーションオプション
'↓
'表示オプションの
'・隠しオブジェクトの表示
'・システムオブジェクトの表示
'のチェックをはずす

'ObjAccess.Run "プロジェクト名.プロシージャ_A"
OSPF　タイプ

OSPFのLSAのタイプについてアウトプットしようと思います。
今回はタイプ1からタイプ５までをアウトプットします。

● タイプ1: ルータLSA
直接接続しているリンクの状態を表すLSAで一般的なLSAはこれに当たります。
これはOSPFルータが生成し、発生したそのエリア内でフラッディングされます。

● タイプ2: ネットワークLSA
マルチアクセスネットワークのDRが生成し、DRのIPアドレスやそのネットワークに
接続しているルータのリスト、サブネットマスクの情報が含まれます。
これは発生したエリア内でフラッディングされます。

● タイプ3: ネットワーク集約LSA
エリア内のネットワークアドレスを他のエリアに通知するためのLSAです。
ABRによって生成され、OSPFドメイン全体にフラッディングされます。

● タイプ4: ASBR集約LSA
これはASBRの情報を他のエリアに通知するためのLSAである。
これはOSPF全体にフラッディングされます。

● タイプ5: AS外部LSA
これは外部ドメインのネットワークアドレスの情報をドメイン全体に
アドバタイズします。しかし、これを生成するのはASBRです。
TerraformでBigQuery Data Transfer Service for Amazon S3を設定する


```terraform
data "google_project" "project" {
}

resource "google_project_iam_member" "permissions" {
  role   = "roles/iam.serviceAccountShortTermTokenMinter"
  member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-bigquerydatatransfer.iam.gserviceaccount.com"
}

resource "google_bigquery_data_transfer_config" "s3-transfer" {
  depends_on             = [google_project_iam_member.permissions]

  display_name           = "s3-transfer"
  location               = "asia-northeast1"
  data_source_id         = "amazon_s3"
  schedule               = "every day 21:00" # UTC
  destination_dataset_id = google_bigquery_dataset.my_dataset.dataset_id
  params                 = {
    destination_table_name_template = "my_table"
    data_path                       = "s3://my_bucket/my_prefix/*"
    access_key_id                   = var.aws_access_key
    secret_access_key               = var.aws_secret_key
    file_format                     = "PARQUET"
  }
}
```

[Terraformのドキュメント](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/bigquery_data_transfer_config)にはs3転送例は載っていないため`data_source_id`や`params`の項目は個別に調べる必要がある。BigQuery Data Transfer Service がサポートするデータソースは[ドキュメント記載のコマンド出力](https://cloud.google.com/bigquery-transfer/docs/samples/bigquerydatatransfer-quickstart?hl=ja#bigquerydatatransfer_quickstart-python)から得られる。
2021-10-02 > [trap] PYNQ-Z1 > Vivado 2019.1でRun Block AutomationするとS AXI HP0関連が消える

````動作環境
Windows 10 Pro (21H1) 
PYNQ-Z1 (Digilent) (以下、PYNQと表記)
Vivado v2019.1 (64-bit)
```

### PYNQ-Z1 > S AXI HP0関連が消える

Block Designにおいて以下を実施する。

1. Zynqを追加
1. ZynqのRe-customize IPにおいて
    1. PS-PL ConfigurationでHP Slave AXI Inteface > S AXI HP0 interfaceを有効にする
    1. Clock ConfigurationでPL Fabric Clocks > FCLK_CLK0を100MHzにする
    1. OKを押す


2の完了時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/d1e6ed9d-14d0-0cf2-0880-396b65d7926a.png)

Run Block Automationを実行するとS AXI HP0 interface関連が消える(以下参照）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/bbb9987c-5c68-0d3b-cb07-81aea86872eb.png)


### Cora Z7 > 症状は発生しない

以下は同じ処理を手順を実施した結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/dd62ae4b-27e4-cadc-b307-cd12b9c47848.png)


### 数時間溶かした

S AXI HP0 interfaceが消えていることに気づくまでに数時間溶かした。
この記事を読んだ人がそのようなことになりませんように。
jqでプロパティの値として特定の文字列を含むオブジェクトを取得する

jqのクエリが全然身につかないので自分メモ

githubの適当なリポジトリからlinux-amd64用の最新リリースを取得したい。

今回はassetsから、nameプロパティに-linux-amd64を含むオブジェクトを取得することで実現するとする。
selectとcontainsを組み合わせて、以下のように書くことで取得できる。

```sh
$ curl -s https://api.github.com/repos/mithrandie/csvq/releases/latest \
  | jq '.assets[] | select(.name | contains("-linux-amd64"))'
```

select内で|(パイプ)があるのが不安になるけど、`.name | contains("特定の文字列")` がboolを返す。
なんとなく `contains(.name, "-linux-amd64")` と書きたくなるのだが、上記で正しい。
SQLで3次メッシュコードをWKT形式に変換する

次のような3次メッシュコードをWKTに変換したいとき

```csvs:mesh3
mcode3
55370046
54390560
```

以下で変換できる。クエリエンジンはPrestoを想定

```sql:convert_wkt
WITH base as (
  SELECT
    ,cast(cast(substr(mcode3,3,2) as double) +100 + cast(substr(mcode3,6,1) as double) * 1/8   + cast(substr(mcode3,8,1) as double) * 1/8/10 as varchar) as west
    ,cast(cast(substr(mcode3,3,2) as double) +100 + cast(substr(mcode3,6,1) as double) * 1/8   + (cast(substr(mcode3,8,1) as double)+1) * 1/8/10 as varchar) as east
    ,cast(cast(substr(mcode3,1,2) as double) /1.5 + cast(substr(mcode3,5,1) as double) * 2/3/8 + cast(substr(mcode3,7,1) as double) * 2/3/8/10 as varchar) as south
    ,cast(cast(substr(mcode3,1,2) as double) /1.5 + cast(substr(mcode3,5,1) as double) * 2/3/8 + (cast(substr(mcode3,7,1) as double)+1) * 2/3/8/10 as varchar) as north
  FROM mesh3
)
SELECT
  'POLYGON((' || west || ' ' || south || ',' ||  west || ' ' || north || ',' ||  east || ' ' || north  || ',' ||  east || ' ' || south || ',' || west || ' ' || south || '))'
FROM base
```

参考：[GISソフトウエアでメッシュコードに対応した値を表示する方法](https://www.nite.go.jp/chem/prtr/map_data/PRTRmapdata_katsuyouhou.html)
OpenStructを使ってみた。

こんにちは、プレイライフの熊崎です！
本日２本目は実務でOpenStructを使用したので、OpenStructについてアウトプットを行っていこうと思います。

## OpenStructとは
> 要素を動的に追加・削除できる手軽な構造体を提供するクラスです。
ref: https://docs.ruby-lang.org/ja/latest/class/OpenStruct.html

> An OpenStruct is a data structure, similar to a Hash, that allows the definition of arbitrary attributes with their accompanying values.
ref: https://ruby-doc.org/stdlib-2.6.6/libdoc/ostruct/rdoc/OpenStruct.html

→ 任意の属性とそれに付随する値を定義することができて、なおかつ属性は動的に追加・削除ができる。

### 構造体とは？
> 構造体（こうぞうたい、英: structure）はプログラミング言語におけるデータ型の一つで、1つもしくは複数の値をまとめて格納できる型。それぞれのメンバー（フィールド）に名前が付いている点、またメンバーの型が異なっていてもよい点が配列と異なる。
ref: https://ja.wikipedia.org/wiki/%E6%A7%8B%E9%80%A0%E4%BD%93

## どんな挙動をするのか？
以下のように、要素を追加したり、削除したりできる。

```sample.rb
require 'ostruct'
user = OpenStruct.new
user.name = "佐藤太郎"
p user # => #<OpenStruct name="佐藤太郎">
user.delete_field("name")
p user # => #<OpenStruct>
```

newメソッドの時点で属性をセットすることもできる。

```sample.rb
require 'ostruct'
OpenStruct.new(:name => "佐藤太郎", :sex => "male")
```

## どんな時に使うのか？

例：何らかの事情で、フロントエンド側から受け取った値を変換したいとき。
わざわざ変換用のクラスを準備するよりもこっちの方が簡単に書ける。

```sample.rb
def conversion_entry_status
  OpenStruct.new(
    "ok": "entry",
    "ng": "not_entry"
  )
end

def save
  user_schedule.update!(entry_status: conversion_entry_status[:ok])
end
```

## 最後に
今回の例以外にも、テスト時のmockを作る時などにも使用されるらしい。
まだまだ理解しきれていない部分もあるため、もっと使用して理解を深めようと思う。

## 参考文献
https://docs.ruby-lang.org/ja/latest/class/OpenStruct.html

https://ruby-doc.org/stdlib-2.6.6/libdoc/ostruct/rdoc/OpenStruct.html

https://ja.wikipedia.org/wiki/%E6%A7%8B%E9%80%A0%E4%BD%93
ゴールデンイメージ ゴールデンAMI とは

## 勉強前イメージ

クローンするイメージ、クローンするAMIって感じだと思ってるけど
ゴールデンとは・・・・

## 調査

### ゴールデンイメージ ゴールデンAMI とは

仮想ネットワークハードウェアのテンプレートとして使用できるクローンであり、
それを使用して新しい仮想環境を作成することができます。
クローンできるイメージ、クローンできるAMIというような感じです。

### AWSでは？

AWSでは `EC2 Image builder` というものを使って
ゴールデンイメージを作成したり、管理・デプロイ・アップデートが出来るサービスです。
仮想環境だけでなく、他のサービスと組み合わせることでオンプレでも使用することができます。
実環境の投入前の検証でも使用できます。

## 勉強後イメージ

ゴールデンイメージ とかってAWSの用語じゃなくて全般的な用語なのね。
今後 EC2 Image builder 調べてよ

## 参考

- [ゴールデンイメージについて](https://techhub.hpe.com/eginfolib/synergy/image_streamer/i3s-ui-help/ja/content/GI.html#:~:text=%E3%82%B4%E3%83%BC%E3%83%AB%E3%83%87%E3%83%B3%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%A8%E3%81%AF%E3%80%81%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE,%E7%94%A8%E3%81%AB%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)
- [AWS Blackbeltちゃんとやる～EC2 Image Builder編～](https://www.ladypuipui.com/techlog/awsblackbelt-ec2imagebulder/)
Safari で Bookmarklet に '%' が含まれていると動かない【Safari】

## はじめに

　前回のブックマークレットの記事を書いている途中で、Safari で動作確認をした際に、どうも動かないなあと思ったので調べてみました。

　Safari 限定です。確認した Safari のバージョンは14.1.2(15611.3.10.1.5, 15611)です。

## 動かない Bookmarklet

　以下のブックマークレットは動きませんでした。開発ツールのコンソールでは、期待通り最初の `alert();` が実行されますが、ブックマークレットにすると動きません。

```javascript
javascript:(function(){alert();return;const s='a';var a='a'.replaceAll(s,'%'+'20').replaceAll('/','%'+'2F');})();
```

　`return;` が入っているので、そこまでは動いて欲しい気がしたのですが、動きません。

## 動くようにするには

　どうも `'%'` が問題になっているようで、以下のようにしたら動作しました。

```javascript
javascript:(function(){alert();return;const P=String.fromCharCode(0x25);const P1=P+'20';const P2=P+'2F';const s='a';var a='a/'.replaceAll(s,P1).replaceAll('/',P2);alert(a);})();
```
ssdを新しく購入したのでLinuxPC(OS:ubuntu)にmountする

ssdを新しく購入したのでLinuxPC(OS:ubuntu)にmountするだけの記事

# 環境

ubuntu18.04
[Crucial SSD P2シリーズ 1TB M.2 NVMe接続](https://www.amazon.co.jp/gp/product/B08C2S7HTT/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1)

# 手順

利用可能なファイルシステムのディスク容量を出力する

```
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev             16G     0   16G   0% /dev
/dev/nvme1n1p2  468G  287G  158G  65% /
```

今回追加したSSDは以下コマンドで確認できる。
（まだmountしてないので、dfコマンドで出力されない）

```
$ sudo fdisk -l
ディスク /dev/nvme0n1: 931.5 GiB, 1000204886016 バイト, 1953525168 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
```

以下を参照させて頂き、mountする。
また起動時に毎回mountされるようにfdiskの設定もする。
（今回の対象は、`/dev/nvme0n1`）
> [SSDのマウント](https://qiita.com/katsuta/items/004b4b4d03921bbf68a3)


再起動後、以下のようになっていればOK

```
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev             16G     0   16G   0% /dev
/dev/nvme1n1p2  468G  287G  158G  65% /
/dev/nvme0n1    916G   77M  870G   1% /mnt/ssd　　★今回追加
```

# 参考
[SSDのマウント](https://qiita.com/katsuta/items/004b4b4d03921bbf68a3)
Flutter環境構築メモ

## Flutterとは
* iOSとAndroidのアプリを1つのコードで作成できるフレームワーク。
* JavaScriptに似た、Dartという言語を使っている。
* Android StudioなどのIDEを利用して開発できる。

## インストール
* [Flutter](https://flutter.dev/) 公式Webサイトにアクセスし、Get startedボタンをクリックする。
* Windowsをクリックする。
* flutter_windows_2.5.2-stable.zip をクリックし、ダウンロードする。(1.6GBもある)
* flutter_windows_2.5.2-stable.zip を解凍し、My Documentsなどに入れる。(バージョンがころころかわりそうなので、私は、My Documents\Flutter\flutter_windows_2.5.2-stable　という階層に配置してみました)
* システムの詳細設定から、環境変数に flutter\flutter_windows_2.5.2-stable\flutter\bin までのパスを追加
* flutterのパスが通っていることの確認

```cmd
>where flutter dart
C:\Users\user\OneDrive\ドキュメント\flutter\flutter_windows_2.5.2-stable\flutter\bin\flutter
C:\Users\user\OneDrive\ドキュメント\flutter\flutter_windows_2.5.2-stable\flutter\bin\flutter.bat
C:\Users\user\OneDrive\ドキュメント\flutter\flutter_windows_2.5.2-stable\flutter\bin\dart
C:\Users\user\OneDrive\ドキュメント\flutter\flutter_windows_2.5.2-stable\flutter\bin\dart.bat
```

* flutter doctorの実行

```cmd
C:\Users\user>flutter doctor
```

* あら、エラーが出た

```cmd
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    X cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    X Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.
C:\Users\user\Desktop\flutter>flutter doctor --android-licenses
```

- Android Studioをダウンロードしてインストール(まだの場合)

* アップデート等いろいろしていたら、Android SDKのインストールも始まった。 
* Android SDK Command-line Tools (latest) をAndroid Studioの設定画面からインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331144/654364cc-2bd2-0510-83a6-6e47268e4ea2.png)

* 再度、flutter doctor を実行
```
C:\Users\user>flutter doctor
C:\Users\user>flutter doctor --android-licenses
y
y
y
... (7回ぐらい？)
C:\Users\user>flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.5.2, on Microsoft Windows [Version 10.0.19043.1237], locale ja-JP)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio (version 2020.3)
[√] VS Code (version 1.60.2)
[√] Connected device (2 available)

• No issues found!
```
* やっとエラーがなくなりました
* Windowsの場合の追加作業

```
C:\Users\user\Desktop\flutter>flutter config --enable-windows-desktop
```
* 再起動

* Android Studioに、Flutterプラグインをインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331144/795bbb89-2c24-32a6-3086-45485a2be18e.png)

* Android Studioを再起動
* New Flutter Projectボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331144/aea34028-11d5-4d09-be31-5d2290fbaedf.png)

* 次の画面で、FlutterとSDKのパスを設定し、 Nextをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331144/d8baea22-8dfa-bcf0-0b50-4cbf167b9851.png)
* 名前をつけてFinishをクリック
* デバイスで適当なブラウザを選択して、再生ボタンをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331144/4dbb4c79-5c28-6a5d-2a2a-a3445f8eda23.png)

* クリック回数をカウントするアプリが表示されました。
ハッシュ

ハッシュとは中身の値 バリュー をそれに対応する名前 キー で管理することができます。配列と同じように複数の値を持つことができる。

```ruby
変数 = {}
```

で生成でき

```ruby
変数 = {キー1 => バリュー1,キー2 => バリュー2}
```

シンボルを使用すると

```ruby
変数 = {キー1 :バリュー1,キー2 :バリュー2}
```

となり、上記も下記も出力すると同じものが出力される。

ハッシュに値を追加するには

```ruby
変数 = {}
変数[追加したいキー] = バリュー
```

で追加できる。

例えば

```ruby
men = {name :Taro,age :28}
```

に身長(キー) 179(バリュー)を追加したければ

```ruby
men[height] = 179
```

となる。

ハッシュを取得したい場合は
ハッシュ[取得したいキー]で取得できる。配列では添字だったがハッシュはキー(名前)でバリュー(値)を管理しているのでキーを指定する。
menのageを取得したい場合は

```ruby
men[age]
```

で取得できる。

ハッシュの値を変更したい場合は

```ruby
変数[変更したい値のキー] = 値
```

で変更できる。
menのheightを変更したい場合は

```ruby
men[height] = 169
```

で変更できる。
保存済みのマイグレーションファイルを編集する方法

こんにちは！テックアカデミーのWebアプリコースを受講している駆け出し高校生エンジニアの安田駿介です。

今回は、「保存済みのマイグレーションファイルを編集する方法」というテーマで解説していきます。

# 保存済みのマイグレーションファイルを編集する手順
１．rails db:migrate:status
２．rails db:rollback
３．rails db:migrate:status
４．マイグレーションファイルを編集
５．rails db:migrate

という手順です。

# 解説

１と３のrails db:migrate:statusは、マイグレーションファイルの状態を確認するコードです。

２のrails db:rollbackは、１で状態を確認したときに、一番下のupになっていたマイグレーションファイルをdownにするコードです。

これにより、マイグレーションファイルを編集することができます。

マイグレーションファイルを編集したら、５のrails db:migrateで保存しましょう。

rails db:migrate:statusで確認したら、upになっていると思います。

# 保存済みのマイグレーションファイル削除してしまったときは？
その場合はこちらの記事をお読みください。

https://qiita.com/yasshun1229/items/de86ee4b65e47e641828

# 開発環境
Ruby 3.0.0
Rails 6.1.3.1
配列

配列とは一つの変数で複数の値を持つことができる値で、中のデータは要素と呼ぶ。要素は順番をもっていて配列に入ると自動的に与えられる。
変数 = [値]　で定義できる。
後から要素を追加することもでき
変数 << 値
で追加できる。 << これを配列演算子という。

要素には添字という番号が割り振られており、

```ruby
animals = [“サル”,”イヌ”,”キジ”]
```

では、サルが0、イヌが1、キジが2、というふうになっている。
配列の要素を取得した場合は

```ruby
配列[添字]
```

で取得できる。animalsでイヌを取得したい場合は

```ruby
animals[1]
```

となる。

```ruby
変数 = 配列[添字]
```

で配列の要素を取得し変数に代入することができる。

配列の値を変えたい場合は

```ruby
配列[添字] =  値
```

で変更できる。animalsのキジをハトに変えたい場合は

```ruby
animals[2] = “ハト”
```

となる。

lengthメソッドを使うと配列の要素の数を数えてくれる。

```ruby
animals = [“サル”,”イヌ”,”キジ”]
puts animals.length
```

を出力すると

3

となる。
railsチュートリアル第6章 ユーザーがセキュアなパスワードを持っている

###ユーザーがセキュアなパスワードを持っている
Userモデルに```password_digest```属性を追加し、Gemfileにbcryptを追加したことで、ようやくUserモデル内で```has_secure_password```が使えるようになりました。

####Userモデルにhas_secure_passwordを追加する 

```rb
class User < ApplicationRecord
  before_save { email.downcase! }
  # データベースに保存する前に処理をする。
  # 入力されたメールアドレスを小文字にする。
  validates :name,  presence: true, length: { maximum: 50 }
  #属性はname,属性の存在を検証、 最大50字まで
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
  #最大255字まで
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
                    #???
  has_secure_password
  #セキュアなパスワードの実装
end
```
red と記しておいたように、まだテストは落ちたままになっているはずです。

```
ubuntu:~/environment/sample_app (modeling-users) $ rails  t
Running via Spring preloader in process 10116
Started with run options --seed 39785

ERROR["test_should_get_home", #<Minitest::Reporters::Suite:0x000055a5c42ddc40 @name="StaticPagesControllerTest">, 0.01687353799934499]
 test_should_get_home#StaticPagesControllerTest (0.02s)
NameError:         NameError: undefined local variable or method `　has_secure_password' for #<Class:0x000055a5c42bc108>
        Did you mean?  has_secure_password
            app/models/user.rb:13:in `<class:User>'
            app/models/user.rb:1:in `<main>'

  17/17: [============================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.07316s
17 tests, 34 assertions, 0 failures, 1 errors, 0 skips
```
```NameError: undefined local variable or method `　has_secure_password'  ```
has_secure_passwordに使う変数、メソッドが見つからないらしい。

テストが失敗する理由は、```has_secure_password```には、仮想的なpassword属性とpassword_confirmation属性に対して```バリデーションをする機能も（強制的に）追加```されているからです。
しかしテストでは、@user 変数にこのような値がセットされておりません

```rb
def setup
  @user = User.new(name: "Example User", email: "user@example.com")
end
```

####パスワードとパスワード確認を追加する

```rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase
  def setup
    @user = User.new(name: "Example User", email: "user@example.com",
                     password: "foobar", password_confirmation: "foobar")
  end
.
.
.
end
```
変数を追加した。

```
ubuntu:~/environment/sample_app (modeling-users) $ rails t
Running via Spring preloader in process 12573
Started with run options --seed 33971

  17/17: [============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.38901s
17 tests, 36 assertions, 0 failures, 0 errors, 0 skips
```
全角スペースでエラーが出た。疲れた。

###演習
1. この時点では、userオブジェクトに有効な名前とメールアドレスを与えても、valid?で失敗してしまうことを確認してみてください。

2.なぜ失敗してしまうのでしょうか? エラーメッセージを確認してみてください。

```rb
>> user = User.find(1)
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2021-09-23 05:29:52", updated_at: "2021-09-23 05:29:52", password_digest: nil>

>> user.valid?
  User Exists? (0.8ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ?  [["email", "michael@example.com"], ["id", 1], ["LIMIT", 1]]
=> false

>> user.errors.full_messages
=> ["Password can't be blank"]
```
パスワードがないみたい。
railsチュートリアル第6章 パスワードの最小文字数

###パスワードの最小文字数
パスワードを簡単に当てられないようにするために、パスワードの```最小文字数を設定```しておくことは一般に実用的です。
Railsでパスワードの長さを設定する方法はたくさんありますが、今回は簡潔にパスワードが```空でない```ことと```最小文字数（6文字）```の2つを設定しましょう。
パスワードの長さが6文字以上であることを検証するテストを示します。

####パスワードの最小文字数をテストする

```rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase
  def setup
    @user = User.new(name: "Example User", email: "user@example.com",
                     password: "foobar", password_confirmation: "foobar")
  end
.
.
.
  test "password should be present (nonblank)" do
    @user.password = @user.password_confirmation = " " * 6
  　# パスワードの空白が六文字
    assert_not @user.valid?
    # バリデーションは認められないよね？
  end

  test "password should have a minimum length" do
    @user.password = @user.password_confirmation = "a" * 5
    # 文字が五文字
    assert_not @user.valid?
    # このパスワードも認められないよね？
  end
end
```
次のような```多重代入（Multiple Assignment）```を使っていることに注目してください。

```rb
@user.password = @user.password_confirmation = "a" * 5
```
パスワードとパスワード確認に対して同時に代入をしています。

```maximum ```を使ってユーザー名の```最大文字数を制限```していましたが、これと似たような形式の```minimum```というオプションを使って、```最小文字数のバリデーション```を実装することができます。

```rb
validates :password, length: { minimum: 6 }
```
空のパスワードを入力させないために、存在性のバリデーション（6.2.2）も一緒に追加します。
結果として、Userモデルのコードはリスト 6.43のようになります。
ちなみに```has_secure_password```メソッドは```存在性のバリデーション```もしてくれるのですが、これは```新しくレコードが追加されたときだけ```に適用される性質を持っています。
したがって、例えばユーザーが' '（6文字分の空白スペース）といった文字列をパスワード欄に入力して更新しようとすると、バリデーションが適用されずに更新されてしまう問題が発生してしまうのです。

```rb
class User < ApplicationRecord
  before_save { self.email = email.downcase }
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }
end
```

```
ubuntu:~/environment/sample_app (modeling-users) $ rails test:models
Started with run options --seed 22618

  11/11: [============================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.06481s
11 tests, 19 assertions, 0 failures, 0 errors, 0 skips
```

###演習
1.有効な名前とメールアドレスでも、パスワードが短すぎるとuserオブジェクトが有効にならないことを確認してみましょう。
2.上で失敗した時、どんなエラーメッセージになるでしょうか? 確認してみましょう。

```rb
>> user 
=> #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2021-09-23 05:29:52", updated_at: "2021-09-23 05:29:52", password_digest: nil>

>> user.password = "aa"
=> "aa"

>> user.save
   (0.1ms)  SAVEPOINT active_record_1
  User Exists? (0.1ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ?  [["email", "michael@example.com"], ["id", 1], ["LIMIT", 1]]
   (0.1ms)  ROLLBACK TO SAVEPOINT active_record_1
=> false

>> user.valid?
  User Exists? (0.2ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ?  [["email", "michael@example.com"], ["id", 1], ["LIMIT", 1]]
=> false

>> user.errors.full_messages
=> ["Password is too short (minimum is 6 characters)"]
```
[git] git初期設定 gitのエディタをVSCodeにしたのにgit commitでエディタが開かない

##はじめに
僕は今までgithub desktopを使用していたので、gitとgithubの理解が浅く、コマンドでgitを使用したことも少なかったので、学び直しています。

その際、タイトルのようなことでつまづいたので記事に残しておきます。

##gitのエディタをVSCodeに設定
gitのエディタを設定する際に、私が参考にしていた教材はAtomというエディタを使用していた為に下記のコマンドで設定するように指示されていました。

```terminal
$ git config --global core.editor "atom --wait"
```

もし、他のエディタを使用するのであれば```atom```の部分を任意のものに変更するだけで良いと解説されていたので、VSCodeを使用していた僕は下記のように設定してしまいました。

```terminal:間違えたコマンド
$ git config --global core.editor "visualstudiocode --wait"
```

恥ずかしすぎます、、、
コマンド自体は通ります。ただ、```visualstudiocode```がVSCodeとして認識しないので、git commitでVSCodeを開こうと思っても下記のようなエラーでおそらく開けないでしょう。

```terminal:gitcommit時のエラー
hint: Waiting for your editor to close the file... visualstudiocode --wait: visualstudiocode: command not found
error: There was a problem with the editor 'visualstudiocode --wait'.
Please supply the message using either -m or -F option.
```

VSCodeに設定する場合の正しいコマンドは下記のとおりです。

```terminal
$ git config --global core.editor "code --wait"
```

codeだったんですね、、、

##それでもgit commitでVSCodeが開かない
git commitしても先ほどのエラー文と変わらず、開けませんでした。
codeというコマンドが見つからないみたいですね。

codeコマンドを使えるようにしなくてはいけないみたいです。

下記の方法で解決しました。

①VSCodeを開いてショートカット「command + shift + p」でコマンドパレットを出す

②コマンドパレットに「シェルコマンド」と打つと「シェルコマンド:PATH内に'code'コマンドをインストールします」が出てくるのでクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1552346/f1cc130b-53ab-b9e5-0279-0873069e6687.png)

これでgit commitでVSCodeが開くようになりました！


参考:
[Udemy 「Git： もう怖くないGit！チーム開発で必要なGitを完全マスター」 山浦 清透](https://www.udemy.com/course/unscared_git/)
https://qiita.com/takeo-asai/items/9bc7e25cd94cd8c9adee
https://qiita.com/grca3/items/0771099a6750840721b1
DjangoにおけるSQLインジェクション

# はじめに
Djangoでの生のSQL文の正確な書き方の記事がほとんどないので、今回の記事の執筆に至りました。
最初にSQLインジェクションの基本事項を抑え後に、具体的にDjangoのSQLインジェクション対策について見ていきましょう。SQLインジェクションの基本事項は、[IPA 安全なアプリケーションの作り方- 1.1 SQLインジェクション](https://www.ipa.go.jp/security/vuln/websecurity-HTML-1_1.html)を多く参考にさせていただきました。
# SQLインジェクションとは？
SQL文の組み立て方法に問題がある場合、攻撃によってデータベースの不正利用を行うこと。

# SQLインジェクションの種類
### インバウンドSQLインジェクション
webアプリケーションからのレスポンスを収集して脆弱性を分析し、その脆弱性をついたSQL文を実行し、データを盗んだり消去したりすること。さらに以下の二つに分けられる。  
- エラーベースSQLインジェクション
攻撃者がデータベースに対してエラーメッセージを生成させるアクションを実行する。  
- UNIONインジェクション
複数のSELECTステートメントの結果を一つの結果に結合し、HTTPレスポンスの一部に結果が含まれて返ってくる。
### ブラインドSQLインジェクション  
攻撃者がデータをwebサーバーに送信し、webサーバーのレスポンスと動作を観察・分析することによって、攻撃者がデータベースの管理情報を盗むことができる。

# 発生しうる脅威
[IPA 安全なアプリケーションの作り方- 1.1 SQLインジェクション](https://www.ipa.go.jp/security/vuln/websecurity-HTML-1_1.html)で以下のように説明されています。
> 
- データベースに蓄積された非公開情報の閲覧
- データベースに蓄積された情報の改ざん、消去
- 認証回避による不正ログイン
- ストアドプロシージャ等を利用したOSコマンドの実行


# 一般的な対策
1. SQL文の組み立ては全てプレースホルダーで実装する。  
文字列連結に対して機械的な処理でSQL文が組み立てられるので、SQLインジェクションを解消できる。プレースホルダーに実際の値を割り当てることをバインドと呼び、データベースエンジンで割り当てる静的プレースホルダーと、アプリケーション側で割り当てる動的プレースホルダーがある。より安全なのは前者。
2. SQL文の組み立てを文字列連結によって行う場合は、エスケープ処理等を行いSQL文のリテラルを正しく構成する。
3. webアプリケーションに渡されるパラメータにSQL文を直接指定しない。

次にDjangoについて具体的に見ていきましょう。

# Djangoで既に行われているSQLインジェクションへの対策
ORMによって対策されている。ORMとは、`Object-relational mapper`の略。これは、オブジェクト志向言語を用いることで、プログラム内のシステム間でデータの非互換なやり取りを行う技法。つまり、オブジェクトを操作することでデータの管理を行うことを可能にした。これを行うことで、クエリのパラメータ化が行われ、それをデータベースドライバーによってエスケープするため、SQLインジェクションを防御できている。

# 生のSQL文を書く時の注意点
Djangoで既に対策されているとはいえ、複雑なクエリを叩きたい時やデータがモデルに対応していない時など、生のSQL文を書きたい時がある。その時は、次のような二つの記法のうちどちらかを用いる必要がある。

- executeを用いた際の対処法

```python
context = super().get_context_data(**kwargs)
con = sqlite3.connect("db.sqlite3")
cur = con.cursor()
sql_input = self.request.GET.get("sql", None)
# プレースホルダーを設ける
sql = "SELECT * FROM books_Book WHERE id = %s"
# 値の入れ方に注意
cur.execute(sql % (sql_input))
context["data"] = cur.fetchone()
con.close()
return context
```
- Raw()を用いた際の対処法

```python
context = super().get_context_data(**kwargs)
sql_input = self.request.GET.get("sql", None)
# プレースホルダーを設けて値の代入も行う
item = Item.objects.raw("SELECT * FROM items_Item WHERE id=%s", str(sql_input))
context["data"] = item[0].overview
return context
```
# 最後に
SQLインジェクションは非常に危険性の高い攻撃ですが、Djangoは基本的にORMによって対策できているようなので、Djangoでコードを書くときはあまり意識する必要はないでしょう。ただ生のSQL文を書く時は、上記の書き方を参考にしていただきたいです。
また初めてのqiitaへの投稿なので、至らない点もあると思いますので、その場合は是非コメントなどをお寄せください。

# 参考資料
[IPA 安全なアプリケーションの作り方- 1.1 SQLインジェクション](https://www.ipa.go.jp/security/vuln/websecurity-HTML-1_1.html)
[油断できない SQL インジェクション。その種類と Web アプリにおける対策](https://yamory.io/blog/sql-injection/)
[DjangoのSQLインジェクション対策](https://docs.djangoproject.com/ja/3.2/topics/security/#sql-injection-protection)
[Djangoの公式のSQL解説](https://docs.djangoproject.com/en/3.2/topics/db/sql/)
Async/Await入門 resolve()について

前に投稿したこの記事では、Async/Awaitについて必要最低限の解説を行いました。
[Javascript初級者がAsync/Awaitが使えるようになる記事](https://qiita.com/aulait/items/c245ee7c4a11bda939ae)

今回はresolveについての解説をします。基本的な解説は↑の記事を参照してください。

# resolve()に値を入れるとどうなるか？

```javascript
const timer=(time)=>{
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve();
        }, time);
    });
 } 
 (async function(){
    $('.春はあけぼの').fadeIn();
    await timer(1000);
    $('.やうやうしろくなりゆく山ぎは').fadeIn();
    await timer(1000);
    $('.すこしあかりて紫だちたる雲のほそくたなびきたる').fadeIn();
 })();

```
このようなプログラムがあったとします。このプログラムは単純に「１秒後ごとにテキストを表示させていく」というプログラムです。
ここでは、resolve()には何も渡していません。

関数timerの内容を変更しresolve()に"〇秒待ちました"という文字列を渡してみます。

```javascript
const timer=(time)=>{
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(time+"秒待ちました");
        }, time);
    });
 } 
```

すると、await timer(1000);が"1秒待ちました"という文字を返すようになります。

```javascript
const result = await timer(1000);
console.log(result);
```
結果
`>> 1秒待ちました`

となると思います。（補足としてtypescriptの場合new Promise\<string\>(～とすると、resultの型がstringになります。）

また、Promise文で書き直すと

```javascript
timer(3000).then(result => {
    console.log(then);
});
```

となり、次のthenで文字列を引き取ることになります。



# 何が嬉しいのか？

先ほど、例だと'1秒待ちました'という文字列が返されますが、何も嬉しくないと思います。
これはファイルやapiなどのアクセスをjs上で行う時に特に役に立ちます。


例えば、

```javascript
$.get( "./枕草子.txt");
```

こういう処理をしたとします。$.getはjQueryのgetメソッドであり、指定パスのファイルを取得するためのメソッドです(素のjsだと面倒くさいのでjquery使ってます)

async/awaitを何も考えずに処理をすると、第二引数にコールバックが用意されているので、

```javascript
$.get( "./枕草子.txt",(txt)=>{
    console.log(txt);
});
```

となると思います。ですが、$.getの戻り値はPromiseなので、async/awaitを用いると

```javascript
const result = await $.get( "./枕草子.txt");
```

とすることができます。これをconsole.log(result)すると、
`>> 春はあけぼのやうやう白くなりゆく山ぎわ～～`
となると思います。

こういった処理ができるのが、嬉しいところです。

これは、$.getが具体的にどんな処理をしているかは分かりませんが

```javascript
$.get = (filePath)=>{
    return new Promise((resolve,reject)=>{
        const file = yomikomi(filePath);
        resolve(file);
    });
}
```
みたいな感じで、resolve()にファイルを入れているので、await $.get( "./枕草子.txt");の戻り値としてファイルの結果を取得できるのです。

# 関連記事

[Javascript初級者がAsync/Awaitが使えるようになる記事](https://qiita.com/aulait/items/c245ee7c4a11bda939ae)
[Async/Await入門 resolve()の引数に値を入れよう](https://qiita.com/aulait/items/b89d11f8b57a06965685)