OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScriptを無効化しているブラウザへの対応

開発中に調べたのでメモです

##目指すところ
JavaScriptを無効化しているブラウザに対して、「お使いのブラウザはJavaScriptをサポートしていません。」と表示させる。

###表示させたい文言→body内に\<noscript\>タグ内に記載

```html:index.html
<body>
   <noscript>お使いのブラウザはJavaScriptをサポートしていません。</noscript>
</body>
```

###スタイルを付けたい→head内に\<noscript\>タグで囲み記載

```html:index.html
<head>
   <noscript><link rel="stylesheet" href="css/noscript.css" /></noscript>
</head>
```
CloudFormationでALBのログをS3に出力する


## 経緯
CloudFormationでALBのログをS3に出力したく、
クラスメソッドの記事を読んだり、リファレンスを読んだりしていたが、ハマってしまったので、記事にかく。
パーミッション適応させているはずなので、なんでパーミッションがないんだとつまづいていた。

## エラー
```
Access Denied for bucket:{{バケット名}}. Please check S3bucket permission (Service: AmazonElasticLoadBalancing; Status Code: 400; Error Code: InvalidConfigurationRequest; Request ID: xxxxx; Proxy: null)
```

原因

DependsOn 指定が必要だった

FYI :https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html

```yml

Resources:
############################################
## S3
############################################

  LogBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Join [ "-", [ !Ref EnvTagPrefix, !Ref ProjTagPrefix, !Ref SubProjTagPrefix, alb-logs ] ]
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      LifecycleConfiguration:
        Rules:
          - ExpirationInDays: 30
            Status: Enabled

  LogBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref LogBucket
      PolicyDocument:
        Statement:
          - Action:
            - s3:PutObject
            Effect: Allow
            Resource:
            - !Sub arn:aws:s3:::${LogBucket}/*
            Principal:
              AWS: arn:aws:iam::582318560864:root


############################################
## ALB Setting
############################################
  ALB01:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    DependsOn: LogBucketPolicy
    Properties:
      Name: !Join [ "-", [ !Ref EnvTagPrefix, !Ref ProjTagPrefix, !Ref SubProjTagPrefix, alb01 ] ]
      Scheme: internet-facing
      LoadBalancerAttributes:
        - Key: "deletion_protection.enabled"
          Value: false
        - Key: "idle_timeout.timeout_seconds"
          Value: 300
        - Key: "access_logs.s3.enabled"
          Value: true
        - Key: "access_logs.s3.bucket"
          Value: !Ref LogBucket
      SecurityGroups:
        - { "Fn::ImportValue": !Join [ "-", [ !Ref EnvTagPrefix, !Ref ProjTagPrefix, alb-sg-public ]] }
        - { "Fn::ImportValue": !Join [ "-", [ !Ref EnvTagPrefix, !Ref ProjTagPrefix, alb-sg-stakeholders ]] }
        - { "Fn::ImportValue": !Join [ "-", [ !Ref EnvTagPrefix, !Ref ProjTagPrefix, alb-sg-unilabo ]] } # for blue/green check
      Subnets:
        - { "Fn::ImportValue": !Join [ "-", [ "Ref":"EnvTagPrefix", "sub-public-01"]] }
        - { "Fn::ImportValue": !Join [ "-", [ "Ref":"EnvTagPrefix", "sub-public-02"]] }
        - { "Fn::ImportValue": !Join [ "-", [ "Ref":"EnvTagPrefix", "sub-public-03"]] }
      Tags:
        - Key: Name
          Value: !Join [ "-", [ !Ref EnvTagPrefix, !Ref ProjTagPrefix, front, alb01 ] ]
```
ぐだぐだ表記 EC-CUBE4インストールに関して

お世話になっております。

スタディのため
EC-CUBEのインストールをしてみようかと思い
とりあえずAWSのLinuxの設定をしてインストールしようとして
[マニュアル](https://doc4.ec-cube.net/quickstart_install)を読んで気がついたのですが

EC-CUBE4ってWindowsとMacしか無いのでしょうか？
と思いましたが[Webインストーラ](https://doc4.ec-cube.net/quickstart_install/web-installer)というものがありますね……

もっとドキュメントが欲しいのでこの記事にぶら下げる予定です。
日曜プログラマがAWSのDBを選定している話をグダグダと表記

なんかAWSでショッピングサイト作りたいなーと思い
そのようなサイトではDB必要だよなー

AWSのDBって気が付かないうちに課金されそうでちゃんと考えないと……
ショッピングシステム？にはECCubeやらzencartやらあけど何が良いんだろ？？？
【初心者向け】検索窓の中に虫眼鏡アイコンを設置する方法

# どうも7noteです。検索ワードを入力するinput要素の中にアイコンをつける方法

Qiitaのように虫眼鏡アイコンをinput要素（テキストボックス）の中にいれる方法。

こんなやつ↓

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/09996abe-c70b-2c72-a470-ba7dd7a980b8.png)

※これは本当にqiitaをスクショしたので、細かい文字色や背景色などは再現しませんのでご注意。

## アイコンをテキストボックスの中に置く方法

```index.html
<div class="search_box">
  <input type="text" placeholder="ここにキーワード">
</div>
```

```style.css
.search_box {
  display: inline-block; /* なくても大丈夫だけど、念の為 */
  position: relative;    /* 基準値とする */
}

.search_box::before {
  content: "";           /* 疑似要素に必須 */
  width: 16px;           /* アイコンの横幅 */
  height: 16px;          /* アイコンの高さ */
  background: url(./icon.png) no-repeat center center / auto 100%; /* 背景にアイコン画像を配置 */
  display: inline-block; /* 高さを持たせるためにインラインブロック要素にする */
  position: absolute;    /* 相対位置に指定 */
  top: 4px;              /* アイコンの位置。微調整してね */
  left: 5px;             /* アイコンの位置。微調整してね */
}

.search_box input {
  padding: 3px 0 3px 2em; /* アイコンを設置するため左の余白を多めに指定*/
}
```

**結果**

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/f85a5302-f069-c498-46aa-5495960b9b51.png)

## 解説

**input要素には疑似要素がつかえません。**なのでinputと同じサイズの親要素を用意します。この親要素に対して疑似要素でアイコンを設置。position指定をして適切な位置に配置します。正確に上下中央に配置したい場合などは`top: 50%; transform: translateY(-50%);`等を指定しましょう。

## まとめ

簡単そうだけど、inputに疑似要素が使えないなどの知識がないと意外と沼にハマってしまいやすいいい例ですね。
疑似要素が使えない要素については過去に記事をまとめたのでよければこちらもご覧ください。

https://qiita.com/7note/items/7cb88dca241a22b54e5c

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
windowsでショートカットキーを自分で作る

①目的となるアプリやフォルダ、ファイルを決める
②右クリックで「送る」→「デスクトップ(ショートカットを作成)」
③出来上がったショートカットアイコンを右クリック→プロパティ→ショートカットキー
④ここに好きなキーを設定。CtrlとAltは必須らしい。

<strong>コツ</strong>
これを色んなファイルでやっていくと、デスクトップに本来のファイルとそのショートカットで溢れてしまう。
かと言って自分で作ったフォルダに入れてしまうと起動しない。
そんな時は③で作ったショートカットアイコンを「C:\ProgramData\Microsoft\Windows\スタ－トメニュー」の中に入れておく。
ProgramDataは隠しファイルなのでローカルディスクCを開いたときに「表示」→「隠しファイル」にチェックを入れて表示させる必要がある。
スタ－トメニューにショートカットアイコンを保存した後で④の設定を行う。

※デスクトップもしくはスタ－トメニューの中にあるショートカットアイコンにのみ設定できる。
VMWare上のVMのOS変更後は設定を編集しないとVMWareToolsのインストールができない

凡ミスです…。

# 「VMWareTools」のインストーラが起動しないぞ…？
VMWare(ESXi)でLinuxのVMを作成後、そのVMが不要になったので別途Windows Serverをインストールし直しました。インストールが完了し、マウス操作やコピペをスムースに行うために「VMWareTools」をインストールしようとした所、インストーラが起動できませんでした。。。

![vmware_tools_for_linux_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376864/39187e11-3391-ef4f-bd4c-7256138342ae.png)

マウントはされているのですが、自動起動もできないし、setup.exeとかautorun的なものがない。

![vmware_tools_for_linux_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376864/23bce18c-b7bd-f82f-9c89-9cdca0b76f37.png)

# VM自体のOSの設定が影響
VMを作る時にOSの種類やバージョンを指定する時があるのですが、その設定に基づいて「VMWareTools」のインストーラバイナリが異なってくるようでした。冒頭に書いた通り、元々Linuxをインストールしていたので、VMを作成する際にもLinuxOSであることを指定していました。

