OmniAICreator/Qiita-1.07M huggingface dataset:
コメント機能　モデル単体テスト　実装

今回、実装時に正常にコメント機能モデル単体テストが起動しなく、悩んだため備忘録のためアウトプット。

`factory_bot_rails`
`faker`

上記二つのjemは導入済みを前提で進めていく。

正常系のテストの際にエラーがでた。

```
Comment
  #create
    コメント投稿できる場合
      コメント入力済みあれば投稿できる (FAILED - 1)
    投稿できない場合
      コメントが空では投稿できない
      ユーザーが紐付いていなければコメントできない

Failures:

  1) Comment#create コメント投稿できる場合 コメント入力済みあれば投稿できる
     Failure/Error: expect(@comment).to be_valid
       expected #<Comment id: nil, user_id: nil, post_id: nil, comment_text: "コメント", created_at: nil, updated_at: nil> to be valid, but got errors: Postを入力してください
     # ./spec/models/comment_spec.rb:11:in `block (4 levels) in <top (required)>'

Finished in 0.29859 seconds (files took 1.59 seconds to load)
3 examples, 1 failure

Failed examples:

rspec ./spec/models/comment_spec.rb:10 # Comment#create コメント投稿できる場合 コメント入力済みあれば投稿できる
```

エラーを読みとくにコメントでは無く、投稿が空になっているためにエラーが出ていると認識。


余談
まだプログラミング学習を始めて2ヶ月ということもあるが、エラーとの格闘が多くなってきているに比例して、エラーを読み解く力も日々ついてきていると実感している。


今回実装中のコードが下記。

`comment_spec.rb`

```
require 'rails_helper'

RSpec.describe Comment, type: :model do
  before do
    @comment = FactoryBot.build(:comment)
  end

  describe '#create' do
    context 'コメント投稿できる場合' do
      it 'コメント入力済みあれば投稿できる' do
        expect(@comment).to be_valid
      end
    end

    context '投稿できない場合' do
      it 'コメントが空では投稿できない' do
        @comment.comment_text = ''
        @comment.valid?
        expect(@comment.errors.full_messages).to include("Comment textを入力してください")
      end
      it 'ユーザーが紐付いていなければコメントできない' do
        @comment.user = nil
        @comment.valid?
        expect(@comment.errors.full_messages).to include("Userを入力してください")
      end
    end
  end
end
```

`comments.rb`

```
FactoryBot.define do
  factory :comment do
    comment_text { 'コメント' }
    association :user
  end
end
```

ここでシンプルな凡ミスをしていることに気づく。
コメントをするのに元である、post（投稿）に対してassociationが組めていない。

そこで、`comments.rb`に

```
FactoryBot.define do
  factory :comment do
    comment_text { 'コメント' }
    association :user
    association :post #追加
  end
end
```

`association :post #追加`

上記を追加することにより、正常に単体テストが実装された。

シンプルな凡ミスであったが、エラーの解読力が日に日に上がっているということも実感でき、5分立たないうちに気づけた。

以前ではもっと多く時間を使っていたと思う。

エラーと向き合えば自然と答えが出せるんだということにも改めて気づけ、今後はこのような記述ミスをなくして行けたらと思う。


ただ、まだまだわからないことも多いので日々勉強あるのみ。

エラーが出たら冷静に対応して行けたらと思う。

ご覧いただきましてありがとうございました。

example等で「このテストもやった方がいいよ」等のご指摘もありましたら、是非アドバイスいただけましたら幸いです。

宜しくお願いします。
LaravelのPHPUnitのテストでなぜか500エラーが返る時。


viewがしっかり200レスポンスを返しているかどうかのテストコード。
テスト関係なく、ブラウザの表示を目で見る限り、問題なく表示され、500レスポンスは返って来ていないのになぜか以下の通りに500レスポンスだと指摘される。

```
$ ./vendor/bin/phpunit ./tests/Feature/ExampleTest.php
PHPUnit 9.5.3 by Sebastian Bergmann and contributors.

Warning:       Your XML configuration validates against a deprecated schema.
Suggestion:    Migrate your XML configuration using "--migrate-configuration"!

F                                                                   1 / 1 (100%)

Time: 00:00.573, Memory: 20.00 MB

There was 1 failure:

1) Tests\Feature\ExampleTest::testBasicTest
Expected status code 200 but received 500.
Failed asserting that false is true.

/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:186
/var/www/tests/Feature/ExampleTest.php:20

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
```

```ExampleTest.php
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $response = $this->get('/');


        $response->assertStatus(200);
    }
}
```

おかしいなと思いわかったのは、
どうやら、phpunit.xmlも環境に応じて変更する必要があるとのこと。

```php:phpunit.xml
    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="DB_CONNECTION" value="mysql"/> #mysqlならmysqlに変更
        <server name="DB_DATABASE" value="〇〇"/> #データベースの名前を入れる
        <server name="MAIL_DRIVER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
    </php>
```

　できました！！


```
$ ./vendor/bin/phpunit ./tests/Feature/ExampleTest.php
PHPUnit 9.5.3 by Sebastian Bergmann and contributors.

Warning:       Your XML configuration validates against a deprecated schema.
Suggestion:    Migrate your XML configuration using "--migrate-configuration"!

.                                                                   1 / 1 (100%)

Time: 00:00.492, Memory: 18.00 MB

OK (1 test, 1 assertion)
```
中間テーブルにデータが保存される仕組み

#目次
①結論
②データを配列で保存する方法




###①結論
親要素を保存するときに、それに紐づいていてかつ、保存したいデータを配列で指定すると、その情報が中間テーブルに保存されるようになっている。


###②データを配列で保存する方法
親要素が登録される時に、has_many :○　,through: ■_○で紐付いている○の部分を単数形にし、_idsをくっつけて保存をストロングパラメーターで許可してあげると、中間テーブルに保存される。

```php:roomモデル
class Room < ApplicationRecord
  has_many :room_users 
  has_many :users ,through: :room_users ←こちら
end

```

```php:roomsコントローラー
 def create
    @room = Room.new(room_params)
    if @room.save
      redirect_to root_path
    else
      render :new
    end
  end

private

  def room_params
    params.require(:room).permit(:name,user_ids:[]) ←user+_ids
  end

```

　親要素のroomが保存される時に、roomのnameとそれに紐づく複数のuser_idが中間テーブルに入ることになる。

※補足:なぜ、モデル+_idsが使えるのか？
⇒この答えは、has_manyでアソシエーションしているからである。
○参考記事
https://web-camp.io/magazine/archives/17680#i-3
RedisをKubernetes上で構築しながら、Kubernetesを説明する。( 1 )

#はじめに
今回は Kubernetesに関してのシリーズで書いていこうと思っています。
どのような構成で書くかというと、
###**RedisをKubernetes上で構築しながら、Kubernetes上で説明していこう！！！**

という感じです。
最終的にはKubernetes上でspring-bootとredis-clusterを構成し、Service化するまでやっていこうかなと思っています。
もし良ければ読んでいってください。


#さっくりとKubernetesの特徴を説明

**Kubernetesは複数マシンにまたがるコンテナ群をオーケストレーションするためのオープンソースのシステムです。**



Dockerの実行環境だと、同一のホストで動くコンテナ同士だとプライベートネットワークではやりとりができます。しかし問題なのが、あくまで1つのホストに閉じていているということです。
これの何が問題なのかを考えてみましょう。

コンテナを複数管理するのであれば、docker-composeで十分です。しかし、考えてみて欲しいところは複数サーバーにまたがった時です。
ロードバランサーの設定を別途実施しないといけないですし、ログの管理も複数サーバーあるので大変です。
スケールアップする時やアップデートをするときには、各サーバーのdocker-compose.ymlを手動で修正しなければいけません。
さらにですよ、何もしなければコンテナが落ちても気づかないので、ずっと監視していないことになります。めちゃくちゃ大変ですね。

#####下図：大変なところ
![server_scale.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/07d24cff-72f1-1fe4-e8d9-70fc3e44fee7.png)

以下の記事が大変参考になりました。
Dockerについて深くまとめてみた - その2 Docker周辺ツール(Docker Compose,Kubernetes)編
https://blog.ecbeing.tech/entry/2019/10/28/114000

＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿

Kubernetesは上記の問題を全て解決できます。
Kubernetesの特徴としては

- コンテナの死活管理 
- スケーリング/オートスケーリング
- ロードバランシング
- ローリングアップデート
- ログの管理　　　etc...
いろいろな機能があります。
しかもなんと、これらの機能を**マニフェストという設定ファイルで管理できてしまう**という。
なんと便利なのでしょうか。これはKubernetesを使うほかありませんね。

# Kubernetesをざっくり説明していく

##ではKubernetesの全体像に関して説明をしていこうと思います。
全体像は以下の図のようになっています。
**クラスタ**というKubernetesの実行環境があります。そこでは**ノード**という各コンテナを動かすマシンが動きます。ノードの中にはコンテナを積んでいるKubernetesのデプロイ単位であるPodが存在します。このPodにラベルをつけると、Kubernetesはそのラベルごとに指示が一斉に行えるのです。
そうすることでラベルごとのオーケストレーションが行われるわけですね！

このKubernetesをローカル環境で使用できるようにするツールに**minikube**というものがあります。次回以降の記事ではminikubeを使用するのでインストールしておきましょう。

``` ruby:macOSでのinstall 
brew install minikube
```


##ではどうやって操作するのかを話していきます。
クラスタ上では、**コントロールプレーン**というクラスタ全体の状態を管理するコンポーネント群があります。
その中には**全体を操作するAPI**や**状態の情報を取得するAPI**が入っています。
このAPIを簡単に扱えるようにしたコマンドラインツールに**kubectl**があります。
こちらも次回以降の記事では使用しますのでinstallしておきましょう。

``` ruby:macOSでのinstall 
brew install kubectl 
```


