OmniAICreator/Qiita-1.07M huggingface dataset:
キャッシュ化された関連データを返すプロパティのためのヘルパ

# よくある

```c#

class Hoge{
  string HogeCode{get;set;}
  
  private string __hogeName =null ;
  //名前を取り出す。名前は別テーブルに入ってるのでHogeCodeを元に取得
  string HogeName {
    get{
      if (__hogeName==null) {
         __hogeName = db.GetHogeName(HogeCode) ; // DBから名前取ったりとか
      }
      return __hogeName;
    }
  }
```

コードが長い割に大したことやってないので毎回書くのがめんどい。

## てってれー

```c#
    /// <summary>
    /// キャッシュ化された値を格納するディクショナリ
    /// <ul>
    /// <li>キャッシュされていたらキャッシュから値を返す</li>
    /// <li>キャッシュされていなければpresenterを使って値をキャッシュする</li>
    /// </ul>
    /// </summary>
    public class NameDictionary {
        private Dictionary<string, object> dictionary = new Dictionary<string, object>();
        /// <summary>
        /// 値を取得する。
        /// PropertyのGetterやGet**メソッドから使われることを想定
        /// CallerMemberNameが取れないとエラーになるので注意
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="presenter"></param>
        /// <param name="PropertyName"></param>
        /// <returns></returns>
        public T Get<T>(Func<T> presenter,[CallerMemberName] string PropertyName=null) {
            return Get<T>(PropertyName, presenter);
        }

        /// <summary>
        /// 値を取得する。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="KeyName"></param>
        /// <param name="presenter"></param>
        /// <returns></returns>
        public T Get<T>(string KeyName,Func<T> presenter) {
            if (!dictionary.ContainsKey(KeyName)) {
                dictionary.Add(KeyName, presenter());
            }
            return (T)dictionary[KeyName];
        }
    }
```

## 使い方

```c#

class Hoge{
  string HogeCode{get;set;}
  private NameDictionary dictionary = new NameDictionary();
  //名前を取り出す。名前は別テーブルに入ってるのでHogeCodeを元に取得
  string HogeName => dictionary.Get<string>(()=> db.GetHogeName(HogeCode) );
```

短くかけて大変うれしい。

## 注意

`CallerMemberName`が取れないとエラーになるので、適宜 `Get<T>(string,Func<T>)`を使う。
【UE4】回収した仲間を厩舎に返す／第13回UE4ぷちコン進捗 - 2020/03/18

[1]:http://historia.co.jp/ue4petitcon13

[株式会社ヒストリアさん主催の第13回UE4ぷちコン][1]の作業進捗。

# ちょっとモデリングしていた

回収した仲間の恐竜を送り届ける先として「厩舎」を作った。
使用しているのは MODO indie。

![20200318_1135.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/682ef316-74ce-f056-761b-e7f07b8ac3ee.png)

プログラマな私でも、こういう定規で引いたような形ならモデリングできる。
というか、何より毎回思うのが、

![20200318_1139.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/058af81f-69b3-e895-0594-f2a08782e6ee.png)

UVマップを作るのが一番大変。なにこの難解パズル。
アーティストの皆さんがあんなにサクサクやっているのが全く信じられない。

これを UE4 でマテリアルを貼ったのがこちら。

![HighresScreenshot00000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/3f957ab5-b7d6-aa43-534e-86aaaef737b4.png)

マテリアルはみなさんご存じの M_Wood_Pine。Starter Content に入っているアレである。
UV のスケール感は、私の好みで大きめ。おもちゃっぽいスケール感が好み。
屋根などの青色はマテリアルインスタンスで色変えができるようにはしてある。

ちなみに、柵は Content Examples に入っていたもの。
UFOを操作してキャトルミューテーションして遊ぶ的なサンプルで使われていたはず。
これをスプラインに沿って並べている。

# で、前回の NavMesh を組み合わせるとこうなる。

![20200318_1130.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/fe8bd61f-cc96-d5ec-9218-3df683fb5ae6.gif)

この GIF 動画だと NavMesh の効能が分かりにくいが、ちゃんと柵とかよけて走るし、必ずドアを通って（壁を突き抜けずに）厩舎に入る。

> 厩舎に戻るモードになった瞬間、恐竜たちがびくっと止まるのが気に食わない…
> だが他にもやりたいことがあるので、いまは保留。

…ということで、仲間を「捜<font color="red">**索**</font>(そう<font color="red">**さく**</font>)」して回収して、「<font color="red">**柵**</font>(<font color="red">**さく**</font>)」の中に返すゲームになります。たぶん。
IonSlidesのinitialSlideオプション使用時に先頭スライドの画像がちらつく問題と対応

##この記事について
IonSlideのinitialSlideオプションを使った際に想定通りの動作がせず、最初のスライドが一瞬表示される現象が発生しました。正攻法での解決ができなかったのでハック的な方法ですが記録しておきます。

