OmniAICreator/Qiita-1.07M huggingface dataset:
Windows上Pythonインタラクティブ実行時にタブ補完を利用するためのメモ(旧版向け)


重要：最新のPythonにはpyreadline3は必要ないうえに悪さするので要れないでください。
少なくともPython3.13ではpyreadline3は不要のようです
AttributeError: module 'readline' has no attribute 'backend'
↑　このエラーはpyreadline3が邪魔してるときに関連して出るエラーの一例です



概要： 
Python インタラクティブ実行（すなわちコマンドラインから操作）のときは「タブ補完」を利用したいのが人情というもの。

けれど Windows 上のPythonはなぜかデフォルトでは補完してくれない。

有効化する方法について調べるたびにつまづいて　いつもあきらめていましたが解決したのでメモ。

・2025/04/14: python3.13に合わせて加筆、「parse_and_bind()」は呼び出しは必須ということに。
・2022/10/31: python3.10以降に合わせて加筆、「pyreadline」→「pyreadline3」に置き換えました。
・2021/09/27：rlcompleterについて追記

---

##   重要：「readline」ではなく「pyreadline3」をインストールする。

環境:
・ Windows10,11
・ Python3.7.4とか

まず、

```パッケージインストール
C:\Python\python.exe -m pip install pyreadline3
```
というように「pyreadline3」をインストールします。


一方で 「readline」というパッケージも存在しこれはインスコ時に「Windowsでは動かない」と吐いてエラーになります。
ネット上に「Windowsも『readline』インスコで済む」説も見つかるのが曲者でした。
筆者はここで混乱し、たびたび断念してました。
※Linuxの場合は「readline」インストールで問題ないはず。

~~pyreadline をインストールした後は
無事、タブ補完できるようになりました。~~

---
## parse_and_bind() でタブ補完を設定。

~~場合によっては~~
``` :Python3.exe (古い情報、比較のため残す)
import rlcompleter
rlcompleter.readline.parse_and_bind('tab: complete'
```
~~せよとかいう情報もあるようですが、ほんとに必要かどうかは不明。  ※その場合「rlcompleter」 も pip で入れるのかな~~ 
【2021/09/27追記】
ZIP配布用のpythonでは上記のrlcompleter設定が必要でした。 (バージョン：python-3.9.7-embed-amd64)
rlcompleterについて追加インストールは不要でした。
ただしこのやり方では履歴（readlineの機能なのかな？）が無効になってしまったため、履歴の登録を追加しました。

【2025/04/14追記】
win11上のPython3.13では parse_and_bind() 呼び出しが必要でした。
なお 「rlcompleter.readline」は 「readline」で読み替えてよいようです。
rlcompleterについて追加インストールは不要。インポート「import rlcompleter」は必要。
parse_and_bind()によって履歴が無効化されるため履歴ファイルを登録し直します
↓　以下、read_and_bind() すなわちタブ補完の登録と履歴ファイル読み書き処理の一例。
```python:
##  For Python3.exe
##  細部書き換えた後未実行のためエラー出るかもしれません。
##  ご利用は自己責任で。
try:
    import rlcompleter  ##  ←　このインポートは必須の模様（謎）
    import readline
    readline.parse_and_bind('tab: complete')

    ##  binding history file
    import os
    histfile = os.path.join(os.environ['HOMEDRIVE'], os.environ['HOMEPATH'], '.python_history')
    try:
        readline.read_history_file(histfile)
    except IOError as e:
        print(e)
        pass
    import atexit
    atexit.register(readline.write_history_file, histfile)
except:
    print(''' To enable TAB-completion, install pyreadlined3. 
ex: > python.exe -m pip install pyreadline3''')
```




##   重要：「pyreadline」ではなく「pyreadline3」をインストールする。
pyreadline はとっくに更新が止まっている。 古めのPythonョンでないかぎりは、「pyreadline3」 を使うべし。
Python3.10 以降に古い方の pyreadline を入れると、`AttributeError: module 'collections' has no attribute 'Callable'`というエラーが出てタブ補完も作動しない。


---
参考
https://qiita.com/cabbage_lettuce/items/4b662801543caee7e6b0

https://stackoverflow.com/questions/74034049/python-on-windows-starts-with-attributeerror-module-collections-has-no-attri

---
日本語で気の利いた記事を見つけられなかったためメモとして残しときます。
【解決】Address already in use - bind(2) for 0.0.0.0:3000 (Errno::EADDRINUSE)

## サーバースタートしたらエラー

```
miyajimayuki@miyajimayuukinoMacBook-Pro web_tech % ruby test.rb
[2020-03-17 14:25:54] INFO  WEBrick 1.4.2
[2020-03-17 14:25:54] INFO  ruby 2.6.3 (2019-04-16) [x86_64-darwin19]
Traceback (most recent call last):
	11: from test.rb:2:in `<main>'
	10: from test.rb:2:in `new'
	 9: from /Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/webrick/httpserver.rb:47:in `initialize'
	 8: from /Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/webrick/server.rb:108:in `initialize'
	 7: from /Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/webrick/server.rb:127:in `listen'
	 6: from /Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/webrick/utils.rb:65:in `create_listeners'
	 5: from /Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/socket.rb:762:in `tcp_server_sockets'
	 4: from /Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/socket.rb:227:in `foreach'
	 3: from /Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/socket.rb:227:in `each'
	 2: from /Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/socket.rb:764:in `block in tcp_server_sockets'
	 1: from /Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/socket.rb:201:in `listen'
/Users/miyajimayuki/.rbenv/versions/2.6.3/lib/ruby/2.6.0/socket.rb:201:in `bind': Address already in use - bind(2) for 0.0.0.0:3000 (Errno::EADDRINUSE)
```

## 原因

- サーバーを**control + Z**で切ったら次にサーバーを立ち上げるとエラーになるようです。

## 解決

いま動いている**port: 3000**のサーバーをターミナルに出力して

```
% lsof -i:3000

COMMAND  PID         USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ruby    2054 miyajimayuki   10u  IPv6 0xb15f9119d06b6d43      0t0  TCP *:hbci (LISTEN)
ruby    2054 miyajimayuki   11u  IPv4 0xb15f9119cf61f0cb      0t0  TCP *:hbci (LISTEN)
```

下記コマンドでプロセスを切る

```
% kill -9 {PID}

履歴

COMMAND  PID         USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ruby    2054 miyajimayuki   10u  IPv6 0xb15f9119d06b6d43      0t0  TCP *:hbci (LISTEN)
ruby    2054 miyajimayuki   11u  IPv4 0xb15f9119cf61f0cb      0t0  TCP *:hbci (LISTEN)
miyajimayuki@miyajimayuukinoMacBook-Pro web_tech % kill -9 2054
miyajimayuki@miyajimayuukinoMacBook-Pro web_tech % 
[1]  + killed     ruby test.rb
```

プロセスが切れたので再度サーバーが起動できるようになりました！

```
miyajimayuki@miyajimayuukinoMacBook-Pro web_tech % ruby test.rb
[2020-03-17 14:32:34] INFO  WEBrick 1.4.2
[2020-03-17 14:32:34] INFO  ruby 2.6.3 (2019-04-16) [x86_64-darwin19]
[2020-03-17 14:32:34] INFO  WEBrick::HTTPServer#start: pid=2126 port=3000
```

以上です！
`array.sorted(by: key)` 的なことがしたかったんだ

# 概要
キーを指定するだけでサクッとソートしてくれるようなextensionを作ってみた


# 実装
```swift:Sequence+KeySort.swift
extension Sequence {
    public func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>) -> [Element] {
        sorted { $0[keyPath: keyPath] < $1[keyPath: keyPath] }
    }

    public func sorted<T: Comparable>(by keyPath: KeyPath<Element, T?>) -> [Element] {
        sorted {
            guard let l = $0[keyPath: keyPath],
                let r = $1[keyPath: keyPath] else { return false }
            return l < r
        }
    }
}
```

# Usage
```swift
struct Person {
    var id: Int
    var name: String
}

extension Person: CustomStringConvertible {
    var description: String { name }
}

let people: [Person] = [
    .init(id: 3, name: "Bob"),
    .init(id: 1, name: "Emma"),
    .init(id: 4, name: "Amelia"),
    .init(id: 2, name: "George"),
]

print(people.sorted(by: \.id))   // -> ["Emma", "George", "Bob", "Amelia"]
print(people.sorted(by: \.name)) // -> ["Amelia", "Bob", "Emma", "George"]
```
国の補助金、助成金

補助金の採択のハードルは高い。
助成金は一定の条件を満たせばほぼ貰える。

責任共有制度の対象外：国が１００％もってくれる。貸し倒れても。会社は借りやすい。