![kube.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/f23911cd-7113-2c75-0371-f3a66a29e114.png)

#最後に
本記事では全然コードもRedisも出てきていませんが次回から構築しながら描ければと思っています。
次回に続きます。

#参考文献
Dockerについて深くまとめてみた - その2 Docker周辺ツール(Docker Compose,Kubernetes)編
https://blog.ecbeing.tech/entry/2019/10/28/114000

Dockerについて深くまとめてみた - その2 Docker周辺ツール(Docker Compose,Kubernetes)編
https://www.amazon.co.jp/%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88%E3%81%A7%E3%82%8F%E3%81%8B%E3%82%8BDocker%E3%81%A8Kubernetes-Software-Design-plus-%E5%BE%B3%E6%B0%B8/dp/4297118378
Power Automate DesktopでSAPを動かしてみる

#**はじめに**
前回のSAPログオンの続きです。
以前にUiPathで作った自動化ツールがありまして、
それを今回PADで作り直しています。
SAP画面の自動処理が出来るように試行錯誤しています。
製作途中で気になった点をいくつか記します。
マニュアルも読まずにいきなり作業開始しています。
覚書ですので、何かのご参考になれば。
ご了承くださいませ。

#**キーの送信**
キーボードの文字を自動的に送信する機能です。
やりたいことは、
Shiftを押しながらC（コピー）
Shiftを押しながらV（ペースト）
をPADでどのように記述するか？です。
答えは
{Control}({C})
{Control}({V})
でした。

続いて、
コントロールとシフトとF9キーの3つのキーを同時に押す。
{Control}({Shift}({F9}))

どうやら、カッコの位置にキーボードを押しっぱなしの意味があるようです。

#**SAPの画面を操作する**
前回も気になったのですが、Ui要素が絡んでいる部分は
何かありそうです。（ここがUiPathとの違いかなぁ）
次の点に注意し、デスクトップレコーダでの記録と修正を行います。
・マウスで操作しないようにする
・限りなくキーボードで操作する
・SAP画面をアクティブにするためには、マウスでアプリケーションの外枠をクリックする
・TABで遷移後、1秒待ってから文字を入力する
・文字を入力後、1秒待ってからEnterキーの押下
・画面切り替わりのタイミングは必要に応じて待ち時間を指定

待ち時間については、
画面下部の「実行遅延」とキーの送信アクション内の「キー入力の間隔遅延」があります。
今回はデフォルトのままで使っています。

SAPの画面操作は、キーボードだけで殆どの操作が可能です。
TABキー(BackTab)でフォーカスを移動させますが、独特に遷移するルールがあるようです。
一定の操作を安定的に動作させるするには各画面の特徴を把握する必要があります。

例えば、SAPの明細画面が表示された後、エクセルファイルに出力する場合、
マウスなら簡単に操作できるのですが、これをキーボードで操作するとなると
TABキーを何度も連打しなければなりません。
でも、自動化なので、正しいTAB押下の回数を指定するだけで、あとは確実に動いてくれます。
便利ですね。

今日はMB52ともう一つの画面操作をPAD作り直してSAP画面が無事動きました。
作り終わって、結局、Ui要素？インスタンス？って何だろう？になりました。

#**インスタンスって何だろう？**
まずはPADのインスタンスについて、エクセルで実験開始です。
エクセルを開いた状態で、次の操作をデスクトップレコーダに記録しました。
ここから---
1. B2セルをコピー(Ctrl+C)
2. ↓キーを2回押して、
3. B4セルに貼付け（Ctrl+V)
ここまで---
この3つのステップだけを記録後、直ぐに実行してみます。
すると、何も動かない！なんでだろう？

Excelのインスタンスが必要なようです。
で、ここを読みました。
https://docs.microsoft.com/ja-jp/power-automate/desktop-flows/actions-reference/excel
これを読んだら、次の2つことがわかりました。
EXCELインスタンスを取得できるのは、
・エクセルを起動したとき
・実行中のエクセルに添付するとき

どうやらエクセルを開いた状態で始めたので、
インスタンスを取得できていないために、エラーに遭遇したのね。
なるほどね。このお作法を理解していない為ですね。
だから最初にエクセルを起動か、ファイルを開く操作から始める必要があるですね。

複数のエクセルを開いた状態で操作するときは、
VBAでの操作と比較すると、このインスタンスで指定するほうが確実に操作できそうです。

おまけに、
エクセルのセルをコピーするには、
Ctrl+Cよりも
「エクセルワークシートからセルをコピー」
で作ったほうが確実に動作しました。

#**SAPのテーマ選択で動きが変わる？**
SAPに話を戻して、
SAP GUIオプションで、ビジュアルデザインのテーマ選択を選ぶと
SAP画面のデザインが変わります。
今回は
Belize Theme
SAP Signature Theme
の2つで今日作った2つのフローを動かしてみました。
どちらもそのまま動作出来ました。
キーの送信でコントロールしているので、
基本的な違いは無いようです。
もう少しここの違いが無いか今後も検証を続けます。

今日はここまで。
【Ruby】自己学習をするときにRubyのバージョンを変えたい時

自己学習でRubyのバージョンを変えたい時には、Homebrewとrbenvを使おう。

## Homebrewとは
HomebrewとはmacOSでのパッケージ管理ツール。
これを利用することによって、ソフトウェアの導入を単純化することができる。

Homebrewのインストールの方法はご自身で調べてください。

### macにHomebrewが導入されているか確かめるコマンド
```
$ brew -v
Homebrew 3.0.7
Homebrew/homebrew-core (git revision 0be2da9986; last commit 2021-03-17)
Homebrew/homebrew-cask (git revision 8b37684cd7; last commit 2021-03-17)
```
このように表示されていればHomebrewはインストールされています。

## rbenvをインストールする
rbenvをインストールすることによって、``Rubyのバージョンの切り替えが簡単にできる``ようになる。

### rbenvのインストール
```
$ brew install rbenv
```
上記のコマンドを実行後、下記のコマンドを実行することでrbenvがインストールできているかを確かめる。

```
$ rbenv --version
rbenv 1.1.2
```
このように表示されていればOK

## 使いたいRubyのバージョンをインストールする
```
$ rbenv install 3.0.0
```
これでRubyの３．０．０をインストールする。
ダウンロードができたら、下記にコマンドでプロジェクトで使えるように設定する。

```
$ rbenv global 3.0.0
```

```
$ ruby -v
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
```

これでOK
PHPの基本

# PHPの出力の仕方

ソースコードの基本の書き方
**<?php**を必ず書く。末尾の**?>**は省力可能
これがPHPの記述をする際のルールになる
**""**の中に出力したい文字列等を記述する
そして、処理の終わりには**;**を記述することが決まり

```php
<?php echo "初めまして";?>
```
この状態で出力すると**「初めまして」**と出力されます。
デスクトップのcsvファイルをJupyter-notebook上にアップロードしたい(超初心者向け)

題目の通り、備忘録的に載せます。(短いです。)

### モチベーション
「Python実践データ分析１００本ノック」をやりたくて、

そのデータを活用するためにデスクトップ上からアップロードしたかったんです・・・。(そっちの方がおしゃれに見える)←お前だけだ

(離れたところからのアップロードがわからなくてモヤモヤするけど面倒くさくて放置していたそこのあなた！向けです。)

### 流れ
既にダウンロードしてあるデスクトップ上のcsvのファイルを開きましょう〜。
こんな画面になりますよね？

![スクリーンショット 2021-03-20 15.11.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031281/bdbb706d-2bd1-7969-883d-a621b23e42e5.png)

そうしたら、ページレイアウトの上部にある「家ボタン🏠」クリックすると

![スクリーンショット 2021-03-20 15.13.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031281/0021bd9b-8e37-9e44-a17e-9bd05079f917.png)

こんなところにいく(よね？)

次は、開きたいファイルの「・・・」の部分(自分が最後に開いた日時の左のところ)をクリックすると

![スクリーンショット 2021-03-20 15.14.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031281/023d9124-257c-2b5b-9030-a5e5fd437864.png)

こんなのが出る(よね？)

あとはパスのコピーをクリックします。

### Jupyter-notebook上
あとはもうこんな感じ

![スクリーンショット 2021-03-20 15.17.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031281/2fd4a6ad-cfb2-f84e-7a95-0b34d6f5bfa6.png)

右の方見えてないけど大丈夫ですかね・・・？
'この中にパス入れます'←これでコピーしたパスを囲ってあげれば、初心者のあなたでも読み込めるはず！

お疲れさまでした！
VBAコンボボックス イベントごとのデータ反映具合

## 検証の動機  
Accessフォームのコンボボックスに入力された文字列を含めたドロップダウンリストを生成したいが思惑通りのリストが表示されない。
なので、どんなイベントがどんな順序で発生し、いつ入力された値を得られるかを調べたかった。

## 結論  
KeyDown -> KeyPress -> Change -> KeyUp の順でイベントが発生
Changeの段階で入力が参照できた
KeyUpの段階で必要な情報がそろった

## 前提
combo1という名前のコンボボックスを用意し、デバッグ用出力のみ記述したイベントプロシージャを用意。引数があればそれも表示。
例：KeyDownイベント  

```
	Private Sub combo1_KeyDown(KeyCode As Integer, Shift As Integer)  
	    Dim ProcName As String: ProcName = "combo1_KeyDown"  
		Debug.Print ProcName & " : Start"  
		Debug.Print KeyCode; " <== KeyCode"  
		Debug.Print Shift; " <== Shift"  
		Debug.Print Me.combo1; " <== Me.combo1"  
		Debug.Print Me.combo1.Text; " <== Me.combo1.Text"  
		Debug.Print Me.combo1.Value; " <== Me.combo1.Value"  
		Debug.Print ProcName & " : End"  
	End Sub  
```  

combo1にフォーカスがあり、何も入力されていない状態から開始。

