OmniAICreator/Qiita-1.07M huggingface dataset:
cross-fields validation

[go-playground/validator.v9](https://pkg.go.dev/gopkg.in/go-playground/validator.v9)を使って、CustomバリデーションはMininのStructの場合、メモしました。
----

```go
package main

import (
	"fmt"

	"gopkg.in/go-playground/validator.v9"
)

type A struct {
	String string `validate:"required"`
}
type B struct {
	Int int64 `validate:"custom=A.String"`
}
type C struct {
	A
	B
}

func main() {
	v := validator.New()
	v.RegisterValidation("custom", customFunc)
	c := &C{}
	// Key: 'C.B.Int' Error:Field validation for 'Int' failed on the 'custom' tag
	c.String = "hoge"
	c.Int = 3
	err := v.Struct(c)
	fmt.Println(err)
	// nil
	c.String = "foo"
	c.Int = 3
	err = v.Struct(c)
	fmt.Println(err)
}

func customFunc(fl validator.FieldLevel) bool {
	param := fl.Param()
	field, _, _, found := fl.GetStructFieldOKAdvanced2(fl.Top(), param)
	return found && int(fl.Field().Int()) == len(field.String())
}

```

https://play.golang.org/p/pNGZISzVhCC

https://github.com/go-playground/validator/blob/c68441b7f4748b48ad9a0c9a79d346019730e207/baked_in.go#L1337
Rest API コンポーネントを使用したデータ統合: Similarweb編

SimilarWeb（シミラーウェブ）という製品をご存知でしょうか？

デジタルのマーケットとそこでの競合他社のスタッツについて調査し、意思決定に必要な情報を提供してくれる製品です。SimilarWebのサイトでは
>SimilarWebはデジタル世界の地図です。これで主要な競合他社を迅速に特定し、トレンドを正確に掴み、業界トップのパフォーマンスに対して自社をベンチマークすることができます

とあります。SimilarWeb（シミラーウェブ）を使うことで競合サイトとの比較やあるキーワードで他社は自社と比較してどれくらいの流入を取れているか？などの質問に回答することが出来ます。

今回は、XplentyからSimilarWebのAPIを利用して、どのようにデータを取得し、加工することができるかについてご紹介します。

**1. SimilarWeb APIについて**
**2. Xplentyでパッケージを作成する**
**3. まとめ**


#1. SimilarWeb APIについて
まずAPIの仕様について、こちらのサイトから確認しました。

今回の記事で利用するAPIは以下の2種類です。

- Desktop Keyword Analysis > Keyword Competitors (Organic)

- Desktop Keyword Analysis > Keyword Competitors (Paid)



サイトには取得されるJSONのサンプルデータがあり、上記のAPIで取得できる項目は以下のようなものがあります。
`{
      "search_term": "wooden door",
      "share": 0.00004544731546152074,
      "visits": 190.59609562344377,
      "change": -0.4384225611154365,
      "volume": 0,
      "cpc": 0,
      "url": "N/A",
      "position": 0
    },`



| 項目       |       説明 |  
|:-----------------|------------------:|
| search_term             |              検索キーワード | 
| share           |            シェア |
| visits             |              訪問回数 | 
| volume               |               検索ボリューム |
| cpc             |             クリックあたりの単価 |
| position          |           掲載順位 | 

#2. Xplentyでパッケージ作成
ここからは、Xplentyを使用して実際にパッケージを作成する手順について紹介します。

###Step1 データ接続：Rest APIコンポーネントを使用する

Rest APIコンポーネントを使用し、今回使用するAPIのエンドポイント（Desktop Keyword Analysis > Keyword Competitors (Organic)）のURLを設定画面に入力します。

その際、分析するサイトおよびAPIキーを含むパラメータをセットします。

例）サイトのキーワードやシェアを取得する場合
`https://api.similarweb.com/v1/website/xxxxx.com/traffic-sources/organic-search?api_key=xxxxx&start_date=2019-01&end_date=2019-01&country=jp&limit=100000&main_domain_only=false&format=json`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/4ac976bc-ed9b-ca47-1382-fd571e33cdac.png)



プレビューを見ると、データは以下のような構造で取得できました。

今回のブログで使用するのは、「meta」と「serach」になります。

「meta」は、指定した条件が格納されたメタ情報です。主にmeta>requestに必要なメタ情報が格納されています。

「search」には、流入キーワードやシェアや訪問回数が多いもの順に配列データとしてBAG形式で取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/9f08450f-6f40-82ab-7329-2d0eae7e5c20.png)


###Step2 変換：Selectコンポーネントを利用し、取得されたデータを加工する

加工する際のステップとしては２段階で行います。

1. meta > searchに格納されたデータを項目ごとにそれぞれ取得する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/f2b4dec4-bbac-264c-ff5e-e2273ad843c9.png)

2.searchに格納された検索キーワードやシェアを取得する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/6c2b72ff-dd5f-e8bb-9e65-0c40305443a3.png)

###Step3 ロード：Amazon S3にCSVファイルとして出力する


今回はS3に出力します。（S3への出力の設定方法については、今回は割愛します。）

最終的なパッケージは以下のようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/010b6407-5350-e504-93c9-4c1f6072c601.png)


#3. まとめ
様々なクラウドにおいてAPIで公開される標準的なデータフォーマットとしてJSONは一般的ですが、Xplnetyを使えばJSON形式のデータもプログラミングせずに少しの関数を利用するだけで簡単に加工し、データウェアハウスやストレージにロードすることが出来ます。