融資
---------------------

セーフティネット保証制度5号　業種×
セーフティネット保証制度4号　売上20%減少しないと×

【小規模企業等振興資金】
融資
限度額：5,000万と2,000万がある。
5,000万は責任共有制度対象。
担保・保証人：名古屋市信用保証協会所定


【小規模事業者経営改善資金融資（マル経）】
融資
限度額：2,000万。
担保保証人：不要（保証協会の保証も不要）


【環境適応資金】
・経営環境の急激な変化の影響を受け、最近3か月の月平均売上高または月平均売上総利益率もしくは月平均営業利益率が、前年同期または2年前同期に比べて3%以上減少していること（経済対策特別資金）
・コロナウイルスにより売上が2年前同月より3%以上減少していること（経済対策特別資金）
限度額：8,000万。
責任共有制度対象。


【事業承継支援資金】
限度額：2億8,000万


補助金・助成金
--------------------

【小規模事業者持続化補助金】
・商工会議所の管轄地域で事業を営んでいる小規模事業者等が対象
・経営計画に基づいて実施する販路開拓等の取り組みに対し、
　原則50万円を上限に補助金（補助率2/3）が支給

公募期間：5/18まで


【IT導入補助金】
ソフトウエア費、導入関連費等
補助率	1/2以下


【事業承継補助金】
・100～200万



【特定求職者雇用開発助成金（三年以内既卒者等採用定着コース）】
・既卒者を雇用（卒業3年以内）
1年定着　50万
2年定着　10万
3年定着　10万
redirect_toとrenderの違い

##redirect_toの場合
redirect_to=>ルーティング=>コントローラー=>ビュー
新たなリクエストがされたのと同じ動きになり、コントローラーを経由してビューが表示されます。
##renderの場合
render=>ビュー
そのままビューが表示されます。
##redirect_toとrenderの違い
いずれも実行するとビューが表示されます。
しかしこれによって、元のインスタンス変数の値が上書きされるかどうかが違います。
【例】例えば@teamという変数があるとして、@teamの変数にはエラーメッセージが代入されているため、これが上書きされないようrenderによってビューを表示させる必要があります。

```
def create
  @team = Team.new(team_params)
  if @team.save
    redirect_to root_path, notice: 'チームを作成しました'
  else
    render :new
  end
end
```
管理画面テーマを作成

#管理画面テーマを作成します。

管理画面テーマのステップを作成します。

1.以下のディレクトリにテーマのディレクトリを作成します
<br>`app/design/adminhtml/[your_vendor_name]/[your_theme_name]`.
2. `theme.xml`ファイルにテーマを宣言する
3. `registration.php`ファイルにテーマを登録する
4. `etc/view.xml`ファイルに画像の設定を設定する
5. テーマロゴを宣言する

##テーマディレクトリを作成する
テーマのディレクトリを作成します:

`MAGENTO_DIRECTORY`/app/design/adminhtmlに、

上記のディレクトリに、`<vendor>`ディレクトリを作成して、テーマのディレクトリを作成します。
私の場合、以下を設定します。
  - ベンダー名： `Karabiner`
  - テーマ名：「green」。

```:app/design/adminhtml/
Karabiner　←ベンダー名
├── green/　←テーマ名
│   ├── etc/
│   │   ├── view.xml
│   ├── web/
│   │   ├── images
│   │   │   ├── karabiner_logo.svg
│   ├── registration.php
│   ├── theme.xml
```

##  `theme.xml`ファイルにテーマを宣言する

`app/design/adminhtml/Karabiner/green`に、 `theme.xml`ファイルを作成します。
`theme.xml`ファイルはテーマの基本情報（テーマ名、親テーマ、プレビュー画像など）を設定します。


```xml:app/design/adminhtml/Karabiner/green/theme.xml
<?xml version="1.0" encoding="UTF-8"?>
<theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
    <title>Green</title> <!-- テーマ名 -->
    <parent>Magento/blank</parent> <!-- 親テーマ -->
</theme>
```
## `registration.php`ファイルにテーマを登録する

テーマの登録ファイルは以下のような感じです。

```php:app/design/adminhtml/Karabiner/green/registration.php
<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::THEME,
    'adminhtml/Karabiner/green', // theme path
    __DIR__
);
```

##`etc/view.xml`ファイルに画像の設定を設定する
これは構成ファイルです。このファイルは、Magento 2テーマでは「必須」※です。
※ - **親テーマに存在する場合はオプションです。**

 `app/design/adminhtml/Karabiner/green/`に、 `etc/view.xml`ファイルを作成する
`theme-adminhtml-backend`テーマなどの親テーマでview.xmlファイルをコピーできます。

`vendor/magento/theme-adminhtml-backend/etc/view.xml`

```xml:app/design/adminhtml/Karabiner/green/etc/view.xml
<image id="category_page_grid" type="small_image">
    <width>250</width>
    <height>250</height>
</image>
```


##テーマロゴを宣言する


Magento 2のデフォルトでは、 `[theme_dir]/web/images/logo.svg`を使用します。`default.xml`では、png、jpgなどの別の画像形式に変更できますが、設定する必要があります。
`[theme_dir]/Magento_Theme/layout/default.xml`
ロゴのサイズは100x100pxにします

```xml:app/design/adminhtml/Karabiner/green/Magento_Theme/layout/default.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="logo">
            <arguments>
                <argument name="logo_file" xsi:type="string">images/karabiner_logo.svg</argument>
                <argument name="logo_img_width" xsi:type="number">100</argument> 
                <argument name="logo_img_height" xsi:type="number">100</argument>
            </arguments>
        </referenceBlock>
    </body>
</page>
```
【Rails】devise gemありきで、ユーザー情報を更新する方法

# 今回こまったこと
devise gemをbundle installして、アカウントを登録。
作ったアカウントを編集する画面を作ったものの、内容が反映されない・・・どうすれば！？

と、言う事でググったら解決できたのでまとめます。

## 事前準備
devise用のuserテーブルには、カラムを追加してます。
`name`　ユーザー名
`text`　プロフィールコメント
`prof_image` プロフィール画像

↓こんな感じ
<img width="818" alt="スクリーンショット 2020-03-17 13.24.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593458/018c97c8-85b8-f6a2-6e6e-e90c815cd3e5.png">

↓コントローラーにお決まりの一文
<img width="562" alt="スクリーンショット 2020-03-17 13.27.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593458/defbbdc2-630d-e391-7757-e9cfde4d843e.png">
この`if: :devise_controller?`は、どうやら、deviseコントローラーで処理をしているかどうか。を判断するヘルパーメソッドみたいです。
ので、before_actionに記述して、ApplicationControllerの処理の前に、判別しているっぽいです。

↓protected配下にこれまたお決まりの一文。
<img width="648" alt="スクリーンショット 2020-03-17 13.27.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593458/e4ea9f3f-ca20-b0f5-d8a0-2e0e1ccf2299.png">
`devise`にもともと用意されていない「:name,:prof_image,:text」の3つのテーブルへ書き込みを許可するぜ。って書いてあげてます。
これについては、sing_upの処理で許可するよ。って書かれてます。※今回はここの理解が甘かった。


## 編集したプロフィールが反映されない問題

プロフィール詳細画面を作成して、ここから編集画面へ遷移するような導線を用意しました。で、以下がプロフィール編集画面です。ここの「更新」ボタンを押しても反映されない・・・！なぜ？

↓プロフィール編集画面（つっこみどころ満載ですが、ゆるしてください。レイアウトも作成中です（汗））
<img width="1073" alt="スクリーンショット 2020-03-17 13.37.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593458/a679d02a-074d-2045-6c33-8deb3c974f10.png">

### なぜ？仮定
エラーは出ないし、きっとコントローラーに記載されている処理が何か足りていない。と仮定。
それならばと思い、コントローラーの記載を確認。むむむ・・・今の自分の知識じゃ訳がわからない・・・。
ということで、ぐぐる。
どうやら、「devise_parameter_sanitizerメソッド」の理解が足りていなかったようだ！

## 少しでもいいから、devise_parameter_sanitizerメソッドのこと思い出してください
この一文は僕が昔大好きだったゲームの一文のパロです。
はい、どうでもいいです。ごめんなさい。

調べていったら、「devise_parameter_sanitizerメソッド」の引数部分の指定不足が原因だと言う事がわかりました。

###そもそもdevise_parameter_sanitizerメソッドとは

deviseではサインアップ時に既存で用意されているカラム`email`と`password`のみを受け取るようにストロングパラメーターで設定してあります。
なので、独自で追加したカラムへのアクセス許可をしてあげる必要があります。
そこで登場するのが、この`devise_parameter_sanitizer`メソッドです。

