OmniAICreator/Qiita-1.07M huggingface dataset:
beautifulsoupで[特定の親要素]配下の[特定の子要素]だけを取得する方法

## やりたいこと
（備忘録を兼ねての内容なのであしからず）

ターゲットとするhtmlから、繰り返される親要素（タグ）のうち、特定の「id」に合致するものを取得。
さらに特定の「class」に該当する子要素（タグ）を取得したい。
※「id」、「class」と記載ありますが、あくまで今回やりたかったケースなので、他の組み合わせも可能

## やったこと
beautifulsoupのfindメソッドを連結させることで対応できました。

簡単にいえば
　find（親要素）.find（子要素）
ですね。

```python:
from selenium import webdriver
from bs4 import BeautifulSoup
import re

browser = webdriver.Chrome((r'C:\Users\[ユーザ名]\chromedriver.exe')
browser.get([目的のURL])

html = browser.page_source
soup = BeautifulSoup(html,'html.parser')

#子要素の名称は部分一致させたかったのでre.compileで対応しています
elements = soup.find([ターゲットの親タグ],id=[ターゲットのid名]).find_all([ターゲットの子タグ],class_= re.compile([ターゲットのクラス名]))
```

## 最後に
beautiful　ってスペル、めっちゃ難しい。
大体、打ち間違えます・・・
ジェネリック型　備忘録

# ジェネリック型の使い方
TypeScriptのジェネリック型について学習したので忘れないようにメモ
## ジェネリック型を使うタイミング
型がnumberやstringのように明確に決まっていない関数を宣言したい時などに使う
いつ型が決まるのかというと、関数を使用するタイミングで決まる（引数を渡すタイミング）
シグネチャの時点ではジェネリック型を使う

# ジェネリック型の使い方
- <>で囲む
- 書く場所によってスコープが決まる
- 通常はTなど大文字のアルファベットを使う

# 例
フィルター関数を作成する  
```typescript
type Fileter = {
 <T>(array: T[],f: (item: T) => boolean): T[]
}
```
上記のようにシグネチャを定義しておき、  
このシグネチャを実装する時に適当に引数を渡せばTの部分が推論される
```typescript
let filter: Filter = (array,f) => //...
filter([1,2,3], _ => _ > 2)
```
filter関数をFilter型で定義  
引数に数値の配列を渡しているのでTはnumberと推論される
文字列の配列を渡せばＴはstringとなる。
「Storybook needs either a "main" or "config" file.」とエラーが出て、Storybookが起動しない

# 経緯とかいろいろ
React + Typescript + storybook の環境で新しくプロジェクトを作成し、storybookを起動すると「Storybook needs either a "main" or "config" file.」が出て処理が中断した。
我々は問題解決のために調査を開始した。そして解決策を探すのにかなりの時間を費やした。
なので、これからStorybookをさわる皆さんが同じ問題にぶち当たり「もうだめ…あきらめよ」とならないために解決策をここに記述する。

# 開発環境
- react 17.0.2
- @storybook/react 6.4.12

# エラー内容
「Storybook needs either a "main" or "config" file.」
上記メッセージの意味は「storybookは、mainファイルとconfigファイルが必要だ」

# 原因
mainファイルが存在するのに、以下の理由で指定パスへのアクセスに失敗している。
原因となるパスの中にバックスラッシュが使用されていて、これのせいでファイルが見つからず「storybookは、mainファイルとconfigファイルが必要だ」と怒られるのだ。
なので、原因となるバックスラッシュをスラッシュに置換することで問題が解決する。

# 解決策
1. 「(プロジェクト)\node_modules\@storybook\core-common\dist\cjs\utils\validate-configuration-files.js」にアクセス
2. 43行目あたりまでスクロールして、コードを以下のように修正する
 ```js:validate-configuration-files.js
//before
return !!_glob.default.sync(_path.default.resolve(configDir, ` ${file}${extensionsPattern}`)).length;

//after
return !!_glob.default.sync(_path.default.resolve(configDir, `${file}${extensionsPattern}`).split(_path.default.sep).join("/")).length;
```
Ubntu16.04.7にPython3.9をインストール

## 初めに
備忘録として残します!

## opensslをversionアップする
```bash
cd /usr/local/src
sudo wget https://www.openssl.org/source/openssl-1.1.1o.tar.gz 
sudo tar xvf openssl-1.1.1o.tar.gz # 解凍
cd openssl-1.1.1o
sudo ./config # sourceをコンパイルしてインストールする
sudo make 
sudo make install 
which openssl # opensslの場所を確認
ldd /usr/local/openssl # opensslの共有ライブラリの確認
```
* wgetを行うダウンロード先は、確認しましょう。
* 共有ライブラリの確認の際、not foundとなっている場合、下のようにldconfigにキャッシュ対象を追加するを参照する

## ldonfigにキャッシュ対象を追加する
```bash
cd ld.so.conf.d/
sudo vim openssl-1.1.1o.conf # /usr/local/をopenssl-1.1.1o.confに記入する
ldconfig #/etc/ld.so.confを/etc/ld.so.cacheに反映する
```

## python3.9をインストール
```bash
sudo wget https://www.python.org/ftp/python/3.9.1/Python-3.9.1.tgz
sudo tar xvf Python-3.9.1.tgz
cd Python-3.9.1/
sudo ./configure --enable-optimizations
sudo make -j 12 
sudo make altinstall
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 3
sudo cp /usr/lib/python3/dist-package/lsb_release.py /usr/local/lib/python3.9
```

参考
opensslインストール
> https://text.baldanders.info/remark/2020/06/installing-openssl-in-ubuntu/

python3.9インストール
> https://codechacha.com/ja/ubuntu-install-python39/
pip installのエラー解決
>https://qiita.com/sinri/items/f819424acc37ac513c99
ゼロトラストのディープダイブ(8)-CNAPP(クラウドネイティブアプリケーション保護プラットフォーム)