Xplentyでは[こちらのページ](https://www.xplenty.com/integrations/)で紹介されている統合対象のデータソース以外にも、今回紹介したようなSimilarwebなど様々なデータに接続可能です。詳細は[HP](https://www.xplenty.com/jp)のチャットより問い合わせてみてください。
HTMLのレイアウト調整基礎

HTMLは1つのブロック（画面）をさらに細かいブロックに分けたり（ブロック要素）、そのブロックの中に文字等を並べる（インライン要素）ことができるプログラミング言語。また、CSS言語を用いることでその見た目を思い通りにできる。  

と僕は理解しています。


#ブロック要素
「div」や「h1」などを用いて**記述可能領域**を形成し、文書等を表現する要素
###特徴

-ブロック要素の前後に改行が入り、要素同士は縦に整列
-横幅や高さを設定可能
-ブロックの外側余白（margin）や内側余白（padding）を設定可能


#インライン要素
「a」や「span」などを用いて**ブロック要素内における**文書等を**横並び**に表現する要素

###特徴
-インライン要素の前後に改行は入らず、要素同士は横並びに整列
-ブロック要素内に横並びに記述する要素であるため、**横幅や高さ、余白を設定できない**


#2つの要素を使いこなすために
CSSの「display」や「float」プロパティを用いることで、レイアウトを調整可能

CCCプロパティ|項目|意味|特徴
---|---|---|---
float:|left|要素が左に流れ、後続の要素が右側に回り込む|「clear:both」「cleat:○○」を用いることで、流れ込みを防げる
||right|要素が右に流れ、後続の要素が左側に回り込む|上と同様
display:|inline|要素がインライン化
||block|要素がブロック要素化
||inline-block|要素がインライン要素とブロック要素両方の特徴を持つ
||none|非表示にする
||flex|親要素に指定すると、子要素が横並びになる|フレックスボックスで検索




#参考
[WEBST](https://webst8.com/blog/css-display/)
[crwive](https://creive.me/archives/13552/)
【Swift】サブスクリプトを公式ドキュメントを元にまとめてみた

#サブスクリプトとは？？

クラス構造体列挙体は、コレクション、リストまたはシーケンスのメンバー要素にアクセスするためのショートカットである添え字を定義できます。

つまり**サブスクリプトとは型が配列等の要素にアクセスするためのショートカットのこと！**

###何がメリットなのか

使用することによって、値の取得・設定をしたい時にわざわざメソッドを用いる必要がなくなり、サブスクリプトのインデックスの値によって行えることです！


###構文

クラス・構造体・列挙体の中で、`subscript(引数)->戻り値{return ~~}`という構文で記述します。

下のコード例では、
`threeTimesTable[6]`により、TimesTable内の`subscriptのindex`に6が代入され、戻り値を返します。


```Swift:Syntax
struct TimesTable{
    let multiplier: Int
    subscript(index: Int) -> Int{ //indexには6がはいる
        return multiplier * index //read-only
    }
}

let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])") //threeTimesTable[6]がサブスク!
```

##サブスクの特徴1「複数のパラメーターを持てる」

サブスクリプトは、複数のパラメータを持つことができます!

下のコード例では、` subscript(row:Int, column:Int)`とあるように2つのパラメータを持ってます。

```Swift:multipleSubscrip

struct Matrix{
    let rows: Int, columns: Int
    var grid: [Double]
    init(rows:Int, columns:Int){
        self.rows = rows
        self.columns = columns
        grid = Array(repeating: 0.0, count: rows * columns)
    }
    func indexIsValid(row: Int, column:Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row:Int, column:Int) -> Double{
        get{
            assert(indexIsValid(row: row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set{
            assert(indexIsValid(row: row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue  //サブスクで渡された値を元にgrid[]を更新
        }
    }
}

var matrix = Matrix(rows: 2, columns: 2)
print(matrix)  //サブスク前の出力：Matrix(rows: 2, columns: 2, grid: [0.0, 0.0, 0.0, 0.0])

matrix[0,1] = 1.5  //サブスク
matrix[1,0] = 2.5  //サブスク
print(matrix)　//サブスク後の出力：Matrix(rows: 2, columns: 2, grid: [0.0, 1.5, 2.5, 0.0])

```

ちなみに、
`assert(indexIsValid(row: row, column: column), "Index out of range")`
については、初めてみたのでここに軽くassertについてメモしときます。

```text
assert → 条件をチェックしfalseの場合はエラーとなる
構文：assert(条件式(Bool),"エラーメッセージ")
```

##サブスクの特徴2「タイプに直接紐づけられる」

タイププロパティのように、タイプに直接紐づけることができます。
これまで紹介してきたサブスクは全てインスタンスサブスクです。
インスタンスに対して添え字を用いてますね。
`threeTimesTable[6]`
`matrix[0,1] = 1.5`

タイプサブスクリプトは、その名の通り、`staticキーワード`を用いることで`タイプ[0]`のようにタイプに直接サブスクを使えます！

```Swift:TypeSubscript
enum Planet: Int {
    case mercury = 1, vanus, earth, mars, jupiter, saturn, uranus, neptune
    static subscript(n: Int) -> Planet{
        return Planet(rawValue: n)!
    }
}

let mars = Planet[4]
print(mars)
```
【備忘録】Rails3ルーティング確認

# はじめに
今回はタイトルの通りにRailsにおけるルーティングの確認方法を残します。
触れているシステムのバージョンが古いため、Webブラウザでの確認が出来ずに詰まりました・・・。

# 環境
Rails 3.0.19
docker-compose version 2

## Dockerコンテナからコマンドで確認する
### 1. サービス用コンテナを起動する

```
docker-compose up -d
```
-d：デタッチド・モード: バックグラウンドでコンテナを実行し、新しいコンテナ名を表示

### 2. railsがインストールされているコンテナに入る（今回はappコンテナ）

```
docker-compose run app /bin/bash
```

dockerやRailsにバージョンによって、コマンドが変わります。
直近で多く見られるコマンドは以下の通り。

```
docker-compose exec app bash
```

### 3. ルーティング確認コマンドを実行する
```
[root@[コンテナID] trunk]# bundle exec rake routes
```

上記コマンドですと全件出力されてしまい見づらいため、grepコマンドを利用すると見やすいです。

```
[root@[コンテナID] trunk]# bundle exec rake routes | grep [絞り込みたい文字列]
```


## 参考
[Docker ドキュメント日本語化プロジェクト](http://docs.docker.jp/compose/reference/up.html)
[docker-composeコマンド]
(https://qiita.com/nikadon/items/995c5705ff1171f7484d)
6809にもあるエッチな名前の符号拡張をCで書いてみた

モトローラの８bitCPU 6809にはSEXという命令があります。
Sign EXtensionの略で、「8ビットアキュームレーター(B)の内容を符号付きで16ビットに拡張し、上位A、下位Bレジスターとして16ビットに連結したアキュームレーター(D)に格納する。」というものです。OPコードは0x1Dです。

任意ビットで符号拡張するコードをCで書いてみました。
2進数nbit(1<=n<=63)の数を64bitに、符号付き拡張をします。

Ver 1.1 fujitanozomu氏による指摘で、nビットを超える数が、a,bに与えられた場合を考慮して書き換え。

```sex.c
/*
   SEX Sign EXtend
   符号拡張
 */

#include    <stdio.h>

/* long sex(long a,int bitn)
 * input:  bitn 何ビット目で符号拡張するか
 *         a    被演算数
 *
 * output: 符号拡張された結果
 *
 */
long sex(long a,int bitn) {
    unsigned long p=-1;
    long r;

    r=(a&~(p<<bitn))|(a>>(bitn-1)&1?p<<bitn:0);

    return(r);
}

int main()
{
    long a=0xc0ffee;     /* 24 bit の負の値 */
    long b=0x7fffff;     /* 24 bit の正の値 */
    long r1,r2;          /* 結果を格納する変数 */

    r1 = sex(a,24);
    r2 = sex(b,24);
    printf("%ld %ld %016lx %016lx\n",a,r1,a,r1);
    printf("%ld %ld %016lx %016lx\n",b,r2,b,r2);
}

```

実行結果

```
12648430 -4128786 0000000000c0ffee ffffffffffc0ffee
8388607 8388607 00000000007fffff 00000000007fffff
```
【Java】BeanValidationに存在するアノテーションの実装クラスはどこにあるのか

## 背景
JavaやSpringでバリデーションを実装する際には`@NotNull`や`@NotBlank`といったBeanValidationを用いることがあると思います。

実装をしている際に、これらのアノテーションに紐づいている実装クラスはどのようになっているのだろうかと思い、ソースコードを見てみたのですが、`@Constraint`のvalidatedByが空白でした。

javax.validation.constraintsパッケージのNotBlankアノテーション[^1]を例に出しておきます。

```java:NotBlank.java
@Documented
@Constraint(validatedBy = { }) // ←でバリデーションの中身が書かれたクラスが指定されていない
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(List.class)
public @interface NotBlank {

	String message() default "{javax.validation.constraints.NotBlank.message}";

	Class<?>[] groups() default { };

	Class<? extends Payload>[] payload() default { };

	/**
	 * Defines several {@code @NotBlank} constraints on the same element.
	 *
	 * @see NotBlank
	 */
	@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
	@Retention(RUNTIME)
	@Documented
	public @interface List {
		NotBlank[] value();
	}
}

```

今回はこのアノテーションの実装結果の場所と紐付けをしているクラスを調べました。

## 調査結果
Googleで検索してみると、[こちら](https://stackoverflow.com/questions/36477544/javax-validation-implementation)のstackoverflowで同様の質問がされており、実装クラスを知ることができました。

それが[こちら](https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/NotBlankValidator.java)のorg.hibernate.validator.internal.constraintvalidators.bv配下のNotBlankValidatorクラスです。

このことからアノテーションとその実装クラスは同じライブラリではなく、別のライブラリに存在しているということがわかりました。

また、これらを紐付けているクラスは実装クラスと同じライブラリに存在し、[こちら](https://github.com/hibernate/hibernate-validator/blob/db7ae586508add6491f1443c8ab4e770d7cb2c20/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java)のorg.hibernate.validator.internal.metadata.core配下のConstraintHelperクラスで紐づけられていることがわかりました。

## まとめ
今回、BeanValidationのjavax.validation.constraintsに存在するアノテーションの実装クラスはorg.hibernate.validator.internal.constraintvalidators.bv配下に存在しているということがわかりました。

また、これらのクラスはorg.hibernate.validator.internal.metadata.core配下のConstraintHelperクラスで紐づけられていることがわかりました。

ただ、なぜアノテーションと実装クラスがわざわざ別のライブラリに存在しているのかがわかっていません。
BeanValidationとHibernateの関係性が関わっていそうな雰囲気はしますが、拡張性を考慮してインターフェースと実装を分けるような感覚なのでしょうか？

この点に関してご存知の方がいらっしゃいましたらご教示いただけますと幸いです。

最後までお読みいただき、ありがとうございました。

## 参考文献
[解決のきっかけになったサイト](https://stackoverflow.com/questions/36477544/javax-validation-implementation)

[NotBlankValidator.java](https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/NotBlankValidator.java)

[ConstraintHelper.java](https://github.com/hibernate/hibernate-validator/blob/db7ae586508add6491f1443c8ab4e770d7cb2c20/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java)

[^1]: jakarta.validation-api-2.0.1
【Java】MapのputIfAbsentメソッドをIntelliJ IDEAに教えてもらった話

## 背景
既存のレガシーコードを改善していく過程で、IntelliJからの警告を減らすようにしていました。

その際に「Mapに対してkeyの値がnullだった場合、値を設定する」という処理があったのですが、それに対するIntelliJからの指摘が勉強になったので、今回記事にしました。

## 具体例(before)
例えば以下のような都道府県名と県庁所在地を持つMapが存在していたとします。

```java
Map<String, String> prefectures = new HashMap<>();
prefectures.put("茨城県", "水戸");
prefectures.put("栃木県", "宇都宮");
prefectures.put("群馬県", null);
```

現在、key群馬県はvalueがnullになっており、ここに値を設定したいとします。
この時既存の実装では以下のような方法で値を設定していました。

```java

if (prefectures.get("群馬県") == null) {
    prefectures.put("群馬県", "前橋");
}
```

この方法に対してIntelliJはputIfAbsentメソッドでよりシンプルに書けると提案してくれました。

## 具体例(After)
putIfAbsentメソッドはまさに上記のようなkeyがnullだった場合に値を設定してくれるメソッドで、このメソッドを用いると、先ほどの例のようなif文はなくなり、

```java

prefectures.putIfAbsent("群馬県", "前橋");
```
と1行でスッキリ書くことができます。

このメソッドの存在を知らなかったので、簡単ではありますが、こうして今回記事にしました。

## まとめ
「Mapに対してkeyの値がnullだった場合、値を設定する」という処理をする場合、if文を使わなくてもputIfAbsentメソッドを用いればスッキリと書くことができます。

今回このような提案までしてくれるIntelliJは凄いと改めて思いましたが、こうした便利なメソッドをどのように知れば良いのだろうかとも思いました。

「JavaDocで調べるついでに眺めてみる」、「JDKのリリースノートを読む」以外に良い方法があれば、ご教示いただけますと幸いです。

少しでもこの記事が誰かの役に立てば幸いです。最後までお読みいただきありがとうございました。

## 参考文献
[putIfAbsentメソッドのJavaDoc](https://docs.oracle.com/javase/jp/8/docs/api/java/util/HashMap.html#putIfAbsent-K-V-)
【Java】文字列から特定の文字を消す方法

## はじめに
タイトルのとおり、業務において文字列から特定の文字を消す必要がありました。

その処理をどのように行ったのかを簡単ではありますが記事にしました。

## 実装例
今回{}で括られている文字列から{}を消したいとします。

この時下記のようにStringクラスのreplaceメソッドを用いれば、{}を消すことができます。

```java:sample.java
public class Main {
    public static void main(String[] args) throws Exception {
        String test = "{test}";

        String result = test.replace("{", "").replace("}", "");

        System.out.println(result); // test が出力される

        System.out.println(result.length()); // 4 が出力される
    }
}

```

replaceの第一引数に消したい文字を指定し、第二引数に空文字を渡すことで特定の文字の消去を実現しています。

## まとめ
文字列から特定の文字を消すにはStringクラスのreplaceメソッドを用い、第一引数に消したい文字列、第二引数に空文字を渡すことで、実現することができます。

よりスマートな方法があれば、ご教示いただけますと幸いです。

この記事が少しでも誰かの役に立てれば幸いです。
最後までお読みいただきありがとうございました。

## 参考文献
[replaceメソッドのJavaDoc](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/String.html#replace-char-char-)
【AWS】IAMの作業用ユーザー作成方法等

# はじめに
現在、AWSについてudemyの教材を用いて勉強中です。
IAMについて学習しましたので、本記事にてアウトプットします。

# IAMとは？
「Identity and Access Management」の略称。
AWSのサービスを利用するユーザー権限を管理するサービスになります。
※WindowsServerで言う「Active Directory」になります。


# ベストプラクティス
AWSの公式ドキュメントによると、AWSアカウントのルートユーザーを使用することはNGであるとのこと。
AWSアカウントとは別に下記を作成することがベストプラクティスであるとのこと。

**担当者ごとの管理者権限付きIAMユーザー**

# 管理者IAMユーザー作成方法

画像付きで解説していきます。

①AWSアカウントのルートユーザーにてログイン後、「サービス」→「IAM」を選択。
![1-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/bfbf6e87-e914-6b7f-8f49-3837972ac4cc.jpeg)


②「ユーザー」を選択

![2-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/f1a6cd51-7229-1d74-42b6-ecc42d8e2b50.jpeg)

③「ユーザーを追加」を選択

![3-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/e88b09a4-79b8-cf61-7c5f-e0e0691e8850.jpeg)

④必要情報を入力

下記画像の赤枠のように入力

![5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/2c67094e-7ee3-f816-0f9f-61f72f4645b6.jpeg)

**項目:**

- ユーザー名  
 **ユーザー名を入力**
- アクセスの種類  
**「AWSマネジメントコンソールへのアクセス」にチェック**
- コンソールのパスワード  
**今回は「カスタムパスワード」を入力**
- パスワードのリセットが必要  
**今回はチェックを外す**

入力完了後、「次のステップ」をクリック

　　
⑤「グループの作成」をクリック

![13-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/c5f360d6-33e1-82d0-d69d-1fad2ff10279.jpeg)


⑥「グループ名」に「Administorators」を入力し、ポリシー名の「AdministratorAccess」にチェックを入れる。

その後に「グループの作成」をクリック。

![14-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/6fe42b12-be15-1b99-a846-12bf35f5752f.jpeg)

⑦「Administrators」が作成されることを確認。「次のステップ」をクリック。

![15-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/c2ceb678-0524-0865-880e-23266c8bb53f.jpeg)

⑧タグは未入力のまま「次のステップ」をクリック。

![16-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/026426f6-659a-de63-1af2-9aadf177e0c9.jpeg)

⑨必要情報を確認し、「ユーザーの作成」をクリック


![20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/9ff3175a-68cf-ef5b-993a-569a2b1ab461.jpeg)

⑩IAMユーザーの作成が成功したことを確認

下記について、ログイン時に必要な情報のため控えるか保存しておく。
**・サインインURL(赤枠の部分)**
**・csvのダウンロード**

![21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/bfc9249c-e78b-3ac6-00f2-11ba0f8f3ef9.jpeg)


※実際にログインしたページはこちらになります。
![19.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/ccc824ef-59f1-902c-593a-baca49c8f3ee.jpeg)



# 参考

最初の IAM 管理者のユーザーおよびグループの作成
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/getting-started_create-admin-group.html
PHPとJavaScriptの違いまとめ（主要項目の対比表）

#PHPとJavaScriptの違いまとめ（主要項目の対比表）
PHPとJacaScriptのメソッドなど主要項目の違いまとめ。
どっちがどっちかわからくなるの防止。

「←」はPHPの記述と同じ。


<br>

| 項目 | PHP | JavaScript |
|:-:|:-:|:-:|
| 変数 *1  | $変数名  | var/let/const 変数名 |
| 関数 | function 関数名(){}  | function 関数名(){}; |
| アロー関数 *2 | fn()=>処理 | ()=>{}; |
| 引数 | $仮引数名 | 仮引数名 |
| 処理の終わり  | ; | ← |
| コメントアウト  | // or /* */ | ← |
| クラス定義  | class クラス名{} | ← | 
| コンストラクタ  | アクセス権 function \_\_construct(){} | constructor(){} |
| インスタンス  | new クラス名()  | ←  |
| プロパティ  |アクセス権 $プロパティ名  | const オブジェクト名 = {プロパティ名:値}  | 
| プロパティの呼び出し  | インスタンス->プロパティ名 | オブジェクト.プロパティ名 | 
| プロパティに関数をセット | なし | {プロパティ名:()=>{処理}}; |
| メソッド | アクセス権 function メソッド名()  | メソッド名(){} |
| インスタンス自身(メソッドのみ)  | $this | this |
| 自身のプロパティ呼び出し | $this->プロパティ名  | this.プロパティ名  |
| メソッド呼び出し | インスタンス->メソッド名()  | インスタンス.メソッド名() |
| 継承  | class クラス名 extends 親クラス名{}  | ← |
| クラスの使用許可| 不要 | export default クラス名 |
| クラス読込み  | require_once('ファイル名.拡張子')  |  import クラス名 from "./ファイル名" |
| コンストラクタのオーバーライド *3 | parent::__construct(); | super()  |
| 出力  | echo/print | console.log() |
| 配列の要素数  | count(配列) | 配列.length |
| 配列  | array()  | [] |
| キーあり配列  | array(キー名=>値) | {キー名:値} | 
| キーあり配列の値取得 *4  | 配列[キー名] | 配列.キー名 | 
| キーあり配列呼び名  | 連想配列  | オブジェクト | 
| for文  | for($変数=初期値; 条件式; ステップ){}  | ←  |
| 配列からひとつずつ抜き出す |foreach($変数名 as 配列) | 配列.forEach((変数名)=> {処理}); |
|if文 | if(条件式){}| ← |
|else if | elseif (条件式){} | else if (条件式){} |
|switch文 | switch(){case 条件: 処理; break;,,, default:}  | ← |
| 変数展開 *5 | "${変数}"| \`${変数}\` |
|and | &&/and  | ← |
|or | パイプ2本/or | ← |
|等しい| == | ===/== |
|異なる| != | !==/!= |
|インクリメント演算子 | ++ |← |
|デクリメント演算子 | -- |← |
|整数型に変換 |intval()  | perseInt()/Number() |
|文字列型に変換*6 |strval() |String()/ .toString() / +''|
|小数点に型変換 |floatval()  | parseFloat() |
|3桁区切り |number_format() | 数値.toLocaleString() |


*1. let：再宣言NG、const：定数(再宣言・再代入NG) 
*2. PHP：アロー関数は1行のみ。
　　JS：複数行OK。代入した変数が関数名になる(phpも)。
*3. JS：super()の引数は親クラスのコンストラクタの引数と合わせる
*4. JS：プロパティと呼ぶ 
*5. PHP：シングルクオテーションだと文字列として出力 
　　JS：バッククオート（shift+@）
*6. JS：空の文字列を足すと自動で文字列型に変換

JSはES6からクラスが使えるようになった。PHPと同じ処理で設定されている（クラスの生成、クラスの継承）。


<br>
PHPとJSは、PHPとPythonよりも似ている部分が多い。その分ちょっとした違いに注意が必要。（elseif と else ifとか）

＞ご参考：[phpとpythonの違いまとめ（対比表）](https://qiita.com/yuta-38/items/d167e57d41b18cc7984a)
数学学習ログ[0]

## 数学やり直し記録
2ヶ月ほど前数学のやり直しを始めた。中学数学をさらっと流し、高校数学も主要なところは軽く読み終えたところで、ふとその先の見通しに霧がかかった。勉強のやり方に対する不安や、そもそもの数学を学ぶモチベーションの低下などが発生。そんなタイミングでTwitterで<a href="https://twitter.com/arts_lib">lib-artsさん</a>お話させて頂く機会があり、メンターになって頂けることになった。週に1,2回ある程度まとまった文章で学習記録をつけることを勧めて頂いたのでここに記録を残すことに決めた。

## 方針
テキストは<a href="https://www.amazon.co.jp/dp/4799105345/ref=cm_sw_em_r_mt_dp_U_hoWWEb2VQ3S7H">ふたたびの高校数学</a>と<a href="https://lib-arts.booth.pm/items/1999302">やさしい数学入門</a>を併用。当面の学習手順などの指示を受けたので、それに従って進める。夜にやろうとすると仕事が遅くなったときに手がつかなくなりそだし、頭がフレッシュな状態で学んだ方がなんとなく良さそうなので、朝起床後に学習するルーティーンを確立できたらと思っている。また業務中隙間時間が頻繁に発生するので、そこで公式等の暗記もできればいいな。

※「やり直し」と書くと一回しっかり学んだ人が改めて学び直すというニュアンスに受け取られるかも知れないが、義務教育時の挫折ポイントはおそらく中2,中3レベルにあったので、私はほぼ初学者ですね。
jupyter-lab で複数ロボを制御

<div align="left">
<a href="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156757/66023a1a-489c-25a7-7258-1799ee3141c3.jpeg"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156757/66023a1a-489c-25a7-7258-1799ee3141c3.jpeg" width="252" height="179" alt="Crabs"></a>

<a href="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156757/70e24ae8-a956-c0fb-97ca-1df9611423d1.jpeg"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156757/70e24ae8-a956-c0fb-97ca-1df9611423d1.jpeg" width="252" height="179" alt="Crabs"></a>
</div>


# はじめに
　AIの開発環境として、pythonが多く使われています。特に開発環境では、VS-code, jupyter-labで開発されている方も多いのではないでしょうか？さらにAIの応用例として、Roboticsが上げられます。先に言っておきましょう、***```ロボは漢[おとこ]のロマンである```***と。

# SBCジャンキー
　SBCとはSingle Board Computerの略称です。ラズパイとかそんなのをイメージしてもらえば良いと思います。これ、自分がそうなのですが、新しいのを出るとつい買ったりしませんか？すぐに「勉強」とか「Armの新しいSoCには常に触れておかねば！」とか適当な理由を付けて買います。期末に予算が微妙に余ると、「じゃ、買っておくか!?」って感じで。SDにイメージを焼くとこまではやるんですが、その後は特に使うまでもなく。のべつまくなしに買うのも大人げないので、もっともらしいルールを自分の中で設けます。「64bit以上のSoCとOS」、「サイズはラズパイと同一」とか。でも、なぜか予算にはあまり縛りを設けず、割と高めのSBCを買ってしまったりします。最近だとJetson-Nanoとか…。

# 応用と運用のたたかい
　最初のうちは、Home-AutomationとかIoTの勉強とかをそれなりにやるんですが、SBCの増殖の方が導入より圧倒的に速く、運用が追いつかかなくなります。しまいには「なんで、こんなボード買ったんだろ？」ってなります。買ったのは自分なのに…。

# 意味のあるスケールとは?
　IoTをはじめとしたシステムのPoCが成功すると、二言目には「それ、スケールできるの？」って話になります。売上だったり、導入台数だったり、その時の営業やコンサルの立ち位置で文脈は変わりますが、PoCの後にこの言葉が来るのは皆さんの皮膚感覚でしょう。なぜかスケールが先に来て「投機的実行」がなされた皆さんのSBCを意味のあるものにしましょう。だからと言って、各SBCにセンサを１個だけ付けて、廊下に50cm毎に設置しても意味ないですよね？

# で、ロボ軍団
　数が多ければ多いほど楽しくうれしいのは軍団を作ることです。古では春秋戦国時代、現代では社内派閥がそれですね。個性に溢れた個で構成されていると魂が揺さぶられます。様々なSBCで構成されたロボ軍団はこの文脈をそのままトレース出来ます。ついでにセンサもつけちゃいましょう。赤外線とか紫外線とか温度とかも。熱源(赤外線)探知が出来るロボに索敵させて、ヘビー級ロボから発射されるミサイル攻撃。妄想が広がりまくリングですね。

![BlockDiagram_wifi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156757/d3eb6dfa-788b-025a-fe64-4f14c5fa0120.png)


# で、jupyter-lab
　やっとjupyter-labまで来ました。自分より皆さんのほうがjupyter-labには詳しいと思うので、そのものの説明はしません。応用例のみ、簡潔に記述します。一言で言うなら、
***```ロボットにそれぞれ、jupyter-labのサービスを実行させ、手元のPCに接続されたゲームコントローラで制御する。```***
　これを行うためには、FrontEnd(PC)のブラウザでゲームコントローラの入力値を読み取り、jupter-lab上で実行されているpythonスクリプトに入力値を渡し、ロボの動作にします。

# リアルタイム制御
　ロボをはじめとした組み込みシステムの制御になると、この言葉が不可分のように出てきます。誤解を恐れずに言えば、どんなシステムにも「```リアルタイム制御成分```」はあります。```リアルタイム制御```とは```リアルタイム性```が成立しているかどうかになります。```リアルタイム性```とは***その時間内での動作実行を運用上、許容出来るか、どうか？***になります。```Linux, クライアント・サーバ, インタプリタ```とリアルタイムとは程遠い三連コンボが今回のシステムです。

# Trade-off
　先程述べた```スケール```がPoC後の話なら、```Trade-off```は設計・開発・実装時に使われる言葉です。今回のシステムにももちろんあります。代表的な例としては、アナログスティックを切り捨てたことです。アナログスティックの読み取り速度(Sampling-rate)とイベントの発生回数(Frequency)が遅すぎました。ロボの移動速度についていけずに制御不能です。ここでのトレードオフとして、```リアルタイム性```を確保するためには、Sampling-rateとFrequencyを上げるか、ロボの移動速度を下げるしかありません。前者はシステムの構成上、不可能ですし、後者は利用していて面白く有りません。

# 最後に
　こんな中二病が結晶化したプロジェクトの顛末記を最後まで読んでいただいて、本当にありがとうございます。システムを作っているうちに、妄想が広がりました。ついでにリアルタムシステムの端緒を知っていただきたく書いてみました。

# 開発リソース
[Build guide:]
(https://gitlab.com/teamknox/groovy-quatro/-/wikis/Build-Guide:-Project-Crab-(Mecanum-Wheels-Rover)-in-Japanese)
[Firmware:]
(https://gitlab.com/teamknox/groovy-quatro)
[Control software:]
(https://gitlab.com/teamknox/q_rover/-/blob/master/teleoperationQ.ipynb)
[Groovy-Quatro:]
(http://www.omiya-giken.com/?page_id=3150)
2ステップで実装！Next.js初心者のための画面遷移

#1.はじめに
Next.jsを使い始めると「画面遷移処理ってどうするん？」って思って手が止まる人が多いのではないでしょうか？
なのでこの記事はNextの画面遷移がしっかり扱えるようにまとめておきました。

#2.なぜNext.jsで画面遷移を設定するのか？
まず初めにNextでなぜ画面遷移を設定するのでしょうか？
別に「aタグで記述しておけば、画面遷移するでしょう！」って考える人もいると思いますが実は違いがあるのです。

aタグはHTMLファイルを取得して全画面を表示していますが、Nextは前の画面と比較して異なる部分だけを入れ替えています。
そのため、Nextの画面遷移のほうが軽く、動きが滑らかに感じます。

#3.Next.jsで画面遷移する方法
それでは具体的にNextで画面遷移する方法を見ていきましょう！
Nextで画面遷移する方法は2種類あります。
1. **Linkコンポーネントを使う**
2. **Router.pushを使う**
    
`Linkコンポーネント`はJSXでHTMLのように記述する方法で`Router.push`はイベントハンドラーなどの処理の中で設定する方法です。
JSXを使うかどうかで使い分けることができ、JSXを使う場合は`Linkコンポーネント`、イベントハンドラの場合は`Router.push`を使います。

- JSXの場合：**Linkコンポーネント**
- イベントハンドラの場合：**Router.push**

##3-1.Linkコンポーネント
Linkコンポーネントはaタグをラップすることで使うことができ、特徴はJSXでタグとして扱えることです。
Linkコンポーネントは2ステップで実装できます。

1. **Linkコンポーネントのインポート**
2. **Linkコンポーネントでaタグを包む**

次のソースは、`/`から`/NextPage`に遷移する方法です

![リンクの設定.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621361/d2a88ffb-4b9c-ed81-f161-4df97ee2d7fa.gif)

```javascript:Linkコンポーネントでの画面遷移
//①Linkコンポーネントのインポート
import Link from "next/link";

export default function Index() (
  <div style={{textAlign: "center"}}>
    <h1>遷移元</h1>
    {/* ②Linkコンポーネントでaタグを包む */}
    <Link href="/NextPage">
      <a>次のページへ進む</a>
    </Link>
  </div>
);
```
①でLinkコンポーネントを使うために必要なモジュールを取り込み、②でaタグをLinkコンポーネントでラップして遷移先を設定するだけの処理です。
この2ステップでNextでの画面遷移を実装できます。

ちなみにリンクにCSSクラスなどのオプションを設定する場合はaタグに設定します。
例えば、別のタブで画面を開きたいときは`taget`属性をaタグに設定します。
![aタグのオプション.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621361/67a015f1-3b2d-e811-b2ef-d88823ba3e9b.gif)

```javascript:aタグにオプションを設定
<Link href="/NextPage">
  <a target="_blank">新しいページを開く</a>
</Link>
```

##3-2.Router.push
次はRouter.pushで遷移する方法です。
Router.pushは処理の中に埋め込めるので柔軟なページ遷移が可能です。
イベントハンドラなどに実装できるのが特徴で、Router.pushでの実装も2ステップで設定できます。

1. **Routerオブジェクトのインポート**
2. **遷移先の設定**

次のソースは`/NextPage`から`/`に遷移するプログラムです。

```javascript:Router.pushでの画面遷移
//①Routerオブジェクトのインポート
import Router from 'next/router'

export default function NextPage() {
  function clickHandler() {
    //②遷移先の設定
    Router.push('/')
    return
  }

  return (
    <div style={{textAlign: "center"}}>
      <h1>遷移先</h1>
      <button onClick={clickHandler}>前のページへ戻る</button>
    </div>
  );
}
```
①でRouterオブジェクトをインポートして、②のpushメソッドで遷移するパスを設定しています。
Next.jsのindex.jsは特殊なページで`/index`でなくて`/`でも遷移できます。
また、Pagesフォルダーを基準にパスを設定するので今回の場合だとpagesフォルダーの直下にあるindex.jsファイルのコンポーネントに遷移しています。

#4.まとめ
この記事ではNextで画面遷移する方法を2種類解説しました

・**JSXでの画面遷移はLinkコンポーネント**
・**イベントハンドラーでの画面遷移はRouter.push**

画面遷移はNext.jsでもよく使う機能なので覚えていて損はないです。

#5.参考文献
[Next.js公式サイト](https://nextjs.org/)
blocklyでobjectを動かす。その16

#概要

blocklyでobjectを動かして見る。
promptを実装してみた。
数当てゲーム。

#フローを書く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/db9bbeb3-026b-589d-28a2-42b7dd5b1749.png)


#objectを書く。


```

Blockly.Blocks.prompt = {
    init: function() {
        this.jsonInit({
            message0: "prompt %1",
	        args0: [{
		        type: "input_value",
		        name: "VALUE",
		        check: ["String", "Array"]
	        }],
	        output: "Number",
	        style: "text_blocks",
	        tooltip: "%{BKY_TEXT_LENGTH_TOOLTIP}",
	        helpUrl: "%{BKY_TEXT_LENGTH_HELPURL}"
        })
    }
};
Blockly.JavaScript.prompt = function(a) {
   	return ["prompt(" + (Blockly.JavaScript.valueToCode(a, "VALUE", Blockly.JavaScript.ORDER_FUNCTION_CALL) || "''") + ", '');", Blockly.JavaScript.ORDER_MEMBER]

};
```

#成果物

https://embed.plnkr.co/plunk/RngM09Ld2hqjMK0Y

以上。
ECSのserviceに複数のTargetGroupを設定する

## tl;dr;
DocumentにはAWS Management Consoleからできると書いてあるが，どこを探しても導線がないので`aws-cli`を使いましょう(知っている人はこっそりコメントを下さい)

## やりたいこと
- 複数のTargetGroupをECSのサービスに登録したい．
- WebConsoleでできれば試してみたい．
- [公式](https://aws.amazon.com/jp/about-aws/whats-new/2019/07/amazon-ecs-services-now-support-multiple-load-balancer-target-groups/) には2019年7月からサポートと書いてあるため実現できそう．

### ユースケース
- 複数のTaskで運用しているサービスのロードバランサを各Taskごとに用意したい．
- 複数のロードバランサを1つのサービスに登録したい．

## Web Consoleを眺める
ECSのサービスを作成する画面で，LoadBalanacerの設定画面があります．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176701/b6e60900-b85c-45d0-0e71-1521cecbab0a.png)

ここでALBやNLBを選択すると，どのTargetGroupを選択する項が表れます．
![tg-image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176701/3f65fe65-e970-873f-f75b-0bfa2bb16a57.png)

同様の手順でTargetGroupを追加しようとしますができません．
どうやらWebConsoleでは，**1つのTargetGroupのみ**しか設定できないようです．

## awsのドキュメントを見てみる
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/register-multiple-targetgroups.html には Web Consoleからできそうな感じで書いてありますが，できなさそうです．

このドキュメントを見ると`cli`の話が書いてあるので，試してみます．

## `aws-cli`を用いる方法
先程のドキュメントのページをみるとどうやらこの形式で登録すれば良さそうです

```
"loadBalancers":[
   {  
      "targetGroupArn":"arn:aws:elasticloadbalancing:region:123456789012:targetgroup/target_group_name_1/1234567890123456",
      "containerName":"webserver",
      "containerPort":80
   },
   {  
      "targetGroupArn":"arn:aws:elasticloadbalancing:region:123456789012:targetgroup/target_group_name_2/6543210987654321",
      "containerName":"database",
      "containerPort":3306
   }
]
```

自分が登録したいtargetGroupArnを調べて以下のような`aws-cli`を用いたコマンドを実行します．細かなパラメータは[こちら](https://docs.aws.amazon.com/cli/latest/reference/ecs/create-service.html)をみて各人設定してください．

```
aws ecs create-service \
  --cluster my-cluster \
  --service-name my-service-name \
  --task-definition my-task \
  --load-balancers '[{"targetGroupArn": "arn:aws:elasticloadbalancing:region:123456789012:targetgroup/target_group_name_1/1234567890123456", "containerName":"webserver",  "containerPort": 80 },{ "targetGroupArn": "arn:aws:elasticloadbalancing:region:123456789012:targetgroup/target_group_name_2/6543210987654321", "containerName": "database", "containerPort":3306 }]' \
  --desired-count 1 \
  --launch-type EC2
```

これを実行すると，web consoleではできませんでしたが無事に複数のTargetGroupを登録できました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176701/5ac9ad37-a672-1760-627a-3f91ccc8be86.png)


## まとめ
- web consoleでは未実装だけど実はできることがあったりするので，ドキュメントを読みましょう．

## 注意
- 既に作成されたECSのサービスにはTargetGroupは設定できません．
    - サービスを作るときにしかできない操作です．

## 参考
- [Amazon ECS サービスで複数のロードバランサーターゲットグループのサポートを開始](https://aws.amazon.com/jp/about-aws/whats-new/2019/07/amazon-ecs-services-now-support-multiple-load-balancer-target-groups/)
- [Registering Multiple Target Groups with a Service](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/register-multiple-targetgroups.html)
- [create-service — AWS CLI 1.18.61 Command Reference](https://docs.aws.amazon.com/cli/latest/reference/ecs/create-service.html)
初心者によるプログラミング学習ログ 320日目

#100日チャレンジの320日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
320日目は、
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>320日目　2h<br>・ポートフォリオ作成<br><br>フッターの下部固定がうまくいかんなあ・・・<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1262473657349050368?ref_src=twsrc%5Etfw">May 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Rubyで文字列の一部を取り出す

## この記事でやること
この記事ではRubyで任意の文字列を取り出す方法を解説します。また、文字列を取り出す際の引数に、負の数を指定した場合の挙動についても解説しております。

## 文字列を取り出すには
コード自体は以下のような感じです。
文字列の0番目から2番目を指定することで、先頭から3文字目まで出力されていますね。

```ruby
def left2(str)
  puts str[0..2]
end

left2('Hello')

--実行結果--
Hel
```

ここで、strの第二引数を-1にしてみましょう。

```ruby
def left2(str)
  puts str[0..-1]
end

left2('Hello')

--実行結果--
Hello
```

全ての文字を取り出してHelloと出力されました。
なぜかというと、-1が文字列の末尾にを表しているからです。
文字列の0番目から末尾までを取り出しているためこういう結果になります。
各文字が何文字目に対応するか表にまとめました。

|文字  |正の数の場合  |負の数の場合  |
|---|---|---|
|H  |0文字目  |-5文字目  |
|e  |1文字目  |−4文字目  |
|l  |2文字目  |-3文字目  |
|l  |3文字目  |−2文字目  |
|o  |4文字目  |-1文字目  |

上記の表に従うと、第一引数に1を設定し、第2引数に-4を設定すれば、
0文字目と1文字目を取り出すため、結果は「He」になる想定です。
早速やってみましょう。

```ruby
def left2(str)
  puts str[0..-4]
end

left2('Hello')
```

・実行結果

```
% ruby test.rb
He
```

想定通り「He」になりました。
文字列を取り出すときは、負の値も引数に使えるんだなーということが今回の記事の肝です。
pipが最新だとうまくいかない時がある話

NLGEvalという自然言語生成の評価指標のためのpython frameworkをpipで入れようとした時、以下のエラーが出た。

```
ERROR: Command errored out with exit status 1:
     command: /hoge -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-1_dfztb4/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-1_dfztb4/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-02126d0b
         cwd: /tmp/pip-req-build-1_dfztb4/
    Complete output (7 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-req-build-1_dfztb4/setup.py", line 24, in <module>
        reqs = [str(ir.req) for ir in install_reqs]
      File "/tmp/pip-req-build-1_dfztb4/setup.py", line 24, in <listcomp>
        reqs = [str(ir.req) for ir in install_reqs]
    AttributeError: 'ParsedRequirement' object has no attribute 'req'
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
```

エラー文でぐぐると、似たようなエラーが違うフレームワークのインストール時に起きていることがわかり、そこではpipを20.1から19.3.1に戻すとうまくいくと書いてあった。
https://github.com/ansible/awx/issues/6870#issuecomment-620979872


素直にしたがって19.3.1に直すと無事うまくいった。

```
pip install pip==19.3.1
```

pipをダウングレードしたのは初めてだ。。。
Rails で HTTP DELETE メソッドを使える条件

# はじめに
Rails では RESTful な設計とするために各種 HTTP リクエストメソッドを使い分けていて、`config/routes.rb` では当たり前に DELETE メソッドを定義すると思います。

が、このルーティング、正しく機能するためには条件があります。その条件を満たしていないと正しく動作しません。


# 結論

`jquery-ujs.js` もしくは `rails-ujs.js` が読み込まれていることが条件です。これら JavaScript が__トリックによって DELETE をエミュレート__しています。


# トリックの正体と有効／無効

一般的にブラウザでは GET と POST しか使えません。DELETE リクエストは送信されないので、当該ルートが発現することはありません。例えば `link_to method: :delete` と書いたとしてもブラウザの素の能力では GET が送信されてしまい、最悪誤動作を引き起こします。

そこで前述 JavaScript が上手いことやって「DELETE のつもりでリクエストするんだぜ」というのを伝えることで、DELETE メソッドではないものの DELETE ルートを発現させています。具体的には form オブジェクトを作って「本来の意図は DELETE だよ」というパラメータを添えて POST しています。

そしてこのトリックは普通に `rails new` すれば自動的にお膳立てされ有効になります。

が、`rails new --skip-javascript` すると無効になります。JavaScript に依存しているんだから当たり前ですね。そして前述のように `link_to method: :delete` は GET になってしまうのです。


# 手作業でトリックを有効にする方法

何らかの事情で `rails new --skip-javascript` しなければならない場合に手作業でトリックを有効にする方法は、下記です。各ファイルに各行を追記します。

```app/assets/javascripts/application.js
//= require rails-ujs
```

```app/views/layouts/application.html.erb
    <%= javascript_include_tag 'application' %>
```


# 別法あります

ここまでは前置きです。
ここからが本題です。

JavaScript を使わなくても DELETE ルートを使うことは出来ます。`button_to method: :delete` です。

JavaScript が生成している form を静的に生成すればいいわけです。


# より link_to ぽく

button_to では `input type='submit'` が１つ（と `input type='hidden'` が幾つか）の form が生成されますが、`class='button_to'` になっています。さらに例えば `button_to class: :anchor` とすると `input type='submit' class='anchor'` になります。

```生成される.html
<form class="button_to" method="post" action="/logout">
  <input type="hidden" name="_method" value="delete" />
  <input type="hidden" name="authenticity_token" value="ナイショ" />
  <input class="anchor" type="submit" value="LOGOUT" />
</form>
```

なので、下記のような CSS (SCSS) を書いてやれば、機能も見た目も link_to の代わりに使うことが可能です。

```app/assets/stylesheets/custom.scss
form.button_to {
  display: inline;

  input.anchor[type='submit'] {
    border-style: none;
    padding: 0;
    font-size: 1em;
    cursor: pointer;
    background-color: $bg-color;
    color: $link-color;
  }
}
```

# 終わりに

もともと --skip-javascript なんて使ってなかったんですが、Rails 6 が Webpacker で yarn や node_modules 必須になってたものの取り急ぎ小さく new したかったので --skip-javascript したら一旦良さそうだったけど logout 出来ず「！？」となって、、、ここに至りました。

静的最高♪
Wordpress で複数ドメインで同一コンテンツを提供したい場合のメモ

マルチサイト構成で example.com でも example.eu でも example.co.jp でも同じコンテンツを提供したい場合には別ドメインでアクセスしてもサイトが見つからなかったり、プライマリドメインへのリダイレクトが発生してしまったりします。

異なるドメインでアクセスした場合にサイトがみつからない元凶は `get_site_by_path()`、リダイレクトが発生する問題は `redirect_canonical()` です。

`pre_get_site_by_path` フィルタはプラグイン読み込み前の処理なため wp-config.php で `define('SUNRISE', true);` を指定することにより wp-content/sunrise.php の読み込みをさせるようにします。

以下の方法で複数ドメインのリダイレクト問題に対応できます。

```php:wp-config.php
// 現在のサイトのホスト名はサーバから貰えるものにする 
// (これをしないと ms-settings.php でリダイレクトが発生する)
define('DOMAIN_CURRENT_SITE', $_SERVER['HTTP_HOST']);
// wp-content/sunrise.php を読ませる
define('SUNRISE', TRUE);

```

```php:wp-content/sunrise.php
// wp-includes/ms-load.php:214
function my_pre_get_site_by_path($pre, $domain, $path, $segments, $paths) {
	$args = array(
		'number'                 => 1,
		'update_site_meta_cache' => false,
	);
	
	// 元ソースからドメインでのフィルタ部分を削除してパスだけでサイトを検索する

	if ( count( $paths ) > 1 ) {
		$args['path__in']               = $paths;
		$args['orderby']['path_length'] = 'DESC';
	} else {
		$args['path'] = array_shift( $paths );
	}

	$result = get_sites( $args );
	$site   = array_shift( $result );

	if ( $site ) {
		return $site;
	}
	return $pre;
}
add_filter('pre_get_site_by_path', 'my_pre_get_site_by_path', 10, 5);

// wp-includes/canonical.php:605
function my_redirect_canonical($redirect_url, $requested_url) {	
	// redirect_url のホスト名が home_url() 基準に変更されてしまうため
	// 元URL を プライマリドメイン基準に変更して差が無ければリダイレクト中止
	$_sanitized = str_replace($_SERVER['HTTP_HOST'], 'www.example.com', $requested_url);
	if ($_sanitized == $redirect_url) {
		return NULL;
	}
	return $redirect_url;
}
add_filter('redirect_canonical', 'my_redirect_canonical', 10, 2);
```

* 管理画面に入るとプライマリドメインに転送される。
* [Force Login](https://ja.wordpress.org/plugins/wp-force-login/) プラグインを使っていると管理画面を経由するのでプライマリドメインになる。
* キャッシュの影響を受けるため、変更後はしばらく待つか、 `wp_cache_flush()` をすること。

追記：
`redirect_canonical` にフックする代わりに `option_home` にフックしたほうが良いかもしれない。

```php:wp-content/sunrise.php
function my_option_home($value, $option) {
	$value = str_replace('www.example.com', $_SERVER['HTTP_HOST'], $value);
	return $value;
}
add_filter('option_home', 'my_option_home', 10, 2);
```
ubuntuにMySQL導入するメモ

## MySQLインストール	
`sudo apt install mysql-server mysql-client libmysqlclient-dev
sudo service mysql status`

## 開発用ユーザー作成(rootのpassはrootからNewPasswordに変更)
### まずはrootでログイン
`sudo mysql -u root -p`
### 開発ユーザーの追加
 `GRANT ALL PRIVILEGES ON *.* TO ユーザー名@localhost IDENTIFIED BY 'パスワード' WITH GRANT OPTION;`
### 保存
 `flush privileges;`
### ついでにrootも初期パスワードから変更
 `ALTER USER 'root'@'localhost' IDENTIFIED BY '新しいパスワード';`
ubuntuでrbenvをaptで導入してrubyを入れる

## 前提
ネット上の自分でライブラリを落としてくるやり方
(参考：https://qiita.com/yuma-ito-bd/items/00f89ca0c04909c7c467)
> sudo apt install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm5 libgdbm-dev

だと開発終了したライブラリの互換が見つけられずinstallに失敗したため、aptでrbenvをinstallしました。

※aptで取ってしまうと古めのrbenvがinstallされるので最新版を使いたい方は注意

## 手順
### 1.aptをupdate
`sudo apt update`


### 2.install
`sudo apt install rbenv`
とすると

### 3.version確認
`rbenv -v # rbenv 1.1.1`
無事にrbenvが入りました
ではrubyをinstallします

### 4.Rubyのバージョンを指定してinstall
`CONFIGURE_OPTS='--disable-install-rdoc' rbenv install 2.6.3`
HTTP リクエストの Host ヘッダフィールドを知ろう

この記事は[RFC7230](https://tools.ietf.org/html/rfc7230#section-5.4)をもとにしています。つまみ食い読みをしているので、間違っていたらすみません。編集リクエストをいただけると幸いです。

-----

HTTP では、クライアントサーバーモデルに基づき、クライアントがサーバーへリソースを要求（リクエスト）し、サーバーはそれに応答（レスポンス）を返します。

クライアントやサーバーが発するものはメッセージと呼ばれます。メッセージは

- 0個以上のヘッダフィールド、
- ヘッダフィールドの終わりを示す空の行、
- オプション（あってもなくてもよい）としてメッセージボディ

からなります。

この記事では HTTP リクエストの特に [Host ヘッダフィールド](https://tools.ietf.org/html/rfc7230#section-5.4)について理解することを目的とします。

HTTP リクエストメッセージとレスポンスメッセージは、以下のようなものです。（[RFC7230 §2.1](https://tools.ietf.org/html/rfc7230#section-2.1)から引用）

```
   Client request:

     GET /hello.txt HTTP/1.1
     User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
     Host: www.example.com // ←ここが Hostヘッダフィールド
     Accept-Language: en, mi


   Server response:

     HTTP/1.1 200 OK
     Date: Mon, 27 Jul 2009 12:28:53 GMT
     Server: Apache
     Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
     ETag: "34aa387-d-1568eb00"
     Accept-Ranges: bytes
     Content-Length: 51
     Vary: Accept-Encoding
     Content-Type: text/plain

     Hello World! My payload includes a trailing CRLF.
```

-----


HTTP リクエストの Host ヘッダフィールドは、アクセスしたい URI とポートの情報をもちます。

```
Host: www.example.com
もしくは
Host: www.example.com:80
```

サーバーは単一の IP アドレスについて複数のホストネームを持つことができます。どのホストネームでリソースを要求されたかによって、提供するリソースを振り分ける必要があります。HTTP リクエストを受け取ったサーバーは Host ヘッダを見ることによって、提供すべきリソースを決めることができます。

HTTP リクエストメッセージは必ず Host ヘッダフィールドを含む必要があります (MUST)。

上の例のリクエストメッセージの1行目

```
GET /hello.txt HTTP/1.1
```

のことをリクエストラインと呼びます。リクエストラインの `GET` の直後、この例では `/hello.txt` の部分を[リクエストターゲット](https://tools.ietf.org/html/rfc7230#section-5.3) と言います。リクエストターゲットはターゲットの URI から作られ、その書き方は4種類あります。

[Authority コンポーネント](https://tools.ietf.org/html/rfc3986#section-3.2) (`johndoe@www.example.com` みたいなもの、ユーザー名と `@` はなくてもいいので通常は `www.example.com` の部分) がターゲット URI に含まれる場合は、 Host ヘッダフィールドにも同じ値  (`www.example.com`) をもつ必要があります (MUST)。


逆にターゲット URI に authority コンポーネントが欠けている場合は、 Host ヘッダフィールドの値は空でなければなりません (MUST)。[^1]

[^1]: Host ヘッダフィールドが空、すなわち authority コンポーネントがない状況というのはおそらく何らかの異常が起きた状況だと思うのですが、具体的にはどのような状況なのでしょうか。ご存知の方がいらっしゃいましたらコメント欄等で教えていただけると幸いです。

Host ヘッダフィールドの値はリクエストを扱うのに重要な情報ですから、ユーザーエージェント（ブラウザとか）は[リクエストライン](https://tools.ietf.org/html/rfc7230#section-3.1.1)のすぐ直後に Host ヘッダを生成すべきです (SHOULD)。例えば `http://www.example.org/pub/WWW/` へのリクエストは

```
     GET /pub/WWW/ HTTP/1.1
     Host: www.example.org
```

というようになります。

HTTP/1.1 リクエストでは、クライアントはリクエストターゲットを absolute-form ([リクエストターゲット](https://tools.ietf.org/html/rfc7230#section-5.3)参照) で書いた場合であっても Host ヘッダを送らなければなりません (MUST)。Host を実装していない可能性がある古代の HTTP/1.0 プロキシはを経由しても Host 情報が渡されるようにするためです。

プロキシが absolute-form のリクエストターゲットを受け取ったとき、プロキシは Host ヘッダフィールドを無視しリクエストターゲットのホスト情報で置き換えなければなりません (MUST)。そのようなリクエストを転送するプロキシも同様です。

Host ヘッダフィールドはアプリケーションレベルでのルーティング機構として振る舞うため、共有キャッシュポイズニングや意図しないサーバーへのリダイレクトを狙うマルウェアの標的となりがちです。透過プロキシがリクエストを内部サーバーに Host フィールドの値に基づいて振り分けていたり、共有キャッシュのキャッシュキーとして用いられていたりしていて、プロキシを通る通信がそのホストにとって有効な IP をターゲットとしているかの検証をしていない場合には、特に脆弱です。

Host ヘッダフィールドがない、または複数ある、または無効な値になっている HTTP/1.1 リクエストに対してサーバーは 400 Bad Request を返さなければなりません (MUST)。
【laravel】Eloquenによるリレーション

# 概要
Eloquentを使用したテーブルの結合です。
ここでは[【laravel】マイグレーション](https://qiita.com/gone0021/items/5cec0c945b41c00441cc)で作成したsampleテーブルを主テーブルとして、「id、sample_id、title」で構成された従テーブルのlistテーブルが存在すると仮定します。

全てをまとめて一つの記事として投稿したかったのですが長くなったため分割しました。
Eloquentの基本的な部分と操作については以下の記事をご参考ください。

[【laravel】Eloquentの基本](https://qiita.com/gone0021/items/4b1b4555b9b8f2eca458)
[データベースの操作：Eloquent ORM編](https://qiita.com/gone0021/items/951cd63a7e591e18cd2a)


# まずは結合
Eloquentでの結合には`hasOne()`と`hasMany()`というメソッドがあります。
`hasOne()`は1対1の結合で、`hasMany()`は1対多の結合です。
どちらもLEFTJOINのように主テーブルから従テーブルのレコードを取得し、値が存在しないレコードはNULLとしています。
これらの結合は主テーブル側で設定を記述します。
ただし、NULLのレコードをテンプレートで表示すると例外が発生するので対策が必要です。


## hasOneメソッド
`hasOne()`は1対1での結合で、従テーブルの最初のレコードのみを取得します。
また、設定がなければ外部キーは`〇〇_id`とされますが、オプションで第2引数によって指定できます。

例として以下のような内容を作成します。
コントローラーで全ての値を取得してテンプレートへ渡し、モデルクラスではlistメソッドを作成して`hasOne()`を返します。
テンプレートではforeachで値を取得して、値がNULLでなければクラスモデルで作成したlistメソッドのうちのtitleを表示しています。

```php:Controller
public function index(Request $request)
{
  $items = Sample::all();
  return view('sample.index', ['items' => $items]);
}
```

```php:Sample
public function list()
{
  return $this->hasOne('App\Models\List');
}
```

```php:view
@foreach ($items as $item)
  @if ($item->list != null)
    {{$item->list->title}}
  @endif
@endforeach
```


## hasManyメソッド
`hasMany()`は1対多の結合で、従テーブルの全てのレコードを取得します。
また、設定がなければ外部キーは`〇〇_id`とされますが、オプションで第2引数によって指定できます。

例は`hasOne()`で作成した内容とほぼ同じです。

```php:Controller
public function index(Request $request)
{
  $items = Sample::all();
  return view('sample.index', ['items' => $items]);
}
```

```php:Sample
public function lists()
{
  return $this->hasMany('App\Models\List');
}
```

```php:view
@foreach ($items as $item)
  @if ($item->lists != null)
    {{$item->lists->title}}
  @endif
@endforeach
```

## レコードの有無を判定して取得
`hasOne()`や`hasMany()`は従テーブルのレコードがNULLでもNULLとして返すため、INNERJOINのような使い方ができません。
そこで`has()`という値があるレコードのみを取得するメソッドです。
また、逆に値がNULLとしてのレコードを取得する`doesntHave()`というメソッドもあります。
`has()`は`クラスモデル::has('メソッド名')->get();`のように記述します。


```php:Controller
public function index(Request $request)
{
  $hasItems = Sample::has('lists')->get();
  $noItems = Sample::doesntHave('lists')->get();
  $param = ['hasItems' => $hasItems, 'noItems' => $noItems];
  return view('Sample.index', $param);
}
```

```php:view
@foreach ($hasItems as $has)
  {{$has->lists->title}}
@endforeach

@foreach ($noItems as $no)
  {{$no->lists->title}}
@endforeach
```


# belongsTo
`belongsTo()`は従テーブルから主テーブルのレコードを取得するメソッドです。
主テーブルのレコードが削除されていた場合はNULLで返されず例外が発生します。

また、従テーブルの`〇〇_id`に一致する主テーブルの`id`を検索して結合しますが、従テーブルで設定する外部キーはオプションで第2引数によって指定できます。

```php:List
public function sample()
{
  return $this->belongsTo('App\Models\Sample');
}
```

```php:view
@foreach ($items as $item)
  @if ($item->sample != null)
    {{$item->sample->name}}
  @endif
@endforeach
```

# 参考
[Laravel 6.x Eloquent：リレーション]
(https://readouble.com/laravel/6.x/ja/eloquent-relationships.html)
MongoDB Atlas はじめ方

# はじめに
学習のためにアプリ開発する際、DBが必要になったが、自分のマシンの性能が低すぎてローカルにDBの環境を構築したくなかった…。
そんなとき世の中どうやって対処しているのだろうと思い、調べてみました。
また、本記事に出てくる画像は2020/05時点のものになります。

# MongoDB Atlas とは
MongoDBが提供するクラウドサービス
Atlas（アトラス）は「地図帳」とかいう意味らしい
[atlasとmap、どこに違いは？どう使い分ける？両方とも「地図」を意味する](https://englishranking.com/atlasmap/)

# アカウント作成
まずはMongoDB Atlasにアクセスし、アカウントを作成しましょう。
[MongoDB Atlas](https://www.mongodb.com/cloud/atlas)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/43f9e435-7c0d-05bd-e247-0a41ffd9a2c8.png)

いくつかのプランが表示されると思いますが、とりあえず無料のものでいいでしょう。
左にあるFREEのものを選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/fda2ea3e-7548-25a3-a231-d04ab451cdf6.png)

次にリージョンの選択ですが、東京があったので、それにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/3ac4df8c-707f-b369-fbd9-33580055a61e.png)

次にティアの設定ですが、無料なのは512MBのものしかないので、これにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/7d2158ea-89a9-3e49-96db-62e94997d8b9.png)

あとは、バックアップの設定は利用不可なので、そのまま無視して、
クラスター名を適当に付けます。
「Create Cluster」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/5517ebd6-7f9b-f0e3-9ae5-d08d880e0e77.png)

作成できました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/c6d52e01-8730-def9-cc20-ec4e4e5010df.png)

# クラスタへの接続
とりあえず、接続してみようと、「CONNECT」ボタンを押すと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/c7e1e7c8-a377-14e6-f1bf-f1f7bb49b26c.png)

ホワイトリストの登録と、ユーザの作成を求められました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/efbebbd8-65dc-eac1-ae29-e5cac2350e07.png)

#### ホワイトリストの登録
「Add Your Current IP Address」ボタンを押すと、自分のIPアドレスが登録されます。

#### ユーザ作成
適当に名前とパスワードを入力して、作成します。

どちらの設定も終え、「Choose a connection method」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/b00fb3d1-2265-92cb-5b2a-38a9a4b99b7d.png)

DBへの接続方法が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/331b00d9-0bdc-e119-5049-df672450aa82.png)

上から順に  

- Mongo Shellからの接続方法
- 任意のアプリからの接続方法
- GUIからの接続方法

となります。

※どれか押したからといって接続方法が固定になったりはしません。
　それぞれの接続サンプル方法が表示されるだけです。

確認が終わったら、「Close」をクリックします。

# サンプルデータのロード
「Load a Sample Dataset」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/898aab3e-d877-dd2b-10a1-7656e7320220.png)

確認ダイアログが出ますが、気にせずロードします。

512MBしか使用できないプランで350MBのサンプルデータですので、動作確認したら削除しましょう。

しばらくしたら、様々なデータがロードされました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/d8555943-516d-cb10-6896-c394f4c4a27a.png)


# サンプルデータの見方
MongoDBでは一般的なDBと異なる名称があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/6838bfd6-5a58-51a7-4369-29e2260ae31e.png)

- Collection  
テーブル
- Document  
レコード
- Field  
カラム


1つ1つのデータはDocumentという名前が表す通り、文書形式になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638864/40998159-ba3d-53e0-bb9e-081dac20a7fa.png)