## 結果  
少ない試行で十分な結果が得られたので、全てのパターンは網羅していない。
わかりやすくするために、StartとEnd以外をインデント。
#### コンボボックスにフォーカスがあり、コンボボックス外をクリックしたとき  
```  
	combo1_Exit : Start  
		0  <== Cancel  
		Null <== Me.combo1  
		<== Me.combo1.Text  
		Null <== Me.combo1.Value  
	combo1_Exit : End  

	combo1_LostFocus : Start  
		Null <== Me.combo1  
		<== Me.combo1.Text  
		Null <== Me.combo1.Value  
	combo1_LostFocus : End  
```  

#### コンボボックス外にフォーカスがあり、コンボボックスの入力欄をクリックしたとき  
```  
	combo1_Enter : Start  
		Null <== Me.combo1  
		<== Me.combo1.Text  
		Null <== Me.combo1.Value  
	combo1_Enter : End  

	combo1_GotFocus : Start  
		Null <== Me.combo1  
		<== Me.combo1.Text  
		Null <== Me.combo1.Value  
	combo1_GotFocus : End  
```  

#### コンボボックスにフォーカスがあり、`9`を入力したとき  
KeyUpイベント時に必要な情報がそろう  

```
	combo1_KeyDown : Start
		57  <== KeyCode
		0  <== Shift
		Null <== Me.combo1
		<== Me.combo1.Text
		Null <== Me.combo1.Value
	combo1_KeyDown : End
	
	combo1_KeyPress : Start  
		57  <== KeyAscii  
		Null <== Me.combo1  
		<== Me.combo1.Text  
		Null <== Me.combo1.Value  
	combo1_KeyPress : End  
	
	combo1_Change : Start  
		Null <== Me.combo1  
		9 <== Me.combo1.Text  
		Null <== Me.combo1.Value  
	combo1_Change : End  
	
	combo1_KeyUp : Start  
		57  <== KeyCode  
		0  <== Shift  
		Null <== Me.combo1  
		9 <== Me.combo1.Text  
		Null <== Me.combo1.Value  
	combo1_KeyUp : End  
```
Rubyでじゃんけんのコードを書く

