OmniAICreator/Qiita-1.07M huggingface dataset:
[Rails]ポリモーフィック関連で、特定のクラスに依存した処理を書くのはやめよう

# まずはNGなコードから

前提:

・メール通知機能を実装する
・通知を表すモデルは `Notification` とする
・通知機能は `User` `Company` `Customer` `Admin` 等、メールアドレスを持つモデル全てが通知対象の候補となる
・`Notification` と通知対象モデルはポリモーフィック関連を持つ

↑この条件で以下のようなコードを書くのはやめましょう。

```ruby:app/models/notification.rb
class Notification < ApplicationRecord
  belongs_to :notifable, polymorphic: true

  # 通知処理の実装
  def notify
    # 送信先取得処理
    # ここのように is_a? でクラス名を見て分岐するのがNG
    to = if notifable.is_a?(User)
           notifable.email
         elsif notifable.is_a?(Company)
           notifable.company_settings.email
         elsif notifable.is_a?(Customer)
           notifable.email
         elsif notifable.is_a?(Admin)
           notifable.email
         end

    # メール送信処理
    send_mail(to: to)
  end
end
```

# 何故良くないのか？

今はまだ比較的シンプルですが、機能追加がされるたびに `notify` メソッドに処理が集中して、コードが読みづらくなります。
例えば以下の仕様が追加されたとしましょう:

- User, Company, Customer は通知をunsubscribeできる（インターフェースはそれぞれ違う）
- Admin は email がからのことがある。その場合はAdmin共用のアドレスに通知する

```ruby:app/models/notification.rb
class Notification < ApplicationRecord
  belongs_to :notifable, polymorphic: true

  # 通知処理の実装
  def notify
    # 通知不要の対象に送信しない処理
    is_unsubscribe = if notifable.is_a?(User)
                       notifable.user_settings.unsubscribe?
                     elsif notifable.is_a?(Company)
                       notifable.company_settings.unsubscribe?
                     elsif notifable.is_a?(Customer)
                       notifable.unsubscribe?
                     end
    return if is_unsubscribe

    # 送信先取得処理
    to = if notifable.is_a?(User)
           notifable.email
         elsif notifable.is_a?(Company)
           notifable.company_settings.email
         elsif notifable.is_a?(Customer)
           notifable.email
         elsif notifable.is_a?(Admin)
           notifable.email.presence || "developers@hoge.com"
         end

    # メール送信処理
    send_mail(to: to)
  end
end
```

こうなるとだんだん複雑になってきました。
実際の業務では更に細かい条件分岐があとから追加されることが多く、コードが一箇所に集中してカオスになることが多いです。



# こうならないためには？

ダックタイピングを使い、特定のクラスに依存した処理は移譲しましょう。
具体的には:

```ruby:app/models/notification.rb
class Notification < ApplicationRecord
  belongs_to :notifable, polymorphic: true

  # 通知処理の実装
  def notify
    return if notifable.unsubscribe_notification?

    to = notifable.notifable_email

    # メール送信処理
    send_mail(to: to)
  end
end
```

```ruby:app/models/user.rb
class User < ApplicationRecord
  def unsubscribe_notification?
    user_settings.unsubscribe?
  end

  def notifable_email
    email
  end
end
```

```ruby:app/models/admin.rb
class Admin < ApplicationRecord
  def unsubscribe_notification?
    false # admin には常に通知を送るので false 固定
  end

  def notifable_email
    email.presence || "developers@hoge.com"
  end
end
```

```ruby:app/models/company.rb
class Company < ApplicationRecord
  def unsubscribe_notification?
    company_settings.unsubscribe?
  end

  def notifable_email
    company_settings.email
  end
end
```

こうすることで処理が一箇所に集中してカオスになるのを防ぐことができます。
SeleniumとAppiumを一緒に使う。

#SeleniumとAppiumを同じテストで使う。
記事にする程の事かと悩んだが一応、実績という事で投稿します。

- 状況: Webアプリで操作ができるテスト対象機器がWindowsでのクロスプラットフォームで動作する。

-  やったこと：WebアプリもWindows上のアプリもPythonで動かしテスト自動化したくなったため、SeleniumとAppiumを同一プログラムで動かした。

一瞬悩んだのはappiumもseleniumジュール名が同じ **webdriver**であることだけ。

```python
import appium.webdriver as appiumdriver
import selenium.webdriver as webdriver
```
で名前を解決すれば問題なし。


環境：
Windows10
Python 3.7
Appium Python Client 1.1.0
selenium 3.141.0
Kotlinでカスタムしたダイアログからコールバックを受ける

#レイアウトをカスタムしたダイアログからコールバックを受ける
・自分で作ったレイアウトをダイアログアラートに適応します。
・ダイアログでOKボタンが押されたら、メインアクティビティでコメントをprintlnします。


```Kotlin:MainActivity.kt
//ダイアログ側で設定したインターフェースを実装
class MainActivity : AppCompatActivity(), TestDialogFragment.TestDialogListener {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //ダイアログの起動ボタン
        val btn = findViewById<Button>(R.id.button)
        btn.setOnClickListener {
            //カスタムダイアログを起動
            val dialog = TestDialogFragment()
            dialog.show(supportFragmentManager,"test")
        }
    }

    //ダイアログのコールバック
    override fun onDialogPositivClick(dialog: DialogFragment) {
        println("カスタムダイアログでokボタンが押されました。")
    }
}
```

次にカスタムしたダイアログフラグメント用のクラスファイルを作成します。

```Kotlin:TestDialogFragment
//カスタムダイアログフラグメント
class TestDialogFragment : DialogFragment() {

    //コールバックするためのインターフェース
    interface TestDialogListener{
        fun onDialogPositivClick(dialog: DialogFragment)
    }
    var mListener:TestDialogListener? = null

    //ダイアログを生成
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = Dialog(requireContext())
        val dw = dialog.window
        dw?.let {
            it.requestFeature(Window.FEATURE_NO_TITLE)
            it.setFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
            )
            it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
        }

        //自作したダイアログのカスタムレイアウトをセット
        dialog.setContentView(R.layout.customdialoglayout)

        //ダイアログのOKボタンのクリックリスナー
        val ok_btn = dialog.findViewById<Button>(R.id.ok)
        ok_btn.setOnClickListener {
            //メインアウティビティのコールバックを呼ぶ
            mListener?.onDialogPositivClick(this)
        }
        return dialog
    }


    //メインアクティビティをキャスト
    override fun onAttach(context: Context) {
        super.onAttach(context)
        try {
            mListener = context as TestDialogListener
        } catch (e: ClassCastException) {
            Log.e("test", "ホストアクティビティにインターフェースが実装されていません。")
        }
    }
}
```

ダイアログのレイアウトはこのコードでいうと、
R.layout.customdialoglayout
にあたります。
適当に作成してください。
DOMとは。

#【DOMとは。】

MDN Web Docs [DOMの紹介](https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model/Introduction)で学習しました。

##DOM（Document Object Model）

Webサイトを動的に書き換える技術。
HTMLやXML文書のためのプログラミングインターフェイス。
　→　<strong>ドキュメントをモノとして扱っているモデル</strong>

ページを表現するためにプログラムが文書構造、スタイル、内容を変更する。
JSなどで記述されたプログラムからHTMLページにアクセスをして、ページを操作する。

##DOMのモデルは文書を論理的なツリーで表現

DOMのモデルは文書を論理的なツリーで表現する。
ツリーのそれぞれの枝はノードで終わっており、ノードがオブジェクトを含んでいる。
DOMのメソッドでプログラム的にツリーにアクセスできることにより、文書構造やスタイルやコンテンツを変更することが可能な仕組みになっている。

特定のノードを基準にした場合に、その上が親ノード、その下が子ノード、同じ階層が兄弟姉妹ノードと表現される。

##DOMは特定のプログラミング言語に依存しない。

DOMは特定のプログラミング言語に依存しないように設計されている。
文書の構造表現を単一の一貫したAPIから利用可能である。

WEBページとプログラミング言語を繋ぐ役割を持っている。
FlutterからCloud Functionsをhttpトリガーでcallしようとした時にハマった話

# 結論
Flutter側でリージョンを指定してるのにも関わらずうまくいかない！ってときは、
`httpsCallable('関数名')`の中に入れる関数名が正しいかを確認しましょう！
**※CloudFunctions内で定義した関数名そのままでは正しくない可能性があります！**

# 起こった問題
Stripeのセッションを作成するためにCloudFunctionsにてAPIを実装し、FlutterからhttpトリガーでCloudFunctionsを実行させる時に下記エラーに直面しました。
Flutterでは`cloud_functions`ライブラリを使用

https://pub.dev/packages/cloud_functions

私の場合、`createRegattaCheckout`という関数をCloudFunctions側で定義し、Flutterから呼び出そうとしています。