この`devise_parameter_sanitizer`メソッドには、第一引数で**どのアクションの時に許可する？**が指定できるみたいです。

| 第一引数書く値  |意味|
|:-------------|:-------------:|
|:sign_in      |ログイン時|
|:sing_up      |新規登録時|
|:account_update|レコード更新時|

## 原因と解決
つまるところ、現状の実装だと`ApplicationController`にはsing_upの処理が走ったタイミングでしか追加したカラムの書き込みを許可していないって事になりますね。
なので実装を修正。

▼Before
<img width="648" alt="スクリーンショット 2020-03-17 13.27.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593458/46bdb858-d2a3-a6c6-f7d3-ec7921eb0ba6.png">

▼After
<img width="731" alt="スクリーンショット 2020-03-17 13.53.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593458/e5e03e35-06da-e329-5450-f0219577bf4e.png">

はい。これで無事更新ができるようになりました！！

##おわり
初の個人アプリ開発もエラー→ググる→トライ→エラー→ググる・・・・・解決！が定着化してきました。
色々な記事を投稿してくださっている先輩方には感謝しかありません！
僕も先輩方と同じように後からエンジニアを目指す人たちの助け舟を出せるような人に育っていきたいです。

あと、補足や認識齟齬があればどうぞご指摘いただけますと幸いです！
自分の知識を正しいものにしていきたいので、是非ともよろしくお願いいたします。

ではでは、ありがとうございました！
フラッシュメッセージ

##フラッシュメッセージとは
ユーザーが、「サインアップ」「ログイン」「ログアウト」を行った直後にメッセージを出すことです。
##flashオブジェクト
deviseを使用すると、ログイン時などに表示させるメッセージが「flashオブジェクト」に自動で格納されます。
flashオブジェクト内には、複数のメッセージがハッシュのように「キー」「バリュー」形式で保存されています。
【例】ファイルを_notificationsとします

```app/views/layouts/__notifications.html.haml
.notification
  - flash.each do |key, value|
    = content_tag :div, value, class: key
```
each文を使うと、これらを1つずつ取り出すことができ、今回は「キー」を「CSS用のクラス名」に、「バリュー」を「表示するメッセージ本文」として使っています。
##フラッシュメッセージの表示
【例】renderしてるとします

```app/views/layouts/application.html.haml
!!!
%html
  %head
(中身)
  %body
    = render 'layouts/flashs'
    = yield
```
これだとまだ英文が出てきてします。
##flash.scssを作成
【例】ファイルをcolors.scsとします

```stylesheets/config/colors.scss
$white: #fff;
$side_blue_dark: #253141;
$side_blue_light: #2f3e51;
$light_blue: #38AEF0;
$light_gray: #999;
$black: #434a54;
$alert_orange: #F35500;
```
次に「通知用」のメッセージと「アラート用」メッセージを作成します。
【例】ファイルをflash.scssとします

```stylesheets/modules/flash.scss
.notification {
  .notice {
    background-color: $light_blue;
    color: $white;
    text-align: center;
  }

  .alert {
    background-color: $alert_orange;
    color: $white;
    text-align: center;
  }
}
```
次にapplication.scssを編集し、作成しファイルが読み込まれるようにします。