[IonSlide](https://ionicframework.com/docs/api/slides)は内部で使用しているSwiper.jsのオプションが利用できます。`initialSlide`オプションを使うと最初に表示するスライドを指定できます。
[Swiper.jsオプション一覧](https://swiperjs.com/api/)

issuesに似たような現象があがっています。
[bug: ionic 4 ion-slide set initialSlide not work immediately](https://github.com/ionic-team/ionic/issues/19486)

##現象
initialSlideで指定した「３」の画像が表示される前に、先頭スライドの「1」が一瞬表示されています。
![slide.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537165/6bf5448b-f645-1a00-7eec-0b739e527192.gif)

再現したコードは下の通り。
Ionicのテンプレプロジェクトをベースに`ion-slides`にオプションを設定しています。

```about.html
<ion-content>
  <ion-slides pager="true" [options]="slideOpts">
    <ion-slide>
      <div class="wrapper">
       <img src='assets/img/1.png' />
      </div>
    </ion-slide>
    <ion-slide>
      <div class="wrapper">
       <img src='assets/img/2.png' />
      </div>
    </ion-slide>
    <ion-slide>
      <div class="wrapper">
       <img src='assets/img/3.png' />
      </div>
    </ion-slide>
  </ion-slides>
</ion-content>

```

```about.ts
export class AboutPage {
  
  public slideOpts = {
    initialSlide: 2,
  };
```

##パッケージ環境
- Angular 8.2.14
- Ionic 4.11.6　※ 5.0.0でも同様の事象が発生しています。

##対応

###表示を遅延させる
`setTimeout`で表示を遅延させることで、指定したスライドが表示されたあとに表に出すようにします。
他に良い方法がなかったのでこの古典的な方法で対応しています。

```about.ts
setTimeout(() => {
  this.showImage = true;
}, 300);
```

###先頭に空のion-slideを挿入する
空のスライドを挿入することで表示時の先頭スライドのチラつきはなくなりましたが、スライド番号がずれてしまいます。

```about.html
<ion-slides pager="true" [options]="slideOpts" #imageSlides >
  <ion-slide></ion-slide> <!-- 空のion-slide-->
  <ion-slide>
    <div class="wrapper">
     <img src='assets/img/1.png' />
    </div>
  </ion-slide>
```

##さいごに
微妙な方法しか紹介できませんでしたが、より良い実装があればコメントやissuesに展開していただけると助かります。
初心者から始めるJava、抽象クラス

#はじめに
この記事は備忘録である。
参考書レベルの内容だが、本記事に掲載するコードについては、
~~**間違えた**ものが中心となる。これは実際にコーディング中に間違えた部分を掲載し、自分で反省するために投稿するという目的によるもの~~。
また、後日にJavaSilver試験問題の勉強を兼ねて復習するため、深い部分の話はここでは触れない。

##環境
言語：Java11、JDK13.0.2
動作環境：Windows10

#オブジェクトを作れないクラス
今まで扱ったクラスはすべて、オブジェクト生成をしたあとのことを考えて内容を作っていた。だが、この**抽象クラスそのものではオブジェクト生成・インスタンス化ができない**。
今回の**抽象クラス**は、「クラスを作ることを考えて内容を決める」必要があるクラスであり、「この抽象クラスを継承したクラスを作るとき、この機能だけはつけてくださいね」というつもりで内容を考えるとよい。

抽象クラスと、そのメソッドのうち**処理内容を定義していないメソッド**について。抽象クラスは、**`abstract`修飾子を持ち処理内容をその場では定義しないメソッド（抽象メソッド）**を持つという特徴があり、`class`の前に`abstract`を付けることで抽象クラスとして宣言できる。

```Java:abstractClass.java
abstract class Wild
{
  protected int number;
  public void getNumber(int n)
  {
    number = n;
    System.out.println("この猫は" + number + "番目の猫です。");
  }

  abstract void show();

}
```
注意点として。抽象クラス内には抽象メソッドが必要だが、**具象メソッド（`abstract`を付けていないメソッド）を実装してもよく、具象メソッドはサブクラスではそのまま継承されたメソッドとして利用できる**。

##抽象メソッドは必須事項を定める
抽象クラスを継承したサブクラスは、**`abstract`のついた抽象メソッドを元に具象メソッドをオーバーライドで実装しなければならない**。
オーバーライドするということは、

1.シグニチャ（メソッド名。この場合引数関係は実装を待つ、と考えている）が同じ
2.アクセス修飾子が同じかより緩い
3.戻り値の型が原則同じ（共変戻り値を除く）

この条件を満たす必要があるということ。

同じ名前のメソッドがサブクラスに必須となるので、抽象クラスの内容をよく理解しないといつまでもエラーを吐き続けることになる。

```Java:HouseCat.java
class HouseCat extends Wild
{
  public void see(int num)
  {
    number = num;
    System.out.println("この猫は" + number + "番目の猫です。");
  }
  //ちょっと待った、show()はどこだ？
}
```

#おわりに
`instanceof`演算子を使うと、**2項の変数が同じクラスに属しているかどうか調べることが出来る**。
[Java SE11 Silver 問題集](https://book.impress.co.jp/books/1118101186)（通称黒本）から引用。
> a instanceof b
>aが、bと同じクラスかbのサブクラスのインスタンスであればtrue

`main`関数内で条件分岐に組み込むことが出来るので、チェック機構に向いている。

今回扱った抽象クラスによく似たものとして、次回予定の**インターフェース**があるのだが、これらの違いをよく確認しておきたい。
#参考
出来るだけ自分で変数や式を書いてコンパイルしているので、完全に引用する場合はその旨記述する。

[やさしいJava 第7版](http://mana.on.coocan.jp/yasaj.html)
[Java SE11 Silver 問題集](https://book.impress.co.jp/books/1118101186)（通称黒本）
超自分用sbt メモ

超自分用なので、参考にしない方がいいかもです

IntellijにてsbtプロジェクトをGitからクローンした。
そのプロジェクトのbuild.sbtのlibrary depenciesには問題があり、`sbt.librarymanagement.ResolveException`で失敗する。ここまでは想定内。
だが、build.sbt　内で、`import sbt`も赤字表示。カーソルあてると`Cannot resolve symbol sbt`と表示。
問題があるので`library dependencies`だけのはずなのに、なぜsbt自体がimportできないのか。とハマっていた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317324/ffd98b78-0be2-6fd3-2a9b-d446143f4a66.png)


試しにビルドが成功するように`library dependencies`を修正したところ、sbtの赤字エラーはなくなった。

その後、`library dependencies`をもとに戻して（`sbt.librarymanagement.ResolveException`が出るようにしても）
sbtの赤字表示はされず、想定通りの挙動となった。

どうやら、一度もビルドに成功していないと、Intellijがsbtライブラリを推測してくれないと、いうことかな、
Shopifyのテーマをローカル環境で開発する

# TL;DR
Shopifyのテーマ開発をローカル環境でやったお話です。

# きっかけ
今回初めてShopifyを操作することになり独自テーマを管理画面上で操作するのはデグレや予期せぬバグが出そうで怖い...と感じ、
ちゃんとローカル環境で開発して、Gitでテーマ管理しなきゃだめだなと思ったのがきっかけです。
実際に作ったスターターキットはこちら=>https://github.com/ikuo00uk/shopify-theme-starter


# 概要  
今回はShopifyのTheme Kitを使いテーマ開発しました。

theme kitで出来ることはこちら
> 複数環境へのテーマアップロードができる
高速でテーマのアップロードとダウンロードができる
ローカルファイルをウォッチして変更した差分をShopify環境へ自動アップロードできる
Windows、Linux、macOS で動かすことができる
（参考：https://shopify.github.io/themekit/）

高速と書いてありますが、１テーマのアップロード・ダウンロードは数分かかります..つらい:sob:

# やったこと

### まずはテーマキットをダウンロード
```
brew tap shopify/shopify
brew install themekit
```  

homebrewを使いますので未インストールの方はインストールしてくださいね

### Shopifyの管理画面でプライベートアプリを作る
Shopify管理画面のアプリ管理から「プライベートアプリを管理」を選択して、新規でプライベートアプリを作成してアプリ名、緊急連絡用開発者メールを入力します。　　
![スクリーンショット 2020-03-17 13.03.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77132/1625e68a-4706-0204-0902-589d68e8964b.png)

これでプライベートアプリが完成 :boom: 
その後、Admin API権限の`Theme templates and theme assets`を`Read and write`にしてください。
これがないとテーマの書き込みができないので忘れずに :sob: 

### 本番テーマを取得する  

プライベートアプリ上のパスワードと、ストアドメインをコマンドライン上からたたきテーマを取得します。
`theme get --list -p=[your-password] -s=[you-store.myshopify.com]`  

そうするとテーマ名とテーマIDが取得できますので、以後このテーマIDを使って開発をしていきます。
`theme get -p=[your-password] -s=[you-store.myshopify.com] -t=[your-theme-id]`  
getコマンド、もしくはダウンロードコマンドで指定したテーマをローカルにダウンロードできます。あとはこのファイルを操作して開発していけばOK。
ちなみにテーマをダウンロードすると、config.ymlが取得できるのですが、開発時はこのファイルを見てストアへの反映・変更しているみたいです。  

```config.yml  
development:  
  store: "ストア名"  
  password: "パスワード"
  theme_id: "テーマID"
```

### 実際に開発、反映  
`theme open`
ローカルで変更したファイルのプレビューを確認できます。  

`theme watch`
ローカルで変更したファイルを監視し、`リアルタイムにshopifyの環境にアップロードします`。
複数人開発だとなかなか怖いコマンドです。  

### スターターキットの作成
ここまでである程度ローカルで操作して、ファイルをアップロードできることが分かったので、これをgit管理にします。  

#### 1.秘匿情報のenv化
まずパスワードやストア情報などの秘匿情報をenv化します。
shopifyのopenコマンドでは変数を引き渡せるのですが、[公式情報](https://shopify.github.io/themekit/configuration/#config-file)を見ると、
`--vars flag provides a path to a file for loading variables`
つまりローカルに.envファイルを作成し秘匿情報は書くようにして、config.ymlはそこを見るように。もちろん.envはgitignore　　

```.env.example  
STORE_NAME = "ストア名"
STORE_PASSWORD = "ストアパスワード"
THEME_ID = "開発テーマID"

PROD_THEM_ID = "本番テーマID"  
```  

```config.yml  
development: 
  store: ${STORE_NAME}
  password: ${STORE_PASSWORD}
  theme_id: ${THEME_ID}

production: 
  store: ${STORE_NAME}
  password: ${STORE_PASSWORD}
  theme_id: ${PROD_THEME_ID}
```



### 2.npmscript化
毎回テーマコマンドを打つのもめんどくさいので、watchやダウンロードなどコマンドをnpm script化しました。
↓のような感じ
`"deploy:dev" : "theme deploy --vars env/.env --env=development",`  

そして完成したのがこちら=>https://github.com/ikuo00uk/shopify-theme-starter

# 所感  
とりあえず土台の土台ができた感じなので、このスターターキットをリッチにしていければ良いなと。。
初めてのShopifyなので、もっとこうしたほうが良い等あれば教えて下さい :pray:
休日ならtrue、平日ならfalseを返すrubyメソッド

今日は、平日ならfalse、休日ならtrue値をとして返すメソッドを書いていきたいと思います。


呼び出し方：
sleep_in(weekday, vacation)

出力例：
sleep_in(false, false) → True
sleep_in(true, false) → False
sleep_in(false, true) → True

こちらを作っていきます。

# まずはコードから

```
def sleep_in(is_weekday, is_vacation)
  if (is_weekday != true) || (is_vacation == false)
    puts "True"
  else
    puts "False"
  end
end


is_weekday = true
is_vacation = false

sleep_in(is_weekday,is_vacation)
```

# 細かくみていきます。

```
def sleep_in(is_weekday, is_vacation)
  if (is_weekday != true) || (is_vacation == false)
    puts "True"
  else
    puts "False"
  end
end
```

こちらで、メソッドsleep_inを定義しています。
引数にis_weekdayと、is_vacationをとっています。

メソッド内では、if文により条件分岐をしており、is_weekdayがtrueではないまたはis_vacationがfalseの時となっています。

つまり

is_weekdayがtrueの時もしくは
is_vacationがfalseの時にこのif文はtrueを返すようになっています。


```
is_weekday = true
is_vacation = false
```

こちらでは引数にtureとfalseを代入しています。

```
sleep_in(is_weekday,is_vacation)
```

ここでメソッドを呼び出しています。


以上で、weekdayつまり平日（ここではtrueを代入）がtrueでない時、vacationつまり休日(ここではfalseを代入)がfalseの時にTrueを返すメソッドが完成します。

今日はここまでで、失礼します＾＾
GAS//Driveのフォルダに格納したCSVを自動転記

##やりたかったこと
GoogleDriveに格納したファイルを一定時間ごとにチェック(←これはトリガーでできる)
特定の返品理由のユーザーのみリストにする(電話して確認するため)
リストにしたファイルは「転記済」フォルダに移す


```GAS:importCSV
var ss = SpreadsheetApp.openById("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
var sheets = ss.getSheets();
var telList = ss.setActiveSheet(sheets[0]);
var date = new Date();

function importCSV() {
  //取得ファイルとディレクトリ
    try {
  var files = DriveApp.getFolderById('xxxxxxxxxxxxxxxxxxxxxxxxxxx').getFiles();
  while(files.hasNext()) {
      var file = files.next();
       Logger.log(files);
       Logger.log(file);
      var data = file.getBlob().getDataAsString("Shift_JIS");
      var csv = Utilities.parseCsv(data);
   
      //指定の列のみシートに移す
      var col1 = Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy/MM/dd hh:mm');
      for (var i = 0; i < csv.length; i++) {
         var col2 = csv[i][7];
         var col3 = csv[i][10];
         var col4 = csv[i][11];
         var col5 = csv[i][14];
         var col6 = csv[i][15];
         var col7 = csv[i][33];
         var col8 = csv[i][34];

        if( ( col7 % 2 ) == 0 ) {// 返品理由区分IDが偶数のデータだけリストにする
         telList.appendRow([col1,col2,col3,col4,col5,col6,col7,col8]);
          }
      }
      
    //転記が終わったらファイルを転記済フォルダに格納
    var destfolder = DriveApp.getFoldersByName('架電リスト転記済').next();
    var sourcefolder = file.getParents().next();
    destfolder.addFile(file);
    sourcefolder.removeFile(file); 
     }
      } catch(e) {
      }
}
```
Firebaseのアプリケーションで複数のプロジェクトを使用する場合、Firebase app named "xxx" already exists.エラーが出る

# はじめに
一つのアプリケーションで複数のFirebaseプロジェクトを利用する際に、最初にServiceAccountを使って初期化するのですが、次に別のファイルとかで使用する際に、同じように初期化しようとすると、すでに同一名で初期化されているとエラーが出ます。
再利用の仕方をドキュメントで見つけられなかったので、備忘録で...

# 参考
- https://firebase.google.com/docs/projects/multiprojects?hl=ja

# 環境
- Node v13.9.0
- npm 6.14.1

# 現象
'Firebase app named "dest" already exists. This means you called initializeApp() more than once with the same app name as the second argument. Make sure you provide a unique name every time you call initializeApp().'
とエラーが出る。

# コード公式(2つ目の別プロジェクトの設定読み込み)(databaseをfirestoreに変更)
```
var admin = require("firebase-admin");

var serviceAccount = require("path/to/serviceAccountKey.json");

var secondaryAppConfig = {
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://<DATABASE_NAME>.firebaseio.com"
};
// Initialize another app with a different config
var secondary = firebase.initializeApp(secondaryAppConfig, "secondary");

// Retrieve the database.
var secondaryDatabase = secondary.firestore();
```

# 上記のsecondaryDatabaseを別のファイルで利用する
```
var admin = require('firebase-admin');
var secondaryDatabase = admin.app("secondary").firestore();
```

以上
pushdはあまり知られていないbashコマンドで使い道が無いコマンドだった

## Pushdはあまり知られていないbashコマンドだ。
Pushdコマンドは、現在のディレクトリをスタックへと保存し、新しいディレクトリへと移動する。

二つのディレクトリを行き来するのに便利だ。

Pushdコマンドの使い方
$ pushd ディレクトリ
もし、ディレクトリを指定しなければ、スタックのトップへと移動する。

# 具体的な使い方
./foo
./bar
という二つのフォルダがルート直下にある。

$ pushd foo
でfooへと移動した後、
$ pushed bar
で、barへ移動する。

その後は、
$ pushd
と打つだけで、foo, barを交互に移動することが出来る。
深い階層のフォルダを行き来出来るのは便利だ。

## 実際の運用
pushdは便利そうに見える。
僕はpushdを使う代わりに二つのディレクトリを２つのエディタで開いている。
こっちの方が便利だったので僕はpushdを使うのを止めた

完
JavaScriptで連想配列から特定のキーだけ抽出


PHPの`array_column($array, 'column')`みたいなことをJavaScriptでやりたいなぁと思ったときのやつ

```javascript

const fruits = [
  {
    id: 1,
    name: "Apple",
  },
  {
    id: 2,
    name: "Banana",
  },
  {
    id: 3,
    name: "Grape",
  },
]

fruits.map(item => item["name"]) // ["Apple", "Banana", "Grape"]
```
Gemfileにおける「>= 」と「~>」の違い

## 背景

Rails初心者の備忘録のため

## 基礎情報

```
gem 'sqlite3'
```

gemコマンドで特定のバージョン番号を指定しない限り、Bundlerは自動的に最新バージョンのgemを取得してインストールする

## 「>=」について

```
gem 'uglifier', '>= 1.3.0'
```

uglifierのバージョンが1.3.0以上であれば最新バージョンのgemがインストールされる。（uglifierはAsset Pipelineでファイル圧縮を行うgem）

## 「~>」について

```
gem 'coffee-rails', '~> 4.0.0'
```

coffee-railsのバージョンが4.0.0より大きく、4.1より小さい場合にインストールされる。 (これもAsset Pipelineで使うgem) 

## 使い分けの理由

マイナーアップグレードですら問題を引き起こすことがあるから。


すべてRailsチュートリアルからの抜粋。完全に備忘録です


参照
https://railstutorial.jp/chapters/beginning?version=5.1#cha-beginning
AIとかHRTechを駆使して伝説の任天堂コンビを復活させたい！


**あつまれ どうぶつの森**発売(直前)記念投稿！

# なれそめ

イントレプレナーキックオフな集まりでは名前順だったり、着想の類似度でチームビルディングされるけど、性格のタイプが違っても噛み合うパートナーって知ってますよね？

Mark ZuckerbergとSheryl Sandberg
Steve JobsとStephen Wozniak
藤子・F・不二雄と藤子不二雄A

##### 名前が似てる？
##### 違う そうじゃ そうじゃない。

### そう、宮本 茂と岩田 聡！！！


# んで？

同テーブルの人への自己紹介とかネットワーキングタイム。あの時間を空振りにしないように**マッチングに使ったら良いじゃない？**


# しでかしたこと

自己紹介を文字起こしからの、**宮本さん度、岩田さん度を分類してマッチングすると強いチームが作れる**はず。なんてったってレジェンドな宮本さん、岩田さんの相性なんだもの。

なので宮本さんと、岩田さんのメディアでの発言をスクレイピングして、**ビジョン・知恵, 教育・学習, 分析・洞察**という大まかな3ジャンルで分類しました。

そこに**同じジャンルで語って頂いて、類似度を判別する**ってことです。


# どうやる？

Web画面から音声認識で各項目について60秒語って頂きます。

![iwamiya2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/b484a357-f460-c4a2-cbe9-1519062a92a4.gif)

全部の項目が埋まったら判定ボタン押しましょう。あなたがどちらのタイプなのか分かりますね？あなたの宮本さん度を埋める岩田さん度の持ち主を探しましょう。

![iwamiya.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/b31ee532-8e8e-fcb6-c73a-00022ed98074.gif)

### イノベーションは目の前です。

# コード

[ここです](https://github.com/yasutakatou/iwamiya)


# あとがき
他のアントレプレナーコンビもスクレイピング足せば判定できるかも？
~~ダジャレがあるとウォズニアックさん度が高まりそうで、ちとそれは・・・~~

#### というかコーパスが足りな過ぎて100%に振り切れてしまいます！残念！！


# 参考情報

### CSSで使いました
[sakura: a minimal classless css framework / theme.](https://oxal.org/projects/sakura/)
blocklyでobjectを動かす。 その7

#概要

blocklyでobjectを動かして見る。
sin波、やってみた。

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d2b158b8-4274-7d68-8439-f8398d73cb0c.png)


#ステージを作る


```
<canvas id="canvas" width="400" height="300"></canvas>
```

#ブロックを書く。


```
Blockly.Blocks.plot = {
	init: function() {
		this.jsonInit({
		message0: "plot %1",
		args0: [{
			type: "input_value",
			name: "TEXT"
		}],
		previousStatement: null,
		nextStatement: null,
		style: "text_blocks",
		tooltip: Blockly.Msg.TEXT_PRINT_TOOLTIP,
		helpUrl: Blockly.Msg.TEXT_PRINT_HELPURL
	})
}};
```

#フローを書く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f7af8041-2cb3-56a0-eb9f-8588e4ed9d31.png)


#objectを書く。

```
Blockly.JavaScript.plot = function(a) {
    return "plot(" + (Blockly.JavaScript.valueToCode(a, "TEXT", Blockly.JavaScript.ORDER_NONE) || "0") + ");\n"
};

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var dx = 0;
var pr = 0;
function plot(data) {
	var hc = 150;
	ctx.strokeStyle = "#f00";
	ctx.lineWidth = 1;
	ctx.moveTo(dx, hc - pr * 60);
	dx++;
	ctx.lineTo(dx, hc - data * 60);
	pr = data;
	ctx.stroke();
}




```

#成果物

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

以上。
あれ？foreign keyがつかない。。



```sql
mysql>     alter table student_course
    ->        add constraint FKq7yw2wg9wlt2cnj480hcdn6dq
    ->        foreign key (student_id)
    ->        references student (id);
```

```bash
 show create table student_course;

| student_course | CREATE TABLE `student_course` (
  `student_id` bigint(20) NOT NULL,
  `course_id` bigint(20) NOT NULL,
  KEY `FKejrkh4gv8iqgmspsanaji90ws` (`course_id`),
  KEY `FKq7yw2wg9wlt2cnj480hcdn6dq` (`student_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |

```

## 原因 > ストレージエンジンがMySAMになってた
MySAMだとforeign keyがつかないのでInnoDBにする


spring bootの設定

```properties
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
```
Ultra 96 v2 に入門する (PetaLinux)

# 0. 概要
2017年頃にPynq-z1がReleaseされ、AIをFPGAで実装することが容易にできるようになった。
その後、さらにLUTの容量が大きいUltra ScaleモデルのUltra96 v1、Ultra96 v2がReleaseされた。
今回は2020年時に最新のUltra96 v2を動作させていきたいと思う。

![006.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/031cb5e9-2afb-5699-510a-f4ea9660a8c6.jpeg)

# 1. Installation
ではUltra96 v2にLinuxをインストールして動作させていきたいと考える。
以下の方法に従ってインストールを行っていく。
https://www.96boards.org/documentation/consumer/ultra96/ultra96-v2/installation/

なお、Ultra 96 v1はついてきたSDカードに既に書き込まれているためこの作業を行う必要はない。

## 1.1 Environment
以下にLinuxインストールをする上で必要なものを列挙する。


 - 本体 Ultra96 v2
 - 電源 12V2A
 - SDカード 16GB以上
 - 作業用のマシン
 - (任意) ディスプレイ表示 Mini-DP 
 - (任意) Ultra96 USB-to-JTAG/UART Pod

## 1.2 Download
以下のURLからDownloadを押しLinuxを得る
[Ultra96-V2 Linux](https://www.96boards.org/documentation/consumer/ultra96/ultra96-v2/downloads/linux.md.html)
解凍して`ultra96v2_oob_2018_3_190917_8GB.img`のファイルが出力されるのを確認する。


## 1.3 Write the IMG to SD
次に解凍したファイルを`dd`コマンドでSDカードに焼く。

``` bash
$ sudo fdisk -l
$ sudo umount <YOUR_DISK>
$ sudo dd if=./ultra96v2_oob_2018_3_190917_8GB.img of=/dev/<YOUR_DISK> bs=64M
```

## 1.4. Run
1をOFF、2をONにしてPWRボタンを押すと起動する

![ultra96-check-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/3d91b97c-5914-26b5-3e98-c382ff852caa.jpeg)


# 2. Serial console
起動後、どのように端末に接続すべきか。
マウスやキーボードをつないでもよいが非常に面倒である。そこでUARTを変換してUSB-Serial通信を行いたい。

以下のUARTをUSBに変換するボードを取り付けUSB接続を行う。

 - (任意) Ultra96 USB-to-JTAG/UART Pod

次に以下のURLから`USB to UART Bridge`をダウンロードしインストールしておく。

https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/6659e6dd-2649-7055-e2a2-18e7c3012f30.png)

後はターミナルから以下のように設定し、接続すればシリアルコンソール接続ができる。

 - baud rate = 115200
 - data bits = 8
 - stop bits = 1
 - flow control = none
 - parity = none

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/301d049b-1db4-c03d-786d-e7b13bb1ab37.png)

こんな感じの画面が出てきたら完了。
`id/pw`は`root/root`である。
トラブったときに参照した記事一覧：Pytnon編

# この記事の目的

開発時にトラブってググったけど、再発時に忘れてるということが多いのでトラブルごとに解決に役立った記事をまとめておく

## DB接続

**カーソル処理をWith句でまとめる**
参照先：[Python+MySQL でコネクションやカーソルと with 文](https://qiita.com/umezawatakeshi/items/6c3483ea0e082f2d8926)

```python
from contextlib import closing
with closing(conn.cursor()) as cursor:
    cursor.execute("SELECT * FROM table")
    rows = cursor.fetchall()
    ...
```
laravel on dockerのimage別速度比較

# 目的
php:fpm-alpineイメージを使ってlaravelを動かしていましたところ、異様にレスポンスが遅かったので調べてみたところこんな話がありました。
https://qiita.com/yoshiken/items/93d170b69d8cb8520bad

どうやらalpineが遅いと。
そこでイメージの選択でどれくらい違いが出るのかを試してみました。

# 比較対象
* alpine
* debian
* centos

# 比較方法
`laravel new`した直後のプロジェクトを`php artisan serve`で起動し、以下の２パターンで比較してみました。

* `/`（Welcomページ)へリクエスト
* `/items`（itemモデルとレコード100件を作って一覧をjsonで返す)へリクエスト

測定には[siege](https://github.com/JoeDog/siege)を利用しています。

# 比較結果

```
$ siege --no-follow -r 10 -c 1 http://localhost:8000
```

| image | response time(s) |
| --- | --- |
| debian | 0.31 |
| alpine | 0.77 |
| centos | 0.81 |


```
$ siege --no-follow -r 10 -c 1 http://localhost:8000/items
```

| image | response time(s) |
| --- | --- |
| debian | 0.19 |
| alpine | 1.90 |
| centos | 1.67 |

意外とcentosでも遅い結果になりました。
原因は何なのでしょうね？alpineとcentosでは動かすためにインストールしたExtensionが似ていたので、Extensionの違いだったりするんでしょうか。。


# 参考
## Dockerfile
```Dockerfile:debian
FROM debian
RUN apt-get update
RUN apt-get install -y php
RUN apt-get install -y php-zip
RUN apt-get install -y php-mbstring
RUN apt-get install -y php-dom
RUN apt-get install -y php-mysql
WORKDIR /app
```

```Dockerfile:alpine
FROM alpine
RUN apk update
RUN apk add php
RUN apk add php-zip
RUN apk add php-mbstring
RUN apk add php-dom
RUN apk add php-phar
RUN apk add php-json
RUN apk add php-openssl
RUN apk add php-session
RUN apk add php-mysqlnd
RUN apk add php-pdo
RUN apk add php-pdo_mysql
COPY php.ini /etc/php7/php.ini
WORKDIR /app
```

```Dockerfile:centos
FROM centos
RUN yum update -y
RUN yum install -y php
RUN yum install -y php-mbstring
RUN yum install -y php-dom
RUN yum install -y php-json
RUN yum install -y php-session
RUN yum install -y php-mysqlnd
RUN yum install -y php-pdo
RUN yum install -y php-pdo_mysql
COPY php.ini /etc/php.ini
WORKDIR /app
```
Amazon Workspaces / AWS Client VPN を多要素認証に対応させる方法

この時期、リモートワークの手段として、Aamzon Workspaces や AWS Client VPN を試そうとしてる方もいるんじゃないかと思います。

どちらも、多要素認証(MFA)が可能なので少しだけ書いておきます。

# Workspaces の MFA について

#### 公式の対応記事
**Multi-Factor Authentication for Amazon WorkSpaces**
https://aws.amazon.com/jp/blogs/aws/multi-factor-auth-for-workspaces/

#### 具体的な方法
**多要素認証による Amazon WorkSpaces の利用**
https://www.slideshare.net/AmazonWebServicesJapan/amazon-workspaces-86568155

以前、こちらの[記事](https://qiita.com/daimatsu/items/75b5924e06a4394b83d2)でAWS Single Sign-On を 多要素認証(MFA) に対応させる方法を書きましたが、多要素認証に対応させる部分は流用できます。方法はほぼ同じで、こちらはAD Connector を使っています。

どちらも、別途RADIUSサーバーを用意してMFAを実現しています。
簡単な流れは次のようになります。

1. 多要素認証用のRADIUSサーバーを用意する
2. AWS Managed Microsoft AD の多要素認証を有効にするか、AD Connector の多要素認証を有効にして、RADIUSサーバを設定に追加する
3. Workspaces で利用するディレクトリとして、多要素認証を有効にしたディレクトリを指定すると


MFAに対応させると、ログイン時にMFAコードを求められるようになります。
![スクリーンショット 0002-03-18 9.52.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323706/507ec96a-73dd-dca9-cf0f-22044bda24f5.png)


# Client VPN の MFA について

#### 公式の対応記事

**AWS Client VPN が Active Directory 用の多要素認証をサポート**
https://aws.amazon.com/jp/about-aws/whats-new/2019/09/aws-client-vpn-now-supports-multi-factor-authentication-for-active-directory/

#### 具体的な方法
Workspaces と同じ手順でAWS Managed Microsoft AD の多要素認証を有効にするか、AD Connector の多要素認証を有効にすればOKです。

[AWSが提供しているClient VPN接続ツール](https://aws.amazon.com/jp/vpn/client-vpn-download/)を使うと、このような感じで接続時にMFAコードを求められるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323706/071c85b2-1d2a-8039-694a-26893c787fc8.png)
Macの仮想環境上でaws-cliが実行できない時の解決方法(Python3.8インストール後)

## 経緯
pythonの仮想環境上で、aws-cliを使用しようと公式のコマンドを実行しようとしても上手くできなかったので、その解決方法の備忘録。
設定を色々いじってもダメだったので全部消してから再インストールしてみました。(2020/03)

## 仕様
Macbook: MacOS Mojave
Python: Python 3.8.0

## aws-cliをインストール
公式に従い、以下を実行

```
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
```

しかし、```$ aws --version``` でバージョン確認したところエラー発生
> cannot execute binary file

## デバッグ
色々試したものの、どれもうまくいかなかったので一度仕様してないファイルはきっちり消すため
```$ rm '/usr/local/bin/aws'```
```$ rm '/usr/local/bin/aws_completer'```
で削除を実行。

そこから

```
$ pip install --user virtualenv
$ virtualenv ~/[仮想環境名]
```
で新たに仮想環境を作成して

```
#仮想環境を activate
$ source ~/[仮想環境名]/bin/activate
```

新しい仮想環境に awscli を pip install

```
([仮想環境名])~$ pip install --upgrade awscli
```
awscli が正しくインストールされたかを確認

```
$ aws --version
```
>aws-cli/1.18.23 Python/3.8.0 Darwin/18.7.0 botocore/1.15.23

インストール成功しました！
この後awsコマンドも正常に利用できていることを確認できました！

## まとめ
色々ググったけれど、公式サイトがなんやかんや最強でした。

参考・引用元
[仮想環境に AWS CLI バージョン 1 をインストールする(公式サイト)](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-virtualenv.html)

(ちなみに私はAWS CLI バージョン 2 をインストールしようとして失敗したので、バージョン 1 をインストールすることで解決しました。)
バージョン 2 インストール公式はこちら↓
[Linux での AWS CLI バージョン 2 のインストール(公式サイト)](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html)
DB間のデータ同期(CDC)出来るツール個人的まとめ

備忘録としてまとめ
※今後書き足し予定

# リアルタイム系
## [OracleGoldenGate](https://www.oracle.com/technetwork/jp/middleware/goldengate/overview/index.html)
oracleからのCDCが出来る
リアルタイムで、ファイル出力も可能
使用するにはoracle側でサプリメンタルロギングの設定が必要


## [Qlik（Attunity）](https://www.qlik.com/ja-jp/products/data-integration-products)
旧Attunity 今はQlinkに買収されQlinkの1サービスになっている？


## [AWS DMS](https://aws.amazon.com/jp/dms/)
AWSのサービスなので、AWSへデータを持ってくる専用
クラウドからの移行などには使えるが、継続的にCDCとして使い続けるには運用厳しそう(?)


## [alooma](https://www.alooma.com/)
googleに買収されたので、そのうちGCPの1サービスとして出てくるかも
買収された直後、データの連携先が絞られたが、今はGCP以外にも連携出来る


## [striim](https://www.striim.com/)
BQ,Redshift,Snowflake,AzureDataLakeなど多くのクラウドへのデータ連携に対応


# バッチ処理系
## [CData](https://www.cdata.com/jp/)
データソースが豊富(100以上)でSalesforceやKintoneのデータを直接BIで見たりも出来る

## [trocco](https://trocco.io/lp/index.html)
Embulkのラッパーサービス　日本製
トラブったときに参照した記事一覧：VSCode編

# この記事の目的

開発時にトラブってググったけど、再発時に忘れてるということが多いのでトラブルごとに解決に役立った記事をまとめておく

## 設定回り

### 自作モジュールのimport時に動作するがエラーが消えない
エラー：unresolved import 'モジュール名'
参照先：[VSCodeで自作モジュールimport時のエラー表示](https://qiita.com/kurikou02/items/beb3d638f93cc372b3c3)

```settings.json
{
    "python.autoComplete.extraPaths": ["./FaceRecognition/"]
}
```
CentOS8からTLS1.0, 1.1 に接続できない

CentOS8から、file_get_contents, wget, curl などで TLS1.1以下のプロトコルを採用しているサーバに接続しにいくと

```
error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol
```

とエラーが出て接続できない

```
update-crypto-policies --set LEGACY
```

とすることで接続できるようになる

参考：
https://stackoverflow.com/questions/58996030/sssd-2-0-0-centos-8-with-old-tls-1-0-only-ldap
Jetson AGX Xavierのセットアップ（JetPack, 日本語入力, ARM版VS Code)

# Ubuntuのセットアップ
## NVIDIA SDK Managerのインストール
JetPackをインストールするための環境は、別のPCにセットアップする必要があります。

ただ、NVIDIA SDK Managerは環境を汚すため、ホストPCに直接入れるのではなく、Dockerなどの仮想環境を利用することが望ましいです。

今回は、Dockerを使った方法を紹介します。

### GitHUbリポジトリからクローン
[こちらの方](https://proc-cpuinfo.fixstars.com/2019/06/nvidia-sdk-manager-on-docker/)が公開してくださっているDockerを利用します。

```
git clone https://github.com/atinfinity/sdk_manager_docker
```

### NVIDIA SDK Managerのダウンロード
[NVIDIA DEVELOPER](https://developer.nvidia.com/nvidia-sdk-manager)から、最新のNVIDIA SDK Managerをサウンロードし、先程クローンしたDockerのフォルダ内に置きます。

### Dockerのビルド
#### 普通の方法
```
docker build --build-arg SDK_MANAGER_VERSION=〇〇 -t jetpack .
```

#### 別の方法
##### Dockerfileの書き換え
Dockerfile内の`ARG SDK_MANAGER_VERSION=〇〇`に、先程ダウンロードしたNVIDIA SDK Managerのバージョンに書き換える。

##### Dockerのビルド
```
docker build -t jetpack .
```

# JetPackのインストール
### Dockerの起動
先程生成したDockerイメージからコンテナを起動します。

```
./launch_container.sh
```
### NVIDIA SDK Managerの起動
```
sdkmanager
```
GUIが表示されるので、NVIDIAアカウントでログインして手順通り進めていけばOK！

# 動作モードの指定＆最大クロックに固定

```
sudo  nvpmodel  -m  0 && sudo jetson_clocks
```
### 参考
http://hiesuke.hatenablog.com/entry/2020/01/09/155431

# 日本語化＆日本語入力のセットアップ
## 日本語化
```
sudo apt-get install -y aptitude && \
sudo aptitude reinstall dbus && \
sudo apt autoremove && \
sudo apt-get update && apt-get upgrade
```
## 日本語入力のセットアップ
```
sudo apt install  -y language-pack-ja-base  language-pack-ja && \
 sudo apt install -y ibus-mozc
```
### 参考
https://demura.net/athome/15471.html

# ARM版Visual Studio Codeのインストール
## terminalをsuperuserで起動
```
sudo -s
```
## ARM版Visual Studio Codeをインストール
```
. <( wget -O - https://code.headmelted.com/installers/apt.sh )
```

## 起動方法
```
code-oss
```

## 参考
https://code.headmelted.com/#linux-install-scripts
学習記録 #1


<h1>学習内容</h1>


<ul>
　<li>progate[ ruby学習コース・I〜V ]</li>

</ul>


<h2>理解したこと</h2>
<ol>
<li>progate[ ruby学習コース・I ]</li>
・っbcbcbcbcbcbcbc<br>
・<br>


<li>progate[ ruby学習コース・II ]</li>
・<br>
・<br>


<li>progate[ ruby学習コース・III ]</li>
・<br>
・<br>

<li>progate[ ruby学習コース・IV ]</li>
・<br>
・<br>


<li>progate[ ruby学習コース・IV ]</li>
・<br>
・<br>

</ol>
OCI Compute(Oracle Linux)の不要なiSCSI情報を削除する

#はじめに
Oracle Cloud Infrastructure(OCI)では、OSが含まれるBoot Volumeの他、追加ディスクとしてBlock VolumeをComputeにアタッチすることができます。

Boot Volumeのアタッチには準仮想化とiSCSIの2種類が選択でき ~~るのですが、パフォーマンスSLAを担保する為にはiSCSIでのアタッチが必要です。マニュアルにもパフォーマンスが早いのはiSCSIと記載があり~~ ます。（実機検証レベルでは変わらないですが）

2021/06/27追記：UHA(Ultra Hight Perfomence)のBlock Volumeがリリースされてから準仮想化でもSLAの対象となり、iSCSIとのパフォーマンス差異はなくなりました。

[マニュアル：ブロック・ボリュームの概要](https://docs.cloud.oracle.com/ja-jp/iaas/Content/Block/Concepts/overview.htm#two)
[Oracle CloudのSLA](https://www.oracle.com/assets/paas-iaas-pub-cld-srvs-pillar-4021422.pdf)

なので、基本的にはiSCSIを選択するのですが、運用が少し面倒です。
iSCSIの場合、OCIでBlock VolumeをマウントしてもOSではまだ見えてこないため、OS内でもiSCSIマウント（OCIコンソールで表示されるコマンドをコピペ）を行う必要があります。

問題になるのが、運用面です。
拡張したい時などでBlock Volumeを切り離す際、OS内でiSCSIをアンマウントせずにOCIでBlock Volumeをデタッチしてしまうと古い情報がOS内部に残ってしまう為、次回同じBlock Volumeをアタッチして、OSでiSCSIマウントする際にマウントできなかったりと色々と問題が出てきます。

また、カスタムイメージの作成時にBlock Volumeをデタッチせずにつくってしまった場合なども。

ここではOS内（Linux) のiSCSI情報をキレイにする手順を案内します。

# 手順

### ①確認

以下で現在のiSCSIデバイスの登録を確認します。
既にファイルシステムも、追加ボリュームも無い（前提）のですが、以下で残存している設定を確認できます。
**iqn.2015-12.com.oracleiaas:99534348-23d7-4bd7-9d1f-9592cc90cd99**　が残っているため削除します。

```
# ls -la /var/lib/iscsi/nodes
合計 4
drwxr-xr-x. 9 root root 4096  2月 19 01:06 .
drwxr-xr-x. 8 root root   90  4月 11  2018 ..
drwx------. 3 root root   32  8月 14  2018 iqn.2015-02.oracle.boot:uefi
drw-------  2 root root   54  2月 19 01:06 iqn.2015-12.com.oracleiaas:99534348-23d7-4bd7-9d1f-9592cc90cd99
```

### ②iSCSI情報削除

以下で情報を削除できます。
（以下で削除できない場合、一旦OSを再起動すると削除できることが多いです）

```
# iscsiadm -m node -o delete -T iqn.2015-12.com.oracleiaas:99534348-23d7-4bd7-9d1f-9592cc90cd99
```

削除後、OSを再起動します。

### ③最後に確認

```
# ls -la /var/lib/iscsi/nodes
合計 4
drwxr-xr-x. 9 root root 4096  2月 19 01:06 .
drwxr-xr-x. 8 root root   90  4月 11  2018 ..
drwx------. 3 root root   32  8月 14  2018 iqn.2015-02.oracle.boot:uefi
```

# 以上
【Ruby on Rails】 検索機能を実装してみた

#はじめに
今回は投稿されたマイクロポストを入力された文字からあいまい検索する機能を追加します。

###作るもの
railsのform_withヘルパーを利用した投稿の検索機能。（題材は自分のポートフォリオ）

###対象読者
railsチュートリアル終了後等に何か機能を追加したい人等。

#作成の流れ
1.対応するビューの作成
2.コントローラーの編集

#1.対応するビューの作成
今回は検索フォームをroot_path上に設けます。（自分のポートフォリオがマイクロポストの一覧をroot_path(static_pages/home)に設けているため）

```ruby:app/views/static_pages/home.html.erb
<%= form_with( url: root_path, class: 'search_form', method: :get, local:true) do |f| %>
  <%= f.text_field :search,class: 'field',value: params[:search]\
  placeholder: "スレ・コメント検索"%>
<%= f.submit '検索', class: "btn" %>
```
form_withを利用して検索フォームを作ります。各値は
url:root_path検索後に表示するページ
method:get(httpメゾット。今回はページの取得なのでget)
local:true(ajax処理（非同期通信）を無効にする。デフォルトではajaxで処理する。)
text_field: search 入力フォームになります。
value: params[:search]と値を設定しておくことで検索後も値を保持します。（URLのクエリから取得。）
あとはget動作を開始させるsubmitを配置します。

検索ボタンを押せばurlのページを表示しようとするので検索の処理は対応するコントローラーのアクション内に書きます。

#2.コントローラーの編集
コントローラーで送られた値を処理しますが、コントローラー内に処理を全て書くとごちゃごちゃしてしまいますのでDBとやりとりをする箇所はmodel側で記述します。

```ruby:app/controller.rb
    @microposts =  params[:search].present? ? Micropost.micropost_serach(params[:search]) :  Micropost.all
```

@microposts =  params[:search].present?で値がsearchに値が入っているか（検索ボタンが押されているか）
値が入っていればmicropost_serachを動作させます。（中身は後ほどmodelに記載）値が入ってなければ、Micropost.allで全てのマイクロポストを表示させます。（そのあとは適宜ページネーション等に渡してください。）
ではmicropost_serachの中身です。

```ruby:app/model/micropost.rb
def self.micropost_serach(search)
    Micropost.where(['title LIKE ?', "%#{search}%"])
end
```
whereメゾットとLIKE旬でマイクロポストの中からあいまい検索をします。


```ruby
モデル名.where([カラム名前　LIKE ?, "検索したい文字列"])
```


検索したい文字列の両サイドにある「%」は任意の複数の文字列を表しています。
上記のは一つしかカラムを指定していませんが複数指定することもできます。

```ruby:app/model/micropost.rb
def self.micropost_serach(search)
    Micropost.where(['title LIKE ? OR content LIKE ?', "%#{search}%", "%#{search}%"])
end
```
複数のカラムを指定する場合はカラム数に応じてORやANDで繋ぎ、検索したい文字列を増やしてあげると検索できます。

今回はさらに、マイクロポストにコメントされた文章も含めて検索してみます。
コメント機能についてこちら
https://qiita.com/E6YOteYPzmFGfOD/items/ef776d34908872ea19f7

```ruby:app/model/micropost.rb
def self.micropost_serach(search)
    Micropost.includes(:comments).where(['microposts.title LIKE ? OR microposts.content LIKE ? OR comments.content LIKE ?',
    "%#{search}%", "%#{search}%", "%#{search}%"]).references(:comments)
end
```

これでコメント内も合わせて検索できるようになりました

＃終わりに
最後までお読みいただきありがとうございました。検索文はいろいろパターンがあるので今後も新しい物を書いたときには記事にしてみようと思います。
ありがとうございました。
なぜjavaでfinal class A{abstract class B{}}が許されるのか

javaでは、抽象メソッドを持つクラスは必ず抽象クラス(かインタフェース)になると決まっている。
**しかし抽象内部クラスを持つクラスは、別に具体的クラスでも構わないのである**。

例えば次のようなコードは実行可能である。


```java:java
final class A
{
    static abstract class B{String str="hoge";}
}

public class Main
{
    public static void main(String...args)
    {
        System.out.println(new A_B().str);
      //System.out.println(new A.B(){}.str); (匿名クラス)でも別に良い
    }
} 

class A_B extends A.B{}
```

# もし具体クラスが抽象内部クラスを持てなかったら

一見矛盾する仮定ではありますが、「マクロ(全体)に多様性を認めたくないが、ミクロ(細部)に多様性を認めたい」という場合を考えます。

このような仮定は統計力学など、ミクロとマクロの関連を考えるとき役立ちます。

例えば`Air`(空気)クラスと`Molecule`(分子)クラスを作ったとします。

分子が集まって空気を作りますので、`Air` has a `Molecule[]` といえるでしょう。

分子には水素分子、水分子、二酸化炭素分子等いろいろ考えられます。
したがって、
`H2 extends Molecule`, `H2O extends Molecule`, `CO2 extends Molecule`
のように継承して使う一方、「単なる分子」という分子は存在しないので、継承せずに使うことはないと思います。
そこで`Molecule`は抽象クラスとなりそうです。

一方、`Air`には下位概念が考えにくいので、抽象クラスにしたくはありません。

ここでもし、**`Molecule`に`Air`からしか呼ばれたくないメソッドを定義したくなったら**どうしましょう。

いつもなら`Molecule`を`Air`のインナークラスにすることで解決できます。
もし具体クラス`Air`が、抽象クラス`Molecule`を内部に持てなかったら、多分次のような面倒くさいことをしなくちゃいけない。

1. `final public static class ${private $(){}}`を`Air`に持たせる
2. `Something`のメソッドに`Air.$ `型引数を持たせる

で実現する。

`Air.$`型は`public static`で`Air`以外からも見えるため、`Air`以外のクラスのメソッドの仮引数型として利用できる。
しかしそのコンストラクタは`private`なので、インスタンス生成は`Air`からしか行えない。`Air`以外はすなわち`Air.$`型実引数を渡せない。

そのおかげで、「仮引数に`Air.$`型を持つメソッドならば、そのメソッドは`Air`クラスからしか呼べない」が成立する。

実例を以下に示す。

```java:
public class Test2 {

	public static void main(String[] args) 
	{

        //new H2O.only_for_air(new Air.$()); はアクセス権限のエラー。つまりAir以外からonly_for_airを呼べない
		new Air().molecule_caller(new H2O());//Airからは呼べる

	}

}



class Air
{
	final public static class ${private $(){}}//Airの子クラスで書き換えされても困るのでfinalizeした
	
	void molecule_caller(Molecule m)
	{
		new H2O().only_for_air(new Air.$());
	}
	
	
}

abstract class Molecule
{
	void only_for_air(Air.$ $)
	{
		System.out.println("succeeded");
	}
}


class H2O extends Molecule{}

```

とまあ、こんな面倒なことをしなくちゃいけなくなる。

だから「抽象内部クラスを持つ具体的クラス」がjavaでは可能なんだろうなと思った次第。
DockerのMySQLコンテナが、Docker Toolbox上で起動に失敗するエラーの対処法

## 概要
### 事象
MySQLが動くDockerコンテナを、docker-composeで立ち上げようとしたところ、コンテナが永遠に再起動(restart)を繰り返す事象が起こりました。この問題の解決方法を、ここにメモしておきます。

ちなみに、私はWindows上でDocker Toolboxを用いていた時にこの問題が起こりましたが、それ以外の環境だとこの問題は起こらなさそうです（おそらく）。
### docker-compose.ymlの設定
docker-compose.ymlのうち、この問題が起こる部分の設定は以下のようになっています。

```yaml
  db:
    image: mysql:5.7
    volumes: 
      - "/tmp/db/data:/var/lib/mysql"
      - "./db:/usr/src/db"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
      MYSQL_DATABASE: $MYSQL_DATABASE
      MYSQL_USER: $MYSQL_USER
      MYSQL_PASSWORD: $MYSQL_PASSWORD
    ports:
      - 3306:3306
```
特別な設定は何もしておらず、単純に`mysql:5.7`のイメージをベースに必要最低限の設定をしているのみです。
## 対処法
立ち上がったコンテナ内で、`--innodb-use-native-aio=0`を実行させます。なので、docker-compose.ymlは以下のようになります。

```yaml
  db:
    image: mysql:5.7
    volumes: 
      - "/tmp/db/data:/var/lib/mysql"
      - "./db:/usr/src/db"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
      MYSQL_DATABASE: $MYSQL_DATABASE
      MYSQL_USER: $MYSQL_USER
      MYSQL_PASSWORD: $MYSQL_PASSWORD
    ports:
      - 3306:3306
     command: --innodb-use-native-aio=0 # <- これ！
```
### なぜこれで解決するのか
[MySQLの公式ドキュメント](https://dev.mysql.com/doc/refman/5.7/en/innodb-linux-native-aio.html)には、以下のような記述があります。
> InnoDB uses the asynchronous I/O subsystem (native AIO) on Linux to perform read-ahead and write requests for data file pages. This behavior is controlled by the innodb_use_native_aio configuration option, which applies to Linux systems only and is enabled by default. 

InnoDB(MySQLのためのデータベースエンジン)はデフォルトでLinuxの非同期I/O(native AIO)を用いるように設定されていますが、この挙動は`innodb_use_native_aio`オプションで変更できます。

今回私はWindows上でDocker Toolboxを用いてコンテナを動かしていたのですが、その場合だとこの非同期I/Oが利用できないため、エラーが起こり再起動が繰り返されていたようです。そのため、公式ドキュメントの上に引用した部分に書いてある通り、`innodb_use_native_aio`オプションで非同期I/Oを用いないように設定して、この問題を回避する必要があります。

### コンテナの再起動について
コンテナが再起動するのは、私がdocker-compose.ymlに`restart:always`を書いているからです。それ以外の場合は、普通にコンテナが落ちると思われます。
WebベースAlloyツール　Sterling 紹介

ある程度試したら加筆したいと思うのですが..

Web ベースの Alloy ビジュアライザー [Sterling](https://sterling-js.github.io/) 良さそうですね
AlloyAnalyzer の UI をブラッシュアップしたものと言えるでしょう
どんなことができるのかは [tour](https://sterling-js.github.io/tour/) を見ると良いでしょう

# 参考

- [Sterling](https://sterling-js.github.io/)
【自分メモ】MySQLトラブルシューティング

# TS01
## 現象
SQL実行時、以下のエラーが発生。

```
Syntax error or access violation: 1055 Expression #124 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'カラム名' which is not functionally dependent on columns in GROUP BY clause;this is incompatible with sql_mode=only_full_group_by
```

## 解決方法
my.cnfに以下を定義する。

```my.cnf
[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

```

### Dockerを利用している場合

```docker-compose.yml
mysql:
  image: mysql:5.7
  command: mysqld --sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
  〜以下省略〜
```

## 参考

- [MySQL5.7にアップデートしたらonly_full_group_byでエラーになった](https://www.p-nt.com/s/technicblog/archives/204)

# T02
## 現象
日本語が文字化けする。

## 解決方法
my.cnfに以下を定義する。

```my.cnf
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

[client]
default-character-set=utf8
```

### Dockerを利用している場合

```docker-compose.yml
mysql:
  image: mysql:5.7
  command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
  〜以下省略〜
```

## 参考

- [Dockerで立ち上げたMySQLにログインすると日本語が文字化け](https://qiita.com/luccafort/items/0553c589dcc6459746bc)

# TS03
## 現象
INSERT、UPDATE時に以下のエラーが発生する。

```
Incorrect string value: '\xF0\xA6\x9A\xB0\xE7\x94...' for column 'my_column' at row 1
```

## 解決方法
[TS02](#t02)の対応のみだと、既存テーブルには反映されないので、個別に変更してあげる。

```
ALTER TABLE <テーブル名> CONVERT TO CHARACTER SET <文字コード>;
```

## 参考

- [MySQL の「Incorrect string value」エラーを直す (サロゲートペアに対応した UTF8MB4 エンコーディングに変更する)](https://neos21.hatenablog.com/entry/2018/09/12/080000)

- [MySQLでテーブルとカラムの文字コードを一括で変更する](https://camcam.info/tips/3441)
UbuntuServer構築にあたって詰まったところ

初めてやった時に大体詰まるんじゃないだろうかと思われるところを纏めたメモです。
アプリやらDB実装についてはまたの機会に。

～やること～
仮想環境(VMでもVirtualboxでもhyper-Vでも良いです)の上にUbuntuのserverEditionを乗っけます。
Tera Termでもログイン出来る様にはしますが、初期設定なのでコンソールを使用。

以降手順的メモ。

その1:OSインストール編
以下のサイトでisoファイルを入手しました。
https://www.ubuntulinux.jp/download

それぞれの環境にあったものをダウンロードしてください。
※恐らく初期構築の中で一番時間がかかります。
後は外部メディアに焼く(あれば何かと便利なので強く推奨)か、適当なフォルダに保存。

その2:実際に構築してみる
仮想環境側の準備を先に整えましょう。
CPU、メモリ、ディスク割当などなどのリソースを、実装するスペックに合わせて設定します。(仕様書があるならそれに従う)
この時に、使用するisoファイルの選択を忘れぬ様注意。
※実装出来るスペックについては、使用する母艦(物理マシン又はクラウド)に依存するため、それ以上の各リソース割当は不可


その3:レッツマウント
仮想マシンの電源を入れると、先に選択していたメディア(isoファイル)が起動します。

後はメディアの指示に従って作成していく。

以上┏〇゛

※抜け漏れあったら後日追記します
Pub/Sub中のProtocol Buffersメッセージを覗いてみる

デバッグ時などに知っていると便利です。



# 準備
[チュートリアル](https://developers.google.com/protocol-buffers/docs/pythontutorial)のメッセージで試しています。

```
from protocol_example import addressbook_pb2
from google.cloud import pubsub_v1

person = addressbook_pb2.Person()
person.id = 1234
person.name = "John Doe"
person.email = "jdoe@example.com"
phone = person.phones.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME

publisher = pubsub_v1.PublisherClient()
topic_path = publisher.topic_path("プロジェクトid", "トピック名")
publisher.publish(topic_path, person.SerializeToString())
```


# 定義ファイルが無い場合

```
gcloud --format=json pubsub subscriptions pull "サブスクリプション名" | jq -r .[].message.data | base64 -D | protoc --decode_raw                                               
1: "John Doe"
2: 1234
3: "jdoe@example.com"
4 {
  1: "555-4321"
  2: 1
}

```


# 定義ファイルがある場合

```
gcloud --format=json pubsub subscriptions pull "サブスクリプション名"| jq -r .[].message.data | base64 -D | protoc --decode tutorial.Person  protocol_example.pb2
name: "John Doe"
id: 1234
email: "jdoe@example.com"
phones {
  number: "555-4321"
  type: HOME
}
```



# 補足
ちょっとややこしいので補足です：

[gcloud pubsub subscriptions pull](https://cloud.google.com/sdk/gcloud/reference/pubsub/subscriptions/pull)

* デフォルトではackしないので、安心して使えます
 * ackしたい時は--auto-ack
* メッセージがあったとしても取れる件数にばらつきがある（一件も取れない時もある）ので注意です
 * "Please note that this command is not guaranteed to return all the messages in your backlog or the maximum specified in the --limit argument. Receiving fewer messages than available occasionally is normal. "
* formatオプションを指定すると下のようなjson形式で取れます
 *  （gcloudの大体のサブコマンドで使えます）

```
[
  {
    "ackId": "TgQhIT4wPkVTRFAGFixdRkhRNxkIaFEOT14jPzUgKEUQC1MTUVx2E0kQazNcdQdRDRh1fTRwOwlCAQNCWX5VWwk8aH58dAdUDBh7fWh2bFobBgRDW1ar3OiojJOCRB1tNZj6iKJASt7drYV3Zhg9XBJLLD5-PThFQV5AEkw2DURJUytDCypYEQ",
    "message": {
      "data": "CghKb2huIERvZRDSCRoQamRvZUBleGFtcGxlLmNvbSIMCgg1NTUtNDMyMRAB",
      "messageId": "1051190936087668",
      "publishTime": "2020-03-16T23:27:40.736Z"
    }
  }
]
```


jq

* ↑のJSONからメッセージの中身を取るために使っています
* デフォルトでは出力にダブルクオートが付くので、rオプションで外しています

protoc

* カレントディレクトリの時は良いのですが、相対ディレクトリを参照するにはIオプションで指定します
 * `protoc --decode tutorial.Person  ../protocol_example.pb2`ではなく、`protoc --decode tutorial.Person  -I=../ protocol_example.pb2`
* パッケージが定義されている時は、そこから指定（tutorial.Person）する必要があります
WKWebViewへの移行が完了してもアプリにはUIWebViewが潜んでいるかもしれない

# はじめ
先日、アプリで使用しているWebViewを非推奨APIとなっているUIWebViewからWKWebViewへ移行しました。
これでアプリ内からUIWebViewはいなくなりました。
と思っていたのですが、それでもAppleから「UIWebViewを使わないでね」という連絡がやってきてしまいました。
> Dear Developer,
We identified one or more issues with a recent delivery for your app, <アプリ名>. Your delivery was successful, but you may wish to correct the following issues in your next delivery:
ITMS-90809: Deprecated API Usage - Apple will stop accepting submissions of apps that use UIWebView APIs starting from December 2020 . See https://developer.apple.com/documentation/uikit/uiwebview for more information.
After you've corrected the issues, you can upload a new binary to App Store Connect.
Best regards,
The App Store Team

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306587/bc7ec220-26cf-b7ab-5fa8-c31f4a905785.png" alt="メールを持っている人のイラスト（男性）" width="300px">

プロジェクト内を「UIWebView」で検索したところPods内のAFNetworking/UIKitがヒットしました。
原因はAFNetworking/UIKitに含まれているUIWebViewの拡張機能でした。
これからプロジェクトを修正してUIWebViewを根絶やしにしていきたいと思います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306587/84290656-322a-ec1e-79f7-c260fff669cb.png" alt="粗探しのイラスト" width="400px">

# 修正方針

AFNetworkingの[issue](https://github.com/AFNetworking/AFNetworking/issues/4428)を参考に修正します。
issueでは以下の修正方法などが紹介されています。

* AFNetworking/UIKit内のUIWebViewに関するファイルを削除する方法
* 不要な依存関係(AFNetworking/UIKit)を削除する方法

前者はチーム開発の場合に各々がファイルを削除することになり、ミスに繋がると思いました。
また、Pods内を編集すること自体にも抵抗があります。
今回は後者の方法で修正することにしました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306587/225511ab-0289-61ee-6598-1677b9f3cd99.png" alt="修学旅行のイラスト「地図を見て道を探す子供達」" width="500px">

# 修正

まずは、Podfileの該当行を修正します。
`'UIKit'`以外の必要なsubspecsを指定します。

```txt:Podfile
# pod 'AFNetworking'
# ↓
pod 'AFNetworking', :subspecs => ['Reachability', 'Security', 'Serialization', 'NSURLSession']
```

そして、インポートするファイルが変わるためアプリ側のソースも合わせて修正します。

```objc
// #import "AFNetworking.h"
// ↓
#import <AFNetworking/AFNetworking-umbrella.h>
```

最後に、`pod install`すれば問題なく動くはずです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306587/a0100578-3c87-9a36-0101-13a7e9864aa3.png" alt="機械のメンテナンスをする人のイラスト" width="400px">

# まとめ
アプリでUIWebViewを使用していないのにもかかわらず、Appleから連絡が来てしまう場合はライブラリが原因かもしれません。
ライブラリのissueを確認するなどして対応するといいと思います。
今後、UIWebViewが含まれているアプリはリジェクトされるようになります(新規アプリは2020年4月、アップデートは2020年12月から)。
本記事がアプリ開発の助けになれば幸いです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306587/71011878-0c57-b5e5-1bfc-5d53f8ac1f3f.png" alt="スマートフォンのアプリのイラスト" width="400px">

# 参考

[審査に出したiOSアプリが ITMS-90809 としてAppleから問題を指摘される話](https://qiita.com/YutoMizutani/items/2b5185c84c31edfdc2d4)
JavascriptのDate型の注意


月計算で何度も出くわしたので、注意書きとしてメモしておく。

## 月取得

getMonthで月を取得できるが返り値は0からはじまっている。  
つまり、1月の場合は0、10月の場合は9が出力される。

```javascript:月の取得
> var today = new Date();
  // Tue Mar 17 2020 14:00:11 GMT+0900 (日本標準時)
> var month = today.getMonth() + 1; // 現在の月を表すために +1 する
  // 3
```

ちなみにgetDateの返り値は1から始まる。

```javascript:日の取得
> var tosay = new Date();
  // Tue Mar 17 2020 14:00:11 GMT+0900 (日本標準時)
> var date = today.getDate();
  // 17
```

## おまけ

実際に試してみると違いを体感できます。  

```javascript
> var testDate1 = new Date("2020-02-02 00:00:00");
  // Sun Feb 02 2020 00:00:00 GMT+0900 (日本標準時)
> var testDate1.getMonth();
  // 1

> var testDate2 = new Date("2020","02", "02", "00");
  // Mon Mar 02 2020 00:00:00 GMT+0900 (日本標準時)
> var testDate2.getMonth();
  // 2
```