```typescript:CloudFunctions
import * as functions from 'firebase-functions';

export const createRegattaCheckout = functions
    .region(locationName)
    .https.onCall(async (data, context) => {
    // 中身は省略
}
```

```dart:flutter
import 'package:cloud_functions/cloud_functions.dart';

final functions = FirebaseFunctions.instanceFor(app: Firebase.app(), region: 'asia-northeast1');
final callable = functions.httpsCallable('createRegattaCheckout');
final results = await callable.call();
```

しかし下記エラーにてスタック！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635010/848bf6dd-a835-fdda-bc66-67787be098d5.png)

[エラーメッセージ]
`Unhandled Exception: [firebase_functions/3840] データのフォーマットが正しくないため、読み込めませんでした。`

# 試したこと
下記記事を参考に、Flutter側でリージョンを指定（`region: 'asia-northeast1'`）してみました。。
がうまくいかず。。。

https://qiita.com/unbam/items/2012cbd41d4ee457d9c9

# 解決策
Flutterの`httpsCallable('関数名')`部分において、関数名を修正する。
（私の場合、`createRegattaCheckout-createRegattaCheckout`でした。）
関数を`index.ts`内に記述しているのではなく、モジュールに分けていたことが原因かも。。

Firebaseが実際に認識している関数名を入れる必要がある。

### 関数名の確認方法

#### 1. Firebase Consoleから確認
Firebase Consoleの`Functions`タブ内のダッシュボードをみると実際にFirebaseが認識している関数名を確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635010/f8ccc40f-766e-818a-d7ec-b30d8fe5e1f8.png)

#### ２. デプロイ時のログから確認

```console
$ firebase deploy --only functions:createRegattaCheckout
<省略>
i  functions: uploading functions in project: createRegattaCheckout-createRegattaCheckout(asia-northeast1)
i  functions: updating Node.js 12 function createRegattaCheckout-createRegattaCheckout(asia-northeast1)...
✔  functions[createRegattaCheckout-createRegattaCheckout(asia-northeast1)]: Successful update operation. 
<省略>
```

# 最後に
結果的にはしょうもないことでしたが、自分は地味にハマって辛かったので、
同じ思いをする人がいませんようにと本記事をまとめました。
AWSでcloud9でWordPressサイト制作を行うとき、MySQL起動しない？

AWSでcloud9を使って、WordPressでウェブサイトを作ろうとしました。
UbuntuのOSを選択して、インスタンスを作りました。

MySQLのバージョン確認しました。
```bash
$ mysql --version                                                                                         
mysql  Ver 14.14 Distrib 5.7.33, for Linux (x86_64) using  EditLine wrapper
```
 

cloud9が起動したので、ターミナルからMySQLを起動しようとしたら、エラーになりました。

```bash
$ sudo service mysqld start
Failed to start mysqld.service: Unit mysqld.service not found.
```

MySQLサーバーがインストールされていないのでは？ということで解説されたネット記事も、ありました。
でも、MySQLサーバーをインストールしても、変わりませんでした。

```bash
$ sudo apt install mysql-server mysql-client
```

結局ルートのパスワード設定のコマンドを入力したら、MySQLが使えるようになりました。

```bash
sudo mysql_secure_installation
```


こちらの記事を参考にしました。

https://qiita.com/houtarou/items/a44ce783d09201fc28f5


https://qiita.com/acecrc/items/a72992a17968d3d9bc00#mysql%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E7%A2%BA%E8%AA%8D
MikanOS を AArch64 で動かしたい（環境構築編）

引っ越しました。

https://github.com/uchan-nos/os-from-zero/wiki/kaz399;-AArch64%E5%90%91%E3%81%91%E3%81%AE%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E6%89%8B%E9%A0%86
アジャイル開発初心者がチームに入ってやること

# 記事を書こうと思ったきっかけ

今日はこちらのセミナ＝に参加させて頂きました。

![スクリーンショット 2021-03-23 21.00.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031281/c2cb5c2a-1de9-05dd-f86f-86db19493413.png)

アジャイルという言葉の意味も分からず参加したので、どういう内容になるかが全く分かりませんでした(そんなこと書いてて恥ずかしくないの)

が、様々勉強になることがありましたので、備忘録的な立ち位置共に、共有させて頂きます。
読んでくれる方、いつもお目汚し下さりありがとうございます！(SMみたいな御礼の仕方)

# 読者対象者
- まだまだ技術力、知識がないのにアジャイル開発のチームに入ってしまった場合に、自分はどう振る舞えばいいのかわからない！
- いずれそういうことになりそう！

そんな方にオススメの内容だと思います。
確かに、そういう状況になったら内心ドキドキですし、何ならリスクを考えすぎて「動かない」という選択肢を取ってしまいそうですよね・・・。周りの方も先輩しかいない訳ですし。

そんな状況に思いを馳せながら、それでは早速アクション内容をどうぞ！

# １，先輩にくっついてアクション！
#### 1.1 質問しまくる
→チームに新人を入れるのはプロジェクトの責務でもあるとのことなので、新人としては、そこも踏まえてガツガツ質問するのも仕事！でもその質問も何がなんだか分からなかったら・・・


#### 1.2 分からないと言う
→意外とベテランは何が分からないのかが、もうわからないとのこと。もう昔のこと過ぎて、わからないことが何かが想像つかない。「聞かないってことは分かってるってことでしょ？」みたいになっちゃう！

なので！

**「分かりませーーーーーん！」**

という発言するだけでもチームの為になりやすいとのこと。

「あ、それって分かりづらいんだ？じゃあもうちょっと仕組み変えていかなきゃね〜。」「そだね」

みたいな気付きになるそうです。

へ〜！そうなんだ！ですよね。ここは意外でした。あ、でもその下のほうがもっと意外だったw


#### 1.3 ぶっちゃけ思ったことを言う
→「残業毎日大変っすねこのチーム」ってざっくばらんに嫌味なく言ってみるのもあり(心の綺麗さが必要そうだと思いましたがw　私は言えません٩(๑´3｀๑)۶)


# 2, 外部のイベントに参加する
#### 2.1 自分の立ち位置、レベルがもっと明確になるとのこと
→自分のレベルがチーム内で低いのか対外的に低いのかがわかるだけでも、動き変わりそうですね。

ここから下は私は全く聞いたことない世界でした(*^^*)

# 3, テストコードを書けるようにする
#### 3.1 そこがエンジニアの基礎知識みたいなところ
→アジャイル開発の基礎らしい

#### 3.2 どこいっても飯食えるようになる

#### 3.3 オススメ教材
https://www.amazon.co.jp/テスト駆動開発-Kent-Beck/dp/4274217884
Udemy
テスターちゃん
https://www.amazon.co.jp/dp/4822282511

# 結論
最後ざっくりで、私もまだまだ何も分かっていないところですが、載せさせて頂きました！
他にも様々な質問に答えられていて、ふだん実務として働かれている方が聞いたら、よりためになるんだろうなと思いました。

むしろ働かれている人がこれ見たら文章内容が

わけわかめちゃん☆彡

かもしれませんが、温かい目で見てやって下さい。

以上です！

(私の書き方のせいで、本来のセミナーの魅力を落としてしまっていたら非常に申し訳ないです。回答頂いている皆さんは、丁寧に、分かりやすく、質問者の立場も踏まえて様々な角度から回答されていらっしゃいました。)
DjangoでTodoアプリ作成その4urlの設定

####一覧画面のボタンにurlを設定する。

href="{% url 'detail' item.pk %}"では、urlというdjangoの機能を使用して'detail'画面に遷移することを指定している。'detail'はurls.pyのnameで指定している。item.pkはDBから取得してきたデータのオブジェクトリスト（object_list）のプライマリーキーのこと。

```template/list.html
{%  extends 'base.html' %}
{% block header %}
<div class="container">
  <div class="bg-warning p-3 p-sm-5 my-4 rounded">
    <h1 class="display-4">Todolist</h1>
    <p class="lead">Todolistを作って毎日を効率的に過ごしましょう。</p>
</div>
{% endblock %}

{% block content %}
    <div class='container'>
    {% for item in object_list %}
        <div class="alert alert-{{ item.priority }}" role="alert">
        <p class="fs-1">{{ item.title }}</p>
        <a class="btn btn-info btn-sm" href="{% url 'update' item.pk %}" role="button">編集</a>
        <a class="btn btn-info btn-sm" href="{% url 'delete' item.pk %}" role="button">削除</a>
        <a class="btn btn-info btn-sm" href="{% url 'detail' item.pk %}" role="button">詳細</a>
        </div>
    {% endfor %}
    </div>
{% endblock %}
```

```todo.urls.py
urlpatterns = [
    path('list/', TodoList.as_view(), name='list'),
    path('detail/<int:pk>', TodoDetail.as_view(), name='detail'),
    path('create/', TodoCreate.as_view(), name='create'),
    path('delete/<int:pk>', TodoDelete.as_view(), name='delete'),
    path('update/<int:pk>', TodoUpdate.as_view(), name='update'),
]
```
【Flutter】IconDataでビルドエラー cannot tree shake icons（備忘録）

