OmniAICreator/Qiita-1.07M huggingface dataset:
Xcode Cloud でプロジェクトをビルドしてみる



## これは何

Xcode Cloud でプロジェクトをビルドする方法のメモです。そもそも Xcode Cloud って何よ？という方は下記サイトを御覧ください。

[Xcode Cloud Overview \- Apple Developer](https://developer.apple.com/xcode-cloud/)

## 利用申請

Xcode Cloud はまだベータ版であり、利用するには下記URLから申し込む必要があります。

https://developer.apple.com/xcode-cloud/beta/request/

何日か待つと「使えるようにしたよ〜」といった内容のメールが Apple から届きます。


## とりあえずビルドしてみる

まずは [Xcode 13](https://developer.apple.com/download/) 以降をインストールしましょう。

次に Xcode のメニューから Product > Xcode Cloud > Create Workflow... を選択します。

![スクリーンショット 2021-11-04 8.42.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8292/505f5250-45dd-d145-1155-eaa809c07641.png)


あとは画面に従って

- 対象プロダクト（iOS, macOS, watchOS 等）
- 対象ブランチ
- Xcode / macOS のバージョン
- アーカイブの有無
- TestFlight 配信の有無

を選択します。

![スクリーンショット 2021-11-04 8.47.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8292/e98fa4a4-c8f2-4fbe-b3a9-b1f1d32b32a7.png)

その後、GitHub のアクセス権限を許可すれば最初の設定は完了です。

![スクリーンショット 2021-11-04 8.53.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8292/396cf80c-72cc-9269-c22a-c15b5844057c.png)


"Start Build" をクリックするとすぐにビルドが始まります。

![スクリーンショット 2021-11-04 8.55.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8292/8a9e793f-7039-f47f-b6dd-d506b96385b1.png)



ビルド結果は App Store Connect の Xcode Cloud タブからも確認できます。

![スクリーンショット 2021-11-04 8.38.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8292/ea65a731-959c-d532-3645-2203a128da31.png)


ビルドに失敗した場合は詳細なログも確認できます。

![スクリーンショット 2021-11-04 9.00.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8292/3b65d575-9bd7-95c0-b14a-03b1796045f4.png)


ビルド結果を Slack やメールで送信することもできるので、まずは色々さわってみるとよいでしょう。

![スクリーンショット 2021-11-04 9.28.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8292/d503af85-a031-3363-52b9-37fcfa5f9e89.png)


## CocoaPods や Carthage を使う

Xcode Cloud には CocoaPods や Carthage 等のサードパーティ製ツールがインストールされていません。もし、CocoaPods を使いたい場合は、次の2つの方法からいずれかを選択できます。

1つ目は Podfile、Podfile.lock、および Pods ディレクトリを丸ごとリポジトリにプッシュする方法です。こうすることで、Xcode Cloud 上で `pod install` を実行する必要がなくなります。ただし、当然アップロードするファイルサイズも膨大になるので注意が必要です。

2つ目はShellスクリプトを書いて自分で CocoaPods をインストールする方法です。Xcode Cloud には Homebrew がインストールされていますので、`brew` コマンドで CocoaPods をインストールすることが可能です。プロジェクトディレクトリ直下に `ci_scripts ` ディレクトリを作成し、`ci_post_clone.sh` という名前で次のスクリプトを作成しましょう。

```shell
#!/bin/sh

# Install CocoaPods using Homebrew.
brew install cocoapods
		
# Install dependencies you manage with CocoaPods.
pod install
```

これで Xcode Cloud で `pod install` が実行可能になります。

Carthage についても同様にShellスクリプトでインストールし、依存関係をセットアップすることができます。

スクリプトの詳細については下記ドキュメントを参照してください。

[Writing Custom Build Scripts \| Apple Developer Documentation](https://developer.apple.com/documentation/xcode/writing-custom-build-scripts)

## リンク

- [Making Dependencies Available to Xcode Cloud \| Apple Developer Documentation](https://developer.apple.com/documentation/xcode/making-dependencies-available-to-xcode-cloud)
- [Writing Custom Build Scripts \| Apple Developer Documentation](https://developer.apple.com/documentation/xcode/writing-custom-build-scripts)
カスタムフックと自作javascript関数は何が違うのか

#はじめに
hooksと普段から呼んでいるが、javascript関数と厳密に言えばどういうところが違うのだろうと思い調べた。

#前提
hooks、javascriptともにアロー関数を想定。ここで言うjavascript関数はtypescript関数を含む（どちらかというとtypescriptより）。

#hooksとは
hook,hooks,フック,Hooks API,React Hooksなどいろいろな呼び方がありますがすべて一緒です。

>**フック (hook)** は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。

React公式[[1]]より引用。

要するにクラスコンポーネントじゃなくて関数コンポーネントでもstateなどのReactの機能を使うためのもの。useState、useEffectなどは特によく使う。自分独自にフックを作成することも出来、自分が作成したフックをカスタムフックと呼びます。

>自分独自のフックを作成することで、コンポーネントからロジックを抽出して再利用可能な関数を作ることが可能です。

React公式[[2]]より引用。

公式ではカスタムフックを作成することでロジック（論理的構造）を切り出すことが可能であるとアナウンスされています。しかしこの表現が僕がhooksを誤解した原因の文です（あとで詳細を述べます）

#hooksのルール
React公式[[3]]を参考に作成。

**フックを呼び出すのはトップレベルのみ**
hooksはif文などの条件分岐の中や、for文などのループの中、ネストされた関数内では使用してはいけません。当然イベントハンドラとしても利用不可能です。

**フックを呼び出すのはReactの関数内のみ**
hooksはjavascript関数からは呼び出してはいけません。呼び出せる場所は以下の２つです。

・Reactの関数コンポーネント内
・カスタムフック内

「Reactの関数コンポーネント」という定義がよく分からなかったので実験してみた感じ、**JSXを返り値とする大文字から始まるjavascript関数**のことのようです。

**この２つのルールは絶対守らなければならないものです。**あとは命名規則として「useXXXX」という名前にするというのもあります。こうするとESLintプラグインなどで認識してくれるので基本的にはこの命名規則に従うべきでしょう。

#カスタムフックと自作javascript関数は何が違うのか。
さていよいよ本題です。２つの違いを列挙していきましょう。

|項目|カスタムフック|自作js関数|
|::|::|::|
|トップレベル以外での使用|不可能|可能|
|hooksの使用|可能|不可能|
|命名規則|基本「useXXXX」|基本自由|
|返り値|なんでも可能|JSXは不可能|

**カスタムフックはトップレベル以外で使えない。自作js関数は使える**
これが一番大きな違いでしょう。トップレベル以外では必然的に自作js関数を使うことになります。

**カスタムフック内ではフックが使用可能、自作js関数では不可能**
ロジック内でフックを使用したい場合はカスタムフックを使用しなければなりません。

**カスタムフックの命名は基本「useXXXX」、自作js関数の命名は基本自由**
カスタムフックは基本的に「useXXXX」にしないと怒られることが多いですし、そうしたほうが明らかにわかりやすいです。自作js関数のほうは特に決まっていなければ自由です。

**カスタムフックはJSXを返り値に出来る、自作js関数は出来ない**
これはそもそもアンチパターンなのであまり気にする必要はないと思うのですが、自分の環境では上のような結果になりました。これも「useXXXX」の命名規則による認識が効いている気がします。当然もしJSXを返したかったら拡張子もjsx(tsx)にしなければいけませんし、基本返さない方がいいと思います。

#具体的な使い分け
**イベントハンドラのロジックを切り出したい**
トップレベルではないので自作js関数。stateを変更したい場合はstateの更新関数（setState()など）をコールバック関数として引数に渡せば自作js関数に出来ます。reduxのdispatchなどを使う場合も多いとは思います。

**DBからのデータの取得ロジックにuseEffectを使いたい**
hooksを使いたいのでカスタムフックです。api処理は別に切り出す必要があるかもしれませんがそれはまた別の話です。


#おわりに
「hooksはロジックを切り出すのにトップレベルじゃないと使えない、じゃあイベントハンドラとかのロジックを切り出す場合はどうすればいいんだ！」と思っていろいろ調べていたんですが、単純にjs関数使えばいいだけでした。書き方的にhooksですべてロジック切り出せるのかと思ってたので、気づくのに時間がかかってしまいました。まだ非同期処理周りが曖昧なので、また何かまとめたら投稿しようと思います。

#参考文献
[1]:https://ja.reactjs.org/docs/hooks-intro.html
[2]:https://ja.reactjs.org/docs/hooks-custom.html
[3]:https://ja.reactjs.org/docs/hooks-rules.html

[[1]]:フックの導入
[[2]]:独自フックの作成
[[3]]:フックのルール
JavaScript——深度理解（1）

#従来のコンパイル言語フロー（コンパイル）

1.分詞・品詞分析（形成品詞ユニット流）

2.解析/文法分析
このプロセスは、語法ユニットストリームを要素レベルごとにネストされた構成に変換するプログラムシンタックス解構成を表すツリーです。この木は「抽象文法樹」と呼ばれています。（Abstract Syntx Tree AST）

3.コード生成
JIT Just in time
AOT Ahead of time

#LHSとRHS

LHSは関連容器を見つける。

RHSは対応する値を見つける。

RHSクエリがネストされているすべてのスコープの中で必要な変数が見つからない場合、エンジンはReferenceErrerをスローします。

対照的に、エンジンがLHSクエリを実行すると、最上階（グローバルスコープ）でも目標変数が見つからない場合、グローバルスコープではその名前を持つ変数が作成され、エンジンに返却され、プログラムが非厳格モードで実行されることが前提となる。

ReferenceErrorは作用域判別失敗に関連していますが、Type Errorは作用域判別に成功しました。しかし、結果に対する操作は不法か不合理です。


#JS変数の割り当て操作

変数の割り当て操作は2つの動作を行います。まず、コンパイラは現在のスコープで変数を宣言します。（もし前に宣言されていないなら）、実行時にエンジンがスコープ内で変数を検索します。見つけられたら割り当てを行います。そうでなければエラーを報告します。

#語法の段階

関数がどこで呼び出されても、どのように呼び出されても、その語法のスコープは関数によって宣言された時の位置によってのみ決定されます。

ワードスコープ検索は一級の識別子だけを検索します。コードにfoo.bar.bazワードスコープを参照すればfoo識別子を検索するだけです。

#関数宣言関数式

関数宣言と関数表現を区別する最も簡単な方法は、functionキーのビットが声明の中に現れる位置を見ることである。Functionが宣言の最初の単語であるならば、関数宣言であり、そうでなければ関数表現です。

(function foo(){.})は関数式としてfooは.で表される位置にしかアクセスできないことを意味します。外部作用領域はだめです。

#位を進める

エンジンはJavaScriptコードを説明する前にまずコンパイルします。コンパイル段階の一部の作業は、すべての声明を見つけ、適切なスコープでそれらを関連付けることです。

```
a = 2

var a

console.log(a); // 2

console.log(a); //undefined

var a = 2;
```
コンパイラは次のように行います。

```
var a;

a=2

consolie.log(a)

var a;

consolie.log(a)

a=2

```

第一部分はコンパイルであり、第二部分は実行である。

```
foo()

function foo(){

consolone.log(a)//undefined

var a=2

)
```

各作用域は向上しますので、このコードは以下の形式として理解されます。

```
function foo(){

var a;

consolone.log(a)

a=2;

)

foo()

```

関数宣言は昇格関数式にはなりません。

```
foo()//ReferenceErrではなくTypeErr

var foo=function bar(){}

```

#スコープ

実際には、クローズドは普通にはっきりと切った事実です。つまり、私たちはワードのスコープの環境でコードを書きます。その中の関数も値です。自由に伝えられます。関数が覚えていて、既存の語法作用領域にアクセスできると、関数が現在の語法のスコープ外で実行されても、この関数は閉じられています。

```
function foo(){
    var a = 2;
    function bar(){
        console.log(a)
    }
    
    return bar
}

var baz = foo();
baz() //2 これは閉包です
```

foo（）が実行された後、エンジンにゴミ回収器がありますので、使用しないメモリを放出します。foo（）の内容は使えないように見えますが、クローズドはこのようなことを防ぐことができます。bar（）自体が使っているからです。

この関数は定義時の語法のスコープ以外で呼び出されます。クローズドは、関数が定義された時の動作領域にアクセスできるようにします。

内部関数を所在の品詞作用領域に渡す以外は、元の定義された作用領域に対する参照を持っています。この関数はどこで実行されてもクローズドされます。
客先常駐（SES）は転職できないと言われる理由

## SESからでも転職はできます

SES企業から自社開発、社内SE、フリーランスなどへの転職はできないと言われるのをよく聞きます。
ですが僕は実際にSES企業から社内SEに転職できましたし、僕より前に転職していった人たちも見てきました。
僕自身は何か特別なスキルだとか経験を持っているわけではないんですが、それでも2社の求人に応募して、2社とも内定をもらうことができています。

実際にはSESから転職している人たちがいるのにも関わらず、転職できないと言われてしまうのはなぜでしょうか。

僕の経験やSES時代の同僚の話、その他いろいろと調べてみた結果、原因は以下のようなところにあると分かりました。

## 転職できないと言われる6つの理由

・SES以外の働き方が視野に入っていない
・転職活動をする時間がとれない
・環境の変化に対する不安
・スキルに対する不安
・客先常駐だと会社を辞めづらい
・自分に合った転職先を見つけられない

上記の原因を見て思うのは、どれも工夫や考え方次第で解決できることだということです。
転職したいと思っているのに転職活動に踏み切れなかったり、そもそも転職事態を諦めてしまってることまであります。

## 原因が分かれば対応できます

もしSESへの不満を抱えているとしたら、転職という選択肢を自ら潰してしまうのは、あまりに勿体ないことです。
誰が何と言おうと、SESからでも転職できるという事実は変わりません。
転職が全てではないですが、少なくとも何かしら行動を起こさない限り**今のままの状態が続いていくだけです。**


プログラムと同じように、問題の原因さえ分かれば対策することができるわけなので、あとは実際に行動を起こすかどうかの違いだけです。

上に書いた原因の詳細と対策方法はこっちの記事にまとめたので、参考にしてもらえると嬉しいです。
→[「SESから転職できない」は嘘？普通に客先常駐（SES）から転職できた話　問題点と解決策まとめ][1]
[1]:https://domona.info/can-change-jobs/
react 関数を子コンポーネントに渡せない

## 子コンポーネントに関数が渡せない


親コンポーネント

```
const searching = (e) => {
    console.log(e.target.value)
    setSearchName(e.target.value)
  }
 return (
        <BasicTextFields
        click={searching} 
        />
)
```

子コンポーネント

```
export default function BasicTextFields(props) {
  const classes = useStyles();

  return (
      <TextField className={classes.root}
      onChange={(e)=> {props.click.searching(e)}}
      id="outlined-basic" label="Search here" variant="outlined" />
    
  );
}
```

何回やっても `searching` 関数が実行されない

コンソール上のエラーは

```
BasicTextFields.js:21 Uncaught TypeError: props.click.searching is not a function
```

上手く関数が渡せていないよう


## 関数を渡す箇所の{ } を二重にした


``` 
const searching = (e) => {
    console.log(e.target.value)
    setSearchName(e.target.value)
  }
 return (
        <BasicTextFields
        click={{searching}}  (←ここ)
        />
)
```

多分 { } が一重だとただ文字列が渡されるだけになる

二重にすることで関数っていうのが認識されるんだと思う
Python3なら4行で単一換字式暗号化プログラムができた

(追記)fsdさんからコメントをいただき、それを参考にしたら、3行でコードが書けた。下のコメント欄に載せました。

(元記事)
　ITエンジニア向け転職・就活・学習サービスサイトのスキルチェック問題に挑戦するなかで、「単一換字式暗号」がでてきた。（単一換字式暗号については、ググってください。）

　最初に提出したコードは`for`、`if`を多用していたので、満足のいくものはでなかった。そこで何種類か考えたなかで、次のコードは初心者なりにうまくできたと思った。

```python3
plain  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz' # 平字
cipher = 'czQPHLsU rneVdEKfvyWSwIGCZqgoFBxtTiklDaOJRjNbAhmYMupX' # 暗字

# 換字表の作成
table = [i for i in range(128)]
for i in range(len(plain)):
  table[ord(plain[i])] = ord(cipher[i])

# 暗号化
text = ''
for c in input():
  text += chr(table[ord(c)])
print(text)


# 入力例
# This is a pen

# 出力例
# WikAqkAqgqjxJ
```

（復号するときは、7行目の`plain`と`cipher`を入れ替えて、`table[ord(cipher[i])] = ord(plain[i])`に変更する。）

　しかし、@KatsunoriNakamuraさんの[「Pythonのテキスト作りました」](https://qiita.com/KatsunoriNakamura/items/b465b0cf05b1b7fd4975)からテキストをダウンロードさせていただき、勉強するなかで、`str.maketrans()`と`str.translate()`を使えば、4行でコードが書けることに気づきました。自己流はだめですね。

```python3
plain  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz' # 平字
cipher = 'czQPHLsU rneVdEKfvyWSwIGCZqgoFBxtTiklDaOJRjNbAhmYMupX' # 暗字
table = str.maketrans(plain, cipher)  # 換字表
print(input().translate(table)) # 暗号化
```

（やはり、復号するときは、3行目の`plain`と`cipher`を入れ替えて、`table = str.maketrans(cipher, plain)`に変更する。）
Google Apps Script: HTTP APIを呼び出してJSONを取得する方法

Google Apps Script(GAS)で外部のHTTP APIを呼び出し、そのレスポンスからJSONデータを取り出す方法です。

GASで外部サイトにHTTPリクエストを送るには、`UrlFetchApp.fetch`を使います。その戻り値は`HTTPResponse`です。`HTTPResponse.getContentText`でレスポンスボディーが得られるので、それをJSONパースすることでデータが得られます。

```js
function fetchJson(url) {
    const res = UrlFetchApp.fetch(url);
    return JSON.parse(res.getContentText());
}
```

## 使い方

```js
function example() {
    const users = fetchJson("https://jsonplaceholder.typicode.com/users");
    console.log(users[0].name); //=> "Leanne Graham"
}
```
Power Automate Desktopの「Webサービスを呼び出します」アクションを使ってDomoのAPIを使ってみる（アクセストークンの取得）

#背景
弊社では、データをリアルタイムに集約・分析・見える化するデータ活用プラットフォームである[Domo(ドーモ)のコンサルティングサービス](https://alpcom.co.jp/products/domo/)を提供しております。
Domoはデータ接続、転送、整形加工、可視化、情報共有がオールインワン提供に加えて、企業向け管理機能も優れているので、例えば、どのようなデータを誰が、いつ作って、今現在どんな状態になっているのか、データ同士の連携など様々な切り口で分類、整理し、最新のツールらしくグラフィカルに綺麗に表示してくれます。ですが逆に、時々旧石器時代のように管理情報をEXCELにテキストでベタ書きした表が欲しくなります。
このような場合には[Domoが用意しているCLIツール](https://domohelp.domo.com/hc/ja/articles/360043437733-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9-CLI-%E3%83%84%E3%83%BC%E3%83%AB)を使えば良さそうなのですが、今回はCLIを使わず、前から気になっていたマイクロソフトの無料RPAツールであるPower Automate DesktopとDomo APIを使って、DomoのDataSet情報をEXCEL表に転記してみました。
今回はそのうち前半戦のアクセストークンの取得に関して手短になるように要点部分を記しています。[詳細な解説は弊社Webのブログ参照](https://alpcom.co.jp/blog/20211113/)をお願いいたします。

後半のDataset情報の取得からExcel転記に関してはコチラをご覧ください。
https://alpcom.co.jp/blog/20211115/

#Domo API仕様 オリジナル情報はコチラです
https://developer.domo.com/docs/authentication/overview-4#Important%20terms
要はDomoデベロッパーポータルからClient IDとClient Secretを取得して下記のようにリクエストすると、お約束のJSONが返ってくるので"access_token"を指定してアクセストークンのみを取得すれば良さそうです。

```
$ curl -v -u {CLIENT_ID}:{CLIENT_SECRET} "https://api.domo.com/oauth/token?grant_type=client_credentials&scope={SCOPE}"
```

#curl表記をPower Automate Desktopではどのように指定するのか
各社絶賛提供中のPRAには表現は異なりますが、HTTPプロトコルをそのまま使える命令が「普通に」実装されています。Power Automate Desktopでは、その名も「Webサービスを呼び出します」です。いろいろ指定の仕方はあると思うのですが、下記のような指定で"access_token"を含むJSONが返ってきました。

1.URL：https://api.domo.com/oauth/token?grant_type=client_credentials&scope=data workflow audit buzz user account dashboard
2.メソッド：GET
3.受け入れる：application/json
4.コンテンツタイプ：application/json
![Webサービスを呼び出しますの指定](https://alpcom.co.jp/cms/wp-content/uploads/webServive1.png "Webサービスを呼び出しますの指定")
URL欄に書くscopeの指定は
scope=data%20workflow%20audit%20buzz%20user%20account%20dashboard
ではなく
scope=data workflow audit buzz user account dashboard
でした。
![CLIENT IDとSECRET指定](https://alpcom.co.jp/cms/wp-content/uploads/webServive2.png "CLIENT IDとSECRET指定")
「詳細」をクリックすると上図が表示されますので、「HTTP認証」を使えるようにして、事前にDomoデベロッパーポータルから取得したClient IDとClient Secretを指定します。
Client IDとClient Secretの取得や、その他のPower Automate Desktop設定詳細は[弊社Webのブログ参照](https://alpcom.co.jp/blog/20211113/)をお願いいたします。
#Domo（ドーモ）とは
ここまで読んでいただきありがとうございます。Power Automate Desktop繋がりで、この記事を読んでいただけていると想定していますので「Domoって何よ？」との方向けに3分程度の手短な紹介ビデオを作っておりますので、是非ご覧ください。

Domoのご紹介-第1回 経営から現場まで、ビジネスユーザーに最適なDomoのご紹介
https://youtu.be/ZjfA6ODnR7g
【JavaScript】関数とオブジェクト⑳　ディスクリプター



#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/558337083753dd4507ed

#目的

* 関数とオブジェクトについての理解を深める

#本題
###1.プロパティーとディスクリプター


下記の記事も参考にさせて頂きました。
ディスクリプターとは「裏設定」みたいなもの？？

https://javascript.keicode.com/lang/object-object-property-attributes.php#2-1



| プロパティの設定値||
|:-:|:-:|
|  value |  値 |
| configurable  |  設定変更可能性 |
|  enumerable |  列挙可能性 |
| writable  | 値の変更可能性  |

####例1


```js
// オブジェクトを１つ用意
const obj = {prop: 0};

// ディスクリプターを確認
// 確認するためにgetOwnPropertyDescriptorというメソッドを使用
// 第一引数にオブジェクトの名前,第二引数にプロパティの値を入れる
const descriptor = Object.getOwnPropertyDescriptor(obj, "prop");
console.log(descriptor);
````

実行結果を出力すると下記のようになります。

````Console.
{value: 0, writable: true, enumerable: true, configurable: true}
configurable: true
enumerable: true
value: 0
writable: true
````

オブジェクトリテラルで記載したときはすべてtrueで返ってくる

####例2

````js
// const obj = {prop: 0};
// 空のオブジェクトを渡してみる
const obj = {};
// definePropertyを使う
// 第三引数には設定値が必要
Object.defineProperty(obj, "prop", {
  value : 0
})

const descriptor = Object.getOwnPropertyDescriptor(obj, "prop");
console.log(descriptor);
`````

実行結果を見てみると

`````Console.
value: 0, writable: false, enumerable: false, configurable: false}
configurable: false
enumerable: false
value: 0
writable: false
`````

valueは0だが、他がfalseとなっている

* configurable: false　→　設定の変更不可
* enumerable: false →　列挙不可
* writable: false　→　値の変更が不可

実際に値の変更が不可であるかコードで確認する

````js
const obj = {};
Object.defineProperty(obj, "prop", {
  value : 0
})
// 下記のようにしてもvalueは0のまま
obj.prop = 1;
// 出力結果も0のままとなる
console.log(obj.prop);
````

このままだと、エラーにならず開発者が気づきにくい
→　use strictというキーワードを先頭に記述すると設けるとエラーが発生する

####例3

writableをtrueにしてみる

```js
"use strict"

const obj = {};
Object.defineProperty(obj, "prop", {
  value : 0,
  // 変更を許可
  writable: true
})

obj.prop = 1;
// 出力結果が1になる
console.log(obj.prop);
````

####例4

enumerable、configurableをtrueにする

`````js
"use strict"

const obj = {};
Object.defineProperty(obj, "prop", {
  value : 0,
  writable: true
})

// もう一個definePropertyを用意
Object.defineProperty(obj, "prop", {
  // エラーになってしまう　
  enumerable: true
})

// configurableによって値を変更（削除を試みてもエラーとなる）
delete obj.prop;

obj.prop = 1;
console.log(obj.prop);
`````

変更後

```js
"use strict"

const obj = {};
Object.defineProperty(obj, "prop", {
  value : 0,
  writable: true,
　　　　// 変更を許可
  configurable: true
})

delete obj.prop;

// obj.prop = 1;
// 上記をコメントアウトするとdeleteが働いて,undefinedと表示される
console.log(obj.prop);

````



今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
* [JavaScriptのオブジェクトリテラルについて現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/36682)
The `development` database is not configured for the `development` environment.の解決法

HerokuにpushしてからHeroku openした時に出てきたエラーです。

エラー
---
```
The `development` database is not configured for the `development` environment.
```

原因
---
database.ymlのインデントが間違えているから

解決
---
```ruby:database.yml
# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
#   gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
#   gem 'mysql2'
#
# And be sure to use new-style password hashing:
#   https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db

development:
  <<: *default
  database: rails-front-demo-db

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: rails-front-demo-db
  host: <%= ENV.fetch("APP_DATABASE_HOST") { 'db' } %>

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
#   DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
#   production:
#     url: <%= ENV['MY_APP_DATABASE_URL'] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
  <<: *default
  database: <%= ENV['APP_DATABASE'] %>
  username: <%= ENV['APP_DATABASE_USERNAME'] %>
  password: <%= ENV['APP_DATABASE_PASSWORD'] %>
  host: <%= ENV['APP_DATABASE_HOST'] %>
```
自動保存の設定のためいつの間にかインデントが変わっていることがあると学びました。
インデントを綺麗にしたらエラー解決しました。
javascript 配列の要素を足す方法

```
const items = [1,2,3,4,5]
```
上みたいな配列があって、
中の要素を足したい場合

```
items.reduce((a, b)=> a+b)
　⇒　15
```
`reduce` メソッドを使うと要素を足してくれる

挙動は少しわかりづらいけど
引数を２つとって
第一引数には累積値が
第二引数には要素が入るよう

配列に対して使うメソッド

要素全てに対して行うので
`map` メソッドとか `filter` メソッドとかに近い

`map` や `filter` との違いは
返り値が配列かどうか。

`reduce` メソッドの返り値は単一に対し、
`map` メソッドや `filter` メソッドは返り値が配列

ちなみに

```
const st = ["a","b","c"]
st.reduce((a, b) => a+b )
　⇒　'abc'
```


こうやって文字列の連結も出来る

これに関しては

```
const st=["a","b","c"]
st.join("")
　⇒ "abc"
```

上のように `join` メソッドと同じような挙動

ただ `join` メソッドの場合は
数値型でも

```
 const items = [1,2,3,4,5]
items.join("")
　⇒　'12345'
```
上みたいになるので
多分計算は出来ない
Google Apps Script: シートの最終行にレコードを追加する方法

Google Apps Scriptでスプレッドシートの最終行にデータを追加する方法を説明します。

## 最終行にデータを挿入する関数

```js
function addRecord(sheet, rowValues) {
  const lastRow = sheet.getLastRow();
  const range = sheet.getRange(lastRow + 1, 1, 1, rowValues.length);
  range.setValues([rowValues]);
}
```

`Sheet`のAPIには最終行にデータを追加するメソッドがないので、上のような関数を作っておく必要があります。

## 使い方

最終行のA列〜C列にそれぞれのセルに1、2、3を追加する例です。

```js
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
addRecord(sheet, ["1", "2", "3"]);
```

`rowValues`の型は`string[]`です。
chromeで機能を有効化/無効化をカスタマイズする

数あるChromeの標準機能ですが自分で有効無効を選択できるのを知らない人も多いのではと思い共有します。

[chrome://flags/](chrome://flags/)
今回は、スマホのChromeにあるようなReadingListをPCでも使用したいので検索タブでさがします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941408/956aa4e6-ace3-a011-4e54-b70429fb1131.png)

あった。有効にしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941408/721aef21-a52b-8385-1699-13a42c00b809.png)

Chromeが一度自動で閉じ、ウィンドウが回復すると、画面右端にReadingListが出現します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941408/3c0125f2-50ce-007d-1fe9-531f4d5203f7.png)

あとでみたいページを追加します。
やっぱりブックマークより手軽でまとめておけるので便利ですね。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941408/b91e97b9-ce49-74d2-1c8b-06bbc41bffdd.png)

私はデフォルトがReadingListがない状態でしたが、逆にもともとあって「ブックマークの数がが限られるしいらないよ」という方は無効にするというように自分でカスタムすることで作業効率が上がるのではと思います。以上！
map メソッドのユニークなキーがないと出るエラー

コンソール上で以下のエラー

```
index.js:1 Warning: Each child in a list should have a unique "key" prop.
```

これは map メソッドで作られる要素に
ユニークなキーがないとでるエラー

しかし

```
 [...Array(12).keys()].map(i =>
              <ItemWrapper >
                <Skeleton  key={i}　variant="rect" width={450} height={180} />
              </ItemWrapper>                
            )
```
ついてますが。は？
ってなった

___

どうやら

```
 [...Array(12).keys()].map(i =>
              <ItemWrapper key={i} >
                <Skeleton variant="rect" width={450} height={180} />
              </ItemWrapper>                
            )
```
一番外側の要素がユニークである必要があるそう
SalesforceCLIのバージョン更新

VScodeで組織に接続しファイルを取得しようとしたら。。


こんなエラーがでました
```No source backed components present in the package```


「？？？接続もできたし何がいけないんだ。。？？？」と調べていくと、
どうやらSalesforce　CLIのバージョンが最新じゃないとでるようですね

自動更新してくれ
※デフォルト設定だと自動更新があるはずなので頻出ではないエラーだとは思います。

ということでターミナルでさくっとアップデートしていきます
現在のバージョンを確認します

```Apex:SalesforceCLIのバージョン確認
sfdx --version
```

```Apex:SalesforceCLIとプラグインの最新バージョンをインストール
sfdx update
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941408/ae0058c1-7ae1-7a2c-2452-516f14d19770.png)

updateが開始されます。所要時間は長くても一分程度。
接続も完了していて今まで作業できていたのになんかデプロイできないぞ？ってときはバージョンが最新かどうかも確認してみてください。
Google Spreadsheet: Google Apps Scriptを定期実行する

この投稿ではGoogle Apps Scriptを定期実行する方法を紹介します。

## Google Apps Scriptとは

Google Apps Scriptは、Google SpreadsheetやGoogle Docsと連携して動くプログラムです。Excelのマクロのような存在です。JavaScriptで書けて、Spreadsheetを参照・変更したり、外部のウェブAPIを呼び出したり、簡単なHTTPサーバーも作れる便利なやつです。

## Google Apps Scriptで設定できるスケジュール

Google Apps Scriptでは次のスケジュール設定が行えます。

- 日時(YYYY-MM-DD HH:MMで指定)
- N分おき (1分、5分、10分、15分、30分から選択)
- N時間おき (1時間、2時間、4時間、6時間、8時間、12時間から選択)
- 1日1回 (24時間のうち何時ごろ実行するかは選べる)
- 曜日 (月火水木金土日から選択した上で、時間帯を選ぶ)
- 毎月 (1日〜31日の間から選択した上で、時間帯を選ぶ)

このようにそこそこ柔軟なスケジュール設定が行えます。

## Google Apps Scriptを定期実行する方法

Google Apps Scriptはcronのように時間指定で起動できます。その設定方法を順を追って説明します。

まず、スプレッドシートの「拡張機能」→「Apps Script」を開きます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/1b310cd5-35ac-0b0e-d89b-178cc6970eec.png)

エディタが開いたら、`myFunction`の実装に`console.log(new Date());`と書き、保存します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/2d2fbf78-03a0-3a2a-6e7b-efc17f4e0003.png)

続いて、「トリガー」ページを開き「トリガーを追加」ボタンを押します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/c7f44dd1-4e7f-a09e-cb7e-529d657a9937.png)


トリガー追加のモーダルが出るので、次のとおり設定します。

1. 実行する関数を選択: myFunction
1. イベントのソースを選択: 時間主導型
1. 時間ベースのトリガーのタイプを選択: 分ベースのタイマー
1. 時間の間隔を選択(分): 1分おき

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/df13afe5-6aab-529f-f84d-944bdab03ac4.png)

設定したら「保存」を押します。これで定期実行の設定が完了です。

## 実行履歴を見る

設定したトリガーが期待通りに動いているかは「実行数」ページで確認できます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/4ecd7032-69f2-1fcd-52fc-69c605c26016.png)

1回実行されるごとに1つ履歴が増えます。各履歴を開くと、`console.log`の結果も確認できます。`myFunction`では現在時刻をロギングするようにしていたので、上の図では現在時刻が表示されています。
djangoのmiddlewareについてざっくりまとめる

今回のお題
-
今回はdjangoのmiddlewareについてまとめます。

最近middlewareについて学習する機会があったのですが、なぜそのように記述するとmiddlewareが動作するのかが理解できませんでした。

原理を解っていた方が応用も効きますし覚えるのも楽だと思うので、今回はmiddlewareの基礎的な部分についてまとめます。

目次
-

- middlewareとは
- middlewareの書き方(関数ベース）
- middlewareの書き方(クラスベース）
- middlewareの登録

middlewareとは
-
まずはmiddlewareそのものの定義を確認しておきます。

middlewareとは「リクエストの前後に実行される共通の処理をまとめたもの」を指します。

djangoではリクエストに応じて様々な関数（もしくはテンプレートビュークラス）が呼び出され、それらの場合分けは`urls.py`と`views.py`によって行われています。

つまり、リクエストの内容によって実行される関数は変わります。

それに対してどのようなリクエストに対しても実行される処理が書かれているのが`middleware`というわけです。

では、概要がわかったところでmiddlewareを書いていきます。

middlewareの書き方(関数ベース）
-
middlewareの書き方には、関数ベースとクラスベースがあります。

ちょうどビューと同じですね。

ビューの関数ベースとクラスベースについては以下をどうぞ。

https://qiita.com/keishi04hrikzira/items/f7babfee873cae03112d

では、middleware.pyというファイルをアプリケーション側に作成し、中身を書いていきます。

```python:middleware.py
def factory(get_response):
  # 処理1
  def middleware(request):
    # 処理2
    response = get_response(request)
    # 処理3
    return response
  return middleware
```
まずmiddleware全体の構造ですが、`middlewareファクトリー`と呼ばれる関数で中央の`middleware関数`本体がラップされ、中心には`response = get_response(request)`という一文があります。

そしてそれらを境界として`処理1 ~ 3`とコメントをつけた領域があります。

これらの役割は以下の通りです。

- 処理１：サーバー起動時に一度だけ行いたい処理を記述
- 処理２：レスポンスを実行する前に行いたい処理を記述
- 処理３：レスポンスを実行した後に行いたい処理を記述

具体例は以下（実用性は全く考慮していません）。

```python:middleware.py
def factory(get_response):
  # 処理1
  print("サーバーが立ち上がりました")
  def middleware(request):
    # 処理2
    print("リクエストが行われました")
    response = get_response(request)
    # 処理3
    print("レスポンスが完了しました")
  return middleware
```

では、次にクラスベースの書き方も見ていきましょう。

middlewareの書き方(クラスベース）
-
クラスベースのmiddlewareは以下のように記述します。

```python:middleware.py
class Middleware:
  def __init__(self, get_response):
    # 処理1
    self.get_response = get_response

  def __call__(self, request):
    # 処理2
    response = self.get_response(request)
    # 処理3
    return response
```
クラスベースの場合には、`__init__`メソッドと`__call__`メソッドを定義してその中に処理を書きます。

ちなみに`__init__`メソッドはサーバー起動時に一度だけ呼ばれ、`__call__`メソッドはリクエストのたびに都度実行されます。

middlewareの登録
-
上記の作業でmiddlewareの作成は完了しました。

ただ、これだけではプロジェクトから存在を認識されていないので設定ファイルに登録する必要があります。

```settings.py
MIDDLEWARE = [
    # 既存のmiddleware
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    # 追加
    "xxx.middleware.factory", # 関数ベース
    # クラスベースの場合には以下のように記述
    # " xxx.middleware.Middleware", # xxxはアプリケーション名
]
```
もともといくつかのmiddlewareが登録されておりこれらは何もしなくても実行されるようになっています。

このmiddlewareリストに先ほど作成したものも追加してあげることで、初めてmiddlewareが実行されるようになります。

余談ですが、この部分におけるmiddlewareの登録順序は実際の実行順序と関わっているようです。

具体的にいうと、リクエストが行われた際には上から下に、逆にレスポンスを返した後には下から上にという順序で実行されます。

終わりに
-
というわけで、以上がmiddlewareのお話でした。

もちろん今回の内容は超基本的なもので、まだまだ応用的な部分はたくさんあります。

そちらについては気が向いたらまとめようかなと思います。
WPFでグリッドを表示してマウスで変更可能にする方法

#備忘録

```xml
<Grid>
 <Grid.ColumnDefinitions>
  <ColumnDefinition Width="*" MinWidth="200"/>
  <ColumnDefinition Width="*" MinWidth="200"/>
  <ColumnDefinition Width="*" MinWidth="200"/>
 </Grid.ColumnDefinitions>
            
 <GridSplitter Grid.Column="0" VerticalAlignment="Stretch" HorizontalAlignment="Right" Width="4"/>
 <GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Right" Width="4"/>
            
 <Grid Grid.Column="0">
 </Grid>
 <Grid Grid.Column="1">
 </Grid>
 <Grid Grid.Column="2">
 </Grid>
</Grid>
```


#参考
https://y-uti.hatenablog.jp/entry/2018/10/07/213204
HTMLスーパー初心者、Anime.jsを使ってみる

ライブラリを使うにあたり、めちゃめちゃ手前でつまずいたので備忘的に記録する。

# Anime.jsとは
HTMLで画像やら文字やら記号やらを動かすことに特化したライブラリ（ざっくり）。
公式サイト（[https://animejs.com/](https://animejs.com/)）を見ると、めちゃめちゃエグイ動きをする。


# 問題発生：スーパー初心者、ライブラリのインストールの仕方が分からない
使いやすいと噂のライブラリを使いたいがライブラリを使うために、そもそも何をどうしたら使える状態になるのかが分からない。
公式サイトのダウンロードボタンを押してダウンロードしても、めちゃめちゃ丁寧に書かれているサイトを見ても、何をどうするのかがまじで全然わからない（絶望）。何故ならスーパー初心者だから。


# 解決策：スーパー初心者、jsDelivrからコードを取得する

https://www.jsdelivr.com/package/npm/animejs

jsDelivrからHTMLに埋め込む用のコードが取得できるという情報を入手。
一番上で「lib/anime.min.js」でCopyHTMLを実行し、コードを取得。
このコードをHTMLのコード内に記載すれば、ライブラリが使える。

![animejs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122226/f447c23a-029e-ad14-13d8-42fff1c5811e.png)



# 実装：スーパー初心者、サンプルコードを使う
初心者は**コードを読むな、コピペしろ。**
公式サイト（[https://animejs.com/](https://animejs.com/)）の一番下にある、「Documentation」「Examples」からいい感じのものを拝借する。
モーションとコードがセットになっているので、スーパー便利。
特に「Moving letters」は無限に遊べる。

![animejs_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122226/d852c99f-e14a-a12c-7804-eccb0e68eaa9.png)
Rails on ECS Fargateでタスクロールを使ってS3にアクセスする

# 背景

FargateコンテナからS3バケットにアクセスしたかったのだが、アクセスキーをコンテナに入れるのはアンチパターン的な話を聞いていたので、AWSオススメ的にECSのタスクロールを使ってアクセスできるように構成したかった。
しかしActiveStorageの本家サイトを見ても、アクセスキーを設定する方法しか紹介されておらず、いろいろ調べたのだがドンピシャの情報が見つからず、ドハマリしたので防備録を書く。

##　通常

`config/storage.yml`に以下のように書くようになっている。

```config/storage.yml
amazon:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  region: ""
  bucket: ""
```

`access_key_id` `secret_access_key`を省略すれば勝手にタスクロールを利用してつながってくれると思い、以下のように設定した。

```config/storage.yml
amazon:
  service: S3
  region: "ap-northeast-1"
  bucket: "myBucket"
```

だが、さっぱりつながらない。`Access Denied`となる。

## コンテナにログインして調査

コンテナにログインして

```sh
$ rails c
> s3 = Aws::S3::Client.new
> s3.list_objects(bucket: 'myBucket')
```

とすると、やっぱり`Access Denied`となる。タスクロールに`S3FullAccess`をアタッチしてもダメ。

## 結論

[Railsガイド](https://railsguides.jp/active_storage_overview.html)には以下のように書かれている。

> 環境変数、標準SDKの設定ファイル、プロファイル、IAMインスタンスのプロファイルやタスクロールを使いたい場合は、上述のaccess_key_id、secret_access_key、regionを省略できます。Amazon S3サービスでは、AWS SDK documentationに記載されている認証オプションをすべてサポートします。

微妙に抽象的なことしか書いていないのでRailsガイドがいつまで経っても苦手なのだが、結論を言うと以下の方法で解決した。

`config/initializars/aws.rb`を作成し、以下のように書く。

```aws.rb
# Configure AWS SDK for Ruby.
if ENV['AWS_ACCESS_KEY_ID'].blank? && Rails.env.production?
  Aws.config.update({ credentials: Aws::ECSCredentials.new })
end
```

`Aws::ECSCredentials`というのは、タスクロールから認証情報を生成してくれるクラスで、`aws-sdk`に含まれている。
タスクロールは自動的には利用してくれず、上記のように明示的に「タスクロールを使用してAWSリソースにアクセスするよっ！」とRubyで宣言しなければならないらしい。

ActiveStorageの解説は、S3やAzureStorageといった様々なストレージサービスを利用できる様になっているせいか、個々のストレージサービスに関する深堀りした説明がちょっと不足しているような気がする。
jQueryでクリックイベントが効かない時の対処法と連続する要素のどれがクリックされたか識別する方法

# はじめに
jQueryでDOM操作をしているとき、appendやprependで挿入された要素の扱いに戸惑ったので調べたことをここにメモとして残します。

実現したいことは下記2点です。

①挿入された要素にクリックイベントを付与すること
②連続する要素をクリックした際、要素を識別すること

# まず通常のクリックイベント
通常、セレクタを指定してclickもしくはonメソッドを用いる。

```main.js

$(".btn").click(function(){
  console.log("クリック");
}

```

通常はこれで良いのですが、appendやprependで挿入された要素にイベントを付与する場合、通常の記述ではうまく動作しない時があります。

その解決策を次で記載していきます。

# ①挿入された要素にクリックイベントを付与する
挿入された要素にイベントを付与する場合は先程のセレクタの位置にdocumentを指定します。そして、onの中にイベント名とセレクタを記載します。

```main.js

$(document).on("click", ".btn", function(){
  console.log("クリック");
}

```

# ②連続する要素をクリックした際、要素を識別すること
時にリストなどの連続するHTML要素では、何番目の要素がクリックされたか識別するのが難しい場合があります。こちらではその識別方法を紹介します。

<br>

まずこちら、一つ準備が必要です。

それは、生成されるHTML要素に識別可能な個別idを仕込んでおくことです。私はFirestoreでのメモアプリ作成時にこの方法を用いたのでFirestoreのドキュメントIDを個別idとして指定しました。

<br>

下記コードはその事例です。

Firestoreのとあるコレクションからオブジェクトを取得、makeMemoCard関数の引数に渡してそれをappendするHTMLタグ内でbuttonのidとして埋め込みをしています。


```main.js
db.collection("collection")
  .onSnapshot((snapshot) => {
    snapshot.docChanges().forEach((change) => {
      if (change.type === "added") {

         //firestoreからデータを取得
         const data = change.doc;

         //表示用のhtml要素を作る
         const memos = makeMemoCard(data);
       }
     });
  });

makeMemoCard(data) {
 const memos =
 '<li class="memo-item">'
 + '<p class="memo-item-textarea">' + data.data().text + '</p>'
 + '<button id="' + data.id + '" class="delete-btn">×</button></li>';

 return memos;
},

```

次にクリックされた要素を識別するため個別idを取得する方法です。

先程紹介した挿入された要素にクリックイベントを付与する方法を用います。そして、取得するセレクタ内にthisを指定してクリックした要素を特定、attrメソッドでその要素のidを指定すれば先程埋め込んだ個別idを取得することができます。

```main.js

$(document).on("click", ".btn", function(){
  const id = $(this).attr("id");

  //クリックした要素のidがコンソール上に出力される
  console.log(id);
}

```

このように個別idが取得できれば、その要素のみ編集したり削除したりすることが可能です。シンプルな方法ですが意外と初学者が詰まりやすいところなのではないかと思い今回記事にさせていただきました（自分が詰まった）。少しでも学習の助けになれば嬉しいです。
HTMLとJSXを混同するな！React初心者がハマるポイント。

Reactを勉強している時に気をつけるポイントとして強く思ったのが…
HTMLとJSXを混同しないことです！

:::note alert
JSXはHTMLを知っている人であればある程度かけてしまうので、HTMLがかける人はHTMLとJSXは全く別物ぐらいに意識する
:::

そうすることでスムーズに学習が進みます。
僕は恥ずかしいことにそれに気が付かず…

- Reactの仕様でエラーが出ているのかな？
- React-Hook-Formの書き方難しい！

と勝手に沼にハマっておりました…

:::note warn
ここより記述されるコード例はreact-hook-formを利用した記述であることを前提とします。
:::

例えば下記のような記述（詳細割愛）

```js
<input id="spring" type="radio" value="1" checked {...register("season", { required: true })} />
```

正しい記述は下記の通りです。

```js
<input id="spring" type="radio" value="1" defaultChecked {...register("season", { required: true })} />
```

HTMLでは`checked`ですが、JSXでは`defaultChecked`となります。
表示はされるのですが、挙動がおかしくなります。
おかしくなるというのはクリックしてもクリックした項目がチェックされません…

僕がドキュメントの一部を見逃していたのが悪いのですが…
初学者でHTMLをかじっている人は特にお気をつけください。

https://reactjs.org/docs/uncontrolled-components.html#default-values
ViewModelProvider.Factory を省略する方法

# ■ 概要
[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel) にコンストラクタ引数が存在する場合に [ViewModelProvider.Factory](https://developer.android.com/reference/android/arch/lifecycle/ViewModelProvider.Factory) の実装を毎回作るのがめんどくさいので、それを省略する。

# ■ Before
こういうのがめんどくさい

```kotlin
// Factory を呼ぶのがめんどい。
// Lazy で受け取る必要性がない。
val viewModel by viewModels<XxxActivityViewModel> { Factory(arg1) }

// Factory を実装するのがめんどい。
class Factory(private val arg1: String) : ViewModelProvider.Factory {
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T =
        XxxActivityViewModel(arg1) as T
}
```

# ■ After
こんな感じでらくちん。

```kotlin
val viewModel = viewModels(::XxxActivityViewModel, arg1)
```

# ■ ライブラリ的なもの
```kotlin
import androidx.activity.ComponentActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProvider.Factory
import kotlin.reflect.KFunction1

// コンストラクタ引数が1つの場合の関数。
// - 静的な型チェックをしたほうがいいと思うので、引数分だけ関数を作るのがよさげ。
// - ()->Unit の lambda 1 つで済ませる方法のほうが万能だが、おいら的には微妙。
//   lamda の括弧が目に入った瞬間に脳のリソースが多めに消費されるような気がする。
// - 以前は Lazy<VM> を返すものを作ってみたが、そもそもライフサイクルのある Activity や
//   Fragment の member として配置するようなバギーなことをさせないためにも、あえて現物を返すようにした。
@Suppress("UNCHECKED_CAST")
inline fun <reified VM : ViewModel, A1> ComponentActivity.viewModels(factoryFunction: KFunction1<A1, VM>, arg1: A1): VM {
    val factory = object : Factory {
        override fun <VM : ViewModel?> create(modelClass: Class<VM>): VM = factoryFunction(arg1) as VM
    }

    return ViewModelProvider(viewModelStore, factory).get(VM::class.java)
}
```

# ■ まとめ
- [ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel) のコンストラクタ引数が存在する場合で、[ViewModelProvider.Factory](https://developer.android.com/reference/android/arch/lifecycle/ViewModelProvider.Factory) の実装が単純にコンストラクタを呼んでいるだけなのであれば、こんな感じでやっても良さそうな気がする。
- Lazy で返せるようにしておくと、Activity の member として `val viewModel` のように定義される可能性が増す。onCreate() 内部で初めてアクセスされる分には問題なく動作するが、別の member 初期化時に viewModel を取得してしまったりして onCreate() 以外の箇所で ViewModel の instance が生成されるようなことが起き得る。また、intent の情報等をコンストラクタに渡す必要があるような場合にコンパイルエラーとして検出できないバグになるようなこともある。
- 引数を `()-> Unit` とすれば lambda 1 つで済ませられる[^1]が、おいら的には微妙。lamda の括弧が目に入った瞬間に脳のリソースが多めに消費されるような気がする[^2]。
- vararg と reflection を使って引数を可変にすることもできるけど、静的に型チェックできたほうが保守性が高いと思うので、引数分だけ関数を作るのが無難な気がしている今日この頃。

ということで、おしまい。

[^1]: どのようなファクトリであろうが関数1個で対応できるので。
[^2]: 純粋においらの主観です。
LPIC102試験直前見直し用チートシート(ユーザーインターフェースとデスクトップ)

# はじめに
LPIC102(ユーザーインターフェースとデスクトップ分野)で問われやすいコマンドや要点などをまとめた記事です。
寝る前の10分でざっと読んで各単元の復習に活かすも良し、試験直前に読んで最後の詰め込みに使うも良しです。
このシートがLPIC102を受けられる方の支えになれば幸いです。

# チートシート

**コマンドとオプション**

| コマンド | 説明 |
|:-|:-|
|xhost|XクライアントがXサーバを利用できるよう許可を与える<br>+：すべてのホストがXサーバに接続することを許可<br>- ：Xサーバ接続許可リストによるアクセス制御を有効化<br>+ホスト名：指定したホストを許可リストに追加(+は省略可)<br>-ホスト名 ：指定したホストを許可リストから削除<br><font color="red">記号とホスト名の間にはスペースを入れないこと</font>|
|xauth|Xサーバへの接続に使用される資格情報の表示、クライアント認証ファイルの編集を行う|
|startx|CUI環境からGUI環境へ移行する<br>CUI環境(ランレベル3)で実行することでX Window System(GUI)が起動|

**xorg.confの主なセクション**

| セクション | 説明 |
|:-|:-|
|Files|フォントやカラーデータベースファイルへのパス |
|Module|ダイナミックモジュールの設定 |
|InputDevice|キーボードやマウスなどの入力装置の設定|
|Device|ビデオカードの設定|
|Monitor|モニターの設定|
|Screen|ディスプレイの色深度や画面サイズの設定|
|ServerLayout|入出力デバイスに関する設定|

**x関連のディレクトリやファイル**

| ディレクトリ・ファイル名 | 説明 |
|:-|:-|
|/etc/X11/xorg.conf.d|X.orgの設定を保存するディレクトリ|
|/etc/X11/xorg.conf|X.orgの設定ファイル|
|~/.xsession-errors|X Window Systemのエラーが出力|
|/etc/inittab|Linux起動時のデフォルトランレベルを指定|

**/etc/X11/xdmにある関連ファイル**

|ファイル名 | 説明 |
|:-|:-|
|xdm-config|XDMの設定ファイル|
|Xresources|XDMログイン画面のデザイン設定|
|Xsetup_0|XDMログイン画面表示前に実行されるスクリプト<br>カラー設定や背景(壁紙)の指定が可能|
|Xsession|XDMのログイン後に実行されるスクリプト|

**代表的なディスプレイマネージャ**

|ディスプレイマネージャ|特徴|
|:-|:-|
|XDM|X.Org標準のディスプレイマネージャ|
|GDM|GNOMEで利用|
|SDDM|KDE Plasmaで利用|
|LightDM|Ubuntuで標準採用|

**代表的なウィンドウマネージャ**

|ウィンドウマネージャ|特徴|
|:-|:-|
|twm|最小限の機能を備えた基本タイプ|
|FVWM|軽快でシンプル|
|Enlightenment|高度なカスタマイズが可能|
|Fluxbox|軽快でカスタマイズ性が高い|


**代表的なデスクトップ環境**

|デスクトップ環境|特徴|
|:-|:-|
|GNOME|Red Hat Enterprise Linux, CentOS, Fedora, Ubuntuの標準デスクトップ環境|
|KDE Plasma|openSUSE, Slackware, Kubuntuの標準デスクトップ環境
|Xfce|上記2つに比べてメモリやCPUの消費量が少なく軽量|


**リモートデスクトップ関連用語**

|用語|説明|
|:-|:-|
|VNC|Virtual NetWork Computing<br>クロスプラットフォーム対応のリモートデスクトップソフトウェア|
|RDP|Remote Desktop Protocol<br>Windows標準のリモートデスクトッププロトコル|
|SPICE|Simple Protocol for Independent Computing Environment<br>4画面までのマルチモニタやネットワーク経由でのUSB転送など、VNCがサポートしていない多くの機能をサポートする画面転送プロトコル|
|XDMCP|X Display Manager Control Protocol<br>ディスプレイマネージャをネットワーク越しに利用できるプロトコル<br>通信経路が暗号化されていないので、SSHを介して利用する必要がある|

**アクセシビリティ**

|設定項目|説明|対象|
|:-|:-|:-|
|スティッキーキー|修飾キー(Ctrl, Shift等)が押されたままの状態になる|複数のキーを同時に押せない人|
|スローキー|キー押下を認識する時間を調整|正確にキーを入力できない人|
|リピートキー|所定の時間だけキーが押されていなければキー入力が繰り返されない|直ぐにキーを離せない人|
|バウンスキー|素早く何度も同じキーが入力された場合に認識しない|同じキーを何度も押してしまう人|
|トグルキー|CapsLockキーやNumLockキーのON/OFFをビープ音に違いで表現する|LEDランプの点灯で認識できない人|
|マウスキー|マウスの代わりにテンキーでポインタを移動|マウスを扱うのが困難な人|

:::note
スローキーとリピートキーはいずれも「キー押下を認識する秒数を設定する」点で共通しているが、目的が異なるため区別をつけておくこと
スローキー：キーの押し間違い防止 (すぐ手を離せば認識されなくなる)
リピートキー：意図せぬ繰り返し入力を防ぐ (kkkkkみたいな誤入力が発生しなくなる)
:::

# 一問一答
<details>Wayland<summary>X Window Systemに代わる新しい仕組みを何というか</summary></details>
<details>1. startxコマンド<br>2. xinitコマンド<br>3. ~/.xinitrc<br>3. /etc/X11/xinit/xinitrc (~/.xinitrcが存在しない場合)<br>→ ウィンドウマネージャなどのXクライアントが起動<summary>ランレベル3からstartxコマンドを実行した際の流れを答えよ</summary></details>


# LPIC102対策用チートシート リンク集
[シェルとシェルスクリプト](https://qiita.com/kjstudy_englife/items/778bf02ef6d16dfd120d)
[管理タスク] (https://qiita.com/kjstudy_englife/items/dd01a5ad684ea1cc9194)
[必須システムサービス] (https://qiita.com/kjstudy_englife/items/e7c587744b486f0f90f7)
STM32L010のPA9に37KHzを出力する HAL


目的
クロックのテスト


![o_con80.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c7f49b4f-0b90-c218-6e18-dec4aa5f2a6d.jpeg)




いろいろスッキリ改良


```c++



/* STM32L010F6P6  -> Mbed NUCLEO-L011K4 program by caa45040 */

#include "mbed.h"

DigitalOut myled(PA_4);

//メインプログラム
int main()
{
    //37KHzのRC発振器を起動する。
    PWR->CR |= PWR_CR_DBP;    
    RCC->CSR |= RCC_CSR_LSION; //RCC->CSR=RCC->CSR | 1; //LSION SET

    //PA9にSYSCLKを出力
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    //HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1);
    //HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO1SOURCE_LSI, RCC_MCODIV_16); //約2KHz
    HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO1SOURCE_LSI, RCC_MCODIV_1);
    
    //無限ループ
    while(1) {

        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);

    }//while

}//main





```




改良前

```c++


/* STM32L010F6P6  -> Mbed NUCLEO-L011K4 program by caa45040 */

#include "mbed.h"

DigitalOut myled(PA_4);

//メインプログラム
int main()
{
    //クロックの初期化
    HAL_RCC_DeInit();



  //16mhz 37khz
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);




    //PA9にSYSCLKを出力
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    //HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1);
    HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO1SOURCE_LSI, RCC_MCODIV_1);
    

    //無限ループ
    while(1) {

        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);

    }//while

}//main




```
Boot Camp Update をローカルに保存する。


### Boot Camp Update (ドライバ更新インストーラー)をローカル保存する手順です。

なんでこんなことを書いているか？というと、2021年6月に、Apple T2チップを搭載したMacが、Boot Camp 6.1.15版で、高精度タッチパッド（Windows Precision Touchpad）に対応したことと、2021年10月にMacBookProもIntel CPU 決別と決別されしまったため、ローカルにバックアップを置いておきたいからです。・・・・といっても、Brigadierのように、いつでもBoot Camp用のドライバがいつでもダウンロードできるのではなく、新規にWindows 10/11を導入するタイミングです。(現在のBoot Camp環境を壊したくなければ、外部SSDとかにWindows 10をインストールしないとできません。)

<font color="red">★★★導入後以降でもダウンロードできることがわかりました。(英語) 2022/03/19追記★★★</font>

https://qiita.com/kmatsuura/items/30b84af032688eccf2c4

ご参考:（Brigadierとは何か？とかが、わかります。）

https://qiita.com/kmatsuura/items/9d098bb20f1c94851a72


## Apple Software Update を起動します。
#### (1) Fileメニュー > tools で、"download only"(英語表記の場合)を選択します。

![boot_camp_update_downloadonly.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147055/4cdb627e-1e3b-b875-ecc5-7384ae7f7ee8.png)
※このメニュー、普段選択できず、アップデートが存在するときにだけ選択できます。（これ・・・意識しないと見逃してしまう。Windows 11のインストールの際に意識して作業するまで数年間知りませんでした。）

なお、上のようにアップデートが複数ある場合、AppleUpdate.exeをダウンロードしても都度上書き更新されてしまうので、画面のようにひとつづつチェックして、"Install 1 item"（ボタンのキャプションは変わったかな？）を押します。

#### (2) Toolsの配下に、Open Downloaded Updates Folder...(英語表記の場合) を選択すると、保存先フォルダが開きます。
※ダウンロード直後は、自動でexploereがPopUpしたかもしれません。

![Screenshot 2021-10-15 221518.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2147055/7d69325c-7370-0762-b7bd-db3416d18f6b.png)

別の版数のAppleBcUpdate.exeをダウンロードするため、AppleBcUpdate.exeは都度この場所から退避させます。
(どの版数も同じ名称なので、フォルダで分けて保存しておくとか、実行ファイル名を変えておくとか・・・・)
なお、6.1.15は、6.1.14を適用した後のBoot Camp Updateで表示されるようになります。

#### 以上です。


-----------
ところで・・・Apple T2チップを非搭載した少し前のMacBookで、高精度タッチパッド（Windows Precision Touchpad）を使うためには
非Officialのドライバが公開されていたりします。

https://github.com/imbushuo/mac-precision-touchpad

これ素晴らしいのですが、Windowsを使うときは、私は、高精度タッチパッドが使いづらく結局USBマウスを挿入してたりしてます。
テストでWindow表示したときにチラつかないようにする方法

## 問題
Window表示（`Window.Show()`）を含むテストをローカルで実行したときに、一瞬Windowが表示されるため、チラつきます。

![スクリーンショット 2021-11-03 09.59.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120077/3891850c-b219-5c76-29f2-549a58f74063.png)

テスト実行するたびにこれが表示されるのはしんどいです。
なので、画面外に押し出してしまいましょう。

## 解決方法

Windowの`Top`プロパティに負の値を設定してしまいましょう。

```csharp
var window = new Window()
{
    Top = -10000,
};
//ウインドウ表示
window.Show();
```

表示自体はされているので、タスクバーには一瞬表示されたりしますが、そんなには気になりません。

## 環境

Visual Studio 2019
C# 9
.NET 5
Microsoft.NET.Test.Sdk 16.11.0
xunit 2.4.1
xunit.runner.visualstudio 2.4.3
nuxt.jsでfirebaseがThis dependency was not foundになって詰まった話

## 背景
firebaseを利用したnuxt.jsのプロジェクトを作ろうと思ったが、pluginsでfirebaseのimportしているところで詰まった。

## バージョン情報
| ライブラリ | バージョン |
| -- | -- |
| nuxt | 2.15.7 |
| firebase | 9.2.0 |

## 問題

以下のコードをpluginsディレクトリに記述して、firebaseを利用しようとしたが、devしたときに`This dependency was not found`のエラーが発生してfirebaseが見つからないとのこと。

```/plugins/firebase.js
import firebase from 'firebase' // -> This dependency was not found

const config = {
    apiKey: process.env.FIREBASE_API_KEY,
    authDomain: process.env.FIREBASE_AUTH_DOMAIN,
    projectId: process.env.FIREBASE_PROJECT_ID,
    storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.FIREBASE_APP_ID,
    measurementId: process.env.FIREBASE_MEASUREMENT_ID,
}

if (!firebase.apps.length) {
    firebase.initializeApp(config)
}

export default firebase
```

## 原因
2021年8月25日にfirebaseのjsのSDKがversion9に上がった際にapiが大きく変化し、firebaseをimportするのではなく、各機能をそれぞれimportするように仕様変更が行われた。

## 解決方法
以下のようにコードを書き換える。

```/plugins/firebase.js
import { initializeApp } from 'firebase/app'

const config = {
    apiKey: process.env.FIREBASE_API_KEY,
    authDomain: process.env.FIREBASE_AUTH_DOMAIN,
    projectId: process.env.FIREBASE_PROJECT_ID,
    storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.FIREBASE_APP_ID,
    measurementId: process.env.FIREBASE_MEASUREMENT_ID,
}

const firebaseApp = initializeApp(config)

export default firebaseApp
```

## 感想
firebaseのversion9のリリースが比較的最近だったこともあり、firebase + nuxtを扱った記事でfirebaseの記述箇所をそのまま利用できなくなっていることが多いので注意が必要。また、どうしても書き換えがめんどくさい場合にはversion8のapiが使える`firebase/compat`を利用してもいいかもしれない。しかし将来性を考えると、version9のapiに慣れておくのがよさそう。

## 参考
- [FirebaseをJavaScriptプロジェクトに追加する](https://firebase.google.com/docs/web/setup)
- [Firebase JavaScript SDK Release Notes](https://firebase.google.com/support/release-notes/js#9.0.0)
- [FirebaseV9の書き方でデータを取得してみる](FirebaseV9の書き方でデータを取得してみる)
- [The new Firebase JS SDK is now GA](https://firebase.googleblog.com/2021/08/the-new-firebase-js-sdk-now-ga.html)
【備忘録】pip3 install TA-Lib でエラーが出た時の対処法

TA-Libインストールで手間取ったので、正常にインストールする手順を備忘録としてまとめます。

```
pip3 install TA-Lib
```

上記実行すると、`ERROR: Failed building wheel for TA-Lib`のようなエラーが出てインストールできない。

以下、インストール手順
まず、homebrewでTA-Libをインストール

```
brew install TA-Lib
```

その後、pip3 でインストール

```
pip3 install TA-Lib
```

これで正常にインストールできました。

上記でもインストールできない場合は
https://qiita.com/aisurta/items/34e8cf47c4eb4fdd5d68
こちらの記事の方法も試してみるとできるかもしれません
GradleのVersion catalogで少し詰まったところ

小一時間ハマりました。
Version catalogでKotlin Serializationを管理したかっただけなんですが。。。

# OK

```groovy:gradle/libs.versions.toml
[versions]
kotlin = "1.5.31"

[plugins]
kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlinserialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }

```

```groovy:app/build.gradle
plugins {
...
    alias(libs.plugins.kotlin)
    alias(libs.plugins.kotlinserialization)
}
```


# NG

```groovy:gradle/libs.versions.toml
[versions]
kotlin = "1.5.31"

[plugins]
kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }

```

```groovy:app/build.gradle
plugins {
...
    alias(libs.plugins.kotlin)
    alias(libs.plugins.kotlin.serialization)
}
```

これで`Sync Now`するとエラーが出ます。

```
A problem occurred evaluating project ':app'.
> Could not find method alias() for arguments [org.gradle.accessors.dm.LibrariesForLibs$KotlinPluginAccessors@11843878] on object of type org.gradle.plugin.use.internal.PluginRequestCollector$PluginDependenciesSpecImpl.
```

`[plugins]`で`kotlin`というaliasを使っているので`kotlin.serialization`というaliasがうまく参照できないんじゃないかと思いますが、実際の所はよく分かっていません。。。


# 最終的な設定

`kotlinserialization`だと見づらかったので最終的にはこうなりました。



```groovy:gradle/libs.versions.toml
[versions]
kotlin = "1.5.31"

[plugins]
kotlin-core = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }

```

```groovy:app/build.gradle
plugins {
...
    alias(libs.plugins.kotlin.core)
    alias(libs.plugins.kotlin.serialization)
}
```

# 参考

https://star-zero.medium.com/gradle%E3%81%AEversion-catalog%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E7%AE%A1%E7%90%86-eb81f8e88444

https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog

https://github.com/Kotlin/kotlinx.serialization

https://qiita.com/takagisou/items/acbef589858d26488776