## はじめに
この記事はRubyを使った初歩的なプログラミングのアウトプットの練習をするためのものです。
見辛い点、わかりづらい点などあったらご指摘していただけると幸いです。
作成時、
[Rubyでじゃんけんプログラムを作成]
(https://qiita.com/JunJun0706/items/939334da3c5b13ab7be5)
の記事とコメントを参考にしました。

## 目標
ターミナルにて自分の手とコンピュータによるランダムな手をじゃんけんで戦わせ、結果が出るところまでを目標とします。

## 概ねの目算
jankenと言うメソッドを作成します。あいこの間は勝負が続くので、あいこと勝負がつく場合で分けることも考え、

```ruby

def janken
  "ジャンケンの処理"
end

draw = true
while draw
  draw = janken
end
```
と言うプログラムを作成します。drawとはあいこのことを指し、drawがtrueの間はjankenを繰り返させる、と言う意図です。

## じゃんけんの処理内容
「最初はグー、じゃんけん...」は繰り返したくない内容なのでメソッドの外側へ用意します。また、手は入力に応じたものとするため、

```ruby

puts "最初はグー、じゃんけん..."
puts "[0]グー、[1]チョキ、[2]パー"
```

を用意します。その後、配列を使って手と数字を対応させます。分かりやすくするために、ターミナルには数字でなく手を表示させます。

```
  hands = ["グー","チョキ","パー"]

  player_hand = gets.to_i
  program_hand = rand(3)

  puts "あなたの手：#{hands[player_hand]}、相手の手：#{hands[program_hand]}"

```

この段階でじゃんけんの結果が判断できます。グー、チョキ、パーは三竦みの関係になっているので、

```ruby
result = (player_hand - program_hand) % 3
```

とすることで、結果を判断できます。（参考記事のコメントでこの方法を知りました。）

## じゃんけんの結果
resultの数値により処理が変わるのでif,else文を使います。
まずあいこの場合は相手の手と自分の手が同じと言うことでresultは0になっているはずです。また、この時はjankenメソッドの戻り値をtrueとしたいので、最後の行にtrueと記述します。resultが０ではない場合、勝敗がついているのでjankenメソッドの戻り値をfalseにする必要があります。

```ruby
if result == 0
  puts "あいこで\n[0]グー、[1]チョキ、[2]パー"
  true
elsif result == 1
  puts "あなたの負けです"
  false
else
  puts "あなたの勝ちです"
  false
end
```

以上です。最後に全体のコードを載せておきます。

```ruby
puts "最初はグー、じゃんけん..."
puts "[0]グー、[1]チョキ、[2]パー"

def janken
  hands = ["グー","チョキ","パー"]

  player_hand = gets.to_i
  program_hand = rand(3)

  puts "あなたの手：#{hands[player_hand]}、相手の手：#{hands[program_hand]}"

  result = (player_hand - program_hand) % 3

  if result == 0
    puts "あいこで\n[0]グー、[1]チョキ、[2]パー"
    true
  elsif result == 1
    puts "あなたの負けです"
    false
  else
    puts "あなたの勝ちです"
    false
  end
end

draw = true

while draw
  draw = janken
end
```

## 最後に
この記事は参考元のコードとコメントを組み合わせ、自分で何も見ずに書いたものです。。まだ改善する余地はあると思います。
自分の理解を深めるために書いた記事ですが、Rubyの練習にじゃんけんのコードを書く人の助けになれば嬉しいです。
Node.jsのnpmモジュールを使ってjsonファイルをminify・整形する手順

#はじめに

Windows環境で、Node.jsのnpmモジュールを使って以下を行う手順をまとめます。

- JSONファイルの軽量化(minify)：改行やスペースの削除
- JSONファイルの整形：改行やインデントにより見やすくする

#使用モジュール

- [jsonminify](https://www.npmjs.com/package/jsonminify) → JSONファイルの軽量化モジュール
- [format-jsonfile](https://www.npmjs.com/package/format-jsonfile) → JSONファイルの整形出力モジュール

#準備：モジュールのインストール

1. Node.jsを取得しインストールする。→ https://nodejs.org/ja/

2. Node.js command promptを起動する。

3. 以下のコマンドを実行する。（2行目のプロキシ設定は必要な場合のみ実行）

```
$ npm -g config set registry http://registry.npmjs.org/
$ npm -g config set proxy http://xxx.xxx.xxx:8080
$ npm install -g json-minify
$ npm install -g format-jsonfile
```

#使用方法

Node.js command promptから、以下のコマンドを実行する。

##JSONファイルの軽量化
```
$ type test1.json
  [
    {
      "name": "foo",
      "age": 10
    },
    {
      "name": "bar",
      "age": 20
    },
    {
      "name": "hoge",
      "age": 30
    }
  ]
$ json-minify test1.json
  [{"name":"foo","age":10},{"name":"bar","age":20},{"name":"hoge","age":30}]
```

##JSONファイルの整形
```
$ type test2.json
  [{"name":"foo","age":10},{"name":"bar","age":20},{"name":"hoge","age":30}]
$ format-jsonfile test2.json
  [
    {
      "name": "foo",
      "age": 10
    },
    {
      "name": "bar",
      "age": 20
    },
    {
      "name": "hoge",
      "age": 30
    }
  ]
```
#参考記事

- [JSONファイルを整形してくれるCLIツールを公開した](https://qiita.com/tomboyboy/items/609cb299fe5869f838af)
（ターミナル）Shell Script 準備 Mac 編（メモ）

記事内容移転しました。

[O.R.Develop Website
Shell Script 準備編（LinuxコマンドをMacで使ってみる）](https://oldriver-develop.com/articles/show/6/Shell%20Script%20%E6%BA%96%E5%82%99%E7%B7%A8)
Udemyでプログラミング学習する時の問題点について

#1.はじめに
現在、私はUdemyでプログラミング学習をしています。
受講回数は**3講座**ほど（全部で200個くらい）そこでUdemy学習での問題点をまとめました。
主観的な意見にはなりますが、参考になれば幸いです。

##2.問題点
Udemy学習においての障壁は主に2つ程あると思っています。

###①講座を見てもすぐ忘れてしまう。

結局Udemyはインプット中心なので、見てもすぐ忘れます。一日後にはほぼ忘れてます。
アウトプット＆インプットの様な講座も多く存在しますが、それでもすぐ忘れます。

###②インプットばかりだから楽しくない。

ひたすら単調に授業を続ける講座だと、どうしても飽きてきます。

**「これ結局どこで使うの？」
「え？なんでそうなるの？」
「んーよくわからん！」
「結局なんでこうなったの？」**

授業が進むにつれてこうなることも多くなります。
その結果、「あんま面白くないな」と思うこともあるでしょう。
主観的な意見にはなりますが、プログラミングが一番おもしろいと思えるのは
``インプットした内容を使って自分が作成したい物を作成すること``
だと思っています。
なので、インプットばかりだと、どうしてもつまらなく感じてしまいます。

##3.解決策
###①講座を見てもすぐ忘れてしまう。

これの解決策は
**自分が今日やった事をまとめてTwitterに報告**
ハードルは上がりますが
**Qiitaなどに今日やった事の解説を投稿**

これが一番効果があると感じました。
学んだことを自分で報告・解説することによって、凄く頭に入りやすくなります。

Qiitaに関しては本当におすすめで、就活での企業へのアピールにもなりますし、やり得です。

###②インプットばかりだから楽しくない。

これの解決策は
**授業がつまらないと感じた瞬間に一旦授業を終了し、
今まで授業でインプットしてきた内容を使って簡単な物を動かしてみる。**

JavaScriptを受講しているのであれば、
**自分でconst,letを定義して出力してみる**
**自分でハンバーガーメニューを作ってみる**
HTML/CSSであれば
**一旦簡単な自己紹介ページを作ってみる。**

ここでまた分からない所が出来てきた場合、またUdemyに戻って受講→作ってみる。
など、一旦インプットを辞めてアウトプットに専念してみるのが良いでしょう。

##Udemy学習はプログラミング学習に最適
Udemyはプログラミング学習において最適と言ってもいいでしょう。
実際に手を動かしながら同時に学習出来るのは本よりも強いです。
是非、Twitter,Qiitaなどでアウトプットしながら学習してください。
ツクールのおまじないからの卒業（即時実行関数編）

**（03/24/2021　02:00追記）
複数のご指摘を元に、内容を全体的に修正・再構成しました**

##結論
今回は短いです。
まず結論。

**「ES20xxでプラグインを記述する際は、即時実行関数の代わりにブロック`{}`で代用可能だよ！**

とはいえ、即時関数をブロック`{}`に置き換える上で幾つか注意点もあるので
順に見ていきましょう。

##そもそもなぜ即時実行関数を使っていたのか
**`var`が関数スコープだったから**です。
スコープについてはあまたある入門書、入門記事でも丁寧に説明されているのでここでは説明しません。
そもそもスコープがわからん、という方は[この辺](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Grammar_and_types#variable_scope)が分かりやすいと思います。

で、本題に返って、なぜ今まで即時実行関数が使われていたのかというと、

`var`が関数スコープのため、スコープ汚染を防ぐためにコード全体を関数化する必要がある。
　→だけど、その場で即座に一回だけ呼び出す関数をわざわざ名前付き関数として作るのも不毛じゃね？
　　→だったら、無名関数をその場で即実行してしまえばいいじゃない。
　　　→**即時実行関数、爆誕**

という考え方です。
`var`、すべてはおまえのせいだ！

##現状は？
`let`と`const`しか使ってないですよね。・・・使ってないですよね？（念押し
**今さらですが`let`および`const`はブロックスコープです。**

つまり、コード全体をブロック`{}`で囲めばそれで事足ります。

```JavaScript:
//今まで
(function () {
    /*なんやかんや*/
})();

//これから
{
    /*なんやかんや*/
}
```
スペースを抜いても**17文字→２文字**。スッキリ！わかりやすい！
また、`var`との決別の意思表示にもなるかと思います。

##注意点も幾つかあります
ただし即時実行関数を無条件にブロックに置き換えられるわけではなく、いくつかの注意すべき点もあります。

###その１－strictモードの扱い
まずは[mdn](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode#invoking_strict_mode "Strict モードの呼び出し")から引用します。

>Strict モードはスクリプト全体または個別の関数に適用できます。
>括弧 {} で括られるブロック構文には適用できません。
>そのような場所に適用しようとしても何も起きません。

特に重要なのが**『括弧 {} で括られるブロック構文には適用できません。』**という部分。

```JavaScript:
{
    'use strict';
    /*なんやかんや*/
}
```
のように、strictモードの呼び出しをブロック内に記述すると、strictモードが適用されません。
これを回避するには以下のように'use strict'をブロックの外側に引っ張り出し、スクリプト全体に対して
strictモードを適用する必要があります。

```JavaScript:
'use strict';
{
    /*なんやかんや*/
}
```

###その２－strictモードにおける即時実行関数とブロックの、thisの解釈の差異
即時実行関数内と、その代替であるブロック内で直接`this`を使用した場合の挙動に違いがあります。

 - 即時実行関数内で`this`を使用した場合

```JavaScript:
'use strict';
(function() {
    console.log(this);    //thisはundefinedとなる
    this.foo = 0;         //そのため、thisのプロパティにアクセスするとTypeErrorが起こる
})();
```
 - ブロック内で`this`を使用した場合

```JavaScript:
'use strict';
{
    console.log(this);    //thisはグローバルオブジェクトを指す
    this.foo = 0;         //なので、グローバルスコープにfooプロパティが作られる形で処理が通ってしまう
}
```
即時実行関数内やブロック内で、意図的に直接`this`を使用することはまず無いと思いますが、
誤って記述してしまった際にブロックだとエラーを吐かずに通してしまう分だけ少し気付きにくかったりします。

「そんなことしないよ」と思う人もいるかもしれませんが、一つ、ありがちな事例がありました。
**ブロックとアロー関数の組合せ**です。
以下、頻出するプラグインコマンドの定義例において、`this`を使用したものです。

```JavaScript:
'use strict';
{
    //プラグインコマンドの定義
    PluginManager.registerCommand(pluginName, "set", args => {
        textPictureText = String(args.text);
        this.foo = args.foo;
    });
}
```

アロー関数と`this`の解釈については良く語られるテーマなので、ここでは説明を行いません。
（詳しくは[ こちら ](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions#description)をご参照ください）
ともかく、function構文と異なり、アロー関数だと宣言時の`this`が呼び出し時にもそのまま適用されます。
結果、**この場合の`this`はアロー関数を超えて、更にはブロックも超えてグローバルオブジェクトとなります**。
怖いですねぇ、恐ろしいですねぇ。
プラグインコマンドに限らず、コールバック関数の類だとうっかりやっちゃいそうです。

そういうことをしなければ問題ないのですが、うっかりした際に思いがけないハマりを起こす可能性はありますので、
**「関数とブロックで`this`の挙動が違う」**
という認識は持っておいた方が良いでしょう。

##最後に
今回の元ネタはこちらの[速習 ECMAScript 2020](https://www.amazon.co.jp/dp/B08F1VNR7L)という本でした。
ES5以前のECMAScriptとの差分のみを簡潔明瞭に、それでいて分かりやすく解説してくれており、たいへんオススメです。
また、より詳しくは[こちらの記事](https://qiita.com/raccy/items/310b4353a757296f797f )も参考になるかと思います。

####謝辞
今回、この記事を書くにあたって複数の方からご指摘、ご意見をいただきました。
正確を期するにあたり、たいへん参考になりました。
厚く御礼申し上げます。
コードを見ていてもやっとしたこと

#レビュー中にもやっとしたことをまとめる
コードレビューってする側からすると
とてもハードルが高い？と思われ勝ちなイメージなのですが
僕が入っているプロサー内ではある一定ラインまではレビューが活発に行われていて
そのおかげで会社のチーム内でのレビューも率先して出来ている。

そもそもレビューとは
>~Weblio辞書から~
一度決められた物事を、改めて調査したり検討したりすること。現在は、批評や評論という意味合いで使用されることが多い。また、商品や作品などについて、評価を付けたり感想を述べたりすることを「レビューする」と表現する。

と辞書では書かれていましたが僕自身は
>評価を付けたり

よりも
>感想を述べたりすること

これがかなり大事だなと痛感しております。
何が言いたいかって
みんなレビューをすることに対して相手そのものを否定していると勘違いしてるし
レビュー受ける人も自分の技術を否定されていると
勘違いしている人は割と多いのかなと思います。
レビューはあくまでもその人の感想だってことぐらいに留めておけば
お互いに気が楽だろうなぁと感じてます。
実務に入っているとその時の案件や環境や方針で
あのときはAパターンの実装は良くないと言われたけど
今回はAパターンでやっていこうとなるのだから
システムも人間と同じ生き物みたいですよね。

前置きが長くなりましたが早速本題にはいります〜

##経緯
チーム内で簡単なレビューを今回の案件でしていくことになり
僕は自分の実装を少しでも早く終わらせて他メンバーのコードを
これでもかってぐらい舐め回すように見ております←汚い

そんなときにもっとこうしたほうがお互いにとって
やりやすかったのでは？(ここでもやっとしました)ということがあって今回の記事作成にいたります。

あとから紹介しますがこの考えに至るまでに
「リーダブルコード」や「Web+DB PRESS」などを読んでいて
インプットしたことを活かしたいとなりました。

##もやっとしたこと
では具体的にどんなことかと言うと
今回の案件ではLaravelを使って実装をしております。
よくあると思うのですが権限毎に同じ画面(仮にindex.blade.phpとする)でも表示される内容が
違うといった実装のFeatureテストをレビューしていたのですが
今回、index.blade.phpに対して3つのFeatureテストを作っていく対応で
1つ目のコードにはその権限毎の表示対してのテストが実装されていなかったのです。

レビューをしていた僕はコメントする前に考えました。
1. 忘れちゃったのかな〜
2. 仕様把握出来てないのかな〜
3. 別のテストにまとめるのかな〜

そして僕はとりあえず下記のようなコメントを残しました。
※意図が伝わるように内容は変えてます。

```
権限別に表示されるテストがないのであったほうがいいかなと！
※別タスクで実装予定であれば問題ないです。
```

そして返ってきたコメントで
予想通りの別タスクで実装を予定しているとのことでした。

過去の自分であればこれで話は終わったのですが
少し成長したいまの自分は違います。
些細なことですがいくつかの課題が見つかったなと思ったのです

ちょっと文章だけで状況が伝わりにくいですが
皆さんは僕が感じた課題がなにかわかりますか？

僕は以下の課題を見つけました。

1. レビュー者が確認しないといけない状況
2. 実装者が返信しないといけない状況
3. 実装者の意図が伝わらない実装

言葉があっているか不明ですが上記の３つが思い浮かびました。
### 1.レビュー者が確認しないといけない状況
割と日々の業務で僕自身もやってしまっているのですが
レビューする人が実装者に確認をしないといけなくなる実装って
効率良くないなと思うわけです。
だって
①レビューする→②意図がわからず確認する→③返事が来る→④再度レビューする
この②と③の工程もったいないですよね？
無くすことはできるんですよ。
でもやらなくても案件の対応はできちゃうんですよね。
それでも改善できる箇所があるのであれば改善するしかないと
僕は思います。

### 2.実装者が返信しないといけない状況
1.とは逆の立場になるのですが実装者側にとっても
もったいない工程ができちゃうんですよね。
また、実装者にとっては普通はこうするだろうから
これでレビューしてもらおうだと
レビューする側の負担が大きくなるので見てもらうからには
相手の負担を軽く出来ないか考えていくことは必須だと思う。

###3. 実装者の意図が伝わらない実装
そもそも実装者は意図があってコードをかいてレビューしてもらうけど
その意図がレビューする人に伝わらなければ
多分半年以上たったあとに自分が書いたコードを見ても
自分ですら意図がわからなくなってると思う。
コードから意図が伝わるようにすることってめちゃくちゃ重要だと思うわけです。

##コメントについて
あれこれ述べたところでじゃあどうするんだよって話だよね！！！←別に意識してないよ

今回の件で僕であればコードにコメントを残しておこうと思いました。
例えば下記のような内容です。

```
// 表示の切り分けのテストは〇〇Testで実施

〜以下実装
```

個人的にはもうこの対応が今回の件で言えば最強じゃないかと思うわけでなのですが
みなさんならどうしますか？

あまりコメントを長ったらしく書くのは良くはないと僕は思っているのですが
上記のコメントがあるだけでレビューする人も実装者も無駄にやり取りをしなくて済むようになったと僕は思うので必要なコメントだと思うわけです。
半年以上たった後に実装者、もしくは第三者が見たときに
「あれ、このテストやってないのか、、あ、なるほどね！」
となるでしょう←保証はない

ほんと些細なことかと思われますがこういうところから
僕は改善していくしかないのでしっかりと考えてみました。
もしも参考になったと思った方は最後にLGTMをいただけると嬉しいです(*´ω｀*)

##参考
[リーダブルコード](https://amzn.to/3tEZxp4)
良いコードを書くのには欠かせないバイブル的な役割の本ですね！
個人的には自力で調べて実装できるよって人からおすすめします。
最近プログラマー目指し始めました！って人が読むと
良いことをしているんだけど実装はできないみたいなことになるのでおすすめできないです。

[WEB+DB PRESS](https://amzn.to/3vJxgzO)
会社で定期的に購入されているのですが過去のもとってあって
最近は毎日借りて読んでます。
ひとつの情報だけでなく幅広く記事にしてくれているので
読みたい内容だけ読むのもいいですよ。

[初めてのSQL](https://amzn.to/3cUb6ly)
意外かもしれませんがここでSQLを出しますｗ
なぜかというとこの書籍の内容がCLIで実行していて
書かれているSQL文が見やすいように書かれている
そこが個人的にも面白くて今回の記事で紹介しました。
SQL自体の勉強にもめちゃくちゃなりますよ。
【Rails】テーブルを結合したら同じレコードが複数selectされたとき

## 起こった問題
Railsチュートリアル第14章の最後の演習（14.3.3）の、`feed`メソッドを`joins`を使ってリファクタリングするところで、サンプルコードをそのまま使ったところ、自身のmicropostが複数表示される不具合が出ました。

<img width="400" alt="スクリーンショット 2021-03-20 13.27.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361302/4d7f3367-1c3b-d675-48a1-e604d1be9db5.png">

全然完成してません。
テーブルの結合をするとよくあることですね。
具体的にどういう結合になっているかは以下で解説されています。自力で考えてみたのですがややこしくて分かりませんでした...
[【Rails】Active Recordのjoinsメソッドで連結したテーブルから一意なレコードを取得する(Rails Tutorial第14章) | LaptrinhX](https://laptrinhx.com/rails-active-recordnojoinsmesoddode-lian-jieshitateburukara-yi-yinarekodowo-qu-desuru-rails-tutorial-di14zhang-203604917/)

該当のコードはこちら。

```ruby
# ユーザーのステータスフィードを返す
  def feed
    part_of_feed = "relationships.follower_id = :id or microposts.user_id = :id"
    Micropost.joins(user: :followers).where(part_of_feed, { id: id })
  end
```

## こう直す
重複を削除するには、後ろに`distinct`をくっつけます。

```ruby
Micropost.joins(user: :followers).where(part_of_feed, { id: id }).distinct
```

生SQLでも、`SELECT DISTINCT microposts.* ...`とすれば同じようになります。

ついでにテストにも重複したmicropostが表示されないことの確認を追加しましょう。
配列から重複を排除したものを返してくれる`uniq`というメソッドがあるのでこいつを使います。

```user_test.rb

  test "feedに期待するmicropostが含まれる" do
    michael = users(:michael)
    lana = users(:lana)
    archer = users(:archer)
    
    # 割愛
    
    # 重複がない？
    assert_equal michael.feed.count, michael.feed.uniq.count    
  end

```

## おわりに
バグに気づいたときは「著者のミスか？」と思ったのですが、最後の演習ですし、もしかしたら[コラム1.2](https://railstutorial.jp/chapters/beginning?version=6.0#aside-technical_sophistication)の考えを実践させるための課題としてあえてそうしたのかも、と思えてきました。だとしたら粋ですね。
Cntlm設定しているLinuxのdocker-composeでプロキシ設定host.docker.internal:3128を使おうとしてビルド失敗

## 結論

Linuxのdocker-compose.ymlバージョン3でhost.docker.internalを使ってDockerホスト上にあるProxyを通ってインターネット接続させながらイメージビルドしたいときはbuildのところでも`extra_hosts`で`"host.docker.internal:host-gateway"`を書く必要あり。

<https://github.com/docker/compose/issues/7323>

```yml:docker-compose.override.yml
version: "3"
services:
  myservice:
    build:
      extra_hosts:
        - "host.docker.internal:host-gateway"
    extra_hosts:
      - "host.docker.internal:host-gateway"
```

環境

```shell:bash
$ docker --version
Docker version 20.10.5, build 55c4c88
$ docker-compose --version
docker-compose version 1.28.5, build c4eb3a1f
```

## 背景

LinuxでDockerを使う際、コンテナ内からDockerホストにアクセスしたい場合に、Docker Desktopで使える`host.docker.internal`を使うことはできません。[^1]

ではCntlmを使って`http://localhost:3128`のようなポートにローカルProxyサーバーを作ってそこを経由しないとインターネット接続できないような場合にはどう設定するか？  
`http://host.docker.internal:3128`の代わりにDockerホストのIPアドレスを書いて`http://XXX.XXX.XXX.XXX:3128`と設定するとうまくいきます。

```json:~/.docker/config.json
{
    "proxies": {
        "default": {
            "httpProxy": "http://XXX.XXX.XXX.XXX:3128",
            "httpsProxy": "http://XXX.XXX.XXX.XXX:3128",
            "noProxy": "localhost"
        }
    }
}
```

ただしこの設定の仕方は、他のコンピュータからこのコンピュータのDockerデーモンに接続する（他のコンピュータの環境変数`DOCKER_HOST`でこのコンピュータを設定する）ときに問題を引き起こします。  
コンテナ内に作られるプロキシ環境変数は、接続元のコンピュータの`~/.docker/config.json`から作られるからです。

そのため接続元のコンピュータからすると、接続先に合わせて毎回`~/.docker/config.json`を書き直さないとコンテナはインターネットに接続できません。

```json:~/.docker/config.json
{
    "proxies": {
        "default": {
            "httpProxy": "http://host.docker.internal:3128",
            "httpsProxy": "http://host.docker.internal:3128",
            "noProxy": "localhost"
        }
    }
}
```

もしもすべてのコンピュータでDockerコンテナのプロキシ設定を↑のように統一できていれば、接続先に合わせて毎回`~/.docker/config.json`を書き直す必要はなく、もちろんプロジェクトのソースコードの中にもプロキシ設定を書く必要はなくなるわけです。

## --add-host=host.docker.internal:host-gateway

<https://github.com/docker/for-linux/issues/264>

上記issue内で散々書かれているように、現在Linux上のDockerコンテナ内で`host.docker.internal`を使うには `docker build`や`docker run`の際に`--add-host=host.docker.internal:host-gateway`を付けてやればよく、`docker-compose up`でコンテナを作る場合にはdocker-compose.ymlの`extra_hosts`のところに書けば良いのですが、docker-compose.ymlバージョン2では`build`のところに`extra_hosts`を指定しなくてもビルド中にも追加のホスト名を解決できたのにバージョン3では今のところ`build`にも指定しないとビルド中はホスト名を解決できないです。

## 参考記事

- [Configure Docker to use a corporate proxy](https://medium.com/@saniaky/configure-docker-to-use-a-host-proxy-e88bd988c0aa)
- [linuxでhost.docker.internalを使う ](https://qiita.com/skobaken/items/03a8b9d0e443745862ac)
- [Cntlmの代わりにpx-proxyでNTLM認証プロキシを手軽に突破する【Windows】](https://qiita.com/eitsupi/items/226b65d54e207a7c5fe7)

[^1]: 「`host.docker.internal`はあくまでDocker Desktopの開発時に使うためのものでLinuxの本番環境でいきなり使えるようになるのはまずい」という言い分も分からないでもないのですが、Linuxで開発している人の立場は……。
Djangoの概念

# はじめに
- Djangoのチュートリアルをやってみて、説明されている概念がすんなり腑に落ちなかったので、自分の理解を元にして、Djangoのとっかかりとしてあるべき形を考えてみました。

## 概念図
![Djangoの概念5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365845/db515224-1b5e-cccd-1a93-cf48a757ea2c.png)

## Model、Template、View、URLConf
- 一般にURLConfは、Viewの一部とされていて、Model、Template、Viewを並べて「MTV」と呼ばれます。
    - これは、Larabelなら、Model、View、Controllerに相当します。
- Djangoは、データベース(Model)、コンテンツ(View)、URL(URLConf)、外観(Template)を分離して抽象化し、互いに実体を隠蔽しようとします。
    - そのため、この記事では、ViewとURLConfを分けて説明しています。

## アプリ (App)
- サイトで、ひとまとまりの機能を実現する単位で、実体はPythonのモジュールです。
- アプリ毎に、独自のモデル、テンプレート、ディスパッチャ、ビューを持つことができます。

## プロジェクト
- 複数のアプリが組み合わさって、一つのサイトを形成します。

## モデル (models.py)
- DBのテーブルをクラスとして表現した設計書です。
    - 背後のO/RマッパーがDBを隠蔽しようと尽力しています。

## URLディスパッチャ (urls.py)
- サイトのURL構成を定義し、URLを抽象化します。
    - クライアントからリクエストされたURLパターンに応じて、複数のアプリやビューに振り分けを行う機構です。
    - 生のURLを隠蔽します。
- プロジェクトが総親でアプリが子となる階層構造を成します。
    - まず総親でアプリ別に大まかに割り振って、受け取ったアプリ内でさらに細かくビューに割り振る感じです。

## ビュー (views.py)
- リクエストに応じて、モデルからデータを取り出し、コンテンツを構成して、テンプレートに描画させる機構です。
    - Pythonでガリガリ書きます。

## テンプレート (templates/*.html)
- ビューから渡されたコンテンツを埋め込むページの外観やUIを構成します。
    - HTMLを拡張した専用マクロ言語で書かれ、レンダリングエンジンが標準HTMLを生成します。

# おわりに
- 執筆者は、Python、Djangoともに初学者ですので、誤りもあるかと思います。
    - お気づきの際は、是非コメントや編集リクエストにてご指摘ください。
    - あるいは、「それでも解らない」、「自分はこう捉えている」などといった、ご意見、ご感想も歓迎いたします。
- 次は、チュートリアルを見直したいです。
ロケーションサービスの紹介

今回は、前回のブログで紹介した PaaS (Platform as a Service) の ArcGIS Platform で提供されているロケーションサービスについて簡単に紹介していきたいと思います。

ArcGIS Platform で提供されているロケーションサービスは、背景地図サービス（ベースマップレイヤー）、ジオコーディングサービス、ルーティングサービス、空間分析サービス、人口統計などのサービスを使用することができます。ロケーションサービスは、Web アプリやネイティブアプリなどのクライアント APIs からサービスにアクセスするために REST API を提供しています。そのため、マップアプリでの利用や自社のソリューション、サービス、製品などにこれらのサービスを組み込むことができます。

https://freedom-tech.hatenablog.com/entry/2021/03/13/175350
ArcGIS Platform で Mapbox GL JS を使ってみる。

Esri 社から ArcGIS Platform が今月にリリースされました。これまでの ArcGIS Online での SaSS (Software as a Service) やオンプレミスでの ArcGIS Enterprise に加えて、新たに PaaS (Platform as a Service) が加わった感じです。

ArcGIS Platform は、ロケーション機能をアプリや業務システム、自社製品などに統合したい場合にフル活用することができます。開発者向けのプラットフォームの ArcGIS for Developers を継承しており、ArcGIS API、SDK に加えて、オープンソース API も利用することができるようになっています。

ArcGIS Platform での大きな変更点は、オープンソースが利用できるようになったことと、商用アプリの利用として、API キーを設定することで利用できるようになったことです。API キーの設定でのアプリ運用は Google Maps や Mapbox も同じ戦略をとっています。開発者ではあればこれが一番分かりやすいのかなと思います。これは、Mapbox など他社の PaaS (Platform as a Service) も意識しているのかなと思います。

今回は、オープンソースが利用できるようになったということで、さっそく Mapbox GL JS を使ってみましたので、簡単な手順を紹介したいと思います。

https://freedom-tech.hatenablog.com/entry/2021/01/31/212510
右クリックから新規作成するでテキストドキュメントが表示されない。

# 状況
エクスプローラーから新規作成をしてもテキストドキュメントが表示されなくなった。調べてみると、メモ帳が消えていた。


# 解決方法
設定のアプリと機能のオプション機能からメモ帳を削除した後インストールしたところメモ帳が復活し、新規作成からテキストドキュメントが表示されるようになった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396969/c0bcbe36-8ec1-a121-0354-9aa388d49275.png)

# 参考サイト
https://winaero.com/install-or-uninstall-notepad-in-windows-10/
Windows 10でワイヤレスネットワークの優先度を変更する。

# はじめに
Windows 10ではWindows 7の時にできていたワイヤレスネットワークの優先度の変更がGUI画面上からできなくなってしまいました。

外出先ではテザリングで繋ぐようにしたいけど、家では自宅のWiFiに繋ぐようにしたいのに優先度の設定ができないのは都合が悪いので、コマンドからの変更方法とワイヤレスネットワークの一連の操作をまとめたバッチを紹介します。

# コマンドからのワイヤレスネットワーク優先度変更方法
優先度の変更はコマンドプロンプト、またはPowershellから`netsh`コマンドで行います。

```batch:ワイヤレスネットワーク優先度変更コマンド
netsh wlan set profileorder name=[SSID] interface=[無線LANインタフェース名] priority=[変更後優先度]
```

上記のSSID、無線LANインタフェース名、変更後優先度は後述のコマンドで確認できます。

## 登録されているワイヤレスネットワーク確認方法
現在登録されているSSIDと優先度を確認するには以下コマンドを実行します。

上から順に優先度が高くなるので、優先度を変更したいSSIDと変更後の優先度を控えておきます。

```batch:登録されているワイヤレスネットワーク確認方法
netsh wlan show profiles
```

## 登録されている無線LANインタフェース確認方法
無線LANインタフェース名は以下コマンドを実行した際に「**インターフェイス名**」として表示される名前を控えます。

```batch:登録されている無線LANインタフェース確認方法
netsh wlan show networks
```

# ワイヤレスネットワーク操作バッチ
登録されているSSIDの確認、優先度変更、削除を行うバッチを作成してGitHubにアップしました。

https://github.com/sakai00kou/qiita/blob/master/batch/wlan_network_mgmt.bat

以下簡単な説明。

## メニュー画面
対話式で進むようにしているので、実行したい操作の番号を選択して`Enter`を押します。

```batch:メニュー画面
----------------メニュー----------------
[1] 登録済み無線APの優先順位を確認
[2] 無線APの優先順位の変更
[3] 登録済みの無線LANプロファイル削除
[4] この処理を終了する
-----------------------------------------
実行する処理が記載された番号を入力してください >
```

## 優先度の変更
優先度を変更したいSSIDを入力します。

```batch:優先度を変更したいプロファイルの入力
インターフェイス Wi-Fi のプロファイル:

グループ ポリシー プロファイル (読み取り専用)
---------------------------------------------
    <なし>

ユーザー プロファイル
---------------------
    すべてのユーザー プロファイル     : wifi1
    すべてのユーザー プロファイル     : wifi2


※上から順に1(優先度高)～n(優先度低)

優先順位を変更するプロファイル名を入力してください。 >
```

変更後の優先度を聞かれるため、変更後の優先度を入力します。


```batch:優先度の入力
変更後の優先順位を数字で入力してください。 >
```

指定の内容で問題なければ「y」を入力。

```batch:優先度の変更
このホスト（xxxxx）で利用する無線LANプロファイル"wifi2"の
優先順位を"1"に変更します。

変更の実行は[Y]、キャンセルは[N]を入力しEnterキーを押下してください。 >
```

## プロファイルの削除
削除したいSSIDを入力します。

```batch:削除したいプロファイルの入力
インターフェイス Wi-Fi のプロファイル:

グループ ポリシー プロファイル (読み取り専用)
---------------------------------------------
    <なし>

ユーザー プロファイル
---------------------
    すべてのユーザー プロファイル     : wifi1
    すべてのユーザー プロファイル     : wifi2


削除するプロファイル名を入力してください。 >
```

再入力を要求されるため、先ほどと同じプロファイル名を入力します。

```batch:削除したいプロファイルの再入力
確認のためもう一度入力してください。 >
```

指定の内容で問題なければ「y」を入力。

```batch:プロファイルの削除
このホスト（xxxxx）から無線LANプロファイル名"wifi2"を削除します。

削除実行は[Y]、キャンセルは[N]を入力しEnterキーを押下してください。 >
```

# 注意点
本バッチは無線LANインタフェース名を「**Wi-Fi**」に指定して実行しています。

実行する端末の無線LANインタフェース名が「**Wi-Fi**」ではない場合は、バッチをエディタで開き、`INTERFACE_NAME`の名前を実行する端末の名前に変更してください。

```batch:無線LANインタフェース名の変更
（抜粋）
set INTERFACE_NAME="Wi-Fi"    ←名前を変更
```

# おわりに
気づいたらSSIDの順番が変わっているので、個人的によく利用するバッチです。

なんでWindows 7ではGUI画面から操作できていたのにできなくなったんでしょう？
AWSの構成図を作りながら主要な機能を学ぼう！その１

#自己紹介
現在AWS SAA合格を目標に学習中の駆け出しエンジニアです。
2021年3月にAWS CLFに合格しました。
次のステップとしてSAAの学習を始めましたが、ハンズオンでAWSに触れながら学習する事と並行して、構成図を作成して自分にも他の人にも解りやすく説明できるレベルになる事を目指していきます。

##記事の読み方
学習中の内容に沿っていくので、具体的なアプリ（ポートフォリオなど）のデプロイ手順とは少し異なる内容になると思います。AWSの仕組みをもっとよく知りたい人や、自分でネットワーク設計を行っていきたい人向けの内容になるかと思います。
もちろん私の様にSAA合格へ頑張る人に役立てれば最高です。
また構成図を見て、各サービスの関係性を理解する事を重視してますので、実際のハンズオンの手順と異なる点があると思います。その点はご容赦ください。

#その１ 構成図作成の環境を構築
##使用ツール　diagrams.net
[diagrams.netのリンク](https://www.diagrams.net/)
[アイコンなどをダウンロード](https://aws.amazon.com/jp/architecture/icons/)

それでは次回から早速構成図を使った学習を進めていきましょう！！

[その２ VPCとサブネットについて](https://qiita.com/megukentarou/items/9b547672c3257830f96f)
Azure SQL Database/Azure Synapse Analytics のユーザーの作成

# 参考サイト
https://www.gixo.jp/blog/7652/#DWU
# 手順
masterデータベースにログインし、下記のSQL文を実行します。

```sql
--DBユーザー(db_test)を作成
CREATE LOGIN db_test WITH PASSWORD = 'PassWord1';
--masterデータベースにDBユーザー(db_test)を追加
CREATE USER db_test for LOGIN db_test;
```

通常のDBにログインし、下記のSQL文を実行します。

```sql
--通常のDBにDBユーザー(db_test)を追加
CREATE USER db_test for LOGIN db_test;

--DBユーザー(db_test)にcontosoedwデータベースのCONTROL権限を付与
GRANT CONTROL ON DATABASE::contosoedw to db_test;

--DBユーザー(db_test)にlargercリソースクラスのロールを追加する
EXEC sp_addrolemember 'largerc', 'db_test';
```
Rで地図を描く【その6: 等深線図】

# 0. 等深線図とは？

等深線図とは端的に言うと等高線図の海洋版で、水深の等しい場所を結んだ線のことです。

# 1. Rで等深線図を描く

下記のリンク先の論文 (Taniguchi et al., 2021) では、`R`を用いて等深線の作図を行なっています。

https://www.mdpi.com/genes/genes-12-00303/article_deploy/html/images/genes-12-00303-g002.png

具体的な手順は以下の通りです。（ここでは、60mと120mの等深線を描きます）

```
library(marmap)
library(ggplot2)
library(mapproj)
library(ggsn)
Japan <- getNOAA.bathy(lon1 =115,lon2 =147,lat1 =20,lat2 = 55, resolution = 1)

png(filename="plot.png")	
ggplot(Japan)  + xlim(125, 140) + ylim(29, 39) + 
  xlab("longitude") + ylab("latitude") +
  geom_contour(aes(x=x, y=y, z=z), colour = "green", breaks = -60) +
  geom_contour(aes(x=x, y=y, z=z), colour = "blue", breaks = -120) +
  geom_contour(aes(x=x, y=y, z=z, ltw = 2), colour = "brown", breaks = 0, size = 1) +
  scalebar(data = NULL, x.min = 125, x.max = 139, y.min = 29, y.max = 39,
           dist = 100, dist_unit = "km", transform = TRUE, model = "WGS84") +
  theme_bw() +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank()) +
  coord_map()
dev.off()
```
JuliaのDataFrameで重複削除

Julia　データフレーム　重複削除
と調べても、なかなか記事が出てこないので備忘録がわり（←言ってみたかった）

環境
Julia 1.5.3
DataFrames　0.22.2

共通データフレーム

```julia
df = DataFrame(A = ["aa","ab","aa","ac","ab"], B = [1, 5, 2, 10, 5])
```

|  | A | B |
|:-:|:-:|:-:|
| 1 | aa | 1 |
| 2 | ab | 5 |
| 3 | aa | 2 |
| 4 | ac | 10 |
| 5 | ab | 5 |


# 全列が共通した行の重複削除の場合
A列とB列が共に共通している行を削除したいのであれば

```julia
unique(df)
unique!(df)
```

のどちらかを使えば良い（！をつけると上書きされる）。

|  | A | B |
|:-:|:-:|:-:|
| 1 | aa | 1 |
| 2 | ab | 5 |
| 3 | aa | 2 |
| 4 | ac | 10 |

# 特定の列で重複削除を行いたい場合
今回の例では、A列の重複削除を行い、

|  | A | B |
|:-:|:-:|:-:|
| 1 | aa | 1 |
| 2 | ab | 5 |
| ３ | ac | 10 |

となるようにしたい。

```julia
# 対象列の値ごとにデータフレームを分割
gd = groupby(df, :A)

# データフレームの行数が
# １ならそのまま、
# １より大きければ１行目を取得する
# という関数を作成
dedup(x) = (size(x, 1)>1) ? x[1,:] : x
# 今回は１行目を選択したが、
# x[1,:]ではなくx[nrow(x),:]として最終行でも良い

# 分割された各データフレームをdedup後、結合
combine(gd, valuecols(gd) .=> dedup)
```

でA列が重複している行を削除できる。
アイコンと文字を横並びにするcss

アイコンの横に文字を入れたい。

参考
https://www.keicode.com/script/align-vertical.php

```

<div><img src='/img/img24x24.png' alt='' style="width:24px;height:24px;vertical-align:middle;"><span style="vertical-align:middle;display:inline-block;">abc</span></div>

```
コマンドプロンプトからpowershellを実行しようとして手こずる。。

# 使用環境
- OS：Window10　home
- PSVersion：5.1.19041.610

# 投稿したきっかけ
最近、教本を参考にしてpowershellのお勉強しているときに記載されているソースを自分でタイピングするとしょうもないところで時間を食ってしまったので備忘録かつ自分への戒めとして投稿しました。

# やろうとしたこと
下記のA.batから現在の時刻を判定し、午前ならB.ps1、午後ならC.ps1をよびだす。
・A.bat
・B.ps1
・C.ps1

```bat:A.bat

@echo off

rem 現在の「時刻」の取得
set now_hour = %time:~,2%

if %now_hour% lss 12(powershell C:\work_ps\temp\am.ps1 
) else (powershell C:\work_ps\temp\pm.ps1 
)

pause
exit
```
```B.ps1
echo "午前です"
```
```C.ps1
echo "午後です"
```
# 手こずってしまった原因
- batで変数を代入する際に半角スペースを入れてしまい値が代入されてなかった
- batのソースの一行を複数行に跨いで記載する場合は改行する場合は「^」（キャレット）が必要と思ったが
ただ自分のif文のお作法を無視した書き方をしただけだった→if文の条件式と実行部分でスペースを空けていなかった

# 経緯
## やったこと①
実行しようとしてもコマンドプロンプトが起動せず。A.batのソースを一行ずつ流したところ、午後の時間帯なのにB.ps1がテキストとして開かれる。
## やったこと②
確かbatのソースの一行を複数行に改行する場合、しかるべき記述が必要だったと思い、if文を修正
「^」（キャレット）を追加したものに修正A.batを実行

```bat:A.bat
@echo off

rem 現在の「時間」の取得
set now_hour = %time:~,2%

if %now_hour% lss 12(powershell C:\work_ps\temp\am.ps1 ^
) else (powershell C:\work_ps\temp\pm.ps1 ^
)

pause
exit
```
コマンドプロンプトが起動せず、また、一行ずつ流すと午後の時間帯なのにB.ps1がテキストとして開かれる。
## やったこと③
「^」（キャレット）を使わず、にif文を一行にしてみて実行するがコマンドプロンプトが起動しない
## やったこと④
elseと処理の（）のスペースを消してみる
## やったこと⑤
式またはステートメントのトークン ')' を使用できません。とエラー発生
## やったこと⑥
elseと処理の（）のスペースを元に戻して、lss 12と処理の（）のスペースを空けてみる
## やったこと⑦
一行ずつ実行すると「午前です」とB.ps1の結果が表示（実施時間は夜）。なぜ、時間帯が正しく判定できていないのか考えてみると
set now_hour = %time:~,2%←ここのnow_hourに正しく時間が入っていないことに気づき、
echo　%now_hour%を実行すると%now_hour%と表示されていること確認
## やったこと⑧
set now_hour = %time:~,2%のスペースを消してみる
## やったこと⑧
set now_hour = %time:~,2%の「=」の左右の半角スペースを消してみる
## やったこと⑨
set now_hour=%time:~,2%
echo　%now_hour%を実行すると今の時間帯の23が表示
## やったこと⑩
if文を最初の改行をいれた状態に戻してみる
## やったこと⑪
午後ですと表示され、B.ps1が正しく実行された

# まとめ
変数を代入する際に半角スペースを入れてはいけないとか、batに長らくふれていなかったことで初歩的なお作法を忘れてました。
ほんとに記憶の忘却は怖い。。
ただ、学習する中で教本に記載されているソースを自分の手でタイピングすることでいろんなことの発見や思い出すきっかけに
なるのは事実だとおもうのでこれからも極力コピペせずにやっていきます。

## 参考文献

この記事は以下の情報を参考にして執筆しました。

- Windows PowerShellでキーボード操作を自動化しよう: Windows10/PowerShell5.0対応(https://www.amazon.co.jp/dp/B07JCK5JW8?tag=note0e2a-22&linkCode=ogi&th=1&psc=1)
Sparkで使う機能

# RDD Transformations
## map
```scala 
def map(clusterAndLabel: RDD[(Int, Int)]): RDD[Int] = {
  clusterAndLabel.map(_._1)
}
```

## filter
```scala
def filter(clusterAndLabel: RDD[(Int, Int)]): RDD[(Int, Int)] = {
  clusterAndLabel.filter(_._2 == 1)
}
```

## groupBy
```scala
def groupBy(medication: RDD[Medication]): RDD[((String, String), Double)] = {
  medication.groupBy { med => (med.patientID, med.medicine) }.map {
    case ((patientID, medicine), meds) =>
      ((patientID, medicine), meds.size.toDouble)
  }
}
```

キーが重複してない場合は `keyBy` を使うとよさそう。

## leftOuterJoin
```scala
def leftOuterJoin(diagnostic: RDD[Diagnostic], medication: RDD[Medication]): RDD[String] = {
  diagnostic.groupBy(_.patientID).leftOuterJoin(medication.groupBy(_.patientID)).filter {
    case (_, (dxs, meds)) =>
      dxs.size() > meds.size()
  }.map {
    case (patientID, _) =>
      patientID,
  }
}
```

## distinct
```scala
def distinct(clusterAndLabel: RDD[(Int, Int)]): RDD[Int] = {
  clusterAndLabel.map(_._2).distinct()
}
```

## union
```scala 
def union(medication: RDD[Medication], diagnostic: RDD[Diagnostic]): RDD[String] = {
  medication.sparkContext.union(medication.map(_.patientID), diagnostic.map(_.patientID))
}
```

# RDD Actions
## count
```scala 
def count(clusterAndLabel: RDD[(Int, Int)]): Long = {
  clusterAndLabel.count()
}
```

## collect
```scala
def collect(clusterAndLabel: RDD[(Int, Int)]): Array[(Int, Int)] = {
  clusterAndLabel.collect()
}
```

## take
```scala
def take(clusterAndLabel: RDD[(Int, Int)]): Array[(Int, Int)] = {
  clusterAndLabel.take(5)
}
```
【CSS】メディアクエリ

学習内容を備忘録としてまとめます。
メディアクエリを実装し、ウィンドウ縮小時レイアウトが崩れないようにしました。

![media_screen_4(100).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/13ec0231-edf3-57a5-9809-aa9d5c7efcb6.gif)

#メディアクエリとは
訪問ユーザーが使用するデバイスの幅に合わせたWebの見せ方を可能にするもので、スマホからアクセスした際にPC用のページが表示されると当然文字が小さくて閲覧しにくいといったユーザビリティを考慮して画面サイズに適したデザイン表示させるために必要なタグです。

##CSSファイルにメディアクエリを実装

```style.css
@media screen and (max-width: 1000px) {
        // スタイルを記載
}
```
style.cssにメディアクエリを書いていきます。
上記だと、ウィンドウが1000px以下になったときに中のスタイルが適用されます。

#実装方法
トップ動作画面の実装方法を記載します。

##ヘッダー
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/3dc7678d-d9b3-cd53-597d-9a0726bb7a59.png)
上のヘッダーのように、ウィンドウ幅が1000px以下のときは『投稿』『メッセージ』『メニュー』だけにします。

```header.php
   <ul>
    <li>app</li>
    <li class="header_menu_wide">ユーザー一覧</li>
    <li>投稿</li>
    <li class="header_menu_wide">投稿一覧</li>
    <li>メッセージ</li>
    <li class="header_menu_wide">ログアウト</li>
    <li class="header_menu_wide">退会</li>
    <li class="show_menu">メニュー
    　<div>
        <ul>
         <li>ユーザー一覧</li>
         <li>投稿一覧</li>
         <li>メッセージ</li>
         <li>ログアウト</li>
         <li>退会</li>
        </ul>
      </div>
     </li>
   </ul>
```
`ユーザー一覧`、`投稿一覧`、`ログアウト`、`退会`のクラス名に`header_menu_wide`を、`メニュー`には`show_menu`を指定します。

```style.css
.show_menu {
    display: none;
}

@media screen and (max-width: 1000px) {
    .header_menu_wide {
        display: none;
    }
    .show_menu {
        display: block;
    }
}
```
このように設定すると、ウィンドウ幅が1000px以下のときクラス名`header_menu_wide`を指定している要素を非表示、`show_menu`を指定している要素を表示します。

##メイン画面
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/82d62a93-ae76-784d-2583-1e7a608c14cc.png)
続いて、メイン画面にメディアクエリを実装します。
先ほどのヘッダーと方法は変わりません。
![無題１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/196ec4c1-e360-f5fa-5049-3d1e9f265c46.png)
メイン画面に2ブロック（`wide_disp`、`narrow_disp`）用意して、それぞれウィンドウ幅によって表示を変更します。

```php:main.php
<div class="row wide_disp">
<div class="col-4">
<?php
$page_type = $_GET['type'];
$page_id = $_GET['page_id'];
：
：
</div>
<div class="col-4">
<?php if($page_type === 'main'): ?>
  <h2 class="left"><?= $current_user['name'] ?>さんの投稿</h2>
：
：
</div>
<div class="col-4">
<div class="col-10 offset-1">
  <h2 class="left">投稿</h2>
：
：
</div>
</div>

<div class="row narrow_disp">
<div class="col-6">
<?php
$page_type = $_GET['type'];
$page_id = $_GET['page_id'];
：
：
</div>
<div class="col-6">
<?php if($page_type === 'main'): ?>
  <h2 class="left"><?= $current_user['name'] ?>さんの投稿</h2>
：
：
</div>
</div>
```

```style.css
.narrow_disp {
    display: none;
}

@media screen and (max-width: 1000px) {
    .wide_disp {
        display: none;
    }
    .narrow_disp {
        display: block;
    }
}
```

###注意点
１つのファイルに同じ内容のコードがある場合、何点か注意点があります。

####・IDが重複していないか
同値のIDを使用している場合、JSなどがうまく動かない時があるので値を変更するなど修正が必要。

####・require_once(PHP限定)
require_onceを2つ以上用いていると、片方が動かなくなる。
ここでいうと、2ブロック中のどちらか一方が機能しなくなります。

requireで正常に動きます。

#参考URL
https://keywordfinder.jp/blog/seo/media-querie
ダークモードのUI変更にてカスタムカラーを適応させる方法 (storyboard)

①　Assetsフォルダ開く
②　左下のプラスボタンをクリックして新しいカラーセットを追加する
③　AnyAppearance, LightAppearance, DarkAppearance カラーを設定する
④　カスタムカラーの名前を設定する


ダークモードの概要
https://developer.apple.com/documentation/xcode/supporting_dark_mode_in_your_interface
もうif文は書かなくても良い！？Javascriptのちょっとした小技

今日はちょっとした知識を書いていきます。

#if文を利用せずに変数・定数を定義する#

```*.js
const answer = (question.select === 'yes')
```

これめっちゃ便利

#三項演算子#

こちらは聞いたことがある方も多いと思います。

```*.js
const isColor = isError ? 'red' : 'black'
```

``isError``が``true``なら``red``に、``false``なら``black``になります。

#return文での条件分岐#

お次はDOM要素におけるif文です。

主に、Reactで使用します。

##if文のみ##

```*.jsx
  return (
    <>
      {(length === 0) && (
        <h1>長さはゼロです/<h1>
　　　 )}
    </>
  )
```

##if else文##

こちらは参考演算子に似ています。

```*.jsx
return (
    <>
      {isError ? (
        <h1>エラー<h1>
      ) : (
        <h1>正常<h1>
      )}
    </>
  )
```

これでもOK！

```*.jsx
return (
    <>
      {isError
        ? <h1>エラー<h1>
        : <h1>正常<h1>
      }
    </>
  )
```

こんな感じでif文を書かなくても変数・定数を定義出来たり、レンダーすることも可能です。

でも個人的には三項演算子はあまり好きではないです。

コーディングはどんどん楽していきましょう！

以上、「もうif文は書かなくても良い！？Javascriptのちょっとした小技」でした！

Thank you for reading
Next.jsでStorybookを入れたときにハマったこと

ハマる部分は人それぞれっぽいので、いろいろな記事があったほうが良いだろうというので残しておきます

そもそもの入れ方とかは複雑ではなく公式なりQiitaなりをあさればたくさん出るかと思うのでココでは書きません

- https://storybook.js.org/docs/react/get-started/install
- https://storybook.js.org/tutorials/intro-to-storybook/react/ja/get-started/
- https://qiita.com/keitakn/items/982d7e6cdfc294c82a95

## SCSSのimportが動かない

CSS ModulesをSCSSの文法で利用しているが、`@import` をするとエラーになった

似たようなのだと下記でも解決するかも
https://mk-engineer.com/posts/css-modules-storybook
https://github.com/storybookjs/storybook/issues/12464


```javascript:.storybook/main.js
module.exports = {
  stories: [
    '../src/components/**/*.stories.@(js|jsx|ts|tsx)'
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
  ],
  webpackFinal: async (baseConfig) => {
    // scss を読み込む
    baseConfig.module.rules.push({
      test: /\.scss$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1, // 1 => postcss-loader
            modules: {
              localIdentName: '[local]___[hash:base64:2]',
            },
          },
        },
        'sass-loader',
      ],
    });
    return {...baseConfig};
  }
}
```

## 画像が読み込まれない

先程のは別にNext.js特有じゃないと思いますが、こちらはNext.js特有と思われます
`next/image` でpublic下に置いた画像がエラーにはならないが表示されない

ココを参考に
https://xenox.dev/next-image-with-storybookjs/
これはstorybook上は`next/image`を上書きして、通常の`<img>` タグで表示する形になっていると思います。

```jsx:.storybook/preview.js

// 下記を追記
Object.defineProperty(nextImage, 'default', {
  configurable: true,
  value: props => <img {...props} />
});

```

下記を変更

```json:package.json
{
  "scripts": {

    "storybook": "start-storybook -s ./public -p 6006",

 }
}

```
Raku (perl6) の使い方

処理系のインストール

```bash
sudo apt install rakudo
```

バージョンの確認

```text
$ perl6 --version
This is Rakudo version 2018.12 built on MoarVM version 2018.12
implementing Perl 6.d.
```

サンプルプログラム

```raku:hello.raku
#! /usr/bin/perl6
#
say '*** start ***';
say 'Hello World!';
my $aa = 12;
my $bb = 34;
my $sum = $aa + $bb;
say $aa,"\t",$bb,"\t",$sum;
say '*** end ***';
```

実行結果

```text
$ ./hello.raku 
*** start ***
Hello World!
12      34      46
*** end ***
```
プレビュー条件分岐

preview.js:3 Uncaught TypeError: Cannot read property 'addEventListener' of null
    at HTMLDocument.<anonymous> (preview.js:3)
(anonymous) @ preview.js:3

"image-list"というidがnewとeditのみ存在するため、indexではこのようなエラーが発生する

そこで
if (document.URL.match(/new/) || document.URL.match(/edit/)) { 

（ここに中身を記述）

}

を加えることで、解消される