# ビルドエラー
```
$ flutter build apk --release --flavor production --dart-define=FLAVOR=production
Running "flutter pub get" in castlinxmobile...                      3.3s
You are building a fat APK that includes binaries for android-arm, android-arm64, android-x64.
If you are deploying the app to the Play Store, it's recommended to use app bundles or split the APK to reduce the APK size.
    To generate an app bundle, run:
        flutter build appbundle --target-platform android-arm,android-arm64,android-x64
        Learn more on: https://developer.android.com/guide/app-bundle
    To split the APKs per ABI, run:
        flutter build apk --target-platform android-arm,android-arm64,android-x64 --split-per-abi
        Learn more on:  https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split

This application cannot tree shake icons fonts. It has non-constant instances of IconData at the following locations:
  - lib/screen/aaaa/xxxx.dart:624:31
  - lib/screen/aaaa/yyyy.dart:139:35

FAILURE: Build failed with an exception.
  ```

## 原因の箇所
```
IconData(0xea62, fontFamily: 'MaterialIcons'),
```
どうやら、IconDataを指定しているのが原因のよう

# 対処法
オプションに
**--no-tree-shake-icons**
を指定する

## 下記実行結果
```
$ flutter build apk --release --flavor production --dart-define=FLAVOR=production --no-tree-shake-icons

You are building a fat APK that includes binaries for android-arm, android-arm64, android-x64.
If you are deploying the app to the Play Store, it's recommended to use app bundles or split the APK to reduce the APK size.
    To generate an app bundle, run:
        flutter build appbundle --target-platform android-arm,android-arm64,android-x64
        Learn more on: https://developer.android.com/guide/app-bundle
    To split the APKs per ABI, run:
        flutter build apk --target-platform android-arm,android-arm64,android-x64 --split-per-abi
        Learn more on:  https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split
注意:/usr/local/bin/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core-0.7.0/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.javaは非推奨のAPIを使用またはオーバーライドしています。
注意:詳細は、-Xlint:deprecationオプションを指定して再コンパイルしてください。
注意:/usr/local/bin/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_analytics-7.0.1/android/src/main/java/io/flutter/plugins/firebaseanalytics/FirebaseAnalyticsPlugin.javaは非推奨のAPIを使用またはオーバーライドしています。
注意:詳細は、-Xlint:deprecationオプションを指定して再コンパイルしてください。
Running Gradle task 'assembleProductionRelease'...
Removed unused resources: Binary resource data reduced from 802KB to 802KB: Removed 0%
Running Gradle task 'assembleProductionRelease'...
Running Gradle task 'assembleProductionRelease'... Done           183.8s (!)
✓ Built build/app/outputs/flutter-apk/app-production-release.apk (69.3MB).
```

# 参考記事
https://stackoverflow.com/questions/63335694/this-application-cannot-tree-shake-icons-fonts/63412500
DjangoでTodoアプリ作成その4UpdateView

####UpdateView

データを更新するときに適したテンプレート

####templateの作成

```template/update.html
{% extends 'base.html' %}

{% block content %}
    <form action="" method="POST">{% csrf_token %}
        {{ form.as_p}}
        <input type="submit" value="更新します">
    </form>
{% endblock content %}
```

####urls.pyの編集

```todo/urls.py
from django.urls import path
from .views import TodoList, TodoDetail, TodoCreate, TodoDelete, TodoUpdate

urlpatterns = [
    path('list/', TodoList.as_view(), name='list'),
    path('detail/<int:pk>', TodoDetail.as_view(), name='detail'),
    path('create/', TodoCreate.as_view(), name='create'),
    path('delete/<int:pk>', TodoDelete.as_view(), name='delete'),
    path('update/<int:pk>', TodoUpdate.as_view(), name='update'),
]
```

####view.pyの編集

```views.py
from django.views.generic import ListView, DetailView, CreateView, DeleteView, UpdateView

class TodoUpdate(UpdateView):
    template_name = 'update.html'
    model = TodoModel
    fields = ('title', 'memo', 'priority', 'duedate')
    success_url = reverse_lazy('list')
```
[JS] メソッドとプロパティ

###プロパティ
(　)で終わらないものがプロパティです。

```
let hello = 'hello world';
console.log(hello.length);
```