```app/assets/stylesheets/application.scss
@import "reset";
@import "config/colors";
(そのほかの@import)
@import "modules/flash";
```
##colors.scssの読み込みの順番
Railsは上から順番に読み込むためcolors.scssは、reset.scssの直後で読み込むようにしましょう。
colors.scssには、他のscssで利用している色についての変数が定義されています。
そのため、色についての変数を利用するCSSの前に先に読み込めていないと、エラーになってしまいます。
##日本語化
「config/locales」フォルダに、「devise.ja.yml」と「ja.yml」という名前のファイルを新規作成します。
[devise.ja.yml](https://github.com/tigrish/devise-i18n/blob/master/rails/locales/ja.yml)
[ja.yml](https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/ja.yml)
それぞれ中身を丸ごとコピーして貼り付けます。
 日本語化のための設定をします。
【例】

```config/application.rb
module ChatSpace
  class Application < Rails::Application
    (中身)
    config.i18n.default_locale = :ja
  end
end
```
これで日本語でフラッシュメッセージの表示がされます。
SSHを使ってSOCKS経由でWebにアクセスする方法

どこにでも紹介されている内容かもしれないが、DNSの名前解決のところで少しはまったので、メモも兼ねて投稿。

#1. やりたいこと

##a. SOCKSを使っていない通常アクセスの場合（赤色線）：

- 端末がDNSで名前解決する
- 端末から目的のサーバーに接続する
- Webサーバーから見たアクセス元IPは端末に紐づけられているGlobal IP

##b. SOCKSを使ったアクセスの場合（緑色線＋青色線）

- 緑色線は、SSHで暗号化＋カプセル化されたSOCKS通信
- DNSの名前解決もSOCKSサーバーであるLinuxが行うことが可能。
- SOCKSサーバーであるLinuxからWEBサーバーにアクセスする。
- Webサーバーから見たアクセス元IPはLinuxに紐づけられているGlobal IP

<img width="659" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/bd9bf55f-fd9f-af0a-c4e9-b696d64f58cc.png">



#2. SSHを使ったSOCKSの有効化

```shell:MacのTerminalからSSH実行
$ ssh -D 9080 xxx@xxx.xxx.xxx.xxx
```

これだけ。本来は、` -D [bind_address:]port`のようにbind_addressも指定できるが、デフォルトはlocalhostなので敢えて他には指定していない。
また、sshのオプションで` -f -N`などを追記してBackgroundで実行するのも１つの方法だが、通信の切り忘れとかもあるので私は特にオプションを他に付けないのが好み。

これにより、以下のように自身の端末のlocalhost:9080にSOCKS用のポートがopenされた。

```shell:MacのTerminalでListenPortを確認。
$ netstat -an|grep 9080
tcp4       0      0  127.0.0.1.9080         *.*                    LISTEN
tcp6       0      0  ::1.9080               *.*                    LISTEN
```

#3. Firefoxの設定

- SOCKSでありHTTPプロキシではないので、HTTPプロキシ欄には何も入力しない。
- SOCKS4では名前解決はクライアント側で行う挙動だったが、SOCKS5であれば名前解決をSOCKSサーバー(Linux)側で行うオプションも選択可能。ここでは選択しています。

<img width="652" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/475db7aa-b126-c5de-0e0d-e932528796fe.png">
HerokuでMySQLに接続しようとしたら[Error2055]が出た

# 概要
HerokuのClearDBを使ってMySQLに接続しようとpythonのプログラムをプッシュして動かしてみたのですが、`error 2055 Lost connection~`というメッセージが出て接続できませんでした。

結果としてはMySQLに関するエラーではなく、プログラムの書き方が原因だったのですが、同じところで悩んでいる方のためにもまとめておこうと思います。

# 環境

- macOS
- python3.7.1
- MySQL5.6.47
- mysql-connector-python

# この記事で書かないこと

- ClearDBの設定方法
- MySQLの詳しい操作方法

# 原因
最初はClearDBを追加した後、何か設定が必要なのだと思い色々調べて、マイグレーションなどを試していました。
しかし、ClearDB自体には接続できて、データベースに繋いで操作するプログラム単体で動かしてもエラーは出ず、いまいち原因が分かりませんでした。

そんな時に[こちらの記事](https://qiita.com/skokado/items/caa31d3845df23bc0913)を見つけなんとなく読んでいたのですが、SQL操作が失敗する原因として**コネクション切断後にクエリ実行する場合**と書いてありました。
それは当然だよなと思い次に行こうとしたのですが、ふと自分のコードを見てこれこそが原因だと判明しました。

というのも、私のコードは下記のような作りになっていました。

```python:main.py
#モジュールのインポート

#データベース操作のプログラムのインポート
import database

#メインの処理
    #database内の関数呼び出し
    database.get_data()
```

```python:database.py
import mysql.connector

#接続先を設定して接続

def get_data():
    #クエリの実行

connection.commit()
connection.close()
```

これを踏まえて[こちらの記事](https://qiita.com/ume1126/items/c1be49cc9ad5553ecc78)を見てみると、`database`をインポートした時点で関数外に記載されているコードが実行されます。

つまり、`main.py`の`import database`で一旦SQLに接続されますが、`database.py`の`get_data()`関数は定義がしてあるだけなので実行はされず、最後の`connection.close()`で接続が切られるという流れになります。

その後に、`main.py`内の`database.get_data()`で関数を呼び出したところで、既に接続は切られているので当然クエリは実行できずエラーが発生するということです。

`database.py`だけ実行しても、接続後何もせず接続を切るという動作をしていただけなのでエラーが出ないのも納得です。

# 対策
というわけでコードを下記のように修正し、関数を呼び出すことで接続を切るようにしたら無事にエラーなく接続できました。

```python:main.py
#モジュールのインポート

#データベース操作のプログラムのインポート
import database

#メインの処理
    #database内の関数呼び出し
    database.get_data()

    #追加
    database.close_db()
```

```python:database.py
import mysql.connector

#接続先を設定して接続

def get_data():
    #クエリの実行

#修正
def close_db()
    connection.commit()
    connection.close()
```

# 参考

- [mysql-connector-python でcommit()が失敗するケース](https://qiita.com/skokado/items/caa31d3845df23bc0913)
- [pythonで他の.pyプログラムを実行する](https://qiita.com/ume1126/items/c1be49cc9ad5553ecc78)
【途中】タスクランナーを使ってWordPressテーマをつくりたい！Sageを使ってみよう

フロントエンド初心者の私が、Sageを使ってみましたが…ちょろっとやって途中で止まってます・・・


https://webya.opdsgn.com/wordpress/wordpress-starter-themes-2019/

## 導入の仕方
公式のドキュメントを見るのが一番わかりやすい
https://roots.io/sage/docs/theme-installation/

## 構成

## SVGの使用
https://github.com/josh-taylor/sage-svg/blob/master/README.md

## カスタムフィールドの作成
https://roots.io/guides/using-acf-builder-with-sage/
https://github.com/StoutLogic/acf-builder/wiki
※[Log1x/sage-directives](https://github.com/Log1x/sage-directives)をインストールする必要あり

## Bootstrapの軽量化
https://qiita.com/pikanji/items/111cfb353bd6ec1eabb5

#blade
https://qiita.com/teru0x1/items/6813948aa6c40980a9b0
## 使った構文
`@hasfield`はカスタムフィールドに値が入っているかどうかを判定してくれる。

```
@hasfield('main-visual')
  <img src="example.jpg">
@endfield
```

## 追加するかも
https://getuikit.com/docs/installation
https://next.tailwindcss.com/docs/installation/
Codeforces Round #622 Div.2 A. Fast Food Restaurant 組み合わせの総当たり(permutations)

https://codeforces.com/contest/1313/problem/A

過去に出たDiv2,3のAで最も難しかった。（力業で良いのか悩んだ）

# 概要
- あなたは3つのメニューをa,b,cずつ持っている。それぞれの人にメニューセットを出したい。しかし、メニューセットは誰一人として同じでならない。
- あなたは何人に料理を提供できるか？
- 言い換えると、[1,0,0], [0,1,0], [0,0,1], [1,1,0], [1,0,1], [0,1,1], [1,1,1]というメニューを最大何個出せるか？

# こう考える
https://mdstoy.hatenablog.com/entry/2020/03/01/165805
のように賢く条件分けをできればいいのですが、私の場合、この条件分けではまってしまいそうだったため、itertoolsで全ケースを回しました。

例えば、(3つだと記載が難しいので2つのメニューだとすると)

- [1,0] -> [0,1] -> [1,1]
- [0,1] -> [1,0] -> [1,1]
- [1,1] -> [0,1] -> [1,0]
- [1,1] -> [1,0] -> [0,1]
- ..(略)...

のようにすべての順列でメニューを提供し、何個提供できたかのmaxを取ります。

# コード
```Python
from pprint import pprint
q = int(input())
menu = ["{:03b}".format(a) for a in range(1, 8)]
menu = list(map(lambda x: [int(y) for y in list(x)], menu))
for _ in range(q):
    a, b, c = map(int, input().split())
    import itertools
    res = 0
    for pat in list(itertools.permutations(menu)):
        x, y, z = a, b, c
        tres = 0
        for xx, yy, zz in pat:
            x, y, z = x - xx, y - yy, z - zz
            if x >= 0 and y >= 0 and z >= 0:
                tres += 1
        res = max(res, tres)
    print(res)
```

以下と等価のコードをライブラリから持ってきました。

```Python
        menu = []
        menu.append([0,0,1])
        menu.append([0,1,0])
        menu.append([1,0,0])
        menu.append([0,1,1])
        menu.append([1,0,1])
        menu.append([1,1,0])
        menu.append([1,1,1])
```
スタンディングデスクを使って1週間経った所感

## 前提
- 身長180センチ、体重100キロのメタボ体系
    - 過去に腰の椎間板ヘルニアで手術経験あり
- 通常のデスク + サンワサプライ社の100-MR139BKでスタンディング化
    - 社から支給されたものなので選んで買ったわけではない
- ノートパソコン + 外部ディスプレイ20インチを載せている

## メリット
- 腰の負担が減った
    - 体感的に「腰痛が減る」というよりも「腰の負担が減る(から結果的に腰痛も減る)」
- 椅子よりも姿勢の自由度が高い
    - 足幅の調整、重心移動、足踏み、軽いスクワット、等々
- 背筋が伸びる
    - 座っている時より呼吸が楽
    - (原因が不明だが)思考がすっきりする、決断しやすくなる

## デメリット
- 足がパンパンになる
    - 5時間連続スタンディングしたら限界
- 首が疲れる
    - ノートパソコンを見下ろすため
    - ノートパソコンを持ちあげる台と手元にキーボードが必要
- 高速で打鍵すると揺れる
    - 人より打鍵が強いので…
    - コードを一気に書きたいときってついついタイピングが早くなるので…
- じっくり考えるのが難しい
    - 一つのことをじっくり考える時に立ったままは厳しい
        - 慣れていないせいも(多分に)ある
- AppleWatchのスタンディングにカウントされない
    - 立っているのに「立ちましょう！」と通知がくる、かなしい
- ちょっとだけ恥ずかしい
    - フロアのほぼ全員が座っているので、目立っている感はある

## スタンディングデスクは必要か？
- 姿勢の選択肢を増やす意味で「必要」
    - 医者曰く「1時間以上同じ姿勢は体に負担がかかるからダメ」なので、選択肢が増えるのは良いこと
    - 「立ち」に完全移行ではなく「座る」と「立ち」の二択が可能となるイメージ
Google Apps Script の割り当て値と制限値

よく忘れて、毎回探しに行くので、メモ。

以下の割り当て値および制限値は、すべて無料のGoogleアカウントの場合であり、
G-Suiteアカウントでは異なります。

## 公式ドキュメント
[Quotas for Google Services](https://developers.google.com/apps-script/guides/services/quotas)

## 割り当て値と制限値

|項目|説明|制限or割り当て|内容|
|:-:|:-:|:-:|:-:|
|Script Runtime|スクリプトの実行時間|制限|6分(1実行あたり)|
|Custom function runtime|カスタム関数の実行時間|制限|30秒(1実行あたり)|
|Simultanceous executions|同時実行数|制限|30|
|Properties value size|プロパティの値のサイズ|制限|9KB(1つの値あたり)|
|Properties total storage|プロパティ全体のサイズ|制限|500KB|
|Properties read/write|プロパティの読み書き回数|割り当て|50,000回(1日あたり)|
|Triggers|トリガーの数|制限|20(ユーザまたはスクリプトあたり)|
|Triggers total runtime|トリガーの合計実行時間|割り当て|90分(1日あたり)|
|URL Fetch response size|URL Fetchしたレスポンスのサイズ|制限|50MB(1呼び出しあたり)|
|URL Fetch header size|URL Fetchしたレスポンスヘッダーのサイズ|制限|8KB(1呼び出しあたり)|
|URL Fetch POST size|URL FetchするときのPOSTデータのサイズ|制限|50MB(1呼び出しあたり)|
|URL Fetch URL length|URL FetchするときのURLの長さ|制限|2KB(1呼び出しあたり)|
|URL Fetch calls|URL Fetchの呼び出し回数|割り当て|20,000回(1日あたり)|
|Cache key length|キャッシュのキーの長さ|-|250文字|
|Cache data amount|キャッシュの値のサイズ|-|100KB(1キーあたり)|
|Cache expire time|キャッシュの保持期間|-|600秒|
|Spread Sheet max cells|スプレッドシートのセル数|-|5,000,000セル(1スプレッドシートあたり)|
|Spread Sheet max characters in cell|セル内の文字数|-|50,000文字|
|Spread Sheet created|スプレッドシートを作る数|割り当て|250回(1日あたり)|
PythonでCSVをJSONに変換するときに文字コードでつまずいた件

#概要
PythonでCSVファイルをJSONファイルに変換するツールを作ったときに、JSONファイルの中身が文字化けしてしまったので、修正方法を残しておきます。

#リソース

CSVファイル→JSONファイル変換ソース（修正前）
※参考→http://hktech.hatenablog.com/entry/2018/09/10/235725

```python:csv_to_json.py
import json
import csv

json_list = []

# CSV ファイルの読み込み
with open('./csv_sample.csv', 'r') as f:
    for row in csv.DictReader(f):
        json_list.append(row)

# JSON ファイルへの書き込み
with open('./json_sample.json', 'w') as f:
    json.dump(json_list, f)
# with codecs.open('./json_sample.json', 'w', 'utf-8') as f:
#     json.dump(json_list, f, ensure_ascii=False)

# JSONファイルのロード
with open('./json_sample.json', 'r') as f:
    json_output = json.load(f)
```

CSVファイル

```csv:csv_sample.csv
名前,順位,出身国
ナダル,2,スペイン
フェデラー,3,スイス
ジョコビッチ,1,セルビア
```

#csv_to_json.pyを実行してJSONファイルを生成

csv_to_json.py実行

```
(csv_to_json_tool) bash-3.2$ python csv_to_json.py
```

実行後に生成されたJSONファイル

```
[{"\u540d\u524d": "\u30ca\u30c0\u30eb", "\u9806\u4f4d": "2", "\u51fa\u8eab\u56fd": "\u30b9\u30da\u30a4\u30f3"}, {"\u540d\u524d": "\u30d5\u30a7\u30c7\u30e9\u30fc", "\u9806\u4f4d": "3", "\u51fa\u8eab\u56fd": "\u30b9\u30a4\u30b9"}, {"\u540d\u524d": "\u30b8\u30e7\u30b3\u30d3\u30c3\u30c1", "\u9806\u4f4d": "1", "\u51fa\u8eab\u56fd": "\u30bb\u30eb\u30d3\u30a2"}]
```
文字化けしてしまった。
[file --mime]コマンドでJSONファイルの文字コードを調べてみる。
※[file --mime]コマンドについて→https://qiita.com/pugiemonn/items/106749351991037fb606

```
(csv_to_json_tool) bash-3.2$ file --mime json_sample.json 
json_sample.json: application/json; charset=us-ascii
```

文字コードがus-asciiになっており、Unicodeエスケープされた状態で書き出されていたっぽい。
※文字コードと解読方法について→https://ferret-plus.com/7007
※エスケープについて→https://blog.ohgaki.net/what-is-escape#i-2

#JSONファイルの文字化けを修正

JSONファイル書き込み時のjson.dumpの第３引数で"ensure_ascii=False"を指定することで、utf-8で書き出してエスケープを回避することができました。
※Pythonのjson.dumpについて→https://docs.python.org/ja/3/library/json.html#json.dump
>ensure_ascii が (デフォルト値の) true の場合、出力では入力された全ての非 ASCII 文字はエスケープされていることが保証されています。ensure_ascii が false の場合、これらの文字はそのまま出力されます。

```python:csv_to_json.py
import json
import csv

json_list = []

# CSV ファイルの読み込み
with open('./csv_sample.csv', 'r') as f:
    for row in csv.DictReader(f):
        json_list.append(row)

# JSON ファイルへの書き込み
with codecs.open('./json_sample.json', 'w') as f:
    json.dump(json_list, f, ensure_ascii=False)      #"ensure_ascii=False"を指定

# JSONファイルのロード
with open('./json_sample.json', 'r') as f:
    json_output = json.load(f)
    print(json_output)
```

```
(csv_to_json_tool) bash-3.2$ file --mime json_sample.json 
json_sample.json: application/json; charset=utf-8
```

実行後に生成されたJSONファイル

```json:json_sample.json
[{"名前": "ナダル", "順位": "2", "出身国": "スペイン"}, {"名前": "フェデラー", "順位": "3", "出身国": "スイス"}, {"名前": "ジョコビッチ", "順位": "1", "出身国": "セルビア"}]
```

そのまま表示された！
Docker上でVueを動かすときに環境変数が読まれない

# なにが起きましたか

* 環境
    * Docker上
    * @vue/cli
    * `npm run build` でビルド
    * `http-server dist/` で配信


Vueのフロントエンドを作っている際，サーバサイドのAPIのエンドポイントを環境変数に格納して動かす方式を取っていた．
ローカルのビルドではちゃんと環境変数が読まれるが，Azure上にイメージをpushしたビルドでは環境変数が読まれないという状況

# 原因

原因は主に２つあった．

- そもそも，クライアントに配信されるjsに環境変数って？？？？
    - `@vue/cli` には，ビルド時にコード中の[環境変数を参照する部分を置き換えてくれる機能](https://cli.vuejs.org/guide/mode-and-env.html#using-env-variables-in-client-side-code)がある
    - `VUE_APP_*` で始まる環境変数のみ置き換えてくれる．それ以外は`undefined`になる．

これは既にそのとおりにしており，`VUE_APP_API_ENDPOINT`にサーバ側URLを設定していた．しかし，それでも環境変数は読まれない．

- Dockerfileで環境変数を設定していたが，**ビルド後に環境変数を設定していた．**

つまりこんな感じに書いていた

```Dockerfile:Dockerfile.production
FROM node:lts-alpine 

RUN npm install -g http-server && \
    npm install && \
    npm run build
EXPOSE 8000

ENV VUE_APP_API_ENDPOINT='https://hogehoge.net'
CMD [ "http-server", "dist", "-p", "8000", "-g", "-b" ]
```

なんとなく「環境変数はランタイムで読み込まれるもの」という思い込みが原因であった．加えて，ローカルでは `npm run serve` で動作していたため，これは実際にランタイムで(コマンドを叩いたタイミング)で環境変数が読み込まれており，何も問題がなかったこともある．
ちゃんとビルドコマンド前に`ENV ~~~`を移動させると，環境変数を参照することができた．

# 結論

* クライアントサイドかつDockerでの開発のときは，ENVをビルドコマンドの前に書こう！
    * 実行時に必要ないし，`RUN`のときに直接指定してもいいかもしれない．そのほうが意味的には良い
* 思い込み怖いね
Prettier 2.0 の主要な変更

ウェブ開発でよく使われているコードフォーマッターである Prettier の 2.0 がリリースされました。実装が間に合わず遅れている間に TypeScript 3.8 のリリースがあったりといろいろあり、当初の予定より 2 ヶ月ほど遅れてしまいました。

主要な変更について紹介します。詳細が知りたい方は、[リリースブログ](https://prettier.io/blog/2020/03/21/2.0.0.html)や PR や Issue を確認してください。

## Node 10.13.0 未満のサポート終了

https://github.com/prettier/prettier/pull/6907
https://github.com/prettier/prettier/pull/6908
https://github.com/prettier/prettier/pull/7302

EOL が来ているバージョンのサポートを終了します。

## デフォルトオプションの変更

いくつかのオプションのデフォルト値が変更されます。現在デフォルト値を使っていてこれによるコードの修正を回避したい場合、明示的に設定をする必要があります。

### `trailingComma`(末尾カンマ)

https://github.com/prettier/prettier/pull/6963

| 1.x    | 2.x   |
| ------ | ----- |
| `none` | `es5` |

1.x ではあらゆる末尾カンマを許容しませんでしたが、2.x では ECMAScript 5 でバリッドになるように末尾カンマをつけます。

```js
// 1.x
const obj = {
  foo
};

// 2.x
const obj = {
  foo,
};
```

ただし、`all` ではなく `es5` なので関数の引数リストの末尾カンマは許容しません。

### `arrowParens`(アロー関数の引数が一つのときのカッコ)

https://github.com/prettier/prettier/pull/7430

| 1.x     | 2.x      |
| ------- | -------- |
| `avoid` | `always` |

1.x では、アロー関数の引数が１つのときカッコをつけないようにフォーマットをしていましたが、2.x では常につけるようになります。

```js
// 1.x
arg => arg;

// 2.x
(arg) => arg;
```

### `endOfLine`(改行コード)

https://github.com/prettier/prettier/pull/7435

| 1.x    | 2.x  |
| ------ | ---- |
| `auto` | `lf` |

1.x ではファイル内の他の改行コードに合わせ、混在している場合は最初に使われているものに統一していましたが、2.x からは `lf` に統一されます。

## フォーマットの変更

よく使われそうな構文のフォーマットに変更があります。

### `function` キーワードのあとの空白

https://github.com/prettier/prettier/pull/3903
https://github.com/prettier/prettier/pull/7516

関数式(関数宣言ではない)の`function`キーワードのあとに空白が入るようになります。

```js
// 1.x
(function() {});

// 2.x
(function () {});
```

ただし、ジェネレータは例外で`function*`のあとに空白を追加します。

```js
// 1.x
const generatorFunc = function*() {};

// 2.x
const generatorFunc = function* () {};
```

## 新機能等

いくつかの新しい機能や改善があります。

### `babel-ts` パーサーオプション

https://github.com/prettier/prettier/pull/6400

1.x では TypeScript のパースに typescript-estree のみを使っていましたが、 2.x からは Babel の TypeScript パーサーを使えるようになります。

ただし、`parser`オプションを指定せずに TypeScript のフォーマットを行った場合は typescript-estree を使ってパースします。Babel を使って TypeScript のパースを行う場合はオプションで明示する必要があります。

```sh
# typescript-estree を使ってパースする
prettier foo.ts

# Babel を使ってパースする
prettier --parser=babel-ts foo.ts
```

### TypeScript 3.8 のサポート

https://github.com/prettier/prettier/pull/7631
https://github.com/prettier/prettier/pull/7764
https://github.com/prettier/prettier/pull/7804

TypeScript 3.8 から新しく追加された次の構文をサポートします。

- [Type-Only Imports and Exports](https://devblogs.microsoft.com/typescript/announcing-typescript-3-8/#type-only-imports-exports)
- [ECMAScript Private Fields](https://devblogs.microsoft.com/typescript/announcing-typescript-3-8/#ecmascript-private-fields)
- [`export * as ns`](https://devblogs.microsoft.com/typescript/announcing-typescript-3-8/#export-star-as-namespace-syntax)

### CLI の改善

https://github.com/prettier/prettier/pull/7660

1.x では CLI にファイル名しか渡せませんでしたが、2.x からはディレクトリを渡せるようになります。

```sh
# 1.x
prettier "**/*.{js,jsx,ts,tsx,md,json,yaml,html}"

# 2.x
prettier .
```

### 非推奨機能の廃止

いくつかの非推奨機能が廃止になります。おそらくこれらの機能を使っている人は少ないので、ここではあまり触れません。詳しくは https://github.com/prettier/prettier/issues/4097 を読んでください。

## 多くのバグ修正

通常のマイナーバージョンアップと同様に、多くのバグ修正が含まれます。
YouTube 再生リストの埋め込み


以下のような YouTube の再生リストのURLがあります。

```
https://www.youtube.com/watch?v=UzMMxZGA9B8&list=PL9nWu5PESvnsluiuv_MMZhDutE0UqHQ7g
```

これの、最後のパラメータ `list` の文字列

```
PL9nWu5PESvnsluiuv_MMZhDutE0UqHQ7g
```

これを以下に埋め込みます。

```
<iframe width="560" height="315" src="https://www.youtube.com/embed/videoseries?list={ここに埋め込む}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
```

こうなります。

```
<iframe width="560" height="315" src="https://www.youtube.com/embed/videoseries?list=PL9nWu5PESvnsluiuv_MMZhDutE0UqHQ7g" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
```

これで埋め込みの再生リストが表示できます。

[![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588914/a924fe01-617f-c88d-ca1e-2658b0f2ad97.png)](https://android.benigumo.com/20200317/youtube/)

[👉 YouTube 再生リストの埋め込み](
https://android.benigumo.com/20200317/youtube/)
Unity WebAPIを使ってデータを扱う


## 環境
PHP（Laravel5）
Unity 2019.1.4f1 (64-bit)

## 概要
WebAPIを使った通信とデータ扱い。
・UnityWebRequest
APIのリクエストするため

・JsonUtility
APIで取得したjsonを使うため

この二点を使う。

## 実装

``` Model.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking; 

public class Model 
{
	public int id;
	public int name;
	public int hp;

	string access_url = "https://hoge.com/api/v1";

	[System.Serializable]
	public class Character
	{
		public int id;
		public string name;
		public int hp;
	}

	[System.Serializable]
	public class Characters
	{
		public Character[] characters;
	}

	public IEnumerator ApiRequest()
	{
		UnityWebRequest request = UnityWebRequest.Get(access_url);
		request.SetRequestHeader("Content-Type", "application/json");
		yield return request.SendWebRequest();

		Characters characters = JsonUtility.FromJson<Characters>("{\"characters\":" + request.downloadHandler.text + "}");

		id = characterClass.characters[0].id;
		name = characterClass.characters[0].name;
		hp = characterClass.characters[0].hp;	
	}
}
```

## 使い方
読み込まれた時点で呼びだしてあげればいいかと思います。
後は好みでどうぞ

```
	public void Start()
	{
		StartCoroutine(getModel());
	}

	IEnumerator getModel()
	{
		characterModel = new CharacterModel(); 
		yield return StartCoroutine(characterModel.ApiRequest());
                // 以下表示させるなど
	}
```


## PHP - Laravel
特別なことはしてない
LaravelのModelを読んでreturnで返すだけです。

```
namespace App\Http\Controllers;
use App\Models\Character;

class ApiController extends Controller
{
    public function index()
    {
        return Character::all();
    }
}
```
配列数式（CSE数式）のすすめ

# 【注意】
CSE数式は今後互換性のために残されるが、SPILLを利用した方が良いとのことです。本記事は現場でどうしてもCSE数式を使わないといけない場合など、やむを得ない状況でのリファレンスとしてご利用ください。
https://support.office.com/ja-jp/article/%E5%8B%95%E7%9A%84%E9%85%8D%E5%88%97%E6%95%B0%E5%BC%8F%E3%81%A8%E3%80%81%E3%81%93%E3%81%BC%E3%82%8C%E3%81%9F%E9%85%8D%E5%88%97%E5%8B%95%E4%BD%9C-205c6b06-03ba-4151-89a1-87a7eb36e531

# 概要
配列数式（以下、CSE数式）の使い方を忘れないための覚書。

# 解説
例えば以下のように入力されたA列の値からセルC1のような値を作成したいとする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286440/d70681d6-eb41-7dca-7022-418833b42bf2.png)

自然にイメージするなら、処理の手順は `数値を括弧で囲む` ⇒ `それらの文字列をハイフンで連結する` となるだろう[^1]。これをCSE数式なしで実現する場合は、以下のように処理の途中で発生する `数値を括弧で囲む` の結果をセルに書き出す必要がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286440/9adf91a9-d5ca-e15a-2fad-42e1e4851c69.png)

これをCSE数式を使って実現すると、以下のようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286440/584b7bc0-a9ec-8c41-7e62-076747f3382e.png)

`数値を括弧で囲む` がTEXTJOIN関数の第3引数として指定した `"("&A1:A9&")"` で実現されているため、処理中における計算結果の書き出しが省かれている。括弧の間の値 `A1:A9` が単一セルではなくセル範囲のアドレスである点に注目する。これは範囲内の各セルの値を一つずつ指定したのと同義であるため、結果は配列形式で返ってくる。

`"("&A1:A9&")"` の結果が配列形式であることを検証してみる。セルC3に同数式を入力し、F2キーを押して編集モードへ移行する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286440/4fa3c86a-d0d9-3b3b-e2ad-6613a6d4f233.png)

ここでF9キーを押すと、計算結果が展開される。複数の値がセミコロンで区切られ、全体が波括弧で囲まれているため、計算結果が配列形式であることが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286440/55a7cdbe-208c-1b8b-d634-04e5882408ea.png)

そしてTEXTJOIN関数の第3引数以降は可変長のオプションである点に注目する。ここに配列を渡すと、イメージとしては値が以下のように展開されて処理される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286440/9ddf4be0-1ff8-e7f3-c5a9-95bbd97d6d9a.png)

# まとめ
CSE数式は、関数の可変長引数に配列を展開して渡したい時に使うものである。
処理途中の計算結果をセルに書き出す必要が無いため、「ドキュメントして無意味なデータ」を省くことが出来る点は、ドキュメントを美しく仕上げられるメリットである。しかし、途中の計算を一切書き出さない数式は作成する難易度が上がるうえに見通しが下がる。また、CSE数式を知らない人（特に非エンジニア）が触って非CSE数式にしてしまった場合にパニックを起こすことを考えると、ドキュメントの美しさと運用の都合を慎重に計らなければならないだろう。

[^1]: セマンティクスに則るなら、という意図である。多少の分かりにくさに目を瞑るなら `="("&TEXTJOIN(")-(",TRUE,A1:A9)&")"` という非CSE数式でも良い。
高輪ゲートウェイでズンドコキヨシを作ってみよう！

#2020年3月14日
###半世紀ぶりに山手線に新駅開業！
おめでとうございます。

というわけで、本題に入ります。
##何をするの？

今回は...
####「Javascriptでズンドコキヨシみたいな高輪ゲートウェイを作成！」
です！

この時点では意味がわからないと思います。

では、実際の画像です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515312/9e2f1295-2f84-c8d0-70f1-932583269515.png)

こんな感じで、「高輪」「ゲート」「ウェイ」がランダムに配列から取り出されて、

高輪ゲートウェイが出たら成功！みたいなゲームです！

完全にズンドコキヨシですね！

####実際にプレイしたい方は[こちら](https://nakano1120.github.io/takanawagateway/index.html)

では、ソースコードです

##ソースコード

```html:index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高輪ゲートウェイ</title>
    <link rel="stylesheet" href="style.css">
    </style>
</head>
<body>
    <div class="takanawa">
        <p id="text"></p>
    </div>
    <script type="text/javascript" src="script.js"></script>
</body>
</html>

```

```css:style.css
body{
    font-family:serif;
    background-color:#dddddd;
    color:#ffffff;
    margin:0;
    
}
.takanawa {
    position: relative;
    height: 40vh;
    background-color: #008000;
    text-align:center;
    font-size:20vh;
}
.takanawa p {
    width: 100%;
    text-align: center;
}
```

```js:script.js
        const takanawa=["高輪","ゲート","ウェイ"] ///ズンドコ風配列
        for(let i=0;i<3;i++){
            let random = Math.floor( Math.random() * takanawa.length );///ランダム
            document.getElementById("text").innerHTML+=takanawa[random]///innerHTMLで挿入
        }
```


##工夫した点
 - 実際のフォント（明朝体）に似せた
 - 色合いも似せた
 - ゲームとして成立させた
 - オリジナリティ
Python3でBOM付UTF-8のCSV(Excelで直接読めるCSV)を出力する方法


CSVファイルを文字コード UTF-8で作ると
Excelで読み込んだ時に文字化けする。
文字化けさせないためには先頭にBOMを付ける必要がある。

```bom.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys

# BOMを出力する
sys.stdout.buffer.write(b'\xEF\xBB\xBF')
# CSVを出力する
print ('ID,名前')
print ('1,山田')
print ('2,田中')
print ('3,坂本')
```
これで

```
./bom.py > excel.csv
```

と実行するとExcelで文字化けしないCSVファイル(excel.csv)が生成される。
undefined method `save' for nil:NilClass の対処法

### エラー内容

```
undefined method `save' for nil:NilClass
```

翻訳すると、Nilクラスに定義されてないsaveメソッドだよ！



####前提は以下の通り

- userモデルとgymモデルが存在する。
- ログインしたuserがgymを投稿する機能である。
- 両モデルでbelongs_to、has_manyを定義してgymはuserに属するものとする。
- gymモデルでvalidationによってgymモデルのカラム（name、content）とuserモデルのidはnilの値で保存されないことを定義する。




```修正前のgyms_controller.rb
class GymsController < ApplicationController
    before_action :logged_in_user, only: [:show, :create, :destroy]
    before_action :correct_user,   only: :destroy

  def index

  end

  def show
  @gym = Gym.find(params[:id])

  end

  def create
   @gym = current_user.gyms.build(gym_params)
   if @Gym.save
       flash[:success] = "投稿ありがとうございます!"
       redirect_to gyms_path
       else
       render 'gyms/index'
       end
  end

  def destroy
  end

  private

     def gym_params
       params.permit(:name, :content)
     end

end
```



```model/gym.rb
class Gym < ApplicationRecord
  belongs_to :user
  validates :user_id, presence: true
  validates :content, presence: true
  validates :name, presence: true
end
```

```model/user.rb
class User < ApplicationRecord
  has_many :gyms, dependent: :destroy
  validates :name,  presence: true
end
```

```view/index.rb
ジム一覧のページ
<%= form_with(model: @gym, local: true) do |f| %>
  <%= render 'shared/error_messages', object: @gym %>

  <%= f.label :ジム名 %>
  <%= f.text_field :name, class: 'form-control' %>

  <%= f.label :口コミ %>
  <%= f.email_field :content, class: 'form-control' %>

  <%= f.submit yield(:button_text), class: "btn btn-primary" %>
<% end %>

投稿する

```

前提の通りに記述をしているのでcreateアクションは問題なく動くはずだが、動かない。






##原因

コントローラのcreateアクションの@Gymが大文字になっていた。
@gymに直し、動きました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568461/fc4d9fd1-f933-2cb4-8b3c-fe23c5cafaa5.png)




インスタンス変数は大文字、小文字も認識するので注意。



エラーのnilClassになっている部分に注目すること。
【Go】ポインタと変数宣言（new, make）


Goには複数の変数宣言（メモリ割り当てと値の初期化方法）がある

&T{...}、 &someLocalVar、 new、 make　など


## ポインタ型

基本こちらで理解

[ポインタ メモリアドレスの秘密](http://wisdom.sakura.ne.jp/programming/c/c20.html)

[徹底図解！C言語ポインタを初心者向けに分かりやすく解説](https://daeudaeu.com/programming/c-language/pointer/)

[Go言語のメモリ管理](https://ascii.jp/elem/000/001/496/1496211/)


## 自分なりの整理

・ポインタ型とはメモリアドレスを格納することができる変数

→ ポインタ型（＝大元アドレス保持型）
→ 指定された変数のアドレスを保持、その大元アドレスを参照し新たにデータ領域を作成する


## 【ポインタ型の宣言】 「new」 または 「&変数 によるアドレス指定」

基本こちらで理解

[Why would I make() or new()?
](https://stackoverflow.com/questions/9320862/why-would-i-make-or-new)

[Is there a difference between new() and “regular” allocation?
](https://stackoverflow.com/questions/13244947/is-there-a-difference-between-new-and-regular-allocation)

## 自分なりの整理

・newのカッコに任意のタイプ型を指定する（または &変数名 でアドレスを指定する）
→ 大元アドレスが渡される
→ その大元アドレスを参照し新たにデータ領域が作成される
→ 受け取り側の変数はポインタ型（タイプ型名の前に*をつける）にする
→ ０で初期化される（不要な初期化時間や領域確保をなくす）

#### 【例：宣言の仕方】

```Go:
func main() {
	var a *int = new(int)  // OK
	b := new(int)          // OK
	
	c := &int              // NG (Not work this address set)

	// Works, but it is less convenient to write than new(int)
	var d int
	x := &d
}
```

#### 【例：ストラクトとポインタ】

```Go:
type House struct {
	Name string
	Room int
}

func main() {
	v := House{"YourHouse", 2} // Without pointer
	fmt.Println(v)

	a := new(House)            // OK
	b := &House{}              // OK
	c := &House{"MyHouse", 3} // Combines allocation and initialization
	fmt.Println(a)
	fmt.Println(b)
	fmt.Println(c)
}

```

結果


```
{YourHouse 2}
&{ 0}
&{ 0}
&{MyHouse 3}
```

→結果に表示される & は大元アドレス保持しているよという意味（＝ポインタ型）



#### 【例：関数とポインタ】

```Go:
func three(x *int) {
	*x = 3          // アドレスの中身を変更
}

func main() {
	var a int = 100
	three(&a)         // アドレスを渡す
	fmt.Println(a)  // 値が変更されている
}

```

結果

```
3
```



## 「make」による変数宣言

基本こちらで理解

[Golangのnew()とmake()の違い](https://cipepser.hatenablog.com/entry/go-new-make)

[Go: Make slices, maps and channels](https://programming.guide/go/make-slice-map-channel.html)

[Which is the nicer way to initialize a map in Golang?](https://stackoverflow.com/questions/31064688/which-is-the-nicer-way-to-initialize-a-map-in-golang)


[Tutor of Go Channels](https://tour.golang.org/concurrency/2)


## 自分なりの整理

・slice,map,channelのみで使用される
・メモリの領域を指定できる（予め領域確保することでリサイズなどが発生しにくいのかも）
・使う前にmakeで初期化した方が良いときがある（特にchannel？）
（mapは15個程データがあるならmakeにした方が良いとか）
・それぞれのタイプ型で初期化される（Structの中身を確認すると良い）


```Go:

// 固定長配列を定義
a := [4]int{1, 2, 3, 4}
 
// サイズ等を持ったスライスを定義
b := make([]int, 4, 8)
 
// バッファー無しのチャネル
c := make(chan string)
 
// バッファー有りのチャネル
d := make(chan string, 10)

```


## 参照リンク

[Goのnew()とmake()の違い](https://qiita.com/tyanchiba/items/d883caf7f80291034a9d)

[new() vs make()](https://www.godesignpatterns.com/2014/04/new-vs-make.html)
.NET Core の SDK がいっぱいインストールされてて大変だよぉ…を解決

.NET Core は、結構頻繁にアップデートされていて、いつの間にか（Visual Studio をアップデートしたりしてるうちに）プログラムの一覧がこのような有様になります。
（これでも定期的にチェックしていらないやつは消してるのに…）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/4c6c998a-fdfa-9a9c-9b55-c1cac0889123.png)

.NET Core SDK は 1 つあたり 500 MB くらいあるので、2 ついらないものが入ってるだけで 1 GB 持っていかれます。ありがとうございます。
ということで、ぽちぽち消していたのですが、先日 .NET Core アンインストール ツールというものが公開されていました。

[.NET Core アンインストール ツール](https://docs.microsoft.com/ja-jp/dotnet/core/additional-tools/uninstall-tool?tabs=windows)

入れてみて Windows Terminal で `dotnet-core-uninstall list` を打ってみると以下のように表示されました。

```
> dotnet-core-uninstall list

This tool can not uninstall versions of the runtime or SDK that are?
    - SDKs installed using Visual Studio 2019 Update 3 or later.
    - SDKs and runtimes installed via zip/scripts.
    - Runtimes installed with SDKs (these should be removed by removing that SDK).
The versions that can be uninstalled with this tool are:

.NET Core SDKs:
  3.1.102  x64    [Used by Visual Studio. Specify individually or use ?-force to remove]
  2.2.402  x64    [Used by Visual Studio 2019. Specify individually or use ?-force to remove]
  2.2.401  x64
  2.1.802  x64    [Used by Visual Studio 2019. Specify individually or use ?-force to remove]
  2.1.801  x64

.NET Core Runtimes:

ASP.NET Core Runtimes:

.NET Core Runtime & Hosting Bundles:
```

ふむふむ、SDK を 2 つくらい消しても大丈夫そうだなぁということで消します！ 1 GB の空き領域ゲットだぜ。

ということでいらない SDK を消す前に、どれがコマンドで消されるのかをチェックする `dry-run` を行います。`dotnet-core-uninstall dry-run --all --sdk` を実行すると以下のような結果になりました。

```
> dotnet-core-uninstall dry-run --all --sdk
*** DRY RUN OUTPUT
Specified versions:
  Microsoft .NET Core SDK 2.2.401 (x64)
  Microsoft .NET Core SDK 2.1.801 (x64)
*** END DRY RUN OUTPUT

To avoid breaking Visual Studio or other problems, read https://aka.ms/dotnet-core-uninstall.

Run as administrator and use the remove command to uninstall these items.
```

`dry-run` で確認したので次は `remove` で消します。管理者権限で起動した Windows Terminal で `dotnet-core-uninstall remove --all --sdk` を実行します。

実行すると以下のような結果になりました。ちゃんと本当に消す前に聞いてくれます。

```
> dotnet-core-uninstall remove --all --sdk
The following items will be removed:
  Microsoft .NET Core SDK 2.2.401 (x64)
  Microsoft .NET Core SDK 2.1.801 (x64)

To avoid breaking Visual Studio or other problems, read https://aka.ms/dotnet-core-uninstall.

Do you want to continue? [Y/n] Y
Uninstalling: Microsoft .NET Core SDK 2.2.401 (x64).
Uninstalling: Microsoft .NET Core SDK 2.1.801 (x64).
```


##### 消す前

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/b72d308c-05d3-c829-1260-69fc29d3fd79.png)

##### 消した後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/25633dc4-204b-1c46-ae6c-03207934250d.png)

空き領域がちゃんと 1 GB 増えました。やったね。

## まとめ

これからは、手動で 1 つ 1 つ心を込めて消す必要がなくなって、心に余裕が生まれそうです。
fastlaneを使って Internal App SharingにAABファイルをアップロードしてSlackにダウンロードリンクを飛ばす

## 事前準備
- fastlaneのバージョン`2.139.0以上`を使えるようにする
- Internal App Sharingを使ってアプリの配布とダウンロードができるようにしておく
    - こちらのスライドを見れば設定やそもそもInternal App Sharingって何？というのは解決できると思います [Internal app sharing 完全に理解した](https://speakerdeck.com/syarihu/internal-app-sharing-wan-quan-nili-jie-sita)
- Google Play Developer APIの[Publishing API](https://developer.android.com/google/play/developer-api?hl=ja#publishing_api_overview)を使えるようにしておく
    - こちらの記事でやり方は紹介されているので参考にしてください https://qiita.com/itog/items/f382a7cc4a38bd079aab
        - 記事内ではKeyにP12を使用する方法になっていますがJSONにします。このJSONが後で必要になります。

## 実装

```rb
  desc 'Submit a new build to Google Play Store Internal App Sharing'
  lane :submit_play_store_internal_app_sharing do
    # cleanを先にすることでbuildフォルダを一度削除する
    # これによってbundle[Flavor][Variant]で生成されたaabファイルのみがoutput配下に存在するようになる
    # [Flavor]や[Variant]は適宜自分たちの環境に合わせて読み替えてください
    gradle(task: 'clean bundle[Flavor][Variant]') 

    download_url = upload_to_play_store_internal_app_sharing(
      package_name: '[your.app.package.name]',
      json_key: 'service-account.json', # 事前準備で用意したjsonを指定します
      # json_key_data	: json_keyでjsonファイルを指定するか生のjsonをこのkeyで指定する
      aab: lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH] # 最初のgradleアクションで生成されたaabのファイルパスが格納されている
      # aab_paths : '' aabを複数アップロードしたい場合はこちらのkeyを使って配列でpathを指定する
    )

    payload = { 'Download URL' => download_url }
    slack(
      message: ':android: :google-play: Submit PlayStore Internal App Sharing!',
      payload: payload,
      default_payloads: %i[git_branch last_git_commit_message]
    )
  end
```

上記が成功するとSlackにダウンロードURLが投稿されるので、このリンクを端末で開くことでアプリのインストールができます。
<img width="536" alt="Screen_Shot_2020-03-17_at_12_27_09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9143/bf5c553e-0915-b9da-edc5-6101a51ca9d3.png">

アップロードするだけであれば`upload_to_play_store_internal_app_sharing`だけ呼び出せば大丈夫です。

## 注意点
API経由でアップロードした場合一覧( https://play.google.com/apps/publish/internalappsharing/ )に表示されないので注意です。
（なにかやり方が行けないのかも？）

## おわりに
完全に余談ですがInternal App SharingへのアップロードはGoogle Play Developer API v3が必要で、まずはそちらのバージョンアップが必要でした。
対応してくれた人には感謝しかないです。

このへんのはなし
https://github.com/fastlane/fastlane/issues/14573


## 参考URL
https://docs.fastlane.tools/actions/upload_to_play_store_internal_app_sharing/
https://docs.fastlane.tools/actions/gradle/
https://docs.fastlane.tools/actions/slack/
https://github.com/fastlane/fastlane/pull/15822/files
Rails6 のちょい足しな新機能を試す 124（eager loading bug fix編)

# はじめに

Rails 6 に追加された新機能を試す第124段。 今回は、`eager loading bug fix` 編です。
Rails 6.0.0 では、 `app` ディレクトリの下にファイルを置くと `rails server` を実行した時に エラーになるというバグがありました。

この事象は、Ubuntu などでは発生しますが、MacOS/X では発生しないようです。

Rails 6.0.1 以降では修正されています。

Ruby 2.6.5, Rails 6.0.2.1, 6.0.1, Rails 6.0.0 で確認しました。(6.0.1で修正が入ってます。）

```shell
$ rails --version
Rails 6.0.1
```

今回は、 `rails new` して、 `app` ディレクトリの下にファイルを作って確認してみます。

# Rails プロジェクトを作る

Rails プロジェクトを新たに作成します。

```shell
$ rails new rails_sandbox
$ cd rails_sandbox
```

# app の下にファイルを作成する

`touch` コマンドでapp の下にファイルを作成します。

```shell
touch app/file.txt
```

# Rails 6.0.1 では

Rails 6.0.1 では、 `rails server` してもエラーになりません。

# Rails 6.0.0 では

Rails 6.0.0 では、エラーになります。

```
$ rails server
...
         1: from /usr/local/bundle/gems/rb-inotify-0.10.1/lib/rb-inotify/notifier.rb:200:in `new'
         /usr/local/bundle/gems/rb-inotify-0.10.1/lib/rb-inotify/notifier.rb:200:in `initialize': Not a directory @ dir_initialize - /app/app/file.txt (Errno::ENOTDIR)
```

# 試したソース

* https://github.com/suketa/rails_sandbox/tree/try124_fix_eager_loading

# 参考情報

* [Correctly classify the files and directories that pass to watcher](https://github.com/rails/rails/pull/37102)