![setting_for_linux.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376864/b681c978-e7d9-bcaa-9858-57466036e709.png)

* ゲストOSが「Linux」
* ゲストOSのバージョンが「Ubuntu Linux(64ビット)」

これをWindowsに合わせて正しく変更後、再度「VMWareTools」をマウントしてインストールしようとした所、Windows用と思われるインストーラ一式が認識され、無事にインストーラが起動できました。

![vmware_tools_for_win.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376864/77216942-b6b4-491b-9f88-e5b63c4bf474.png)

当たり前といえば当たり前ということで。。。こんなところで詰まる人はいそうにないですが、メモしておきます。
Pythonの協働作業で気を付けること

# はじめに

Twitterで一時期流行していた 100 Days Of Code なるものを先日知りました。本記事は、初学者である私が100日の学習を通してどの程度成長できるか記録を残すこと、アウトプットすることを目的とします。誤っている点、読みにくい点多々あると思います。ご指摘いただけると幸いです！

# 今回学習する教材

- [Effective Python](https://www.amazon.co.jp/Effective-Python-%E2%80%95Python%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E6%94%B9%E8%89%AF%E3%81%99%E3%82%8B59%E9%A0%85%E7%9B%AE-Brett-Slatkin/dp/4873117569/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=Effective+python&qid=1609408832&sr=8-3)

    - 8章構成
    - 本章216ページ

- 第7章：協働作業

## すべての関数、クラス、モジュールについてドキュメンテーション文字列を書く

Pythonは、`__doc__`でドキュメンテーション文字列を取り出せます。
ドキュメンテーション文字列は、3連二重引用符 (""") を使います。


```python
def sampledoc(word):
    """ドキュメンテーションはアクセス可能です。"""
    pass

print(repr(sampledoc.__doc__))
```

実行結果

```result
'ドキュメンテーションはアクセス可能です。'
```

ドキュメンテーション文字列は、関数、クラス、モジュールに付与することができます。

### モジュールのドキュメンテーション

このドキュメンテーション文字列の目的は、モジュールとその内容の紹介です。
1行目は、モジュールの目的を述べる1文、その次の段落は、モジュールの全ユーザが知るべき動作の詳細を記述します。

### クラスのドキュメンテーション

ほぼモジュールのドキュメンテーション文字列と同じ形式です。
1行目は、クラスの目的を述べる1文、次の段落は、クラスの演算の詳細を記述します。
それ以降の段落は、以下の情報を記述します。

- クラスの重要なパブリック属性とメソッド
- プロテクテッド属性やスーパークラスのメソッドを正しく扱うためのサブクラスに対するガイド

### 関数のドキュメンテーション

モジュールやクラスと同じ形式です。
1行目は、関数が何をするか記述します。
次の段落は、振る舞いと引数、戻り値があれば戻り値も記述します。
呼び出し元が関数のインターフェースの一部として扱う例外は説明します。

### 関数のドキュメンテーション文字列を書く際の重要な注意事項

- 関数が引数を持たず単純な戻り値を返すなら、1文の記述で十分
- 関数が何も返さないなら、「returns None」と書くよりは戻り値について何も書かない方がよい
- 関数が通常の演算で例外を起こさないはずなら、それについては何も述べない
- 関数が可変長引数を取るなら、引数リストの中で*argsと**kwargsをその目的とともに述べる
- 関数がデフォルト値のある引数を取るなら、そのデフォルト値について述べる
- 関数がジェネレータなら、ドキュメンテーション文字列でジェネレータが何をyieldするか述べる
- 関数がコルーチンなら、ドキュメンテーション文字列でコルーチンが何をyieldし、yield式から何を受け取ると期待し、いつイテレーションを止めるかを述べる

## 隔離された複製可能な依存関係のために仮想環境を使う

Pythonを使うとき、パッケージをインストールするために、pipを実行することが多々あると思います。その際、依存パッケージもインストールしてきます。
この際に、複数のパッケージが同じ依存パッケージを要求する場合があると思います。例として、Sphinxパッケージと、flaskパッケージが依存しているパッケージをみてみます。

```code
pip show Sphinx
---
Name: Sphinx
Version: 3.4.3
Requires: docutils, Jinja2, setuptools # ...略

pip show flask
---
Name: Flask
Version: 1.1.2
Requires: Werkzeug, Jinja2, click, itsdangerous
```

Sphinxとflaskのパッケージは、ともにJinja2パッケージに依存していることが分かります。
これは、Jinja2が新しいバージョンに移行して、最新版に更新した場合に、flaskは問題なく動くのに、Sphinxは動かないというような状況が起こり得るということを意味しています。
このような問題は、Pythonが1つのモジュールに1つのバージョンしか持てないことが原因です。
このようなバージョンによる動作の問題は、協働作業の場合、より顕著になります。
バージョンが異なることにより、コードベースがあるプログラムのマシンでは動くのに、他の人のでは動かないということが起こり得ます。

こういった問題を解決する方法は、pyenvやdockerなどの仮想環境を利用することです。
pyenvは、パッケージの明示した版とその依存関係を完全に別のディレクトリ構造にインストールします。全く同じ環境を整えることで、バージョンによる破綻を避けることができます。
【Flutter + microCMS】ランダムストレス解消アプリ作ってみた

## 0. はじめに

- [**【Windows編】FlutterとCodemagicを使ってAndroid/iOSアプリを生成するまで**](https://qiita.com/i-tanaka730/items/a00b82701ccdf13883b3)

↑を書いたとき、Flutterアプリ作るよーと言っておきながら、全然手を付けていませんでした:cold_sweat:ｗ
いや、言い訳すると、アプリは作ってあったんですけど、記事を書いていなかったんです！ｗ

ということで、以前使ってみたmicroCMSが面白かったので、今度はFlutterと連携したアプリを作ってみました。
以下は過去に投稿したmicroCMS関連の記事になります。

- [**【Nuxt.js + COTOHA API + microCMS】COTOHAチックなフラッシュカード作ってみた**](https://qiita.com/i-tanaka730/items/3f97a9d1d668f424fc50)

## 1. どんなアプリ？
ストレス解消法をランダムに表示するアプリです。
※現状は10件しかデータが入っていません:poop:

単純ですが、こんな感じで動作するようにしました。

1. microCMSにて、「タイトル」「画像」「説明」を登録する。
2. アプリ起動時にenvファイルからmicroCMSのURLとAPIキーを読み込む。
3. microCMSに通信して、登録したデータを全て取得する。
4. 更新ボタン押下時に、取得したデータをランダムに表示する。

## 2. 環境
- Flutter
    - http・・・microCMSへのリクエスト
    - flutter_dotenv・・・envファイル読み込み（microCMSのURL、APIキー）
    - dart:math・・・乱数取得
    - dart:convert・・・Jsonデコード
- microCMS

## 3. クラス図
![RandomDeStress_クラス図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247638/f583b2ed-fbb4-841a-6c64-2fc24f5bfbd8.png)

## 4. 実装
[**random_de_stress**](https://github.com/i-tanaka730/random_de_stress)

## 5. デモ
![rds.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247638/c167f3a0-a4e9-1a14-b3ad-b6273971ac5b.gif)

## 6. 参考
とても分かりやすかったです！ありがとうございましたm(_ _)m

 - [**わかりやすいFlutterリファレンス（HTTPにリクエストする）**](https://nzigen.com/flutter-reference/2018-04-19-http.html)
 - [**FlutterとmicroCMSで作るシンプルなメディアアプリ**](https://microcms.io/blog/flutter-micrcocms-tutorial/)

## 7. おわりに
ちなみにCodemagic使いましたが、いい感じに動いてくれてました:innocent:
業務で使ってない言語をごりごりやるのは大事ですな:innocent:
次はFlutter＋Firebaseあたりで何か作ってみようと思います:innocent:
React分からんけとReact Nativeも触ってみんといかんな:innocent:
Android端末ほしい:innocent:
【2021年最新】アプリ開発者・運営会社向けセキュリティ商品ランキング

アプリケーションの増加に伴い、セキュリティにおける脅威も日々増加し続けています。高い開発技術を保有していたとしても、セキュリティ上の観点から課金・送金の限度額やアプリの各種機能を制限するケースなどが多く見られます。


アプリを運営する上で付きまとうこれらの脅威に対し、“脆弱性の診断”や、“堅牢化”などの対抗サービスも充実してきており、それぞれの特色により機能も大きく異なってくるため、あなたのアプリに合ったサービスを利用することが重要です。


そこで今回はアプリを開発・運営する上でのセキュリティ７商品を、ランキング形式でご紹介します。アプリのセキュリティを考えられている方はぜひ参考にしてみてください！



７位　[株式会社IERAE SECURITY](https://ierae.co.jp/)
![図7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078265/82b0554a-f79d-242a-6f17-d17ce952bee3.png)
参考サービスページ：https://ierae.co.jp/service/

- - -

６位　[ネットムーブ株式会社](https://www.netmove.co.jp/index.php)
　　　サービス：[SaAT](https://www.saat.jp/)
![図6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078265/41f24fd5-634e-edcb-7e0c-2611e65c3ea4.png)
参考サービスページ：https://www.saat.jp/

- - -

５位　[大日本印刷株式会社](https://www.dnp.co.jp/)
　　　サービス：[CrackProof](https://www.dnp.co.jp/biz/solution/products/detail/1188699_1567.html)
![図5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078265/5bd6c154-29c1-4a09-7fe6-5070ae3d993e.png)
参考サービスページ：https://www.saat.jp/

- - -

４位　[東芝情報システムズ株式会社](https://www.toshiba.co.jp/index_j.htm)
　　　サービス：[verimatrix](https://www.tjsys.co.jp/embedded/MatrixSSE/index_j.htm)
![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078265/f26b66e2-4ab4-e740-3aba-27d007c17e7e.png)
参考サービスページ：https://www.tjsys.co.jp/embedded/MatrixSSE/index_j.htm

- - -

３位　[ITM株式会社](https://www.itmanage.co.jp/)
　　　サービス：[AppProtect](https://www.itmanage.co.jp/security/)
![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078265/6c456250-8b9c-71e6-b101-54566aa986d6.png)
参考サービスページ：https://www.itmanage.co.jp/security/

- - -

２位　[株式会社Asgent](https://www.asgent.co.jp/)
　　　サービス：[ARXAN Technologies](https://www.asgent.co.jp/products/arxan.html)
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078265/a4631c84-8513-3bef-9c74-784c8acccd0c.png)
参考サービスページ：https://www.asgent.co.jp/products/arxan.html

- - -

１位　[MsafeTechnology株式会社](https://www.seciron.com/JP/index2.html)
　　　サービス：[SecIron](https://www.seciron.com/JP/index2.html)
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078265/42a5a75e-9fd1-bfd9-c736-ef68472fb0a8.png)
参考サービスページ：https://www.msafe.co.jp/
　
　
　
　アプリを開発・運営する上でのセキュリティ７商品を私的な機能の多さと最新の脅威への対応度、信頼性の観点からランキングにしてみましたが、あなたのアプリに合ったサービスは見つかりましたでしょうか？セキュリティはアプリの運営にとって重要な課題の一つですので、ランキングを参考にぜひ検討してみてください。
Java  PowerPointを印刷

<p> </p>
<p><strong>今日はSpire.Presentation for Java でPowerPointを印刷する方法を紹介します。主に二つの方法があります。すなわち：</strong></p>
<ol>
<li><strong>PresentationPrintDocument を利用することで</strong></li>
<li><strong>PrinterSettingsを利用することで</strong></li>
</ol>
<p><strong>というほうに行うことができます。</strong></p>
<h4><strong>下準備</strong></h4>
<p><strong>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/presentation-for-java.html">Free Spire. Presentation for Java</a>無料版をダウンロードしてください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210203/20210203172902.png" alt="f:id:lendoris:20210203172902p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong>2.</strong><strong>IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire. Presentation.jarを参照に追加してください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210203/20210203172915.png" alt="f:id:lendoris:20210203172915p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<h4><strong> PresentationPrintDocument</strong></h4>
```JAVA
import com.spire.presentation.Presentation;
import com.spire.presentation.PresentationPrintDocument;

public class PrintPPT {
    public static void main(String[] args) throws Exception {
    String inputFile = "Sample.pptx";

    
    Presentation presentation = new Presentation();
    presentation.loadFromFile(inputFile);

    //すべてのスライドを印刷します。 
    PresentationPrintDocument document = new PresentationPrintDocument(presentation);
    document.print();
    presentation.dispose();

    }
}
```
<h4><strong>PrinterSettings</strong></h4>
```JAVA
import com.spire.ms.Printing.*;
import com.spire.presentation.*;
public class PrintPPT {

    public static void main(String[] args) throws Exception {
       
 //ファイルをロードします。
        Presentation presentation = new Presentation();
        presentation.loadFromFile("Sample.pptx");

        //PrinterSettingsで印刷します。
        PrinterSettings ps = new PrinterSettings();
        ps.setPrintRange(PrintRange.AllPages);

        //ps.setPrintToFile(true);

        //印刷時に枠をつけます。
        presentation.setSlideFrameForPrint(true);

        //灰色にします
        presentation.setGrayLevelForPrint(true);

        
        presentation.setSlideCountPerPageForPrint(PageSlideCount.Four);

        //印刷の方法を設定します。
        presentation.setOrderForPrint(Order.Horizontal);

        //印刷したいスライドを選びます。 
        presentation.SelectSlidesForPrint("1", "3");

        //印刷します。
        presentation.print(ps);
        presentation.dispose();
    }
}
```

<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210203/20210203173035.png" alt="f:id:lendoris:20210203173035p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong> </strong></p>
Homebrewの再インストール

# Reinstall Homebrew
どうやら**Homebrew**内の`reinstall`のようなものがないようなので一旦アンインストールしてからインストールしなおしてみます．

## Attention
Homebrewを一旦消してしまうので**元々入れていたパケージは消えてしまいます**．なのでそれらも入れ直す必要があります．

## Cause
一応ですが**Homebrew**を入れなおそうと思った理由を述べておきます．

```
$ brew update

/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/brew.sh: line 653: homebrew-update: command not found
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/brew.sh: line 653: homebrew-update: command not found
Traceback (most recent call last):
        5: from /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/brew.rb:31:in `<main>'
        4: from /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/brew.rb:31:in `require_relative'
        3: from /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/global.rb:122:in `<top (required)>'
        2: from /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        1: from /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/config.rb:32:in `<top (required)>': uninitialized constant GitRepositoryExtension (NameError)
```

となってしまい色々試しても改善できなかったということがあります．

## Uninstall Homebrew
```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)"

~省略~

You may wish to remove them yourself.
```

最後にこのメッセージが表示されていれば大丈夫だと思います．

## Install Homebrew
```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

以上です．
Matlabのmod()とfloor()をまとめてPythonで

Matlabでは剰余は```mod(a, b)```という関数で取れる。
割り算の商は```floor(a/b)```と丸めるのがおそらくは簡単だと思われる。

Pythonだと、余りは```a % b```で　商は```a // b```という演算子で書けてスッキリ。
商と剰余、両方必要なときは```divmod(a, b)```という便利関数も組み込みである。

余談ながら、累乗はMatlabでは```^```だったけど、Pythonでは```**```だ。

#例:in Matlab
```matlab
>> floor(5^0.5/1)

ans =
     2

>> mod(5^0.5,1)

ans =
    0.2361
```

#例:in Python
```python
>>> (5 ** 0.5) // 1
 2.0

>>> (5 ** 0.5) % 1
 0.2360679774997898
```
本当はカッコは要らなくて、```5 ** 0.5 // 1```とか```5 ** 0.5 % 1```で良いのだけれど、カッコがある方が読みやすい気がする。

商と剰余両方ほしいときはdivmod()

```python
>>> divmod(5 ** 0.5, 1)
 (2.0, 0.2360679774997898)
```

divmod()の出力のタプルは、もちろんアンパックして受けてもOK

```python
>>> (q ,r) = divmod(13, 5)
>>> q
 2

>>> r
 3
```

divmodは地味に便利そうだ。
dockerでnginxとphp-fpmコンテナのログをホスト側からローテーションする方法

nginxとphp-fpmコンテナのログはホストにマウントされており、ホスト側からログをローテーションしたい場合。

## ログ用ボリュームのマウント
こんな感じで、ホスト側のvolume/logs/nginxにひっつけてあったとする。

docker-compose.yml

```yaml
  nginx:
    image: nginx:latest
    volumes:
      - ./volume/logs/nginx:/var/log/nginx
  php:
    image: php-fpm:latest
    volumes:
      - ./volume/logs/php-fpm:/var/log/php-fpm
```

## ログローテーションの設定
dockerホスト側のlogrotationの設定をする。
圧縮ありなし、タイミング、個数等は適当に（例は日毎、30個、圧縮あり）。

### nginx
ポイントは`kill -s HUP nginx`の部分。

/etc/logrotete.d/nginx

```
/home/username/docker/volume/logs/nginx/*.log 
{
    missingok
    notifempty
    daily
    rotate 30
    compress
    delaycompress
    sharedscripts
    postrotate
        /usr/local/bin/docker-compose -f /home/username/docker/docker-compose.yml kill -s HUP nginx
    endscript
}
```

### php-fpm
こちらは`kill -s USR1`を送る。

/etc/logrotete.d/php-fpm

```
/home/username/docker/volume/logs/php-fpm/*.log 
{
    missingok
    notifempty
    daily
    rotate 30
    compress
    delaycompress
    sharedscripts
    postrotate
        /usr/local/bin/docker-compose -f /home/username/docker/docker-compose.yml kill -s USR1 php
    endscript
}
```

## 確認
強制的にローテーションさせて、ログがちゃんとローテーションされ、***最新のものに書かれるか***を確認。

```
logrotate -f /etc/logrotate.conf
```
expoでKeystore作成に失敗する

expoでandroid用にビルドしょうと思ったらkeystoneの作成に失敗したのでメモです。

## 環境
* macos 11.2 (Big Sur)
* expo

## 状況：

KeyStore作成に失敗する

```
> expo build:android

Failed to generate Android Keystore, it will be generated on Expo servers during the build
keytool exited with non-zero code: 1
...
```

## 原因＆解消方法

macosではjavaが標準でインストールされていないため、keytoolの実行に失敗します。

Javaをインストールします。まる。

これとか
https://www.azul.com/downloads/zulu-community/?version=java-11-lts&os=macos&package=jdk&show-old-builds=true
LineAPIから受け取った数値テキストをGoogleスプレッドシートへ追記するアプリ


#記事内容
QiitaにはGASでLineチャットボットを作成する記事はいくつかありましたが、スプレッドシートへの書込みまでを記載している記事がありませんでした。
そこで、LineAPIから受け取ったテキストをスプレッドシートへ追記するアプリの作り方を記載します。

・QiitaのLineBOT記事の一例
[Google Apps ScriptでLINE BOTつくったら30分で動かせた件](https://qiita.com/hakshu/items/55c2584cf82718f47464)

##開発目的
ダイエットをする際に、体重をGoogleスプレッドシートで管理したかったので、
「体重を測定した結果をLineチャットで入力したらGoogleスプレッドシートへ記録する」
というアプリを作りました。

※高い体重計を買えば済む話なのですが、勉強も兼ねてプログラミングしました。

##環境（使うもの）
・Google Apps Script
・Line Message API
・Google Spread Sheet
・スマホ

スマホ以外は基本無料で利用できます。

#開発手順
##設計図
今回のアプリは以下のイメージとなります。

![gas01_BD_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1050189/afc27ede-cd8a-8a04-f2cd-c48995275030.png)


簡単な入力チェック（数値かどうか）を実施し、実施結果を返答する仕様です。

##開発手順
まず始めに以下の環境を準備します。
・Googleアカウント
・Line開発アカウント

アカウントを準備したらAPIの認証（トークン）連携の設定を行います。

アカウントの登録～トークン設定などの一連の手順は以下の記事が参考になります。
[GASでLineチャットボットの作り方【初心者向け手順解説】](https://gurishunin.com/line_gas_beginner/)


各種設定を実施後、スプレッドシートへ書込む部分をコーディングしていきます。


##スクリプト
あまり綺麗ではありませんが、参考までに共有します。

```javascript
// LINE developersのメッセージ送受信設定に記載のアクセストークン
const ACCESS_TOKEN = 'アクセストークン';

function doPost(e) {
  // WebHookで受信した応答用Token
  var replyToken = JSON.parse(e.postData.contents).events[0].replyToken;
  // ユーザーのメッセージを取得
  var userMessage = JSON.parse(e.postData.contents).events[0].message.text;
  // 応答メッセージ用のAPI URL
  var url = 'https://api.line.me/v2/bot/message/reply';
  //応答メッセージ
  var resMessage;
  //入力チェック結果
  var chFlg = 0;

  //記録先シート
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const wSheet = ss.getSheetByName('weight');

  //最新行を取得
  const lastRow = wSheet.getLastRow();
  var nRow= lastRow+1;
  
  //本日日付を取得
  var date = new Date();
  var today = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy/MM/dd hh:mm:ss');

  //入力チェック
  if(!isNaN(userMessage)){
    chFlg = 1;
  }else{
    resMessage = "数値を入力してください。";
  }

  //入力チェックOKの場合、スプレッドシートへ内容を記録
  if(chFlg != 0){
    //記録
    wSheet.getRange(nRow, 1).setValue(today);
    wSheet.getRange(nRow, 2).setValue(userMessage);

    //応答メッセージをセット
    resMessage = "記録しました！";
  }
  

  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{
        'type': 'text',
        'text': resMessage,
        //'text': userMessage,
      }],
    }),
  });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}
```

#実行結果
##Lineへの入力
今日のやりとりの部分が最終的なLineへの入力イメージとなります。
※すみませんが、テスト中のメッセージが残っています。

![Line_15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1050189/ab257c90-721d-5bfd-407b-08f196be2f8f.jpeg)

##スプレッドシートへの書込み結果
先ほど入力したメッセージが以下のようにスプレッドシートに書き込まれます。

![GAS_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1050189/d001a573-e756-887a-2afb-e6c4be3f8728.jpeg)

#まとめ
LineとGASを利用して簡単なスプレッドシートへの記録アプリを作成しました。

本記事の内容をベースに、Lineをユーザインターフェースとして様々なことができるアプリが構築できると思いました。

みなさんも是非遊んでみてください。
【Laravel6.x】 子分を雇って使役する方法（スケジューラーとキューワーカー）

人気ランキングの集計や月間売上の集計とかをしなきゃ！

でも、お客(ユーザー)がひっきりなしに来ている状態でお店（サーバー）を休めない！

変わりのお店（サーバー）を用意できればいいですけど、
お金がもったいないときは子分(キューワーカー)を雇って使役しちゃいましょう。

スケジューラーを使えば、必要なタスク（集計とか）を定期的に追加できるので便利です。

## キューワーカーの準備
キューワーカーは、子分です（雑）。

タスクを登録した順（First In First Out）で順番にこなしてくれるカワイイやつです。
ぜひこき使いましょう！

```bash
# 以下を.envに追記 (キューをデータベースを使って管理する設定)
QUEUE_CONNECTION=database
QUEUE_DIRVER=database

# キュー管理用のテーブル作成
php artisan queue:table
php artisan migrate

# ワーカーの起動 （起動したプロセスを維持する必要あり）
php artisan queue:work
```

## キューワーカーの準備(本番環境)
本番でワーカーを起動しっぱなしにするには、Supervisiorを使いましょう。
参考：https://readouble.com/laravel/6.x/ja/queues.html#supervisor-configuration

## ジョブを作成
子分にこなしてもらうジョブ（タスク）を作りましょう！

例として、ランキング作成と売上集計するジョブ、、、はめんどくさいので、単にログってくれるものを作ります。

```php
// Jobの雛形を作成
php artisan make:job RankingCulculatingJob

// app/Jobs/RankingCulculatingJob.php
    ...
    public function handle()
    {
        \Log::info('ランキング計算したよ！');
    }

// もう一つ売上集計ジョブを作成
php artisan make:job SalesCulculatingJob

// app/Jobs/SalesCulculatingJob.php
    ...
    public function handle()
    {
        \Log::info('売上計算したよ！');
    }
```

## スケジューラーの準備
Laravelのartisanコマンドに`schedule:run`があります。

こいつをCronで毎分実行するようにすると、`app/Console/Kernel.php`の設定通りにタスクを実行してくれます。

そのためCronの設定ファイルを編集します。

```bash
# 以下のコマンドを実行
crontab -e

# 以下のように編集
* * * * * php 【あなたのプロジェクトフォルダ】/artisan schedule:run >> /dev/null 2>&1
```

## スケジューラーにジョブを登録
`app/Console/Kernel.php`に実行したいジョブを登録していきます。

```php
...
protected function schedule(Schedule $schedule)
{
    $schedule->job(new RankingCulculatingJob)->everyMinute();
    $schedule->job(new SalesCulculatingJob)->everyMinute();
}
```

必要なのはこれだけ！！！！！

## 動作確認！
php artisan queue:workを実行したプロセスをみるとこんな感じ！

```php
[2021-02-03 16:31:09][2] Processing: App\Jobs\SalesCulculatingJob
[2021-02-03 16:31:09][2] Processed:  App\Jobs\SalesCulculatingJob
[2021-02-03 16:32:03][3] Processing: App\Jobs\RankingCulculatingJob
[2021-02-03 16:32:03][3] Processed:  App\Jobs\RankingCulculatingJob
[2021-02-03 16:32:03][4] Processing: App\Jobs\SalesCulculatingJob
[2021-02-03 16:32:03][4] Processed:  App\Jobs\SalesCulculatingJob
[2021-02-03 16:33:03][5] Processing: App\Jobs\RankingCulculatingJob
[2021-02-03 16:33:03][5] Processed:  App\Jobs\RankingCulculatingJob
[2021-02-03 16:33:03][6] Processing: App\Jobs\SalesCulculatingJob
[2021-02-03 16:33:03][6] Processed:  App\Jobs\SalesCulculatingJob
```

Logが毎分増えていく！

```php
// ログ監視を開始する
tail -f storage/logs/laravel.log

[2021-02-03 16:31:09] local.INFO: ランキング計算したよ！
[2021-02-03 16:31:09] local.INFO: 売上計算したよ！
[2021-02-03 16:32:03] local.INFO: ランキング計算したよ！
[2021-02-03 16:32:03] local.INFO: 売上計算したよ！
[2021-02-03 16:33:03] local.INFO: ランキング計算したよ！
[2021-02-03 16:33:03] local.INFO: 売上計算したよ！
[2021-02-03 16:34:00] local.INFO: ランキング計算したよ！
[2021-02-03 16:34:00] local.INFO: 売上計算したよ！
[2021-02-03 16:35:03] local.INFO: ランキング計算したよ！
[2021-02-03 16:35:03] local.INFO: 売上計算したよ！
```

## ※エラーが出る場合
```
The server requested authentication method unknown to the client
```

スケジューラー経由のジョブ登録時に↑のようなDB接続問題が出ましたが、以下の記事にある方法で解消できました！

参考記事 ： [macでLaravelでmysql8を使う \(mysql8の認証プラグインの変更\) \- Qiita](https://qiita.com/yoshinyan/items/60dea12f84d48a4fa9eb)
tp-linkのArcher T9UH AC1900 をラズパイで利用

結果的にバッファローのWifiドングルと同じ方式で動作できました。。
一回バッファローのやつ刺してから、tplinkつけたからいたのかな？？？

###接続確認

```
lsusb
```

![NoName_2021-2-3_16-41-7_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/b2e193d2-b089-83f4-16af-54fbd944765e.png)


###ラズパイに合ったドライバーのバージョン確認

```
pi@raspberrypi:~ $ uname -a
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l GNU/Linux
```

必要な情報は下記の箇所

```
5.4.83-v7l
```

###ドライバーファイルのURL探索

http://downloads.fars-robotics.net/wifi-drivers/8812au-drivers/

「5.4.83-v7l」をブラウザの機能なんかで探すと楽

![NoName_2021-2-3_16-34-26_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/2cb4ac4b-3d2d-bf62-b974-bf52eb15fbaa.png)

ダウンロードに必要なtargファイル

```
http://downloads.fars-robotics.net/wifi-drivers/8812au-drivers/8812au-5.4.83-v7l-1379.tar.gz
```

###ドライバーのダウンロード/解凍/インストール

``` 
mkdir drivers
cd drivers
wget http://downloads.fars-robotics.net/wifi-drivers/8812au-drivers/8812au-5.4.83-v7l-1379.tar.gz
tar zxf ./8812au-5.4.83-v7l-1379.tar.gz
sudo ./install.sh
```

###認識状況を確認

```
ifconfig

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.1  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::61f5:8b71:43b7:4457  prefixlen 64  scopeid 0x20<link>
        ether dc:a6:32:d3:6d:a0  txqueuelen 1000  (イーサネット)
        RX packets 11395  bytes 4382038 (4.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 9319  bytes 4306094 (4.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.9  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::cd4e:7a29:9662:5060  prefixlen 64  scopeid 0x20<link>
        ether d0:37:45:23:55:52  txqueuelen 1000  (イーサネット)
        RX packets 17965  bytes 1711512 (1.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 80  bytes 12215 (11.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```


###ラズパイWifiと比べて

5Gなど帯域の違いがあるかもですが、結構違う感じがしました

![NoName_2021-2-3_16-28-39_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/697e6ddc-43f4-4ab3-b262-44fa764aa27f.png)

![NoName_2021-2-3_16-28-51_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48015/0bce59e4-4264-b68b-782e-3007105b5e31.png)


##参考サイト

Raspberry PiでTP-Link Archer T9UHを使う
https://qiita.com/kmorimoto/items/f09462ee8da05470a912

Raspberry Pi に無線LAN USBドングルを追加して、2つのネットワークに接続する方法
https://qiita.com/Mitsu-Murakita/items/bfc0a491e0a8d6d17029

Index of /wifi-driverｓ
http://downloads.fars-robotics.net/wifi-drivers/

Archer T9UH AC1900 ハイパワー デュアルバンド 無線LAN子機
https://www.tp-link.com/jp/home-networking/adapter/archer-t9uh/
Qiita での記事の書き方（初心者・備忘録）

# 目次
- [1. Qiitaに記事を書く理由](#1-Qiitaに記事を書く理由)
- [2. Markdown方式](#2-Markdown方式)
- [3. 目次の書き方](#3-目次の書き方)
- [4. おわりに](#4-おわりに)

#1. Qiitaに記事を書く理由
2020年4月から機械学習を用いた開発プロジェクトに携わるようになりました。しかし、仕事を進める中でなかなかアウトプットの機会を自分で作ることができました。そこで同僚と相談し、2021年2月3日から定期的にQiitaに技術記事を書くことにしました。内容としては自身の備忘録としての意味合いが強くなるかとは思いますが、お付き合い頂けますと幸いです。

#2. Markdown方式
Qiita で記事を書くためには Markdown 方式で書く必要があります。Qiita 独特の表現もあるみたいなので、この記事を書く上で調べたことをつらつらと書いていこうと思います。

##見出しについて
文頭に#をつけることで見出しを書くことができます。

#見出し
##見出し２
###見出し３

```

#見出し
##見出し２
###見出し３
```

##箇条書きについて
文頭に-と半角スペースを付けることで書くことができます。

- 箇条書き１
- 箇条書き２
    - 箇条書き２－１
        - 箇条書き２－１－１
    - 箇条書き２－２
- 箇条書き３

```

- 箇条書き１
- 箇条書き２
    - 箇条書き２－１
        - 箇条書き２－１－１
    - 箇条書き２－２
- 箇条書き３
```
##コードの挿入について
バッククオート三つ（```）で囲うことでコードを挿入することができます。

```python:hello.py
print("hello world")
```

```
    ```python:hello.py
    print("hello world")
    ```
```
↑スペースは要りません。コード挿入で三連バッククオートを表示する方法があったらどなたか教えてください…。

#3. 目次の書き方
この記事の目次を書くと以下の様になります。

```

- [1.Qiitaに記事を書く理由](#1-Qiitaに記事を書く理由)
- [2.Markdown方式](#2-Markdown方式)
- [3.目次の書き方](#3-目次の書き方)
- [4.おわりに](#4-おわりに)
```
見出しに対してリンクを張る様に書けば、目次にリンクが付いた状態で表示することができます。

#4. おわりに
今後とも学んだことを随時記入していきたいと思います。初学者ですので至らぬ点など多いかと思いますが、記事に対してご意見・ご感想頂けますと幸いです。
スマホを普段あまり触っていない方への説明hack

# 動画で説明する際は操作している指も含めてカメラで撮影する
画面キャプチャでの動画と
カメラを使って指で操作している動画では
格段に理解度が違いました。
数人で同様の反応があったので意外と有効な方法だと思います。

# 今どのアプリで開いているか？｜壁その１
ウェブアプリの場合、リンクを送った際にそのままタップして開く
↓
ブラウザではないアプリで開くことが多い
↓
結果アプリ内のwebviewが立ち上がりバグが発生することが少なくない

これもただメールでブラウザを指定して指示するよりも
前述の指撮影でブラウザを指定して指示することでかなりスムーズに理解度が進みました。

まずは今どのアプリで開いているかという認識を持ってもらい
webviewの存在を知ってもらうと意外と理解が進む印象でした。

# コピーペーストができない｜壁その２
乾燥で反応が悪かったり、
目が悪かったり、
油が飛んでいるキッチンなどだと反応が悪なったり、
指が太っかったり

まずテキスト選択でも壁があるようです。
選択後に表示されるコピーという表記も
マークで表記されることもあり、わかりにくい事がありました。
また『ペースト』という表記も『貼り付け』の方が理解率が高かったです。

# キーボードの切り替え、文字入力｜壁その３
キーボードの種類が複数あるという認識がない方もいます。
特に記号はとっさに入力するのは難易度が高いようです。
これは特にandroidだと画面が違うことも多い印象で
全て細かく説明するのはかなりのコストなので
まずはキーボードが数種類あるということを認識してもらい慣れてもらうことが早い気がします。

# 所感
PC、スマホを毎日触っているとついつい説明を端折ってしまいがちですが
整理してみるといくつかポイントがあるなと思い書いてみました。
意外とまだPC、スマホ自体に慣れていない方は一定数いますね。
スマホネイティブ世代でもみんながスマホ好きということもなく
できれば触りたくない層というのは数％はいる気もします。（個人的感覚値ですが）
ここはビジネス的にもチャンスがありそうなので見続けて行きたいですね。
まぁUIの進化も凄いので解消される部分もあると思いますが
ウェブアプリで機能を減らすというのは限界があると思うので残る部分もありそうな感じがします。
個人的感覚ばっかりで恐縮です。最後まで読んでいただいた方ありがとうございました。
Rails 6.1にあげたらundefined method `file_fixture_path' for FactoryBot::SyntaxRunner:Classになりましたとさ

# 背景
Rails のバージョンを 6.0 系から 6.1 系にあげた時にspecが大量にfailした

```rb
       Failure/Error: sample_image { fixture_file_upload("fixtures/sample.png") }
       
       NoMethodError:
         undefined method `file_fixture_path' for FactoryBot::SyntaxRunner:Class
       # ./spec/factories/**.rb:**:in `block (3 levels) in <main>'
```

# 確認
Railsのリリースノートを確認すると以下の記述を発見。
どうやらfixture_file_uploadedの利用する*_pathが変更されたらしい
https://github.com/rails/rails/releases/tag/v6.1.0
![スクリーンショット 2021-02-03 16.08.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280595/041dbd1f-670e-d862-71ab-e945e386ca61.png)

ファイルが見つかりませんではなく NoMethodError が出ていた背景を見るとFactoryBot内部でfile_fixture_pathが解決できていない
↓RailsのPRはこちら
https://github.com/rails/rails/pull/39086

# 対処
`rails_helper.rb` で `ActiveSupport::Testing::FileFixtures` を includeすることで解決できました。

```rb
FactoryBot::SyntaxRunner.class_eval do
  include ActionDispatch::TestProcess
  include ActiveSupport::Testing::FileFixtures
end
```
特徴ベクトルについて簡単にまとめた

こんにちは．

今回は機械学習やパターン認識を勉強しているとよく出てくる「__特徴ベクトル__」について自分なりにまとめてみました．（大学の講義資料を自分でまとめ直しただけですが．）

間違いがあるかもしれませんがご容赦ください笑

#まずベクトルについて

__ベクトル__とは，簡単に言うと複数個の数値の組で表される量のことです．
$$
\boldsymbol{ x } = (x_1,x_2,...,x_d)
$$
$x_1,x_2...$には数値が入ります．（例：$\boldsymbol{ x } = (2,4,5)$）

そして，高校数学でも習いますがベクトルには__長さ__や__距離__，__内積__といった概念があります．ベクトルの長さは「__ノルム__」，距離は「__ユークリッド距離__」と言ったりもします．

計算式は以下のようになります．

__ベクトル$\boldsymbol{ x }$のノルム（長さ）__: 
$\Vert \boldsymbol{ x } \Vert = \sqrt{ x_1^2 + x_2^2 + \cdots + x_d^2} = \sqrt{\langle \boldsymbol{ x },\boldsymbol{ x } \rangle}$ 

__ベクトル$\boldsymbol{ x }$とベクトル$\boldsymbol{ y }$との距離（ユークリッド距離）__: 
$\Vert \boldsymbol{ x }-\boldsymbol{ y } \Vert = \sqrt{ (x_1 - y_1)^2 + \cdots + (x_d - y_d)^2}$

__ベクトル$\boldsymbol{ x }$とベクトル$\boldsymbol{ y }$との内積__: 
$\langle \boldsymbol{ x },\boldsymbol{ y } \rangle = x_1y_1 + x_2y_2 + \cdots + x_dy_d = \Vert \boldsymbol{ x } \Vert \Vert \boldsymbol{ y } \Vert \cos \theta$ 

以上がベクトルの基礎の考え方となります．

#特徴ベクトル

__特徴ベクトル__とは，パターン情報を変数値を要素とするベクトルの形式で表現したものです．パターン情報は濃淡画像の画素値等です．

例えば，以下のような「3」を表す画像（白が画素値0，黒が画素値1とする）があったとします．
<div align="center">
</div>
![3_pa.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880557/2186ce85-011a-cd69-5749-aa381cf0766e.jpeg)

この画像を特徴ベクトルとして表すと，以下のようになります．(見やすいように行の終わりと始まりの間に空白を設けています)
$$
\boldsymbol{ x } = (0,1,1,1,0,　0,0,0,1,0,　0,1,1,1,0,　0,0,0,1,0,　0,1,1,1,0)
$$

同様に「2」を表す画像だと，以下のようになります．

![2_pa.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880557/40c16af0-d822-e9cc-3971-9a064b7a07bd.jpeg)

$$
\boldsymbol{ x } = (0,1,1,1,0,　0,0,0,1,0,　0,1,1,1,0,　0,1,0,0,0,　0,1,1,1,0)
$$

また，例で表した2つの画像は25画素であるとしているので，特徴ベクトルの要素数が25となります．このとき，これらの特徴ベクトルは25次元であるといえます．

このことから，実際の写真等を特徴ベクトルで表す場合，何十万次元となります．

#特徴空間

__特徴空間__とは，特徴ベクトルが表現される空間のことです．特徴ベクトルが2次元であった場合は，特徴空間は2次元空間となり，25次元であった場合は特徴空間は25次元となります．

#おわりに

今回のようにデータを特徴ベクトルに変換することは，パターン認識等のコンピュータによる識別において重要だと考えられます．
Node.js で文字列に改行を入れる

作業メモです。

# 環境

```bash
$node --version
v10.17.0
```

# やりたいこと

Slack に Node.js から Webhook 経由で投稿する際に改行した文字列郡の投稿をしたいがどうやればいいか分からず、少し調べた

# やりかた

以下の記事が参考になった

[Node.js Tips — Send Message, Adding End of Line, and S3 Uploads](https://medium.com/javascript-in-plain-english/node-js-tips-send-message-adding-end-of-line-and-s3-uploads-699a5fe466da)

`os.EOL` で出来るらしく、Mac 上でやってみたら出来た

```
const os = require("os");

var str = '1';
var str2 = '2';
var res = str + os.EOL + str2
console.log(res);
```

```bash
$node test.js
1
2
```

OK

Node.js の [ドキュメント](https://nodejs.org/api/os.html#os_os_eol)を見ると

>The operating system-specific end-of-line marker.

と書いてあるので恐らく Linux/Windows 上でも動くと思われるが、未確認
gitのリポジトリの情報を取得したい【GitHub/Bitbucket】

コピペが苦手。なのでリポジトリの情報はコマンドラインから取得することにしました。
参考：
https://docs.github.com/ja/rest/guides/getting-started-with-the-rest-api
https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D

GitHub Docsが分かりやすくマニュアル化されていて、これを参考にBitbucketも同じ感じで対応したらできました。

事前準備
-
どちらのサービスでもコマンドラインからhttpで接続し情報を取得します。
接続の際にはREST APIを使用する為、認証の為のトークンが必要です。

####トークン作成画面へのリンク
**GitHub**
https://github.com/settings/tokens
**Bitbucket**
https://bitbucket.org/account/settings/app-passwords/

どちらのサービスでも、トークン作成時にr/w権限などを設定できます。
尚、このトークンで取得できる情報は自分にアクセス権限が与えられているリポジトリに対してのみでした。
試していないけど、ワークスペースの管理者ならワークスペース単位のトークンも作成できそうな画面を見たので、そっちを使う方法もありそう。

####情報の整形
json形式での情報取得になる為、出力されたものの整形にjqコマンドを使用します。

```
//macでhomebrewが使える前提
brew install jq
```

リポジトリ名取得
-

####GitHub
```
curl -u <username>:<token> https://api.github.com/orgs/<workspace>/repos | jq -r '.[].name'
```

####Bitbucket
Bitbucketはプロジェクト名も一緒に取得するパターンでコマンド作成。
また、取得できるvalue[]がデフォルトだと10のようなので100に変更し更にリポジトリ名でソート。

```
curl -u <username>:<token> 'https://api.bitbucket.org/2.0/repositories/<workspace>?pagelen=100&page=1&sort=name' | jq '.values | map({ name : .name , group: .project.name })'
```
インデックスの出力が不要な場合

```
curl -u <username>:<token> 'https://api.bitbucket.org/2.0/repositories/<workspace>?pagelen=100&page=1&sort=name' | jq '.values[] | .name , .project.name' 
```
Amazon Linux 2 で PHP 7.2 から 7.4 へアップデートする

# きっかけ

Laravel Passport を Laravel 6.0.4 へインストールする際に色々とはまって（PHP 7.2 から 7.4 にアップデートする必要があり）丸一日かかってしまったので、被害者がこれ以上増えないように記事にしました。

# やり方

## 現在有効になっている PHP バージョンを確認する

`amazon-linux-extras`（Amazon Linux 2 から使えるパッケージ管理ツール）の実行結果から現在 `enable` になっているバージョンを確認します。

以下の例では `7.2` になっていることがわかります。

```bash
$ amazon-linux-extras | grep php
 15  php7.2=latest            enabled      \
 17  lamp-mariadb10.2-php7.2  available    \
  _  php7.3                   available    \
  _  php7.4                   available    [ =stable ]
```

実際に `php` のバージョンを確認すると、以下のような結果となります。

```bash
$ php -v
PHP 7.2.24 (cli) (built: Oct 31 2019 18:27:08) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
```

## 有効になっている PHP 7.2 を無効にする

ここの手順がすごい重要です。

ま、簡単なことですが。

```bash
$ sudo amazon-linux-extras disable php7.2
Beware that disabling topics is not supported after they are installed.
（たくさん表示されるので割愛）
```

## 最新の PHP 7.4 を有効にする

無事 `php7.2` が `disable` になっていることを確認後に、今度は `php7.4` を有効化します。

```bash
$ amazon-linux-extras enable php7.4
You lack permissions to write to system configuration.  /etc/yum.repos.d/amzn2-extras.repo
$ sudo amazon-linux-extras enable php7.4
```

なお、特権（`root`）が必要です。参考までに一般アカウントでの実行結果も貼っておきます。
（個人的に思うことなんですけど、世の中の記事は大半が `sudo` を必要としていない場面で使っていますね、あれやめてほしい）

## PHP 7.4 をインストールする

さて、やっと本題です。

このやり方も色々と紹介されており、めちゃくちゃ混乱したのですが `amazon-linux-extras` 一択でいきましょう。

```bash
$ sudo amazon-linux-extras install php7.4
（たくさん表示されるので割愛）
```

## PHP 7.4 にアップデートされたかを確認する

```bash
$ amazon-linux-extras | grep php
  _  php7.2                   available    \
  _  lamp-mariadb10.2-php7.2  available    \
  _  php7.3                   available    \
 42  php7.4=latest            enabled      [ =stable ]
```

無事 `php7.4=latest` が `enable` になっていることが確認されました。

では、最後。

```bash
$ php -v
PHP 7.4.14 (cli) (built: Jan 14 2021 20:52:40) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
```

以上です。

今回は触れませんでしたが、これで Laravel 6.20.16 に無事アップデートできました。（いや、このためにやったんですけどね）

```bash
$ php artisan -V
Laravel Framework 6.20.16
```
Vue(Webpack)+Rails+Mysql+Cloud9

#1 現状のMySQLバージョンを確認

```
$ mysql --version
```

#2 旧バージョン(5.5)パッケージ関連を削除

```
$ sudo yum -y remove mysql-config mysql55-server mysql55-libs mysql55
```

#3 新バージョン(5.7)パッケージ関連をインストール

```
sudo yum -y install mysql57-server mysql57
```

#4 日本語文字化け対策を実施
```
$ sed -e "/utf8/d" -e "/client/d" -e "/^\[mysqld_safe\]$/i character-set-server=utf8\n\n[client]\ndefault-character-set=utf8" /etc/my.cnf |sudo tee /etc/my.cnf
```

#5 MySQL確認&起動

```
$ mysql --version
$ sudo service mysqld start
```
#6 MySQL Account を作る

```
$ sudo mysql -u root   #rootユーザーでログイン
$ mysql> create user 'ユーザー名' identified by 'パスワード';  #ユーザー作成
$ mysql> grant all on *.* to 'ユーザー名';  #ALL権限付与

#作成したユーザーの確認は下記コマンド
$ mysql> select User,Host from mysql.user;
```

#7 順番にライブラリをインストール&mysql2(gem)のインストール

```
$　sudo yum install mysql57-devel
$　sudo yum -y install ruby-devel
$　sudo yum groupinstall "Development Tools"

$　gem install mysql2
```

#8 Railsをインストール

```
$ gem install rails -v 5.2.1
```

#9 yarnインストール
```
$ npm install -g yarn
```

#10 プロジェクトを作成

```
$ rails new vueapp --webpack=vue --database=mysql
```

#11 config/database.ymlの編集

```
default: &default
  adapter: mysql2
  encoding: unicode
  pool: 5
  # 以下、3行追加
  username: <username> # 設定したMySQL Accountと同一のもの
  password: <password> # 設定したMySQL Accountと同一のもの
  host: localhost

development:
  <<: *default
  database: appname_development # appnameのところは、rails new時のappnameになっているはずです。
test:
  <<: *default
  database: appname_test # appnameのところは、rails new時のappnameになっているはずです。
```

#12 rails db:createでデータベースを作成

```
$ cd appname
$ rails db:create
```
#13 foreman+Procrile

```diff:Gemfile

group :development do
  ...
+ gem 'foreman'
end
```
追記が終わったら`bundle install`を実行してください。

設定用のProcfileをアプリケーションルートに作成し、実行内容を記載します。

```:Procfile
rails: bundle exec rails server
webpack: ./bin/webpack-dev-server
```
```bash
$ foreman start
```
tech-unlimited.comでSSL証明書と中間証明書の内容が正しいか確認する

### tech-unlimited.comでSSL証明書と中間証明書の内容が正しいか確認する
　以下のサイトを利用して、各証明書の内容を確かめる。

SSL証明書(crt) 内容確認ツール
https://tech-unlimited.com/parsecrt.html
### SSL証明書
　上記サイトで確認する内容は以下の通り。

・証明組織のコモンネームが対象のドメインネームになっていることを確認する
・有効期限が想定通りの期間になっているかを確認する
・発行組織が想定通りの機関が発行したことになっているかを確認する
### 中間証明書
　上記サイトで確認する内容は以下の通り。

・中間証明書が証明するSSL証明書の発行組織と中間証明書の証明組織が一緒になっていることを確認する
・発行組織のコモンネームが想定通りのroot機関になっていることを確認する
対応ブラウザをIEからChromeに変更する時の注意点その４(IME制御)

# 対応ブラウザをIEからChromeに変更する時の注意点その４(IME制御)

対応ブラウザをIEからChromeに変更する時の注意点について備忘録的に記載します。

# 発生問題点
IE使用時はime-modeプロパティによりIME制御を行っていたがChromeでは対応
していないためIME制御ができなくなった。
そのため、ime-modeプロパティの代替方法が無いか調査した。


# 環境
* <font color="Green">__OSはWindows10__</font>
	* バージョン：1803(OSビルド17134.407)

* <font color="Green">__Microsoft Internet Explorer__</font>
	* バージョン：11.407.17134.0
	* 更新バージョン：11.0.95(BK4466536)

* <font color="Green">__Google Chrome__</font>
	* バージョン：76.0.3809.100(Official Build) (64ビット)

# 調査結果
inactive(IMEオフ)の代替となり得る方法が以下2種類あった。
inactive以外(active(IMEオン)、disabled(IME完全オフ))の代替方法は見当たらなかった。
そもそも、世間一般ではIMEの変更はユーザに任せる(制御は行わない)方向らしい。


1.inputmode属性を使用する
試してみたが、現時点では期待する動作にならなかった。
→この方法はNG
参考URL
https://allabout.co.jp/gm/gc/23804/#aa23804-inputmode

2.input typeのtelを使う
telを使用するとIMEをオフにしてくれました。(inactiveと同様の動きになったが結構ダーティな方法らしい)
ただし、この方法はテキストのみ対象でテキストエリアは対応できない。
参考URL
http://reviews.f-tools.net/Site-Making/Chrome-IME-ON-OFF.html
kafka rest proxy

（重要）ただの推測で裏取りが出来ているわけではない話なので、そのつもりで読んでください。

Kafka rest proxy でメッセージを Produce する際は、一般的には次のように送り込んでいると思う。

```bash
$ curl -X POST http://localhost:8082/topics/name \
    -H Content-Type:application/vnd.kafka.json.v2+json \
    --data '{"records":[{"value":"test"}]}'
```

上の例では json として埋め込んでいるけれども、binary として埋め込むこともできる。

```
$ curl -X POST http://localhost:8082/topics/name \
    -H Content-Type:application/vnd.kafka.binary.v2+json \
    --data '{"records":[{"value":"dGVzdAo="}]}'
```

[公式ドキュメント](https://docs.confluent.io/platform/current/kafka-rest/api.html#content-types)では、そのほかのパターンも記載されている。もっと言うと `application/json` も後方互換性として残されていると記載されている。ところがメッセージを Produce する際にはこれは**使えない**。**なぜだろうか**。

[ソースコード](https://github.com/confluentinc/kafka-rest/blob/master/kafka-rest/src/main/java/io/confluent/kafkarest/Versions.java#L47)を眺めると、次のように書いてある。

```
  // These are defaults that track the most recent API version. These should always be specified
  // anywhere the latest version is produced/consumed.
  public static final String JSON = "application/json";
```

現行の API では使えそうな雰囲気をだしている。ドキュメントに戻ると、省略時は embed は binary と解釈すると書かれているので、上の二つ目の例の形で良さそうだが、動作しない。

解釈をすすめると most recent API というのは、ひょっとすると V3 API のことを指すのかもしれない。おそらく most recent API と書いた人は、バージョンが上がるたびに API セット全体が更新されるイメージを持って書いていたようだ。ところが実際の V3 API は API セット全体を更新するものではなく、既存の API に cluster 操作を追加した増築部分を指している。おそらくここでねじれたと思われる。`application/json` は V2 API では使用できなくなり、よって後方互換性もなくなった、と。残念。
【前回から続いて】Google Colaboratoryで簡単な画像処理してみました。#２

前回に続いて画像処理を行いたいと思います。

#使用環境
- [google colaboratory](https://colab.research.google.com/notebooks/intro.ipynb#)
- OpenCV

#輪郭抽出
今回は、前回の内容を用いて輪郭抽出を行いたいと思います。
これが、今回作成したプログラムになります。

```python:輪郭抽出
import cv2
import numpy as np
from matplotlib import pyplot as plt

src = cv2.imread(img)
#numpy配列化
pixels = np.array(src)
#グレースケール化
plt.gray()
img_gray = cv2.cvtColor(pixels, cv2.COLOR_BGR2GRAY)
#二値化
retval, img_binary = cv2.threshold(img_gray,128, 255, cv2.THRESH_BINARY)
#輪郭抽出
contours,hierarchy=cv2.findContours(img_binary,cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) 
#抽出した輪郭をオリジナルの画像に描画
img_binary = cv2.drawContours(src, contours, -1, (0,255,0), 8)
#画像の表示
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.imshow(cv2.cvtColor(img_binary, cv2.COLOR_BGR2RGB))
ax1.axis('off')
plt.show()
plt.close()

```

二値化のしきい値は、画像によって任意で設定してください。

##引数の解説
`cv2.findContours`は、輪郭を抽出するためのOpenCVの引数です。

第二引数に`cv2.RETR_LIST`とすることで、全輪郭を探査することが可能になります。
また、ここの引数に`RETR_EXTERNAL`とすることで、最も外側にある輪郭を表示することができます。

`cv2.drawContours`で、抽出した輪郭を描画することができます。今回のプログラムでは、オリジナルの画像に描画しています。

`-1, (0,255,0), 8`の、`-1`はすべての輪郭の表示を表しています。この数値を変えていくと`0,1`などに対応する輪郭を1つずつ表示することができます。`8`は、このプログラムで使用した画像には、8つの輪郭が存在しました。したがって8にしています。今回の使用した画像には、-1（全描画）を含めて、0~7までの輪郭が存在しました。ここは、画像によって調整してください。`(0,255,0)`はBGRを表しており、今回は、輪郭を緑にして、描画しています。
Laravel環境構築の個人的メモ


①xamppインストール
apache,MySQL起動しておく
②cd C:\xampp\htdocs
③composer create-project laravel/laravel=6.x フォルダ名
④git cloneで持ってきたフォルダに③をコピーして上書き
⑤③のファイルを適当にリネーム
⑥WindowsPowerShellでhtdocsに移動してcmdモード
⑦シンボリックリンクを作成
```mklink /D .\フォルダ名 [git clone先フォルダへのフルパス]```
⑧リンク先が表示されることを確認
⑨git 差分を解消
⑩フォルダのディレクトリでvscodeターミナルからphp artisan serve

migrationとseederの設定を行う


LaravelにてDBの構成が変更になった時の手順メモ
キャッシュクリア手順
SQLSTATE Access denied for user 'root'@'localhost'(using password;No)が出た時
```php artisan cache:clear```
```php artisan config:cache```


テーブルの型が変更になった時にロールバックしてシーダーを流す必要がありそう？
(よくわかってないけどとりあえずこれでうまくいってるのでメモ)
```php artisan migrate:rollback  --path=database/migrations_**** --database=mysql_private
php artisan migrate --path=database/migrations_**** --database=mysql_private
php artisan db:seed
```
Laravel 独自のTraitが読み込まれない場合に確認してみたこと


Laravelで `Trait 'App\Traits\CustomTrait' not found` というエラーが出て、
何回コードを見ても絶対あっているはずなのに、not foundと言われます。

その際に確認することをメモとして残しておきます。

※コメントでご指摘をいただいていますので、そちらも併せて見てください！


# `/vendor/composer/autoload_classmap.php`をみる

TraitのディレクトリがAutoloadに読み込まれているか確認します。
（autoloadは名前空間とパスの対応表みたいな感じになっています。）


僕の場合はTraitを置いていたパスが `app\Trait`でした。

そのファイルの中に、下記の文言があるか確認します。

```php

App\\Trait\\CustomTrait
```

ここでファイルの中に存在する場合は、ただのコードのミスのような気がしますが、
僕の場合はここに記述がありませんでした。


# `composer.json` に追記する

composer.jsonのautoloadの部分に、Traitを置いているディレクトリを追記します。

```php

"autoload": {
    "classmap": [
        "database/seeds",
        "database/factories",
        "app/Trait"  // これを追記する
    ],
    "psr-4": {
        "App\\": "app/"
    }
},
```

# composer dump-autoload をする

composer dump-autoloadで設定を更新します。

```php
composer dump-autoload
```


これで、Traitがみつかるようになりました！！



# おわりに

なかなかいろいろ調べて、解決するのが大変でしたので、
他の方の支えになれば幸いです。
Dockerコンテナからメール送信 (sSMTP)

## セットアップ

コンテナからメール送信するにはssmtpを使うのが簡単だった。

```sh:インストール
apk add ssmtp
```

```diff:/etc/ssmtp/ssmtp.conf
- mailhub=
+ mailhub=リレーサーバー名
```


## Gmailの設定例

* https://wiki.archlinux.jp/index.php/SSMTP

```go:/etc/ssmtp/ssmtp.conf
mailhub=smtp.gmail.com:587
rewriteDomain=gmail.com
hostname=gmail.com
AuthMethod=LOGIN
UseSTARTTLS=YES
FromLineOverride=YES
TLS_CA_File=/etc/pki/tls/certs/ca-bundle.crt

root=アカウント名@gmail.com
AuthUser=アカウント名@gmail.com
AuthPass=アカウントのパスワード
```

```sh:ubuntuの場合
# 設定
update-alternatives --set mta /usr/sbin/sendmail.ssmtp

# 確認
update-alternatives --display mta
```

### Gmailからリレー拒否された場合

1. [2 段階認証プロセスを無効にする - パソコン - Google アカウント ヘルプ](https://support.google.com/accounts/answer/1064203?co=GENIE.Platform%3DDesktop&hl=ja)
2. [安全性の低いアプリのアクセス「有効」に変更](https://myaccount.google.com/lesssecureapps)
【Ruby】継承チェーンとは？意外と知らない人も多いので解説してみた！

Rubyの学習歴がまだ浅い人の中には、継承チェーンについて知らない人も多くいるのではないでしょうか。

Rubyの深い理解が必要なプログラムを書くためには、継承チェーンについての理解は必須だ。

私は、Rubyを学習していく過程で、そのように強く感じました。

## 継承チェーンとは

継承チェーンとは、クラスの連なりのようなものです。

クラスにはスーパークラスがあります。そして、スーパークラスをたどっていくと、BasicObjectまでたどり着きます。

この連なりのことを継承チェーンと言います。

例えば、以下のコードがあるとします。

```ruby
class ClassA

end

class ClassB < ClassA

end
```

ClassBはClassAを継承しているので、ClassBのスーパークラスはClasssAということになります。

では、ClassAのスーパークラスはなんでしょうか。

答えはObjectです。

そして、ObjectはBasicObjectを継承しています(Kernelに関しては説明を簡単にするために省略させていただきます。)。

この道のりを継承チェーンと言います。

## 継承チェーンを理解する重要性

では、これを理解したからと言って、何ができるようになるのでしょうか。

それは、メソッドがどのように実行されているかを知るとわかります。

Rubyのメソッドがよびだされた時、Rubyはまず現在のクラスを確認します。

そして、そこに呼び出されたメソッドがない場合、スーパークラスを確認して、そのメソッドがないか確認します。

それでもない場合は、同じようにまた次のスーパークラスへと移っていきます。

Rubyは継承チェーンをたどって呼び出されたメソッドを解釈しているわけです。

これを理解しておくと、Rubyの理解に大いに役に立ちます。

## まとめ

今回は継承チェーンについてみたのですが、しっかりと伝わりましたでしょうか。

記事の内容をまとめると、継承チェーンとは、現在のクラスからたどるスーパークラスたちの連なりということです。

Rubyはメソッドを実行する際に、継承チェーンをたどってメソッドを発見します。

もし何かあればコメントをくださると、私自身の成長にもつながりますので、是非是非よろしくお願いします！