[![Image from Gyazo](https://i.gyazo.com/3c61468ab6842064b94bc6d246e5d1de.png)](https://gyazo.com/3c61468ab6842064b94bc6d246e5d1de)

###メソッド

console.log(hello.~~~(　))のように、.で始まり(　)で終わるものがメソッドです。
ブラウザがデフォルトで持っている機能をネイティブのメソッドと呼びます。

##substring, slice
指定の数字分だけ、文字列を切り取るメソッド

```
let hello = 'hello world';
console.log(hello.substring(0, 4));
```

[![Image from Gyazo](https://i.gyazo.com/851bfa38c1c397ac6d4f8169d81c96ea.png)](https://gyazo.com/851bfa38c1c397ac6d4f8169d81c96ea)

---

```
let hello = 'hello world';
console.log(hello.substring(1));
```

[![Image from Gyazo](https://i.gyazo.com/26484656276b656455199603ef65302e.png)](https://gyazo.com/26484656276b656455199603ef65302e)

split
---
文字を分割するメソッド
配列のデータ型に変換される

```
let hello = 'hello world';
console.log(hello.split(''));
```

[![Image from Gyazo](https://i.gyazo.com/73902a99b479bba14443cd640bea120b.png)](https://gyazo.com/73902a99b479bba14443cd640bea120b)

---

```
let hello = 'hello world';
console.log(hello.split('  '));
```

[![Image from Gyazo](https://i.gyazo.com/92012433453a30785541f46f8cc86b8f.png)](https://gyazo.com/92012433453a30785541f46f8cc86b8f)
ARMのgdbでloadしたら"load failed."と言われるとき

症例：

```
(gdb) load
Loading section .vectors, size 0xc0 lma 0x8000000
Loading section .text, size 0xa644 lma 0x80000c0
Load failed.
```

.binファイルのサイズを見てみよう。flashに収まらないサイズになっている。
Pandas df.to_sqlのプライマリキー

#困りごと

Pandasのdataframeをsqliteに保存しようとしています。

いくつかのEXCELシートをdfに入れた後、```df.to_sql```の追加操作でappendしております。

その際に、```index_label='id'``` を指定すると、
テーブルを空にしている状態では、問題なくidが生成しますが、
さらに別のデータを追加しようとすると、idが最初から振り直されてしまいます。

このid列をプライマリーキーにして、すでにある連番とは異なるユニークな値になるようにして、
書き込むには、どうすればよいのでしょうか？

別のPandas からの書き込み方法があれば、```df.to_sql```以外でも結構です。

```
def df_write_to_sql(df,model,mode="replace"): #省略時は置き換えとする、アペンド時はmode="append"とすること

    df.to_sql(name=name,con=engine,if_exists=mode,index_label='id')

```

```
一つ目のデータ

0	AP	AD
1	AP	AD
...
258	ORS	OTH
259	ORS	PL
260	ORS	DI
261	ORS	EX

二つ目のデータ　

0	AP	C-L　　　→　262として書き込みたい
1	AP	C-L　　　→　263　　〃
2	AP	C-L　　　→　264　　〃
3	AP	C-L　　　→　265　　〃

```


#解決策

丸1日悩んで結論を得た。

下記が参考になった。
https://stackoverflow.com/questions/54808848/pandas-to-sql-increase-tables-index-when-appending-dataframe


###ポイント
* プライマリーキーにオートインクリースをつける
* to_sqlのindex=Falseにする

こうすると、pandasはindexを無視してDBに書き込むことになる。
→　そもそもPKと言うものは、データベース側に委ねるというのがセオリーであった。
It would be nice to have a way to delegate auto-indexing to the database. 

```
 id = db.Column(db.Integer, primary_key=True,autoincrement=True)
 df.to_sql(name=name,con=engine,if_exists="append",index=False)
```
コンマでリストunpack（Python）

忘れやすいのでメモ

リストを変数に代入するとき、変数名の後にコンマを入れるとUnpackされたものが代入される

知らないとタイポにみえてしまう。

```python
array = [[0, 1, 2]]
array

>>> [[0, 1, 2]]

array, = [[0, 1, 2]]
array

>>> [0, 1, 2]
```

Googlabity低めながする。


参考

https://stackoverflow.com/questions/17853680/animation-using-matplotlib-with-subplots-and-artistanimation

https://note.nkmk.me/python-tuple-list-unpack/
[Swift5]'SegementSlide'を用いたスマートニュース風タブの実装方法

## 今回やること
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643372/df6eb843-f62b-95ca-beef-24720edc4ab0.gif)

動画のようにスライドで遷移できるタブ（スマートニュース風タブ）の実装をおこないます。
[参考リンク](https://github.com/Jiar/SegementSlide)

## SegementSlideのインストール
```swift
pod 'SegementSlide', '3.0.1'
```

今回は`Cocoa Pods` を用いて実装します。

## ベースとなるControllerの作成

`SegementSlide`はメインとなるControllerを作成し、その配下でControllerを管理します。
また、インスタンス化をすれば配下でstoryboardを管理することもできます。

```swift
import UIKit

// ライブラリのインポート
import SegementSlide

// 各ViewControllerを扱うクラス
class SegementViewController: SegementSlideDefaultViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // SegementSlideの更新
        reloadData()
        
        // SegementSlideの初期位置（最左）
        defaultSelectedIndex = Count.zero
    }
    
    // MARK: - SegementSlideの設定
    // スライドのタイトルを決める
    override var titlesInSwitcher: [String] {
        return ["翻訳ページ", "履歴ページ", "メニュー"]
    }
    
    // スライドにControllerを返す（今回はstoryboardをインスタンス化しています）
    override func segementSlideContentViewController(at index: Int) -> SegementSlideContentScrollViewDelegate? {
        
        // withIdentifier == storyboardID
        switch index {

        case Count.zero:
            let homeVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "homeVC") as! HomeViewController
            return homeVC

        case Count.one:
            let recordVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "recordVC") as! RecordViewController
            return recordVC

        case Count.two:
            let menuVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "menuVC") as! MenuViewController
            return menuVC

        default:
            let homeVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "homeVC") as! HomeViewController
            return homeVC
        }
    }
}
```

これで各ControllerはSegementSlideのは以下で管理されます。
割とシンプルに実装することができます。

ぜひ参考にしてください！
データベースってなんぞ？？

#まず始めに
　エンジニアをしていると必ず、耳にする**データベース**について
　改めて、まとめてみました！
　
#データベースとは？？
　情報である**データ**を使いやすい形に整理したかたまりのことを**データベース**といいます。
　コンピュータ上のソフトウェアのイメージが多いですが、電話帳や単語帳などもデータベースの一種です。
　また、コンピュータ上でデータベースを管理するシステムや、
　そのシステム上で扱うデータ群のことを、データベースと呼ぶ場合もあります。

　Webサービスの基本的なサーバー構成(Web3層構造)には、必ずデータベースが含まれています。

#データベースのメリットとは？
　データベースを用いると下記のようなメリットが得られます。
　　・**データの統一**
　　　　1か所にデータをまとめているため、複数のユーザー間でデータの矛盾がなくなります。
　　・**データの活用**
　　　　データベースにアプリケーションを組み合わせれば、必要なデータを見やすく加工して表示できます。
　　・**管理の簡略化**
　　　　データベース1つｍのバックアップで大量のデータを保存でき、様々なリスクに備えることができます。

#データベース管理システム(DBMS)
　データベースを安全に共有・利用しやすくするためのシステムを
　**データベース管理システム（Database Management System：DBMS）**といいます。
　ユーザがデータベースへアクセスするときは、DBMSを間においてアクセスします。
　主な役割として
　　・データベースの操作・管理
　　・アクセスの制御、処理
　　・障害時の復旧
　
#SQL
 データベースを操作するための言語を**SQL**といい、DBMS上でデータの追加や削除、並べ替えなどを行うようコンピュータに命令するための手段です。基本的に１行ずつ入力して確定し、直ちに実行されます。複数のSQLを組み合わせて大きな一つの塊のSQLとして実行することもできますが、通常のプログラミング言語のように一連の操作をまとめてセットすることのできる「ストアドプロシージャ」という機能のあるDBMSもあります。

　どのデータベースであっても基本的には共通の命令を使用していますが、そのDBMS専用のSQLなども存在しています。

####※ストアドプロシージャ
　if文の条件分岐やfor文のループをSQLと組み合わせて、データベースを操作することのできるDBMSの機能。

 主に機能のちがう3種類の言語から成り立っています。

　・データ操作言語（DML）・・・データを操作する言語
　　　INSERT・・・データを挿入する
　　　SELECT・・・データを取得する
　　　UPDATE・・・データを更新する
　　　DELETE・・・データを削除する
　・データ定義言語（DDL）・・・データベースやテーブルを操作する言語

　　　CREATE・・・データベース/テーブルを作成する
　　　DROP・・・データベース/テーブルを削除する
　　　ALTER・・・データベース/テーブルを変更する
　・データ制御言語（DCL）・・・主にデータベースの権限を管理するための言語

　データベースの構築や運用といった場面では、SQL文（SQLの構文）を単体で実行して利用します。

#データベースの種類
　データベースには主に以下ような種類があります。
　　・リレーショナル型データベース
　　・階層型データベース
　　・ネットワーク型データベース
　
###リレーショナル型データベース(RDS)
　主流のDBMS。行と列からなる表で表されたデータベースです。
　列にはそれぞれ重複しない項目名が設定され、行としてデータを追加していきます。
　表にすることによって、人間の目で見ても関係性がわかりやすくなっています。
　この表を**テーブル**といい、列を**カラム**、行のデータを**レコード**といいます。

###階層型データベース
　ツリー構造をとっており、名前の通りデータが階層のように構成されているデータベースです。
　特定のデータを検索する際には常に一つのルートのみしかないため、速度が非常に速いです。
　しかし、横のつながりと持てない為、多数の要素を持ったデータはその分重複登録が必要で
　対応できる状況や情報の編集に対して柔軟性が低いというデメリットがあります。

###ネットワーク型データベース
　階層型データベースの重複登録を避けるようにネットワーク構造を採用したデータベースです。
　しかし、検索開始が最上階のノードからに限定で使用できるため、
　リレーショナル型ほどの利便性はないです。

#DBMSの種類
　代表的なDBMSの製品として以下のような種類があります。
　　**Oracle(Oracle Database)**…有償でサポートが充実。世界で最もシェアが高く、クラウド版有。
　　**MySQL**…無償と商用利用のしての有償版がある。Wordpressなどに使用されている。
　　**SQL Sever**…有償だがOracleよりは安価。Microsoft社開発のため、windowsとの相性がいい。
　　**PostgreSQL**…MySQLとともに、人気の無償DBMS。バランスよく機能が実装されている。

#最後に
　今回はデータベースについてまとめてみました。
　WEBサービス、アプリケーションの開発をおこなう中で必須といっていいほど、
　データベースはとても密接に関わってくるため、今後も学習、理解を深めようと思います。
　次はDBMSの製品それぞれの特徴などをまとめようと思います。
DjangoでTodoアプリ作成その３DeleteView

####DeleteView
データを削除するときに適したテンプレート

####テンプレートの作成

```template/delete.html
{% extends 'base.html' %}

{% block content %}
    <form action="" method="POST">{% csrf_token %}
        <input type="submit" value="削除します">
    </form>
{% endblock content %}
```

####urlsの編集

```todo.urls.py
from django.urls import path
from .views import TodoList, TodoDetail, TodoCreate, TodoDelete

urlpatterns = [
    path('list/', TodoList.as_view(), name='list'),
    path('detail/<int:pk>', TodoDetail.as_view(), name='detail'),
    path('create/', TodoCreate.as_view(), name='create'),
    path('delete/<int:pk>', TodoDelete.as_view(), name='delete'),
]
```

####views.pyの編集

```views.py
from django.views.generic import ListView, DetailView, CreateView, DeleteView

class TodoDelete(DeleteView):
    template_name = 'delete.html'
    model = TodoModel
    success_url = reverse_lazy('list')
```
Linux　基本的なコマンド2

#touch
ファイルのタイムスタンプの変更

**touch [オプション] ファイル名**

-t ファイルの更新時刻を指定する

タイムスタンプはlsコマンドの-iオプションをつけることで確認可能

#head,tail
ファイルの一部の取得

###head
ファイルの先頭部分を標準出力をする

**head [オプション] ファイル名**

-n 行　先頭から指定した行を標準出力する
-n バイト　先頭から指定したバイト分を標準出力する

###tail
ファイルの終わり部分を標準出力する

**tail [オプション] ファイル名**

-n 行　末尾から指定した行を標準出力する
-n バイト　末尾から指定したバイト分を標準出力する

特別なオプション　-f
このオプションをすることで、変更をリアルタイムでモニタすることが可能

**tail -f ファイル名**

#sort
テキストファイルの中身をソートする

**sort [オプション] ファイル名**

-r 逆順でソート
-k n　n行目のデータをソート
-n　数値としてソート

#uniq
行の重複の消去、同じ内容は出力しない。

**uniq ファイル名**


#tr
文字列の置き換え

**tr 文字列１ 文字列２**

#diff　
ファイルの比較、変更の有無を調べる場合の用いられる

**diff [オプション] ファイル1 ファイル2**

-c context diff形式で差分を出力
-u unified diff形式で差分を出力

context形式は1つ目のファイルの内容と2つ目のファイルの内容を別々に出力
unified形式は1つ目のファイルの内容と2つ目の内容を合わせた状態で出力
SQLの基本構文その2

下記のようなテーブルがあったとする。

![スクリーンショット 2021-03-23 20.03.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182751/27dbd68b-2ee4-d5a8-c39e-7c1bf378f8c7.png)

なお、idカラムは「AUTO INCREMENT(データを追加すればレコードに自動的に付与される)」ものとする。

<h2>テーブルを見たい場合</h2>

```
SELECT *
FROM jojo;
```

SELECT周りは以下の記事でテクニック的なものをまとめています。

https://qiita.com/RikiLog/items/836bb5e1832acfeab414


<h2>新しくレコードを追加したい場合</h2>
(例)ナランチャ・ギルガのデータを追加したい時


```
INSERT INTO jojo(name, part, part_name, type, stand) 
VALUES('ナランチャ・ギルガ', 5, '黄金の風', '仲間', エアロスミス);
```
というように、テーブル名と()の中に追加したいもののカラムを指定。
valueの()の中には、それぞれカラムの値を指定。

なお、指定していないカラムにはnullが自動的に入る。

![スクリーンショット 2021-03-23 20.15.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182751/71f6d199-218a-d2b9-668a-afbcb2c69392.png)

<h2>既にあるレコードの中身を変えたい時</h2>
(例)id = 3(ジョセフ・ジョースター)のstandを変えたい時


```
UPDATE jojo
SET stand = 'ハーミット・パープル'
WHERE id = 3;
```

なお、WHEREで条件を指定しないと、jojoテーブルに入っている全レコードのstandが変わってしまうので注意。
stand以外にも変えたい場合は、SETの箇所をコンマで区切って一斉に変更することができる

![スクリーンショット 2021-03-23 20.21.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182751/bd5eac4f-6a72-46b6-865b-4c3841d641c4.png)

<h2>すでにあるレコードを削除したい場合</h2>
(例)id=17(ディオ・ブランドー)を削除したい場合


```
DELETE FROM jojo
WHERE id = 17;
```
![スクリーンショット 2021-03-23 20.31.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182751/845fd84a-d0d9-05a6-1a7e-40aa818f44ee.png)


なお、WHEREで条件を指定しないと、テーブルが全部消えるので注意。
ellipsisに記号を使いたい。CSSのみでやりたい

文字が見切れた時に「...」を表示するellipsis。
これを「...」じゃないほかの何かを表示したいことがあった。
ググっても出てこなかったので自分で作ってみた。ので公開する。

ちなみにJSを使いだすと画面サイズ変わったイベントとかいちいち取らないといけないのが面倒なのでCSSだけでやりたい

---
## 見切れた時に★を表示するサンプル

[サンプル(codepen)](https://codepen.io/wlljuodg-the-sasster/pen/xxgxojX)

見切れた時、文末に★が出る。
![e1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234002/805aeb83-4484-07d1-da3b-7db2b0f06c73.png)

↓
![e2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234002/ea325894-a880-5ef8-0405-1fe97a6f8905.png)


## HTML
```html
<div class="container">
  <div class="long_text">
    長いテキスト長いテ長いテキスト長いテキスト長いテキスト長いテキスト長いテキスト長いテキスト長いテキスト長いテキスト長いテキストキスト長いテキスト
  </div>
  <div class="ellipsis">
    ★
  </div>
</div>
```

## CSS
```css
.container {
  width: 100%;
  height: 24px;
  overflow: hidden;
}

.long_text {
  padding-right: 24px;
}

.ellipsis {
  width: 24px;
  margin: -48px 0 0 auto;
}
```

## しくみ

- ★は.ellipsisのCSSで指定しているネガティブマージンによって-48px上にずれて表示されている。
で、.containerの外はoverflow: hiddenによって見えなくなっているので長いテキストが全部見えているときには上にずれてる★は見えない。

- 幅が縮んで長いテキストが折り返されるとテキストの後ろにおいてある★も折り返されて一段下に降りてくる。
そうすると.containerの表示領域内に入ってくるので★が表示される。
折り返された先のテキストはoverflow: hiddenによって見えなくなる。

- ★はmargin: autoによって常に右寄せになっているので、「...」の位置的な所に★が表示される。

- 長いテキストのお尻には★を表示するため１文字分paddingを入れてある

- 英語とか混ざる場合は単語折り返しを無効にしないと変な感じになるかも
さくらのオブジェクトストレージで空バケットが消えない


```:エラーメッセージ
MultipartUploadsRemaining, Multipart uploads remain, delete them beforehand.
```

# アップロード時のゴミを消しましょう

[マルチパートアップロード](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/mpuoverview.html)の残骸が残っている模様
表示されないがバケット内には存在するので消してあげる必要がある

コントロールパネルからは触れないのでAWS CLI（API）を使う
AWS CLIの初期設定は省略。

```console:残骸を一覧表示
$ aws s3api list-multipart-uploads --bucket【バケット名】 --endpoint-url=https://s3.isk01.sakurastorage.jp
{
    "Uploads": [
        {
            "UploadId": "8s7seb5t64v78s7seb5t64v7",
            "Key": "example.zip",
            "Initiated": "2021-02-01T00:00:00.554000+00:00",
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "339277735285",
                "ID": "8s7seb5t64v78s7seb5t64v78s7seb5t64v78s7seb5t64v78s7seb5t64v7"
            },
            "Initiator": {
                "ID": "arn:aws:iam::396873998292:user/controlled/root/root",
                "DisplayName": "root"
            }
        }
    ]
```

表示された残骸を一個ずつ消す。

```console:残骸を削除
$ aws s3api abort-multipart-upload --bucket 【バケット名】 \
  --key 【Key値】 \
  --upload-id 【UploadId値】 \
  --endpoint-url=https://s3.isk01.sakurastorage.jp
```

全部消し終わったらコントロールパネルに戻ってバケット削除♪
DjangoでTodoアプリを作成その２

#### CreateView
データを新しく作るときに適したテンプレート

TodoCreateクラスを作成する。
fieldsで作成する入力フォームの要素を指定する。
success_urlはフォームをPOSTしたあとに表示するページを指定する。
reverse_lazyは表示するページを指定するための便利な関数。

```views.py
from django.urls import reverse_lazy

class TodoCreate(CreateView):
    template_name = 'create.html'
    model = TodoModel
    fields = ('title', 'memo', 'priority', 'duedate')
    # リバースとは逆回し。
    success_url = reverse_lazy('list')
```

urls.pyにcreateを追加。name=を指定することで、reverse_lazy関数の引数に指定することができるようになる。

```todo/urls.py
from .views import TodoList, TodoDetail, TodoCreate

urlpatterns = [
    path('list/', TodoList.as_view(), name='list'),
    path('detail/<int:pk>', TodoDetail.as_view(), name='detail'),
    path('create/', TodoCreate.as_view(), name='create'),
]

```

{% csrf_token %}はセキュリティ対策用。
form.as_pはｐタグでフォームを作成するという意味。

```create.html
{% extends 'base.html' %}

{% block content %}
    <form action="" method="POST">{% csrf_token %}
        {{ form.as_p}}
        <input type="submit" value="作成する">
    </form>

{% endblock content %}
```
ReactでGoogle Calendar連携を超簡単に実装する方法

## 概要

今回はReactでGoogle Calendar連携を実装する際に便利な[react-google-calendar-api](https://www.npmjs.com/package/react-google-calendar-api)というパッケージを紹介します。
このパッケージを利用するだけ**超簡単**にGoogle Calendar連携を行うことができます！

## 事前に

### アプリの作成
[Reactのアプリを作成](https://create-react-app.dev/docs/getting-started/)しておいてください。

### Calendar APIの準備
[こちら](https://developers.google.com/calendar/quickstart/js)からClient IDと API Keyの取得をしてください。
[Google Cloud Platform](https://console.cloud.google.com/?hl=ja)の「APIとサービス」>「認証情報」からも設定可能です。

## 実装

### APIの設定

プロジェクトのルートに```apiGoogleconfig.json```作成し、情API報を記載します。
Scopeはcalendar.eventsとしていますが、実際には[こちら](https://developers.google.com/calendar/auth)を参考に用途に応じて設定してください。
*本番用にAPI申請する場合、こちらのScopeが必要最低限の設定になっていないとリジェクトされます。

```
{
  "clientId": CLIENT＿ID,
  "apiKey": API_KEY,
  "scope": "https://www.googleapis.com/auth/calendar.events",
  "discoveryDocs": ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"]
}
```

### インストール
パッケージをインストールします。

```
npm install --save react-google-calendar-api
```

### 取得処理

1.パッケージを読み込む
2.認証チェック
2’.認証していなければOAuth認証
3.イベントの取得

```
// 1.パッケージを読み込む
import ApiCalendar from "react-google-calendar-api";
import './App.css';

function App() {
  const getEvents = async () => {
    return new Promise(async (resolve, reject) => {
      // 2.認証チェック
      if (ApiCalendar.sign) {
         // 3.イベントの取得
         ApiCalendar.listEvents({
            timeMin: new Date().toISOString(),
            timeMax: new Date().addDays(10).toISOString(),
            showDeleted: true,
            maxResults: 10,
            orderBy: 'updated'
          }).then(({ result }) => {
            if (result.items) {
              console.log("Events From Calendar", result.items);
            } else {
              console.log("No Events")
            }

            resolve(result);
          });
      } else {
        // 2’.認証していなければOAuth認証
        ApiCalendar.handleAuthClick();

        resolve(null);
      }
    })
  };
  
  return (
    <div className="App">
      <button onclick="() => getEvents()">Get Events</button>
    </div>
  );
}

export default App;

```

### 取得結果

![スクリーンショット 2021-03-20 22.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542018/bfbe2c96-3d47-838f-46dd-31c43b55a227.png)


### 他にも

イベント取得以外にもGoogle Calendarに関する処理を簡単に実装できます。
下記はカレンダー情報を更新する例です。

```
    const event = {
      description: "detail", // 詳細
      summary: "ミーティング", // タイトル
      start: { date: tartDate }, // 開始日
      end: { date: endDate }, // 終了日
    };
    await ApiCalendar.updateEvent(event, EVENT_ID);
```

## まとめ

react-google-calendar-apiを利用すれば超簡単にGoogle Calendar連携ができることをわかっていただけたと思います。
ぜひ活用してみてください！
また、データベースの予定とカレンダーから取得した予定の差分取得をlodashで行う方法を[こちら](https://qiita.com/k8m/items/fe84cf9b58460a3a30e1)に書いているので、よければこご覧になってください。

<br>
- Miyata Koki -
[O:inc.](https://o-inc.jp/)でAmplify×React×React Nativeを使用して開発しています。大学のゼミでは統計学をPythonで行っています。
インターンやゼミで学んだ情報を発信していくので、フォロバもしますのでぜひこちらのアカウントのフォローお願いします！
Linux基本

#標準入出力
Linuxには、標準入力・標準出力・標準エラー出力がある
**標準入力**：プログラムに入ってくるデータ
**標準出力**：プログラムの実行結果を書き出す先のこと
**標準エラー出力**：エラーメッセージを書き出す先のこと

#リダイレクト
コンソールに標準出力された文字列はリダイレクトを使ってファイルに書き込むことができる

###出力のリダイレクト
「**>**」を使ってリダイレクトできる

例
ls>ls-yamada

コマンド実行すると、la-yamadaというファイル作成される。中身確認するとlsを実行したときと同じ内容が含まれている

#grepコマンド
ファイルの中からデータを検索する

**grep [オプション] 検索条件 [指定ファイル]**
検索条件としては正規表現が用いられる

-e　文字列を検索のパターンとして扱う
-i　検索パターンと入力ファイルの双方で、英大文字と小文字の区別行わない
-v　検索パターンとマッチしなかった行を選択する
WiFiの通信量ページから判断して接続先SSID切替える

Nuro光の工事が3か月たっても終わらないので
諦めてWiFiとキャリアのテザリング回線を使い倒す環境作っていく。


memo:
*WiFiはキャッシュされた情報を使いまわすため指定プロファイルで接続できない事が多い。
対策として、つなぎ直す前にインターフェースを一旦無効化しwlanscanを発生させることにした。* 

###環境
Windows10 ノートPC。
事前にWiFi接続して使用するSSIDのプロファイルが保存されている必要があります。

**WiFiの回線** *SSID "GroupWiFi_xi0aouh"*
1日最大10GB。１バイトでも超えると容赦なく128kbpsに切り替える。
回線状態は ttps://192.168.65.1/status_info_iframe.html に表示されていることを確認ずみ。

**テザリング回線** *SSID "なぜここがわかった"*
mineoの500kbps使い放題。Youtubeも最低画質にすれば見れる。

###実装
タスクスケジューラで10分ごとに次のPowershellを実行します

```Powershell
#netshで接続中のSSIDを取得
$text =(netsh wlan show interface | Select-String "プロファイル  ")
#3/26 検索文字に半角スペース足した

if($text.ToString().Contains("GroupWiFi_xi0aouh")){
    #HTMLを取得
    $html=(Invoke-WebRequest http://192.168.65.1/status_info_iframe.html)

    #現在の使用量が書かれているクラスの値を取得
    $bytes=($html.ParsedHtml.getElementsByClassName("ui-em-20")|Select-Object innerText)

    #10GB超えてたらテザリング回線に切り替え
    if($bytes.innerText.Contains("10.")){
        #WLANキャッシュ対策
        netsh interface set interface name=Wi-Fi admin=disabled
        netsh interface set interface name=Wi-Fi admin=enabled
        Start-Sleep -s 2
        netsh wlan connect name="なぜここがわかった"
    }
}
```

はやく光の工事きてくれーーー！！
cssで@charset "UTF-8"に関するエラー「at-rule or selector expected」

初学者です。出会ったエラーを軽くアウトプットしていきます。

# 開発環境
PHP 7.3.9
MAMP 5.7
Mysql 5.7.26
Laravel 6.20.7

# エラー内容
vsコード内にて`public/scc/app.scc`のステータスバーにある"問題"で__「at-rule or selector expected」__という表示がある。
viewには特に問題なく表示されている。

＊ただし、過去に同様のエラーがあった際はviewで何らかのエラーが出ていたと記憶しています。
再現性がなくて申し訳ないです。

# 原因
単純に__`@charset "UTF-8";`__という文字コードが2行目でこのように定義されていたのが原因です。

```app.css

@import url(https://fonts.googleapis.com/css?family=Nunito);@charset "UTF-8";
```

# 解決法
`@charset`の文字コード定義は必ず1行目かつ`@charset`の前には何も書いてはいけないので、

```app.css
@charset "UTF-8";
@import url(https://fonts.googleapis.com/css?family=Nunito);
```
こうすれば解決します。

正直、何が原因で`@charset "UTF-8";`が2行目になってしまっているのか特定できてないですが、
laravel/uiパッケージをインストールした後、スカフォールドを生成。ターミナルで`npm install`を実行してフロントエンド開発に必要な依存パッケージをインストールして`app.css`が作成された段階ですでに`@charset "UTF-8";`が2行目になっているので適宜修正するしかないかと...
どのポートがどう使われているか調べたい

Linux(CentOS)でどのポートがどのプロセスに使われているか調べる必要があったので。
備忘録的に記載します。

## ssコマンド
### 使い方
```
ss [オプション][フィルター]
```
よく使うオプションは以下です。

  -  -4 IPv4のソケットだけを表示(IPv6なら-6になります)
  -  -t tcpソケットを表示
  -  -u udpソケットを表示
  -  -l 接続待ち状態（LISTEN）状態のソケットだけを表示する
  -  -n サービス名の名前解決を行わない（ポート番号で表示）
  -  -p ソケットを使用しているプロセスも表示する

こんな感じで使います。当然ながらオプションは連続して書いてOK。

```
ss -p4tuln
```

## lsofコマンド
たまにssコマンドで-nをつけても名前解決してくれないポートがあるときに使っています。本来は開いているファイルを一覧表示するコマンドですが、オプション指定でネットワークソケットを対象にすることができ、どのファイルが使われているか調べることができるので対象のポートが何をしているのか分かります。


流れとしては  
ssコマンドで使用されているポート番号を調査→このポート番号名前解決されないな、何に使われているんだろう　
　
という気持ちの時です。

### 使い方
```
lsof [オプション][パス名]
```

ポート番号が分かっている前提ですが、こんな感じで使います。

```
lsof -i:80(調べたいポート番号)
```
<br>
<br>
まだまだLinux初心者でいろんなところで詰まります。頑張ります。
ヒトの染色体ごとのファイルを繰り返し処理するためにブレース展開を学ぶ

# ヒトの染色体ごとのファイルを処理する？
　ヒトのゲノム情報等のファイルは一般的に非常に巨大になるので、染色体ごとに処理したくなるのが人情ですよね。
　Linuxをほとんど触ったことが無かった時に、染色体ごとにファイルを処理することは様々なLinuxのブレース展開を覚える良い勉強になったので、まとめてみました。
　以下は、bashが使用できる環境（Linux, MacまたはWindowsのWindows Subsystem for Linux 2）を想定しています。
　Windows Subsystem for Linux 2の導入については、[こちら](https://qiita.com/whim0321/items/ed76b490daaec152dc69)を参照しました。感謝感謝。

# ファイルの繰り返し処理
　ヒトのゲノムに存在するバリアントは、全ゲノムシークエンスデータからだと１個人あたり数百万個も検知されます。
　7,609人の全ゲノムシークエンスデータからだと、約8000万弱のバリアントが[検知されて](https://togovar.biosciencedbc.jp/doc/ja/datasets/gem_j_wga)います。ﾋﾄﾊﾐﾅﾁｶﾞｳ。
　上述したバリアントデータには頻度情報も含まれますが、データの大きさは約1.8GBにも上ります。
　ちなみに、データは[こちら](https://togovar.biosciencedbc.jp/downloads/gem_j_wga/)からダウンロード可能。
 　これらのように染色体ごとに分割されたファイルに対して同じような処理を適用することを考えます。

#　ヒトの染色体の番号を表示する
　ヒトのゲノムの染色体には、常染色体は1番から22番、性染色体はX、Y、ミトコンドリアが存在しています。
　一般的には、染色体番号は1~22、X、Y、MTと表記されますが、SNPの解析で良く用いられるplinkでは　X⇒23、Y⇒24、XのPseudo-autosomal region⇒25、MT⇒26　[なんてこと](http://zzz.bwh.harvard.edu/plink/data.shtml#map)もありますし、chr1~chr22, chrX, chrY, chrMTと表示されることもあります。。
 　今、染色体の番号が1~26までのファイルがあり、これに対して[ブレース展開](https://qiita.com/ine1127/items/6e5fe80f4a9c64509558)というものを使うと、とても便利です。

```
$ echo {1..26}
と打つと
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 
となる。
```

便利！
これを使って、for文で以下のように繰り返し処理すれば、

```
  for chr in {1..26}
  do
     cat なんちゃらファイル.chr${chr}.vcf
　done
```

これで、なんちゃらファイル.chr1.vcf から なんちゃらファイル.chr26.vcf　までのファイルを対象に、同じコマンド（ここでは、catコマンド）を実行できます。

#　ヒトの染色体は 1~22、X、Y、MT　じゃろがい
そうですよね。染色体の番号が1~26までなんて都合が良いことは無いですよね。
ということで、何とか、1~22、X、Y、MTを出力するように頑張りましょう。
1~22までは

```
$ echo {1..22}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
````

で良いとして、これの後に　X、Y、MTを出力することを考えます。
ブレース展開で、{X,Y,MT}　と書くと

```
$ echo {X,Y,MT}
X Y MT
```

となります。ここまでくれば出来たも同然。二つのブレース展開をつなぐと、

```
$ echo {1..22} {X,Y,MT}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 X Y MT
```

パチパチパチ。

よって、

```
for chr in `echo {1..22} {X,Y,MT}`
do 
    cat なんちゃらファイル.chr${chr}.vcf
done
```

と、書いてあげると　1番染色体から22番染色体、X、Y、MTのファイルにコマンドを実行（ここでは cat）出来ることになります。
↓は単純な応用例で、上記の出力の先頭にchrが付くはずです。

```
for chr in `echo chr{1..22} chr{X,Y,MT}`
do 
    cat なんちゃらファイル.chr${chr}.vcf
done
```

このようにブレース展開を利用すると、解析のプログラムもすっきり書けるようになると思います。
それでは良いゲノム解析ライフを！
Linuxディレクトリ作成、ファイルコピーで遊んでみた

_私はずっとGUIで操作してたためリナックスのコマンドを全く触ったことがなくずっと敬遠していました。重い腰をあげて今回は黒い画面（CUI)のコマンドでディレクトリ作成、ファイルのコピー、移動を今更ながら学んだので記事にしてみました。_
#目的
黒い画面（CUI)でコマンド操作のみでディレクトリの作成、ファイルコピー、ファイルの移動ができるようになる。
・環境 mac
#ディレクトリの作成
```console
###ディレクトリ作成コマンド
$ mkdir studyLinux
            └ (作成したい任意のディレクトリ名)
```
#ファイルの移動
```console
###同じディレクトリにファイルコピー
$ cp 「コピーする元のファイル」　「元のファイルをもとに新たに作成されるファイル名」

$ cp hoge.txt hoge.txt1

###別のディレクトリにコピーする場合
***ディレクトリ構成***
home
├ hoge.txt
│　　　　
├ sample000/
│　└ smpTest00/

###別のディレクトリにコピーする
***コピーするファイル名を別にして別のディレクトリに作成する場合***
$ cp 「コピーする元のファイル」　「コピーを作成したいディrクトリ名」/ 「元のファイルをもとに新たに作成されるファイル名」

$ cp hoge.txt sample000/smpTest00/hogehoge1.txt

***コピーするファイル名は元と同じで別のディレクトリに作成する場合***
$ cp 「コピーする元のファイル」　「コピーを作成したいディrクトリ名」/

$ cp hoge.txt sample000/smpTest00
```
#ファイルの移動
```console
$ mv hoge.txt 「移動させるディレクト」

$ mv hoge.txt /sample000/smpTest00
```
#まとめ
__学ぶ前は、抵抗がありましたが実際に触ってみると面白かったです。
何よりもいちいちマウスを使わなくていいのでめっちゃ楽でした。
僕は他のファイルとか弄ったら嫌だったので、適当なディレクトリを作ってGUIも見ながら実際に期待した動きになっているか確認しながら遊ました。__
go言語でSlackのWebhookをやろうとして苦労したので備忘録

### 環境
* go 1.15
* slack 2021/03/22時点

## goの `url.QueryEscape` は空白( )をプラス(+)に変換する
URLエンコード的にはプラス(+)でも問題ないが、 `%20` に変換したい場合は以下のようにする。

```
str = regexp.MustCompile(([^%])(+)).ReplaceAllString(str, "$1%20")
```

## Slackのサンプルには下記コマンドが提供されているがダブルクォートのエスケープが必要なのか分からない。。

`curl -X POST --data-urlencode "payload={\"channel\": \"#any_channel\", \"username\": \"webhookbot\", \"text\": \"This is posted to #any_channel and comes from a bot named webhookbot.\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/T5L640XXX/B01S6CZXXXX/XXXXXXXXXXXXXXXXXXXXXXXX`

これは単に `curl` の `--data-urlencode` オプションやシェルのダブルクォートの話。  
この文字列の指定であれば、Value(イコール(=)の右側)の部分のみURLエンコードされるらしい。
ダブルクォートの中の変数や式は展開されるのでエスケープが必要らしい。
以下が詳しい。
https://qiita.com/tkms0106/items/4272ce690217c259739c
https://qiita.com/aosho235/items/d89bb027db0c5662d8c5

goだと以下のようなコードでOK。

```
str := url.QueryEscape(string(body))
str := "payload=" + regexp.MustCompile(`([^%])(\+)`).ReplaceAllString(str, "$1%20")
```

## リクエストのContent-Typeは `application/x-www-form-urlencoded`
まあ当たり前といえば当たり前。。
goのコードは以下のような感じ。

```
req, err := http.NewRequest("POST", baseURL, bytes.NewBuffer([]byte(str)))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
```

## リクエストのUser-Agentは必須
User-Agentヘッダーが無い場合は、`400 Bad Request` になりボディに `invalid_payload` が返る。
User-Agentの値は何でもよい。
goのコードは以下のような感じ。

```
req, err := http.NewRequest("POST", baseURL, bytes.NewBuffer([]byte(str)))
req.Header.Set("User-Agent", "hogehoe client")
```
inode番号について

LPICの勉強をしている際にinode番号について調べてみたので自分用にまとめます。
#参考記事
・[inode番号とは｜「分かりそう」で「分からない」でも ...](https://wa3.i-3-i.info/word14803.html)
・[wikipedia](https://ja.wikipedia.org/wiki/Inode)

#まとめ
###表示方法
lsコマンドにiオプションを指定すれば表示ができる。
または、findコマンドのinumオプション。
```ls -li```などの併用も可。
下の写真は```ls -i```のみ実行した例。
![Screen Shot 2021-03-23 at 19.05.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722539/99e08ee1-00c0-d32d-3d6a-c55621433642.png)
一番左に表示されている番号がinode番号。(ls -li を実行しても一番左に表示される。)

inode番号の使用状況は```df -i```でみる。
IUseが100%に近いのであればそのディレクトリではファイルを作成できない可能性がある。

###詳細
1.inodeの数は有限。

2.最大に達したら、いらないファイルを削除する必要がある。

3.ファイルには以下の属性を所持しなければならないらしい。
・ファイルの長さ
・デバイスID
・ファイル所有者のユーザーID
・ファイルのグループID
・ファイルシステム内でファイルを識別する inode 番号
・ファイルモード
・タイムスタンプ群
・inode を指すハードリンクがいくつあるかを示す参照カウント

これらを保持しているデータ。

4.ハードリンクの場合はinodeが同じだけど、シンボリックリンクは違う値が割り振られる。

余談みたいに書いてあったけど、
ReiserFSなどの最近のUnix系ファイルシステムでは inode を使用していないらしい。

この記事が役に立つ人は少ないと思いますが、役に立てたら嬉しい^_^です。
【BigQuery初心者の雑記 vol.3】Re:dash 入力値を IN 句の条件で使う〜実務の分析で使いやすくした話

株式会社オズビジョンのユッコ (@terra_yucco) です。
最近ずっと BigQuery でクエリを書く生活をしていたため、今日もその関係となります。

# 前提
オズビジョンでは、AWS 上に立てた MySQL Aurora や Google Analytics といったデータソースの閲覧のため、Re:dash を立てて運営しています。
最近 BigQuery がそのデータソースに仲間入りし、その桁違いの演算能力に惚れ込む人が続出。そのため、大量データを走査するような集計は BigQuery にデータを定期同期し、そのデータソースから参照するという使われ方をしています。

# きっかけ

![スクリーンショット 2021-03-23 19.11.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95030/85d24d9b-1e47-9f18-f32e-8db13dc2ec93.png)

スプレッドシートも併用してデータをフィルタリグしているメンバからのフィードバックがきっかけでした。
※この元になる抽出もクエリでやれればいいのですがそこは目を瞑ってください

## カンマ区切りにするだけなら

split でいいんじゃんと思ったのですが

```text
@xxxx 使う先がわからないのですけど、replaceってので行けるかと思いますよ。

サンプル
select replace("{{ value }}", " ", ",")

redashのvalue窓には 1 2 3 を入れました。
スプレッドシートで縦に 1 2 3 って入れたものをコピペした状態です。
```

これだとあくまでカンマで区切られた文字列になるだけで、その後他のクエリと結合して IN 句として利用するようなことはできませんでした。

## IN 句として使う方法

他の Redash クエリでもコピペ＆小改変で使えるようにしたかったので命名が雑いですが、最終的にはこれで動かすことが出来ました。

```sql
WITH
  -- {{ input1 }} の文字列に対して以下の順番で操作をして、WITH の対象にできるデータ次元に変換
  -- 1. スペース分割で配列に変換
  -- 2. 配列を展開する UNNEST() 関数を利用し SELECT で取得
  -- 3. このままでは STRING 型
  -- 4. 今回は数値と比較したいので INT64 に変換
  -- 5. data1 という名前で結合先で使えるようになる
  INPUT1 AS (
    SELECT CAST(raw1 AS INT64) AS data1
      FROM UNNEST(split("{{ input1 }}", " ")) AS raw1
  )
-- この後使いたい SELECT などのクエリをここに書く
```

コメントの中にも書いたように、利用するときに STRING であれば CAST は要りません。

# まとめ

件数が少ない (get パラメータで渡せる範囲) のデーであれば、スプレッドシートからコピーしてきて Re:dash の変数窓に入れるだけで、クエリの条件に使うことができるようになりました。
Prism コードサンプル学習：08-ViewModelLocator

# Prism コードサンプル学習：08-ViewModelLocator

## はじめに

以下の記事の続きです。
<https://qiita.com/mngreen/items/dedaef545e3f5122b672>

## 08-ViewModelLocator

[本サンプル](https://github.com/PrismLibrary/Prism-Samples-Wpf/tree/master/08-ViewModelLocator)ではViewModelとViewの紐付けが自動で行えることを示しています。
ポイントとなるコードは以下の```prism:ViewModelLocator.AutoWireViewModel="True"```となります。

```xml
<Window x:Class="ViewModelLocator.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">
    <Grid>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
    </Grid>
</Window>
```

- 上記の値は添付プロパティとして[ここ](https://github.com/PrismLibrary/Prism/blob/master/src/Wpf/Prism.Wpf/Mvvm/ViewModelLocator.cs#L19)に定義されています。
  - 添付プロパティのコールバックに設定されているAutoWireViewModelChangedメソッドが呼び出されると、[ViewModelLocationProvider.AutoWireViewModelChanged](https://github.com/PrismLibrary/Prism/blob/342689ba9a10e511418943438d0f5c57534ca623/src/Prism.Core/Mvvm/ViewModelLocationProvider.cs#L89)が呼び出されます。この中で、Viewと紐づくViewModelが取得されてDataContextに設定されます。
  - デフォルトでのView-ViewModelの紐付けは[ここ](https://github.com/PrismLibrary/Prism/blob/342689ba9a10e511418943438d0f5c57534ca623/src/Prism.Core/Mvvm/ViewModelLocationProvider.cs#L45)で定義されている。
  - [ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver](https://github.com/PrismLibrary/Prism/blob/342689ba9a10e511418943438d0f5c57534ca623/src/Prism.Core/Mvvm/ViewModelLocationProvider.cs#L78)メソッドを利用すればルールを変更できそうであるが、UTでしか利用されていなかったため、後のサンプルを読み進めることで実際の利用箇所を見てみようと思います。

## おわりに

今回はViewModelLocatorの読み込む方法について確認しました。
ViewとViewModelが意識することなく紐付けられるのはとても強力に感じました。
次回、[09-ChangeConvention](https://github.com/PrismLibrary/Prism-Samples-Wpf/tree/master/09-ChangeConvention)について見ていこうと思います。
【Rails】アセットパイプラインやプリプロセスとは？


個人メモです。

##アセットパイプラインとは？
JSやCSSファイルの容量を最小化するためのフレームワーク。実行するのはスペースやコメントアウト削除などの記述の効率化とファイル数の削減。

複数ファイルをコンパイルして一つのファイル（jsは.js, cssは.css）にまとめるなど、WEBブラウザのリクエスト回数を減らし高速化につなげる。

Sprockets-railsというgemで実装され、デフォルトで有効になっていた。Sprocketsと呼ばれる。

###scssのコンパイル
railsにはデフォルトでscss-railsパッケージが入っている。Sprocetsはcssの圧縮にscss-railsを使用する。


##コンパイル後のファイル
コンパイル後のファイルは個別になるように固有のハッシュ値がつく（フィンガープリントと呼ぶ）

例えば、application.cssというファイルをコンパイルした場合は以下のようになる。

```
applciation-908e25f4bf641868d8683022a5b62f54.css
```

##コンパイル元のファイル
ファイルはassets配下に作成する。JSの場合は、`app/assets/javascripts/ファイル名.coffee`。scssの場合は`app/assets/stylesheets/ファイル名.scss`


##ファイルのインポート方法
ファイルのインポートには、`javascript_include_tag`と`stylesheet_link_tag`を使う。

**▼JS**

```
<%= javascript_include_tag 'ｊｓファイルパス' %>`
```

ファイルパスは、app/assets/javascripts/配下で指定する。
test/index.jsであれば、

```:例
<%= javascript_include_tag 'test/index.js' %>
```


<br>
**▼css**

```
<%= stylesheet_link_tag 'cssファイルパス' %>
```

ファイルパスは、app/assets/stylesheet/配下で指定する。
test/index.cssであれば、

```:例
<%= stylesheet_link_tag 'test/index.css' %>`
```


<br>
**▼画像**
画像の場合は`image_tag 'ファイルパス'`を使う。

```:例
<%= image_tag "icons/rails.png" %>
```

app/assets/images/icons/rails.pngを参照している。


<br>
##アセットの置き場所
アセットの置き場所は用途に応じて３種類ある。

| ディレクトリ | 内容 |
|:-:|:--|
| app/assets  | 現在のアプリケーション独自のコード  |
| lib/assets  | 他のプロジェクトと共有するライブラリコード  |
| vendor/assets  | 外部団体が所有するフレームワーク  |

いずれの場合もファイルを呼び出す時に`require 'ファイル名'`を使うため、異なるファイル名をつける。

```:例（ファイルパス）
app/assets/javascripts/home.js #require home
lib/assets/javascripts/navi.js  #require navi
vendor/assets/javascripts/slider.js #require slider
vendor/assets/somepackage/phone.js #require phone
```


##プリプロセスとは？
一つのファイルに対し異なるフォーマットで処理をしていくことをプリプロセスという。

プリプロセスの順番は拡張子の右からになる。

例えば、projects.scss.erbというファイルの場合、右から、erb -> scss -> cssの順で処理される。

projects.coffee.erbであれば、erb -> coffee -> jsの順となる。

**▼エラーになる例**
projects.erb.scssだと、最初にscssで処理（プロセス）され次に、erbに渡されるが、scssで処理されたデータをerbが処理できないためエラーになる。


<br>
##マニュフェストファイル
application.jsやapplication.cssをマニュフェストファイルよ呼ぶ。読み込むアセットファイルを記述する。記述した順番に読み込まれる。




<br>
##Sprockets（アセットパイプライン）は使わない？
Rails4まではアセットパイプラインが使われていたが、Rails5からは同じ目的（js, cssファイルのコンパイル）として、Webpackerが使われるようになった。

そしてRails6では完全にWebpakcerに移行している。