[前回] [ゼロトラストのディープダイブ(7)-SSPM(SaaSセキュリティ状態管理)](https://qiita.com/mingchun_zhao/items/f8729d64f5e5faf2b67d)

## はじめに

今回は、クラウドセキュリティ技術の一つである、
CNAPP(Cloud Native Application Protection Platforms)
を勉強します。

## CNAPPの前提

以下3点を理解する必要があります。

- CSPM(Cloud Security Posture Management)
- CWPP(Cloud Workload Protection Platform)
- CIEM(Cloud Infrastructure and Entitlements Management)

### CSPM(クラウドセキュリティ状態管理)とは

- IaaS上の設定不備を検出するためのツール
    - IaaS(イアース、Infrastructure as a Service)とは、クラウドコンピューティングの1つ
        - 仮想化技術を利用し、ハードウェアリソース(CPU/メモリ/ストレージ)などデジタルインフラを
        - インターネット経由でオンデマンドで提供するサービス
- 脆弱な設定や設定不備を自動修復するための仕組みを提供
- 外部からなりすましによるIaaSへの不正アクセスを防ぐ
- 内部犯行によるIaaSへの不正アクセスを防ぐ
- マルチクラウドを1つのコンソールで統合管理可能
- クラウドの設定がベストプラクティスに従っているかチェック
    - データストレージがインターネットに直接さらされていないか
    - データベースの暗号化が行われているか
    - 重要なシステムアカウントで多要素認証が有効になっているか
    - 違反が検知された場合の通知機能があるか

### CWPP(クラウドワークロード保護プラットフォーム)とは

IaaSのワークロードとアプリケーションのライフサイクル全体を把握し保護するソリューション。

CWPPの機能:

- コンテナやマイクロサービスのランタイムにおける不審な振る舞いを防止・検出
- コンテナの脅威に対する対応を自動化
- ホスト上で動作するVMベースのワークロードの異常な振る舞いを検出
- CI/CDやレジストリに格納されたコンテナイメージから、本番環境にデプロイする前にOS/非OSの脆弱性を検出
- コンテナやKubernetes内のネットワークトラフィックを可視化し、Kubernetesネイティブのネットワークセグメンテーションを実施
- コンテナのコンプライアンスを検証し、コンテナ内のデータ整合性を監視
- コンテナがなくなった後も、コンテナやKubernetesのフォレンジックやインシデント・レスポンスを行う

### CIEM(クラウドインフラストラクチャーエンタイトルメントマネジメント)とは

- クラウドのID管理とデータプライバシーを保護するソリューション
- 最小特権のアクセスを付与するようにポリシー変更を提案
- 動的なマルチクラウドインフラストラクチャにおける過剰な特権を持つIDのリスクを軽減
- 特権の昇格、認証情報の漏洩、その他疑わしいアクセスを可視化しリスクを軽減

## CNAPPの背景
- CWPPにおいて、ワークロードのコンテキストを提供する状態管理機能が必要となった
- CSPMにおいて、ワークロードをドリルダウン可能な可視化機能が必要となった

そこで、CSPMとCWPPを統合し、さらにクラウドセキュリティ機能を追加した、CNAPPソリューションが必要となった。

## CNAPPの目標

- クラウドネイティブ環境に完全なエンドツーエンドのセキュリティを提供
- クラウドセキュリティに対し、統合プラットフォームのアプローチを提供

## CNAPPとは

クラウドネイティブのアプリケーション、インフラストラクチャ、および構成に対し、
リスクを特定、評価し、リスクの優先順位付けを支援する、セキュリティソリューション。

- IaaSのワークロードを保護し、設定を監査するためのフレームワーク
- CNAPPは、CWPP、CSPM、CIEMの各カテゴリーに属するさまざまな機能の組み合わせ
- パブリッククラウドのインフラと、そのインフラ上のワークロード両方を可視化
- CNAPPはクラウドの下記リスクを特定し優先順位をつける
    - 設定ミス
    - 過剰な権限や許可
    - 機密データ漏洩の危険性
    - パッチ未適用による脆弱性
- CNAPPはセキュリティリスクに対し、自動修復または手動修復を支援
- CNAPPのプロセスは継続的に行われ、動的に変化するクラウド環境のリスク状況に対応

## CNAPPに求められる機能

- 開発環境と本番環境両方で、クラウド・ネイティブ・アプリケーションのセキュリティ保護を支援
- 開発環境と本番環境の間でコンテキストを共有することで、アプリケーションのリスクを完全把握
- アプリケーションを保護
    - アプリケーションのライフサイクルを通して追跡し、アプリケーションのコンテキストを特定
    - コンテキストリスクに対処するセキュリティ管理を適用
- ソリューションが、CI/CDパイプラインに組み込まれ、最新のDevOpsツールと統合
- ビルド段階でアーティファクトをスキャンし、ビルドからデプロイまでの整合性を維持

## CNAPPが企業にもたらすメリット

- チーム(SecDevOps、DevOps、クラウドセキュリティオペレーション)間のコラボレーションを促進
- 単一の統合プロダクトを使用し、クラウド・ネイティブ・アプリケーションのライフサイクル全体を保護

## CNAPPとゼロトラスト

- ゼロトラストアーキテクチャにおいて、CNAPPはリスクコンテキストを提供
- リスクコンテキスト情報に基づき、クラウドワークロードのアクセスレベルを決定
- リスクのあるクラウドワークロードに対し、アクセスレベルを制限

## おわりに

CNAPPと関連ソリューションを勉強します。
次回は、技術の観点から各種サービスやソリューションを深掘りします。
お楽しみに。

##### [次回] [ゼロトラストのディープダイブ(9)-SSE製品理解(Zscaler社)](https://qiita.com/mingchun_zhao/items/7d9de25c61cea649d576)
RubyのSymbol（シンボル）とは？文字列とは何が違うのか

Rubyでは全ての値はオブジェクトのため、一見ただの数値に見えてもそれは`Integer`クラスのオブジェクトです。
そこで`methods`メソッドを使って、そのオブジェクトが所属する`Integer`クラスのメソッドを見てみたいと思います。

```irb:irb
irb(main):006:0> 123.class
=> Integer
irb(main):007:0> 123.methods
=> [:-@, :**, :<=>, :upto, :<<, :<=, :>=, :==, :chr, :===, :>>, :[], :%, :&, :inspect, :*, :+, :ord, :-, :/, :size, :succ, :<, :>, :to_int, :coerce, :to_s, :to_i, :to_f, :divmod, :to_r, :fdiv, :modulo, :remainder, :abs, :magnitude, :integer?, :floor, :ceil, :round, :truncate, :^, :odd?, :even?, :allbits?, :anybits?, :nobits?, :downto, :times, :pred, :pow, :bit_length, :digits, :numerator, :denominator, :rationalize, :gcd, :lcm, :gcdlcm, :next, :div, :|, :~, :abs2, :angle, :+@, :conjugate, :to_c, :conj, :phase, :rect, :polar, :eql?, :singleton_method_added, :i, :real?, :zero?, :nonzero?, :finite?, :infinite?, :step, :positive?, :negative?, :clone, :dup, :arg, :quo, :rectangular, :real, :imaginary, :imag, :between?, :clamp, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :instance_variable_get, :instance_variable_set, :instance_variables, :protected_methods, :private_methods, :public_send, :method, :public_method, :singleton_method, :define_singleton_method, :extend, :to_enum, :enum_for, :=~, :!~, :respond_to?, :freeze, :object_id, :send, :display, :class, :nil?, :hash, :singleton_class, :then, :itself, :yield_self, :untaint, :taint, :tainted?, :trust, :untrust, :untrusted?, :singleton_methods, :frozen?, :methods, :public_methods, :equal?, :!, :instance_exec, :!=, :instance_eval, :__id__, :__send__]
```

このとき、メソッド名が「：（コロン）」が付いて始まっています。
これがSymbol（シンボル）なのですが、それって一体何なのでしょうか。

## Symbolとは
Ruby3.0リファレンスマニュアルで調べてみました。

>**シンボルの実装**
Rubyの内部実装では、メソッド名や変数名、定数名、クラス名などの名前を整数で管理しています。
そしてその整数をRubyのコード上で表現したものがシンボルです。

ここで「へぇ～」と思ったのが**名前を整数で管理している**という点です。
なぜそんなことをしているのでしょうか。名前なんだから文字列で管理すれば良いのでは…？
答えは書いてありました。

>これは名前を直接文字列として処理するよりも速度面で有利だからです。

ふむふむ、どうやらSymbolを使った方が処理が速いようです。

## 文字列とシンボルの速度を比較してみた

百聞は一見に如かずなので、実際にやってみたいと思います。
速度の判定には`Benchmark-ips`というRubyGemを使ってみます。
【参考】[Rubyの処理速度を確認したい時に使うGem【Benchmark-ips】](https://losenotime.jp/rubygem-benchmark-ips/ "Lose No Time")

```ruby:measure.rb
# 文字列とシンボルの速度を比較するクラス
require 'benchmark/ips'
class Measure
  Benchmark.ips do |x|
    x.report("String"){
      hash = {}
      (1..1000).each do |n|
        hash.store(n, "abc")
      end
    }
    x.report("Symbol"){
      hash = {}
      (1..1000).each do |n|
        hash.store(n, :abc)
      end
    }
    x.compare!
  end
end
```
```ruby:処理結果
Warming up --------------------------------------
              String     1.027k i/100ms
              Symbol     1.301k i/100ms
Calculating -------------------------------------
              String     10.815k (± 3.8%) i/s -     54.431k in   5.041519s
              Symbol     13.327k (± 3.5%) i/s -     67.652k in   5.082751s

Comparison:
              Symbol:    13327.4 i/s
              String:    10815.3 i/s - 1.23x  (± 0.00) slower
```

確かに！リファレンスに書かれている通り、Symbolのほうが速い結果となりました。
HashオブジェクトのvalueもSymbolにしたほうがより早く処理できそうということが分かりました。
ポアソン推定量について

# はじめに
千葉大学/Nospareの[米倉](https://sites.google.com/site/shoutoyonekura/)です．今回はポアソン推定量について解説したいと思います．

# モチベーション
ある$\mu$を推定したいとし，その対数をとった不偏推定量のみ利用可能だとします．つまり，
$$
\mathbb{E}[\hat{\log\mu}]=\\mu
$$
なる推定量$\hat{\log\mu}$が手元にあります．この時に，$\mu$の不偏推定量を$\hat{\log\mu}$から構成することは可能でしょうか？一見抽象的な問いですが，統計学では
$$
\mu(x)=\exp(-\frac{1}{n}\sum_{i=1}^n g(x_i))
$$
のような形の推定対象良く与えられ，$n$が非常に大きい時，この量は爆破的に大きくなり計算するのに適さないことが多々あります．
このような時，その対数をとって$n$より小さい$m$を適当に選び
$$
-\frac{1}{m}\sum_{i=1}^m g(x_i)
$$
とすれば，これは適当な仮定の下で$\log\mu(x)$の不偏推定量になります．しかし，イェンセンの不等式を使えば
$$
\mathbb{E}[\exp(\hat{\log\mu})] \geq \exp(\mathbb{E}[\hat{\log\mu}])=\exp(\mu)
$$
なので，上の$-\frac{1}{m}\sum_{i=1}^m g(x_i)$は$\exp(-\frac{1}{n}\sum_{i=1}^n g(x_i))$の不偏推定量にはこのままではならないです．

# ポアソン推定量
今，$\mathbb{E}[\lambda_i]=\log\mu$なるiidの確率変数$\lambda_i$があったとします．言い換えれば，推定対象の$\log$を取ったものの不偏推定量があるとします．この時，
$$
\hat{\mu}=e^{\delta}\prod_{i=1}^J\frac{\lambda_i}{\delta}, J\sim Poisson(\delta)
$$
は$\mu$の不偏推定量であることを示すことが出来て，これをポアソン推定量と呼びます．ここで$ Poisson(\delta)$はパラメーターが$\delta$のポアソン分布です．

# 証明
証明は意外と簡単です．まずパラメーターが$\delta$のポアソン分布に従う確率変数$Jの$密度関数は
$$
Prob(J=k)=\frac{\delta^ke^{-\delta}}{k!}
$$ 
で与えられます．これよりポアソン推定量を$J$に対して期待値を取ると
$$
\mathbb{E}[\hat{\mu}]=\sum_{k=0}^{\infty}\frac{\delta^ke^{-\delta}}{k!}e^{\delta}\prod_{i=1}^k\frac{\lambda_i}{\delta}
=1+\sum_{k=1}^{\infty}\frac{1}{k!}\prod_{i=1}^k\\lambda_i
$$
と計算できます．各$\lambda_i$は$\log\mu$の不偏推定量でiidだったので，$\lambda$に対しても期待値を取ると結局
$$
\mathbb{E}[\hat{\mu}]=1+\sum_{k=1}^{\infty}\frac{\lambda^k}{k!}
$$
となります．これは$\exp(\lambda)$のテイラー展開に他ならないので，結局
$$
\mathbb{E}[\hat{\mu}]=\lambda
$$
であると示すことが出来ます．最後のテイラー展開のところが天才的だなと思います．

# 実際に使う時
ポアソン推定量をそのまま使うとかなり分散が大きくなるので，ある実数$c$を用いて
$$
\hat{\mu}=e^{\delta+c}\prod_{i=1}^J\frac{\lambda_i-c}{\delta}
$$
の形で使われることが多いです．ただしいい感じの$c$を見つけることが困難です．

また非常にサイズが大きいデータに対してメトロポリス・ヘイスティングス法で推論を行うと，棄却確率を求める際の尤度の評価の計算コストが非常に高くなります．これを解決するために全てのデータを使うのではなく，上記の様に適当なサイズで区切って対数尤度の不偏推定量を構成し，ポアソン推定量を用いて尤度の不偏推定量を作り棄却確率を近似することが考えられます．しかしこのようにすると，残念ながらMCMCのアウトプットの分散が非常に大きくなることが分かっていて，理論的には美しいのですが実用上は中々うまくいかない推定量であることが知られています．
詳しくは例えば [Korattikara et al (2014) Austerity in MCMC land: Cutting the Metropolis-Hastings budget](http://proceedings.mlr.press/v32/korattikara14.pdf) を参照してください．
# おわりに
株式会社Nospareでは統計学の様々な分野を専門とする研究者が所属しております．統計アドバイザリーやビジネスデータの分析につきましては[株式会社Nospare](https://bit.ly/38WtGZH) までお問い合わせください．
<a href="https://bit.ly/38WtGZH">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023506/d5c625c0-d6f4-680b-d702-3c40f11d6c39.jpeg" alt="株式会社Nospare" width=400>
</a>
Rails DM機能 showアクションの解説

## 開発環境
Mac
Ruby 2.6.5
Rails 6.1.3.2
```rooms/show.html.erb
<% @entries.each do |e| %>
<h5><strong><a href="/users/<%= e.user.id %>"><%= e.user.name%>さん</a></strong></h5>
<% end %>

<hr>
<% if @messages.present? %>
<% @messages.each do |m| %>
<strong><%= m.content %></strong>
<small>by <strong><a href="/users/<%= m.user_id %>"><%= m.user.name %>さん</a></strong></small>
<hr>
<% end %>
<%else %>
<h3 class="text-center">メッセージはまだありません</h3>
<% end %>

<%= form_for @message do |f| %>
<%= f.text_field :content, :placeholder => "メッセージを入力して下さい" , :size => 70 %>
<%= f.hidden_field :room_id, :value => @room.id %>
<br>
<%= f.submit "投稿する" %>
<% end %>
```
```rooms_controller.rb
class RoomsController < ApplicationController
  def show
    @room = Room.find(params[:id])・・１
    if Entry.where(user_id: @current_user.id, room_id: @room.id).present?・・２
      @messages = @room.messages・・３
      @message = Message.new・・４
      @entries = @room.entries・・５
    else
      redirect_back(fallback_location: root_path)・・６
    end
  end
end
```

## コードの解説
１・・１つのチャットルームを表示させる必要があるので、findメソッドを使います。
2・・Entriesテーブルに、現在ログインしているユーザーのidとそれにひもづいたチャットルームのidをwhereメソッドで探し、そのレコードがあるか確認します。
（補足whereメソッド＝＝テーブル内の条件に一致したレコードを配列の形で取得することができるメソッド。）
３・・もし現在ログインしているユーザーのidとそれにひもづいたチャットルームのidがあったら、メッセージと名前を表示させるため、@messagesに@room.messagesを代入します。
４・・また、新しくメッセージを作成する場合は、Message.newをすることでメッセージのインスタンスが生成され、Message.newを@messageに代入させます。
５・・そしてrooms/show.html.erbでユーザーの名前などの情報を表示させるために、@room.entriesを@entriesというインスタンス変数に入れ、Entriesテーブルのuser_idの情報を取得します。
６・・もしidがなかったら、前のページに戻るための記述である、redirect_backを使います。
# 参考記事
[RailsでややこしいDM機能を1万字でくわしく解説してみた](https://qiita.com/bindingpry/items/6790c91f374acc25bea2)
[RailsでDM(ダイレクトメッセージ)を送れるようにしよう](https://qiita.com/ki_87/items/a344ea566c88b10b950c)
【Flutter】Unimplemented handling of missing static target のエラーが発生した場合

### 対処方法
以下のコマンドを実行することで解消された
```
flutter clean
flutter run
```

### 原因
ネットでいろいろ調べると「main.dart」を変更した際に起こることがあるらしい
確かにこのエラーが発生する直前は「main.dart」を編集していた
大きな変更をした場合には、再コンパイルすると良さそうな印象
Macbookでgtkwaveを動作させる

【忘れないように】

1.パスを通す

2.作成済みのファイルcpuを使う
```
3.make IMEMFILE=ファイル名.txt cpu.out
```

```
4.make cpu.vcd
```

5.Macbookではターミナルのコマンドで起動しなかったので手動で起動
🔰【初学者用】RSpecでテストコードを書こう！③【コントローラーの単体テスト簡単な実装例】

# はじめに
①🔰【初学者用】RSpecでテストコードを書こう！【概念・準備】

https://qiita.com/hondano_gentuki/items/2003971a4f5a97481930

②🔰【初学者用】RSpecでテストコードを書こう！②【簡単な実装例】

https://qiita.com/hondano_gentuki/items/0a91a595df9c0d76f1cc

今日の投稿は③になります！
前回はモデルの単体テストを行ったので今回はコントローラーの単体テストです。

# コントローラーの単体テストはどんなテスト？
モデルのテストでは、インスタンスを生成し、それがモデルに規定した通りの挙動になるか（バリデーションが正しく働くかなど）を確かめます。
コントローラーのテストでは、あるアクションにリクエストを送ったとき、想定通りのレスポンスが生成されるかどうかを確かめます。

## Request Spec
RSpecの導入が完了していれば使用できる、コントローラーのテストコードを書くために特化した手法のこと。

# テストコードの具体的実装
まずはファイルを生成します！今回は簡単なツイートアプリを作っている想定です！
```rails:ターミナル
rails g rspec:request tweets
```
実行後は`request`ディレクトリに、`tweets_spec.rb`が生成されます。
続いてテストコードを記述していきます。

```rails:spec/requests/tweets_spec.rb
require 'rails_helper'
describe TweetsController, type: :request do

  before do
    @tweet = FactoryBot.create(:tweet)
  end

  describe 'GET #index' do
    it 'indexアクションにリクエストすると正常にレスポンスが返ってくる' do 
　　 　get tweet_path(@tweet)
    　expect(response.status).to eq 200
    end
    it 'indexアクションにリクエストするとレスポンスに投稿済みのツイートのテキストが存在する' do 
　　　 get tweet_path(@tweet)
      expect(response.body).to include(@tweet.text)
    end
    #一部省略
  end
end
```

前回同様１つづつ説明していきますね！

### create
ActiveRecordの`createメソッド`と同じです！
`build`とほぼ同じ働きをしますが、createの場合はテスト用のDBに値が保存されます。
※テスト後にはテスト用に保存された値が削除されます。

### get
`get 〇〇_path`のように、どこのパスにリクエストを送りたいかを記述します。
ターミナルで`rails routes`を実行して確認します。

### response.status
`response.status`と実行することによって、そのレスポンスの`HTTPステータスコード`を出力できます。
HTTPステータスコードは以下に記述します。

### response.body
`response.body`と記述すると、ブラウザに表示されるHTMLの情報を抜き出すことができます。

### 200とは？（HTTPステータスコード）
記述内に200とありますがこれは一体なんの数字でしょうか？
実はこれ、HTTPステータスコードと言って通信の処理がどのような結果になったかを表す数字です。
以下に主なステータスコードをまとめておきます。
| ステータスコード | 結果 |
|:-|:-|
| 100〜  | 処理の継続中  |
| 200〜  | 処理の成功  |
| 300〜  | リダイレクト  |
| 400〜  | クライアントエラー  |
| 500〜  | サーバーのエラー  |

ここまでの記述が理解できたらテストコードを実行しましょう！
```rails:ターミナル
bundle exec rspec spec/requests/tweets_spec.rb
```

`response.body`ではそのページでしか返ってこないレスポンスをテストするようにしてます！
例えば投稿を検索するためのページがあったとしてそこには検索フォームがあるはずです。検索ページをテストする際はその検索フォームがあるかどうかでテストするというイメージです。

# 終わりに
なんとなく流れはつかめましたか？
モデルの単体テストコードに比べたらボリュームにかけますが、次の結合テストがボリューミーなので、お楽しみに！笑
OutSystemsでクリックするたびにGoogleMapのマーカーの位置を変える

## やろうとしていること
googlemapをクリックするごとにマーカーの位置を表示させて、尚且つ中央に配置する。
※イメージとしては、クリックしたらマーカーを表示させ、クリックするごとに緯度と経度を取得します。

## 実現方法
まず、クリックしたらマーカーを表示させたいので、Booleanのローカル変数を作成します。デフォルトをFalseにします。
![スクリーンショット 2022-06-03 23.04.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276481/aa24bf29-766c-028c-cf15-853f86f28030.png)

次に、IFウィジェットを置いて、Conditionを先ほどのローカル変数に設定します。
Falseのブランチには何も置きません。
![スクリーンショット 2022-06-03 23.07.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276481/376de9ea-764c-9ba7-5229-499812badbdf.png)

取得した緯度と経度が中央になるようにMapのCenterを編集します。
ここでは、緯度と経度のローカル変数を作成してクリックする度に値が変わっても対応できるようにします。
![スクリーンショット 2022-06-03 23.24.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276481/2ef263cf-0762-fcbb-17a9-7c0bf69608ec.png)

そして、MapウィジェットのEvents_PlaceholderにMap_Eventのウィジェットをドラッグ＆ドロップし、EventNameプロパティをEntities.MapEventTriggered.Clickに、EventsのHandlerには新しいクライアントアクションを作成します。そうすると、MapEventActionという名前のクライアントアクションが自動的に作成されます。
![スクリーンショット 2022-06-03 23.11.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276481/151b60be-3c2b-6bf2-2198-00588e036779.png)
![スクリーンショット 2022-06-03 23.14.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276481/d0212d36-1b08-e302-6b1e-08ee6b263801.png)

次に、クリックするたびにマーカーを表示させ、緯度と経度を取得するためのアクションを書きます。
ここは結構簡単です、先ほどのローカル変数ShowMarkerをTrueにしてクリックした箇所の緯度と経度をAssignを使ってぶち込みます。
![スクリーンショット 2022-06-03 23.27.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276481/94bee451-c4e2-6150-c952-9f4a34fd50d9.png)

これで、最初はマーカーがない状態で、クリックするとマーカーが出現し、緯度と経度を取得して常に中央配置になります。

## 参考情報
https://outsystemsui.outsystems.com/OutSystemsMapsSample/AddMarkerOnMapClick
cordova+android SDKのコンテナ

Cordova, Node.js, Android sdkを含んだ開発環境をコンテナで作成してみました。
android-sdkも入っているので、androidの実機動作までできます。

# 動作環境準備

WSL2とDocker desktopをインストール（Windows環境です）
vscodeにRemote Developmentを入れおきます。

# コンテナの起動

WSL2のシェルから次のコマンドを実行します

```
$ git clone https://github.com/masahiro-999/cordova-container
$ cd cordova-container
$ code .
```
VSCODEが開いたら、F1を押し、コマンドパレットで、Build and reopen in containerを実行

これでCordovaの開発環境が起動します。

# サンプルアプリを実行してみる

以下は、Cordovaでサンプルアプリを実行する方法です。

## プロジェクトの作成

```
$ cordova create hello-app
$ cd hello-app/
```

## ブラウザーで動作させる

```
$ cordova platform add browser
$ cordova run browser
```

## Android端末で動作させる
Android端末にUSB接続したadbで、adb tcpip 5555を実行しておく
Wifiで接続して、開発機と通信できる状態にする

```
$ cordova platform add android
$ adb connect 10.0.33.3:5555
$ cordova run android
```
10.0.33.3の部分はAndroid端末のWifi接続のIPアドレスに変更してください。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/78dc8024-fb4c-1e09-0218-f6c1423b4b8a.png)


# うまくいかない時の確認点

ContnerのBuild時に次のようなエラーがでてうまいかない事がありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/68392d50-1571-b318-6b87-310b469faab1.png)

WindowsのDocker DesktopのSettings>Docker Engineの
"buildkit": false に変更する
ことで解決しました

```json
{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "features": {
    "buildkit": false
  }
}
```

# 参考
https://github.com/hamdifourati/cordova-android-builder
【Flutter】minSdkVersion 16 cannot be smaller than version 19 declared in library　のエラーが出た場合の対処方法

### エラー内容
Flutter と Firebase の連携をするためにサンプルのコードをコピペして、アプリを実行した場合に以下のエラーメッセージが表示されたのでその対処方法です。

エラーメッセージ：
```
C:\Users\UserName\StudioProjects\ProjectName\android\app\src\debug\AndroidManifest.xml Error:
	uses-sdk:minSdkVersion 16 cannot be smaller than version 19 declared in library [:cloud_firestore] C:\Users\UserName\StudioProjects\ProjectName\build\cloud_firestore\intermediates\merged_manifest\debug\AndroidManifest.xml as the library might be using APIs not available in 16
	Suggestion: use a compatible library with a minSdk of at most 16,
		or increase this project's minSdk version to at least 19,
		or use tools:overrideLibrary="io.flutter.plugins.firebase.firestore" to force usage (may lead to runtime failures)
```
「minSdkVersion を19以上に設定してください」という意味らしいので、以下の設定をする

C:\Users\UserName\StudioProjects\ProjectName\android\app\build.gradle の設定を以下のように修正する
```
android {
   defaultConfig {
     minSdkVersion 19 // このように修正（元々は、minSdkVersion flutter.minSdkVersion）
   }
 } 
```

### D8: Cannot fit requested classes in a single dex file (# methods: 92002 > 65536) のエラー
minSdkVersion を19に設定したら別のエラーメッセージが表示された
```
ERROR:D8: Cannot fit requested classes in a single dex file (# methods: 92002 > 65536)
com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
The number of method references in a .dex file cannot exceed 64K.
```

調べると [Android公式サイト](https://developer.android.com/studio/build/multidex?hl=ja) に対処方法が載っていたので以下のように修正したらエラーが解消されアプリが起動した

```
android {
    defaultConfig {
        multiDexEnabled true // これを追加
    }
}

dependencies {
    implementation "androidx.multidex:multidex:2.0.1" // これを追加
}
【React】【Hooks】useStateでトグル(toggle)やカウンター(Counter)を実装する際の注意点について



## はじめに
useStateを使い、前の状態を元に状態を設定する必要がある場合に、通常時の`setItem(〇〇)`とは少し違った書き方にすべきことを知ったのでまとめておく。

## 結論

前の状態を元に状態を設定する必要がある場合には、`setCheck(prevIsOpen => !prevIsOpen);` という書き方を使う必要がある。

## 詳細

状態の更新は非同期で行われる可能性があります。

Reactは、パフォーマンスのために、複数の`setState()`コールを1回の更新にまとめることがあります。

よって、`this.props`と`this.state`は非同期に更新される可能性があるので、次の状態に更新するために元々の値をコードに含めてはいけません。

例えば、以下のコードではカウンターの更新に失敗する可能性があります。

```jsx
this.setState({
  // 新しくsetStateするcounterを計算する際に元々のstateとpropsの値を参照している
  counter: this.state.counter + this.props.increment,
});
```

この問題を解決するには、オブジェクトではなく以下のような関数を受け取る形式の`setState()`を使用します。

```jsx
// 明示的に、更新前の(state, props)を受け取り、setStateによる更新を行う。
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));
```

HooksのuseStateを用いる場合も同じ用に、書くことができます。

```jsx
// 何かしらの開閉をisOpenというstateで管理する場合を例にします。
const [isOpen, setIsOpen] = useState(false);

// 更新前のisOpenを受け取り、"!"で反転させる
// 更新前の値であることがわかるように、prev~~とつけても良い
setCheck(prevIsOpen => !prevIsOpen);
```

## おわりに

Hooksの細かい部分ではあるが、setStateが非同期に行われる可能性があることなど、新しい領域のことを学べている実感があった。
【Python】Pythonで特定の拡張子のファイルリストを作る

## 背景
- pythonでカレントディレクトリから特定の拡張子のファイルリストを作りたい時がある。

## 目標
- pythonでカレントディレクトリから特定の拡張子のファイルリストを作る。

## コード
```python:特定の拡張子だけのファイルリストの作り方
import os
files = os.listdir(os.getcwd())
md_files = [i for i in files if i.endswith('.md') == True]
```

```python:特定の拡張子だけのファイルリストの作り方：コメント入り
import os

#カレントのファイルリストを読み込む
files = os.listdir(os.getcwd())

#特定の拡張子のファイルのみを取り出す
#（例として「.md」ファイルを取り出してる）
md_files = [i for i in files if i.endswith('.md') == True]
```

## 参考資料

## 個人ブログ

https://takuma-tech.com/2022/09/27/230/
Next.js製のアプリをVercelにデプロイしたら404NOT_FOUNDになってしまう

## 事象

Next.js のアプリをVercelにデプロイし、デプロイ先に遷移すると下記のように表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/a45510f0-2fe6-5a3b-837b-fd2388078d65.png)

## 対応策

Project SettingsのBuild & Development Settingsから、
「FRAMEWORK PRESET」にNext.jsを選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/6ef96d7b-5469-d121-ae1d-0c993184c8ff.png)

OUTPUT DIRECTORYの参照先が誤っていたため、404が返却されていました。
Nest.jsのデフォルトアウトプット先(.next?)をプリセットが参照してくれるようになり解決。

(しょうもないことでめっちゃ時間使いました。。)
(同じ事象で時間取られないことを願います。)
AppStoreでXcodeアップデートの進捗状況を表示するには

# 1. 背景

App Store アプリで Xcodeアップデート が遅いのでイライラしていませんか？

データダウンロードが終了してから、更新メーターがくるくる回っていますが、

いつ終わるねん・・・

本当にアップデートしてるの？

って思ってました。



# 2. AppStoreアプリでXcodeアップデートの進捗状況を表示するには

くるくる回っている更新メーター上に、カーソルを移動させて数秒待っていると

進捗状況が表示されます。

:::note warn
くるくる回っている更新メーターをクリックするのではありません。
間違えないようにしてください。
:::


（表示サンプル・スクリーンショット）
![xcode_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189425/83f9de1b-8fbd-3314-bf42-8a3095f4df52.png)


# 3. 動作環境

MacOS Monterey バージョン 12.4（21F79）

App Store アプリ バージョン3.0 (1006.5.18.1.3)

以上です
Jetpack ComposeのNavigationを使うと遷移先の画面が繰り返し表示される問題

こんにちは。
最近は宣言的UIが流行っていますね。
Flutterでよく書いていてもう見慣れたのですが、初めて見たときはネストの量にギョッとした記憶があります。
最近はJetpack Composeに挑戦中です。
そんな中でログイン機能を実装していてどハマりしたので共有したいなと思い今回の記事を書くに至りました。

まず状況として、「ログインしていない場合は上からログイン画面を被せる」という仕様を満たそうとした時に、ログイン画面が繰り返し表示されてしまう不具合にハマりました。

これが起きてしまった原因は、結論から言いますと、「Composable内で画面遷移をしようとしたから」です。
具体的にどんなコードを書いていたかというと、

```kotlin:HomeScreen.kt
@Composable
fun HomeScreen(
    viewModel: HomeViewModel,
    navController: NavController
) {
    val uiState by produceState(
        initialValue = HomeUiState(isLoading = true)
    ) {
        val currentUser = viewModel.currentUser()
        value = HomeUiState(isLoading = false, currentUser = currentUser)
    }

    if (!uiState.isLoading && uiState.currentUser == null) {
        navController.navigate(ScreenRoutes.login)
    }
```

こんな感じで、currentUserがnullのとき（ログインしていないとき）はログイン画面に遷移するというコードを書いていました。
Composable内でnavigate()をしているのがまずかったようです。

全然原因がわからずブレークポイントを貼ったり公式ドキュメントをあちこち読んで途方に暮れていました。
が、よく見たら・・・

```You should only call navigate() as part of a callback and not as part of your composable itself, to avoid calling navigate() on every recomposition.```

めちゃくちゃ書いてた・・・
Composableの一部としてnavigate()を呼ぶな、と[公式ドキュメント](https://developer.android.com/jetpack/compose/navigation)にめちゃくちゃ書いてました・・・

とても辛い気持ちになりましたが、これが原因でした。

ちなみに解決策としては
```kotlin
    if (!uiState.isLoading && uiState.currentUser == null) {
        LaunchedEffect(Unit) {
            navController.navigate(ScreenRoutes.login)
        }
    }
```

これでオッケーでした。

Jetpack Compose自体がまだまだ出来立てだから不具合が多いのかなと思っていましたが、想像以上に自分の知識不足だったパターンが多いです。
ちゃんと勉強しなきゃですね・・・
Turborepoを使ってMonorepoへ移行する

あるアプリケーションをMonorepoで管理したくなり、Turborepoを使ったのでまとめます。

## Turborepoとは

昨年末にVercelに買収されたことで話題となった、monorepoを管理するためのツールです。

https://vercel.com/blog/vercel-acquires-turborepo

この分野ではLernaが人気ですが、Turborepoも昨年末以降ダウンロード数を伸ばしているようです。

https://www.npmtrends.com/turbo-vs-lerna

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/cb382063-77a6-8a9a-6735-0d4a9207d6c6.png)

## Monorepoツールの比較

それぞれのMonorepo管理ツールで何ができるかといった機能の比較などはこちらにまとまっていました。

https://monorepo.tools

LernaのメンテをNrwlが引き継ぐなどのニュースもあったので、今どれがベストかを判断するというよりも、好きに試してみるというモチベーションでTurborepoを選択しています。

https://blog.nrwl.io/lerna-is-dead-long-live-lerna-61259f97dbd9

## 手順

### Workspaceの設定をする

Turborepoはyarn workspaceなどと互換性があります。
そのため、まず単一のリポジトリからWorkspaceを設定します。

`./apps`ディレクトリを作成し、`package.json`を書き換えます。

```diff_json:package.json
{
  ...
  "private": true,
  "scripts": {},
+  "workspaces": [
+    "apps/*"
+  ],
  ...
}
```

これでapps以下にディレクトリを切って、アプリケーションを配置します。

```
.
├── apps
│   └── repo1
│   └── repo2
├── README.md
├── package.json
└── yarn.lock
```

## turboの設定

[turbo](https://www.npmjs.com/package/turbo) のインストールをします。

```bash
yarn add turbo -DW
```

Turborepoは`turbo.json`で設定を管理します。

```json
{
  "$schema": "https://turborepo.org/schema.json",
  "baseBranch": "origin/main",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"]
    },
    "dev": {
      "cache": false
    }
  }
}
```

このように設定すると、以下のコマンドで、全アプリケーションのbuildを実行することができます。

```
yarn turbo build
```

buildに設定されている、`"dependsOn": ["^build"]` の `^` は、dependencies、devDependenciesのbuildタスクの完了を待つ記号です。

## 補足

Turborepoは各アプリケーションのタスクの依存関係を解決しながら処理を実行してくれます。
それらを管理するのがpipelineの設定です。

pipelineによって、依存しているタスクを並列実行することで、処理の最適化もしてくれます。

### キャッシュ

Turborepoはコンテンツのハッシュから、タスク実施が必要なものを判断します。

例えば、複数のアプリケーションでbuildを行う時に、変更があったアプリケーションを自動で判定し、必要なbuildだけを行ってくれます。
これにより処理時間の短縮をすることができ便利です。

また、今回は設定していないですが、Vercel上にキャッシュを保存することで、CI/CDなど他の環境で実行した結果を用いて、タスクの処理時間の短縮をすることもできるようです。

## 最後に

Lernaにあるようなパッケージの公開、バージョン管理などはまだ無いようですが、アプリケーションの開発においては便利に感じました。

引き続き使って行きたいと思います。
MasoniteでチョットController

（Python素人が、）ひっそりとMasoniteして行こう、Controller編。

[Masonite Documentation: Controllers](https://docs.masoniteproject.com/the-basics/controllers)

# バージョン
```bash
Python 3.10.4
Masonite version 4.14.1
```

# ファイルの場所
```app/controllers```にあります。
最初は```WelcomeController.py```のみ。

# 作成
Laravelと同様craftで作成できます。
```bash
$ python craft controller UserController
Controller Created (app/controllers/UserController.py)
```
```python:app/controllers/UserController.py
from masonite.controllers import Controller
from masonite.views import View

class UserController(Controller):
    def show(self, view: View):
        return view.render("")
```

折角なら、最初からdocstringを付けておいてくれたらなぁとは思ったり。

ただ、```--resource```のオプションはいけました。
素晴らしい:relaxed:


# Responses
## よくあるパターン
パラメータを受け取りデータ取って、画面と一緒に返すやつ。
```request```と対象の```model```のimportを忘れずに。

```python
from masonite.request import Request
from app.models.User import User

def show(self, view: View, request: Request):
    user = User.find(request.param("id"))

    return view.render("welcome", {"user": user})
    # return view.render("welcome", {
    #     "user": User.find(request.param("id"))
    # })
```

## JSON
json返却も可能
ModelもCollectionもキャストすれば大丈夫そう。
[](https://orm.masoniteproject.com/collections#to_json)

```python
return {"key": "value"}
return User.find(1).to_json()
return User.where('name', 'hogehoge').get().to_json()
```

## Redirects
nameを利用したredirectもいけます。

```python
from masonite.response import Response

def show(self, response: Response):
    return response.redirect("welcome")
    return response.redirect(name="user.index")
```

# 終わりに
とりあえずは以上といった感じでしょうか。
最初はここに色々処理を書いて、次に```Service```導入といったLaravel雰囲気ができたらいいなと思ってま。

※さて続くのか。
source_genで生成ファイルのディレクトリをオリジナルのソースの配下ディレクトリに出力する

## 汚いディレクトリ構成はいや

最近Flutterでアプリを作って見ているんですが、freezedが便利でいっぱい使いたい気持ちになります。
が、生成ファイルがディレクトリに氾濫するので、ものごっつ醜くなってしまい、嫌な気持ちになってました。

build.yamlの指定で出力ディレクトリを単純にlib/generated/*配下などに出力することもできますが、partの指定が相対的になるため、オリジンのファイル側の指定がまた汚くなるジレンマ、、、、

vue.jsのデコレータのように、rootのパスを@とかで指定できればいいんですがね、、、（package:を使えればいいのですが）
先輩に相談したところ、LiveTemplateでpart部を自動生成するのを教えてもらいました。それで半自動でpart部を生成するのも良いかと思います。
で、教えてもらったドキュメントをみて、build.yamlの[configuring-outputs](https://github.com/dart-lang/build/blob/master/docs/writing_a_builder.md#configuring-outputs)を見てたら、ディレクトリ指定の出力方法書いてあるじゃないですか。

## 今の所の答え

```build.yaml
targets:
  $default:
    builders:
      source_gen|combining_builder:
        options:
          build_extensions:
            'lib/{{dir}}/{{file}}.dart': 'lib/{{dir}}/generated/{{file}}.g.dart'
      freezed:
        options:
          build_extensions:
            'lib/{{dir}}/{{file}}.dart': 'lib/{{dir}}/generated/{{file}}.freezed.dart'

```

で、```part 'generated/filename.g.dart'```と書けばいいし。

こうすればディレクトリ構成が下記のようになります。
```
root/
　└ src/
　　　　　└ domain/
　　　　　　　 └ filename.dart
　　　　　　　 └ generated/
　　　　　　　　　  └ filename.g.dart
　　　　　　　　　  └ filename.freezed.dart
```

これは綺麗なのでは？

## まとめ

いったん、気分は落ち着きましたが、できれば本当は生成ファイルなど一つにまとめて気にしなくてもいいようにしたいです。
良い方法があったら教えて欲しいです。

## 参考

- https://torikatsu923.hatenablog.com/entry/2022/02/07/235634
-
あえて引数名を書くパターン

C# では、メソッドやコンストラクタに引数を渡す際に引数名を省略してコードを書く場合が多いと思いますが、明示的に引数名を書くこともできます。

```csharp
int Add(int x, int y)
    => x + y;

// 引数名を省略する場合
var hoge = Add(10, 20);

// 引数名を明記する場合
var fuga = Add(x: 10, y: 20);
```

省略しても問題ない引数名を、わざわざ明記するパターンは以下のような場合が考えられます。

## メソッドで定義している引数の順番とは違う順番で書ける
```csharp
float Div(float x, float y)
    => x / y;

// x と y をメソッド定義とは異なる順番で渡す
Console.Write(Div(y: 2f, x: 1f));
// 0.5
```

とはいえ、何か特別な意図がない限りこういった使い方はしないと思います。

## 複数の省略可能引数（オプション引数）のうち一つを明示的に指定する
```csharp
void Demo(int x, bool isHoge = false, bool isFuga = false, bool isPiyo = false)
{
    Console.WriteLine($"x: {x}");
    Console.WriteLine($"isHoge: {isHoge}");
    Console.WriteLine($"isFuga: {isFuga}");
    Console.WriteLine($"isPiyo: {isPiyo}");
}

// isHoge と isFuga はデフォルト値のまま、isPiyo のみ指定
Demo(10, isPiyo: true);

// x: 10
// isHoge: False
// isFuga: False
// isPiyo: True

// 名前付き引数を使用しない場合、すべての引数を明示的に指定する必要がある
Demo(10, false, false, true);
```

これも、元々のメソッドの設計があまり良くないなどの理由で、後付けで省略可能引数がわんさか付いているようなメソッドというのは古いコードではよくあります。

## 可読性の向上；「この引数でどうなるんだっけ？」対策
例として以下の `StreamWriter` の場合を考えてみます。
```csharp
var path = GetPath();
using (var sw = new StreamWriter(path, false))
    sw.Write("hoge");
```
`StreamWriter` のコンストラクタの第2引数に `false` を渡しています。この第2引数は `append` という引数名で定義されており、既にファイルが存在する場合に末尾に書き込むか、新しく上書きするかを真偽値で指定します[^1]。

ところが数年ぶりに `StreamWriter` を使ってこのコードを見た場合、この `false` がどういう作用をもたらすのか**瞬時に**理解できるでしょうか？

もちろん、IDE上で見る場合は引数の説明をいつでも参照することができます。そうでない場合でも、[公式のリファレンスソース](https://referencesource.microsoft.com/)を参照することができることでしょう。この `false` が何をもたらすかというのは、数十秒あれば解決できる疑問かもしれません。

しかし、引数名を明記しておくと数十秒とかからず、**コードを見ただけで瞬時に**判断できるようになります。
```csharp
var path = GetPath();
using (var sw = new StreamWriter(path, append: false))
    sw.Write("hoge");
```
「この `false` の引数名、`append` ってことはこの場合追記じゃなくて上書きなのか」と、**定義やドキュメントを参照するまでもなく**コードを読んだ瞬間に意味を理解することができます。これはかなり大きなメリットなのではないでしょうか。

さらに、今回は `StreamWriter` を例に出しましたが、もしこれが公式のライブラリではなく、ドキュメントもろくにメンテされていない独自ライブラリだとしたらどうでしょう。「そのような環境の方が問題だろ！」というのももっともですが、しかし全てのドキュメントのメンテが行き届いている環境ばかりではありません。

個人的には、コメントに「falseは上書き」みたいなことを書くよりは、`append: false` と書いた方が余程良いと思います[^2]。

***

以上、個人的に想定する「引数名を明示する理由」をまとめてみました。

以下、おまけ。

最後のコメント的な用法に関しては、自作クラスを使う場合は `WritingMode` みたいな `Enum` を受け取るようにして、
```csharp
using (var ow = OriginalWriter(path, WritingMode.Overwrite))
    ow.Write("hoge");

// WritingMode は
// WritingMode.Overwrite => 上書き
// WritingMode.Append    => 追記
```
という形で受け取るようにすれば、引数名を書かずとも「**この引数では書込みモードを指定してますよ**」という意図が明確になることもあります。自作する場合は、たとえ真偽値で判断できる場合でもあえて `Enum` を併用して、より意図を込めやすくなるように工夫できれば良いと思います。

## その他
ブログとCrieitでも記事を公開しているので、よければご覧ください。

ブログ：BOYISH KINGDOM

https://boyi.sh

Crieit：apashoni

https://crieit.net/users/apashoni


[^1]:**参考** StreamWriter クラス｜StreamWriter(String, Boolean)
[https://docs.microsoft.com/ja-jp/dotnet/api/system.io.streamwriter?view=net-6.0](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.streamwriter?view=net-6.0)

[^2]:コメントが悪という主張ではなく、**コードで表現できることは、できるだけコードで表現すべき**という主張です。たとえば「なぜ追記じゃなくて上書きをするのか」という意図が共有してあるのは良いコメントだと感じます。
pytestでSQLAlchemyの接続先をオンメモリSQLite3に挿げ替える

## 目的

外部への依存度を減らしつつ、DB関連コードのユニットテストを書くこと。

## 方法

表題の通り。

## コード例

```python
"""pytestによるSQLiteの接続先の挿げ替え例."""
from typing import Iterator, List, Tuple
from unittest.mock import patch

from pytest import fixture
from sqlalchemy import create_engine, text


def get_stocks() -> List[Tuple]:
    """Product code."""
    user = "user"
    password = "password"
    host = "xxxx.xxxxxxx.us-east-2.rds.amazonaws.com"
    database = "mysql"

    engine = create_engine(
        f"mysql+pymysql://{user}:{password}@{host}/{database}"
    )

    with engine.begin() as connection:
        return list(connection.execute(text("select * from stocks;")))


@fixture(autouse=True)
def mock_db() -> Iterator[None]:
    """Fixture."""
    engine = create_engine("sqlite://")
    with engine.begin() as connection:
        connection.execute(
            text(
                "CREATE TABLE stocks "
                "(date text, trans text, symbol text, qty integer, price real)"
            )
        )
        connection.execute(
            text(
                "INSERT INTO stocks VALUES "
                "('2006-01-05','BUY','RHAT', 100, 35.14)"
            )
        )

    with patch(f"{__name__}.create_engine", return_value=engine):
        yield


def test_get_stocks() -> None:
    """Test code."""
    assert get_stocks() == [
        ("2006-01-05", "BUY", "RHAT", 100, 35.14),
    ]
```
年月単位の連続データをRで作る

仕事でいろいろなデータを集計していると、月別にまとめたいことが多々あります。
しかし月単位で連続のデータを生成する関数がないので方法を考えました

```.R
> library(tidyverse)
> library(lubridate)

#2020年1月から2022年5月まで、連続の月次データを生成する
> year_month <- seq(as.Date("2020-01-01"), as.Date("2022-05-01"),by="1 day") %>% floor_date(unit="months") %>% unique()
# [1] "2020-01-01" "2020-02-01" "2020-03-01" "2020-04-01" "2020-05-01" "2020-06-01" "2020-07-01" "2020-08-01" "2020-09-01" "2020-10-01" "2020-11-01" "2020-12-01" "2021-01-01"
#[14] "2021-02-01" "2021-03-01" "2021-04-01" "2021-05-01" "2021-06-01" "2021-07-01" "2021-08-01" "2021-09-01" "2021-10-01" "2021-11-01" "2021-12-01" "2022-01-01" "2022-02-01"
#[27] "2022-03-01" "2022-04-01" "2022-05-01"

> class(year_month)
[1] "Date"

```

月次データの完成です。
Tauri+VueでVue Devtoolsを使う方法

一行要約。
Vue Devtool の standalone 版でインターセプトすれば良い。

https://devtools.vuejs.org/guide/installation.html#standalone

環境は Windows10 だが、OSを問わない解決法。  
なんなら React の `react-devtools` も同じ方法で解決するはず。



----

## はじめに Tauri の宣伝

皆さん `Tauri` をご存知ですか？
超意訳すると超軽量版 Electron です。

RC版が出たと騒がれていたので触ってみると、まさに私が求めていたもの！
正直、これからのデスクトップ向けアプリはこれでいいのでは？（Web屋さんの感想）
と思うほどでした。

とにかく軽量なのが偉い。
Rustという言語が取っつきにくい場合、ブラウザの世界でコードを書くことも可能ではあるので、ぜひお試しあれ。

https://tauri.studio/

> electron はビルド周りがゴチャっとしてて、生成ファイルが大きすぎるのが、個人的バットポイント。



## Vue Devtool が使えない！

Windows での Tauri は、`WebView2` という内部ブラウザを使用してレンダリングします。
これが曲者で、拡張機能が使用できない...

つまり Vue 開発の味方 `Vue Devtools` が使えないのです；；
（知らない方は損しすぎなので、とりあえずDL！）

https://devtools.vuejs.org/

> 拡張機能の議論はこのあたり。
> あんまり乗せる気は無さそう...
>
> Add Ons or Extensions with WebView2 · Issue #98 · MicrosoftEdge/WebView2Feedback
> https://github.com/MicrosoftEdge/WebView2Feedback/issues/98

色々検索しても対策がヒットせず、途方に暮れて拡張機能のDocに迷い込みました。
すると **`standalone`** 版があるではないですか！

https://devtools.vuejs.org/guide/installation.html#standalone

きたこれ！
（昔こんなの無かった気がするんだが？？）



## standalone Vue Devtools

とりあえずグローバルに yarn でインストールする。
npm マンは `npm install` に読み替えて。

```bash
# グローバルにインストール
$ yarn add --global -D @vue/devtools

# 起動
$ yarn vue-devtools
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105139/87276548-e354-5fa6-431e-d9cf09e1705f.png" width="480" />

なんか出てきた。

`<script src="http://localhost:8098"></script>` 
を埋め込めとおっしゃっている。


### Vue の場合

`index.html` に script を埋め込む。  

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>Vite App</title>
    <script src="http://localhost:8098"></script>
  </head>
  ...
```

### Nuxt3 の場合

`nuxt.config.ts` に script を埋め込む。

`&&` 演算を使って、production のときだけコードを記載するようにする。
2でも似たような感じで。  

```ts
const isProduct = process.env.NODE_ENV === 'production'

export default defineNuxtConfig({
  ...
  app: {
    head: {
      script: [
        !isProduct && { src: 'http://localhost:8098' },
      ],
    },
  },
}
```

> 多分どこに埋め込んでも問題ないので、いい感じにやればOK。

その後 `$ yarn tauri dev` でアプリを起動すると。。。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105139/8573fa75-358a-a61c-419b-073cb0b27548.png" width="480" />

！！！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105139/30ea2b30-eb37-1079-1d1d-b32a8ec84111.png" width="480" />

！！！！！



## おわりに

**リリース時にはこのコードが載らないようにしましょう！！！**
そのまま残したら立派なセキュリティホールです。
`process.env.NODE_ENV` を使って、開発モードが production ではない時だけ埋め込むのが賢そう。


良き Tauri Vue ライフを🙌
GASでChat Work通知

## やること
スプレットシートの情報をGASでChat Work通知する

## コード

    function myFunction() {

    //Chat Work API
    const token = 'xxxxxxxxxxxxxxxxxxxxxxxxx';
    const base_url = 'https://api.chatwork.com/v2';
    const room_id = 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
    const url = base_url + '/rooms/' + room_id + '/messages';

    //スプレットシート
    const sheet_id = 'xxxxxxxxxxxxxxxxxxxxx';
    const ss = SpreadsheetApp.openById(sheet_id);
    const sheet = ss.getSheetByName("シート 1");
    const cell = sheet.getDataRange().getValues();
    const value = cell.toString();
    
    //確認のため
    console.log(value);

    const options = {
    'method': 'post',
    'headers': {'X-ChatWorkToken' : token},
    'payload': {'body' : value}
    };

    const result = UrlFetchApp.fetch(url, options);
    const json = JSON.parse(result.getContentText());
        
    //確認のため
    console.log(json);

    }

※`room_id`はCWのURLに入っている`rid`以降
※`sheet_id`はスプレットシートのURLに入っている`spreadsheets/d/`以降

## 気をつけること

setValue：1 つのデータだけをセットする
setValues：複数のデータをセットする

`s`がついているかついていないかで大きく変わる！！

## 最後に
今回は全てのセルを取得してますが自動でスプレットシートにデータが入ってきたら、範囲を指定してCWで通知するとか使えそうですね。

## 参考文献

https://help.chatwork.com/hc/ja/articles/115000172402

https://developer.chatwork.com/ja/index.html
pingが通らなかった話

# 起こった事件

Ubuntuでネットワーク周りの設定をしていたところ、奇妙なことが起こった。
LANケーブルさして、IPアドレスももらえているのに、なぜか`ping`が通らない。

ちなみに、そのときのnetplanの設定ファイルがこちら。

```yaml: /etc/netplan/99_config.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: false
      addresses:
      - 192.168.13.100/24
```

`sudo netplan apply`を実行して、この設定ファイルの設定を反映されても、なにもエラーが出ない。
でも、`ping`が通らない。

同じネットワークないからのSSHもつなげるし、IPアドレスもきちんと望んだものが割り当てられているのにも関わらず。。。

Wi-Fiなら、普通につなげるし、LANケーブルや、ルーターのポートがぶっこわれているんではなかろうか、とかいろいろ考えて、原因を探ってました。

# 原因

`dhcp: true`のときはうまくいって、`dhcp: false`のときだけうまくいかなかったから、試行錯誤していたら発覚しました。
ゲートウェイが登録されていなかったのが原因でした。

# 解決策

```yaml: /etc/netplan/99_config.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: false
      addresses:
      - 192.168.13.100/24

      # 以下を追加
      routes:
      - to: default
        via: 192.168.13.1
```

# 最後に

私みたいなこんな間違いする人は、いないと思いますが、苦労した記念に書いときました。
viewport完全に理解した

■概要
------------------------------

htmlでスマホレイアウトをするときは`viewport`を指定するが、微妙に思い通りの動きをしてくれないので、動きをまとめてみた。

viewportはスマホ画面に、どんな大きさのhtmlレイアウト領域(＝ビューポート)を、どんな倍率で表示するかを指定するための設定。
例: `<meta name="viewport" content="width=device-width,initial-scale=1">`



■device-widthについて
------------------------------

スマホの横幅を、論理ピクセル数で示した値。

スマホは解像度が高いので、論理ピクセル数＝物理ピクセル数(デバイスピクセル)ではない。
例えば`width:100px`の要素は100論理ピクセルの幅を持つが、スマホ液晶上では100以上の物理ピクセルによって表示される。
`device-width`は、この論理ピクセル数で画面幅を示す。




■viewportの指定方法（width、initial-scaleの指定）
------------------------------

viewportの指定がどのように機能するのかを理解するには、以下のそれぞれを別に考えると分かりやすい。
・`width`のみを指定する場合
・`initial-scale`のみを指定する場合
・`width`と`initial-scale`両方を指定する場合


### width(レイアウト領域幅)のみを指定する場合

指定された`width`幅を持つレイアウト領域に対してページレイアウトが作成される。
そのレイアウト領域が、スマホ幅内に表示しきれるように`initial-scale`(初期のズーム倍率)が自動設定される。
(つまり必ず1画面で表示できる倍率でページが表示される)

device-width=400の場合
widthは400			→	自動設定されるinitial-scale=1.0
widthは800			→	自動設定されるinitial-scale=0.5
widthは1600			→	自動設定されるinitial-scale=0.25



### initial-scale(初期のズーム倍率)のみを指定する場合

`initial-scale`倍に拡大縮小したとき`device-width`でぴったり収まる幅に対してページレイアウトが作成される。
`width`(レイアウト領域幅)は上記の幅に自動設定される。
(つまり必ず1画面で表示できるレイアウト領域幅でページが表示される)

device-width=400の場合
initial-scale=1.0	→	自動設定されるwidth=400
initial-scale=0.5	→	自動設定されるwidth=800
initial-scale=0.25	→	自動設定されるwidth=1600

ちなみにズーム倍率とは「(拡大縮小して)画面表示されている論理ピクセル幅」に対する「画面幅の論理ピクセル数(device-width)」の割合のことである。
例えば表示論理ピクセル=200、device-width=400なら2.0倍のズーム倍率で表示していることになる。



### width と initial-scaleを指定する場合

指定された`width`幅を持つレイアウト領域に対してページレイアウトが作成される。
そのレイアウト領域が、指定された`initial-scale`のズーム倍率でスマホ画面に表示される。
(必ずしも1画面でレイアウト領域幅が表示しきれるとは限らない)

device-width=400の場合
width=400, initial-scale=1.0　→　レイアウト領域幅400が、1.0倍で表示されるので画面にぴったり収まる。
width=800, initial-scale=1.0　→　レイアウト領域幅800が、1.0倍で表示されるのでレイアウト領域は半分ほど画面溢れする。
width=400, initial-scale=0.5　→　レイアウト領域幅400が、0.5倍で表示されるのでレイアウト領域に画面の半分に縮小された内容が表示される。
width=800, initial-scale=0.5　→　レイアウト領域幅800が、0.5倍で表示されるので画面にぴったり収まる。




■その他のプロパティと既定値
------------------------------

minimum-scale=0.25		ズーム倍率 最小
maximum-scale=1.60		ズーム倍率 最大
user-scalable=yes		ズーム率の変更許可 yes|no




■その他情報
------------------------------

### viewport未指定の場合

`<meta name="viewport" content="width=980">`
と同じ意味になる。

### 一般的に使われる設定

`<meta name="viewport" content="width=device-width,initial-scale=1">`
これは、スマホの画面幅を示す論理ピクセル数のレイアウト領域に対して、ページレイアウトを行う設定。

### メディアクエリとの関係

`@media (max-width: 520px) {...}`などの条件は、`device-width`には関係なく`width`(＝レイアウト領域幅)に対する条件になる。
そのため`<meta name="viewport" content="width=980">`などの指定をすると、スマホのデバイス幅がいくら狭くても、メディアクエリでは980ピクセルの幅があると判定される。
（だから一般的には`<meta name="viewport" content="width=device-width,initial-scale=1">`が推奨される）
SQL チートシート （登録・取得・更新・削除）

# 初めに
SQLの基本（登録・取得・更新・削除）をまとめています!

### SQL基本
◇ SQLコマンド(データ操作)
```
INSERT:  データを“登録”
SELECT:  データを“表示“
UPDATE:  データを“更新”
DELETE:  データを“削除“
```

## INSERT(データ登録)
DBにデータを**登録**する

◇書式:
```
INSERT INTO [テーブル名]([カラム1], [カラム2]) --データを入れる場所の指定
VALUES([値1], [値2]) ;                  --入れるデータを記述
```
◇例:
```
INSERT INTO sample_table(name, email, indate)
VALUES('現役次郎', 'test2@test.test', sysdate() );
```
※A.Iにチェックを入れたID等に関しては自動で入力される
※``sysdate()``は現在の日付と時刻を返してくれる

## SELECT(データ取得)
DBからデータを**取得**する
◇書式:
```
SELECT [表示するカラム] FROM [テーブル名];
```

◇例:
```
全指定:    SELECT * FROM sample_table;
単体指定:  SELECT name FROM sample_table;
複数指定:  SELECT name, email FROM sample_table;

--※WHERE を使用して特定のデータを抽出。 
SELECT * FROM gs_an_table WHERE name = 'ジーズ太郎'; 
```
### [様々な条件をつけて検索]

**・演算子を使う**
```
SELECT * FROM [テーブル名] WHERE id = 1;
SELECT * FROM [テーブル名] WHERE id >= 3;
```
**・AND, OR で検索条件を複数指定**
```
SELECT * FROM [テーブル名] WHERE id=1 OR id=2;
SELECT * FROM [テーブル名] WHERE id >= 1 AND id<=3;
```
**・あいまい検索**
```
--前方一致
SELECT * FROM [テーブル名] WHERE indate LIKE ’2015-06%'; 
--後方一致
SELECT * FROM [テーブル名] WHERE email LIKE ’%@gmail.com'; 
--部分一致
SELECT * FROM [テーブル名] WHERE email LIKE ‘%@%';
```

### [ソートと制限]
**・表示をソート（並び順を変える）**
※ DESCは降順、ASCは昇順
```
SELECT * FROM [テーブル名] ORDER BY [ソートしたいカラム名] [並び順の指定];

SELECT * [FROMテーブル名] ORDER BY id DESC;
SELECT * [FROMテーブル名] ORDER BY email, name ASC;
```
**・表示件数を制限**
```
SELECT [表示するカラム] FROM [テーブル名] LIMIT ***;

SELECT * FROM [テーブル名] LIMIT 5;    --5個目まで
SELECT * FROM [テーブル名] LIMIT 3, 5;  --3個目から5個目まで
```

## UPDATE(データ更新)
DB上のデータを変更する。

◇書式:
```
UPDATE [テーブル名]　 SET [変更するカラム名(列)]　＝　[新しい値] WHERE [変更するレコード(行)];
```
◇例:
カンマ　で区切ることで複数のカラムを一度に変更が可能。
```
UPDATE sample_table SET name='変更さん',email='henkou@jp' WHERE id=1;
```

## DELETE(削除)
DB上のデータを削除
◇書式:
```
DELETE FROM [テーブル名] WHERE [変更するレコード(行)];
```
◇例:
※``WHERE``での指定を忘れると、table内の全てのデータが消えるので注意
```
DELETE sample_table SET WHERE id=1;
```
成長に繋がる質問の仕方についての一考察

## はじめに

思考力や課題解決力がある人とそうでない人とでは、困った時の質問の仕方が違うと感じています。

逆に言えば、良い質問をするよう心がけることが、その人の能力を高めることになるはず。

この記事ではそんな質問の仕方を言語化してみたいと思います。

※バリバリ独断と偏見が入ってますので、ご容赦ください。

## 読んでほしい人

- 「質問内容がわかりにくい」と言われがちな人
- 「いつも同じようなところで躓いて、先輩に質問してるな...」と感じている人

## こんな質問してませんか？

### 長い＆聞きたいことから話せてない

<b>「AをBしたいんですけど、うまくいかなくてCになっちゃうんです。自分で色々調べてみたんですけど、うまく解決できなくて...これってどうすれば良いですか？」</b>

- 質問された方は、最後まで聞いてやっと内容がわかることになります。それまでずっと漏れなく聞いていないといけません。


###  そもそも質問の形になっていない

<b>「この実装で詰まっちゃってて...」</b>

- 「ヒントが欲しいのかな？」「一緒に実装を見てほしいのかな？」「はたまた...」と、質問された方は、何を求められているのかわからなくなってしまいますね。


## 質問する時に心がけたいこと。

相手に負担をかけない（必要以上の情報を与えない）ような質問ができると、コミュニケーションもスムーズです。

何より、「そこまで質問自体をブラッシュアップすること」が、自身の成長に繋がります。

### 相手に求めることをピンポイントでまとめ、まず最初にそれを伝える

<b>「実装詰まっている部分があるので、ヒントを貰っても良いですか？」</b>

- 「相手に求めること」をじっくり考えれば、それが「自分が困っていることを伝えること」ではないのがわかるはずです。

### （可能ならば） 「YES」か「NO」で答えられる質問にする。

<b>このエラーは〇〇が原因だと思うんですが、テストコード書いて確認進めても良いですか？</b>

- この質問に至るまで考え抜くことが成長に繋がります。

## とはいえ、ケースバイケースで

質問の仕方に悩みすぎて、時間を使いすぎる結果になっては本末転倒ですね。

質問相手には相手のペースもあるので、その辺も見極めたいところ。（これが一番難しいんですけどね。）


## おわりに

じっくり考察記事を書こうと思いながら、ペラッペラの内容になってしまいました...。

そのうち加筆するかもです。


弊社では、経験の有無を問わず、社員やインターン生の採用を行っています。
興味のある方は[こちら](https://www.recruit.nuco.co.jp/)をご覧ください。
【k8s】ヘルスチェックの機構

# はじめに
この記事ではkubernetes（以下k8s）の勉強の自己学習のメモです。本コンテンツではk8sのヘルスチェックについて記載します。

# Liveness ProbeとReadiness Probe
k8sにはPodの正常性の判断として「Liveness Probe」と「Readiness Probe」という２種類のヘルスチェック機構が用意されています。

## Liveness Probe
Liveness ProbeはPodが正常に動作しているかを確認（正常に動作しない場合は再起動する）

## Readiness Probe
Podがサービスインする準備が出来ているかの確認（正常に動作しない場合、トラフィックを流さない）
例）プロセスが起動していない、バックエンドのDBに接続できていないetc

Liveness ProbeとReadiness Probeは片方のみ、両方設定可能。

# チェック方式（3種）
Liveness ProbeとReadiness Probeは以下の3種類のチェック方式に従ってヘルスチェックします。

## exec
コマンドを実行し、正常終了（終了コード0）であれば成功、それ以外は失敗と判定します。

## httpGet
HTTPGETリスエストを実行。ステータスが200～399なら成功、それ以外は失敗と判定します。

### tcpSocket
TCPセッションを確立できれば成功。それ以外は失敗と判定します。

# まとめ
ヘルスチェックの機構と方式で混乱するのでまとめました。皆様のお役に立てれば幸いです。