OmniAICreator/Qiita-1.07M huggingface dataset:
Nginx Config サンプル: 特定拡張子ファイルが見つからなかったら特定ディレクトリにリダイレクトする (例えば PDF)



サイトの引っ越しなどで、ディレクトリ構造をよく入れ替えます。
ただ、古いサイトのファイルなどをそのままアーカイブ的なものとして利用したい場合があります。
例えば、PDFファイルとか・・・。

ISO 127001 認証を取得しているセキュアかつ簡単な操作が可能で開発もしやすい [Concrete CMS](https://concrete5-japan.org) のサイトに移行した際に必要になりました。

今回は PDF ファイルが見つからなかった場合に特定ディレクトリ配下にリダイレクトできるという Nginx Config サンプルを作成しました。

`https://example.com/foo/bar.pdf` にアクセスしても、PDF ファイルが見つからなかったら「`/pdf_redirect`」ディレクトリにリダイレクトする。

というルールです。

```
server {

	# いろいろ省略

    # /pdf_redirectディレクトリ以外全部の .pdf 拡張子のリクエストで、ファイルが見つからなかったら @pdf_redirect ロケーションに処理を持っていく
    location ~* ^(?!\/pdf_redirect)(.*\.pdf($|/)) {
        try_files $uri @pdf_redirect;
    }

    # サイトの /pdf_redirect/ ディレクトリに 301 リダイレクトする
    location @pdf_redirect {
        return 301 https://$hostname/pdf_redirect$request_uri;
    }
}
```


参考
http://nginx.org/en/docs/varindex.html
https://www.nginx.com/blog/creating-nginx-rewrite-rules/
https://heartbeats.jp/hbblog/2012/04/nginx05.html
https://muziyoshiz.hatenablog.com/entry/2019/06/30/203903
https://uxmilk.jp/50674
Dart (Flutter)でvalue of type 'TableRow' can't be returned from the method 'build' because it has a return type of 'Widget'.と怒られた。TableRow Classはウィジェットではないらしい。 


Tableウィジェット配下のTableRowをコンポーネント化しようとしたら、`value of type 'TableRow' can't be returned from the method 'build' because it has a return type of 'Widget'.`と怒られました。

```dart
class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return TableRow();
  }
}
```

そして、このページを見ろと言われました。

https://dart.dev/tools/diagnostic-messages?utm_source=dartdev&utm_medium=redir&utm_id=diagcode&utm_content=return_of_invalid_type#return_of_invalid_type

`return_of_invalid_type`という「診断メッセージ」で、宣言されたreturnの型と合わないということで怒られているみたいです。
特にreturnの型を宣言しているつもりはないのですが...。

こちらのページにヒントがありました。同じエラーではないですが。

https://stackoverflow.com/questions/56693424/what-is-causing-the-error-return-type-tablerow-isnt-a-widget-as-defined-b

Flutterでは全ての要素がウィジェットだと思っていたのですが、どうやら`Table Row`クラスはウィジェットではないらしいです。その証拠に（？）、明確にWidgetである`Table`や`Text`では公式ドキュメントで、Widgetであるという文面がありますが、TableRowは`A horizontal group of cells in a Table.`という説明になっています。

また、ウィジェットのドキュメントにあるものが`Table Row`にはありません。それはInheritance（継承？）の情報です。

TableRow class
https://api.flutter.dev/flutter/widgets/TableRow-class.html

Table class
https://api.flutter.dev/flutter/widgets/Table-class.html
>Inheritance
Object > DiagnosticableTree > Widget > RenderObjectWidget > Table

Text class
https://api.flutter.dev/flutter/widgets/Text-class.html
>Inheritance
Object > DiagnosticableTree > Widget > StatelessWidget > Text

ちなみに`TableRow`はWidgetではないけど、`TableCell`はWidgetらしい :thinking:
ドキュメントにそう書いてあるし、手元で試してみたら確かにコンポーネント化できました。 

TableCell class
https://api.flutter.dev/flutter/widgets/TableCell-class.html
>Inheritance
Object　> DiagnosticableTree　> Widget　> ProxyWidget　> `ParentDataWidget<TableCellParentData>`　> TableCell

対応としては、 TableRow周りをコンポーネントに切り出したいと思ったら、`TableRow`の中身の`Container`とか`TableCell`をコンポーネント化するか、Tableごとコンポーネント化するとかなのかなと思います。
【Swift】XcodeGenを使用してる際のFirebaseCrashlyticsのDEBUG_INFORMATION_FORMATの設定方法

# はじめに

https://qiita.com/SNQ-2001/items/c25f61fdaf0c7a46f568

3日前にXcodeGenを使用してる際のFirebaseCrashlyticsのRunScriptの設定記事を書きました。
今回は`DEBUG_INFORMATION_FORMAT`の設定方法です。

ドキュメントはここです。

https://firebase.google.com/docs/crashlytics/get-started?hl=ja&platform=ios#set-up-dsym-uploading

# 実装
```diff_yaml:project
    settings:
      base:
        INFOPLIST_FILE: Sample/Application/Info.plist
        CODE_SIGN_STYLE: Manual
        DEVELOPMENT_TEAM: XXXXXXX
        CODE_SIGN_ENTITLEMENTS: Sample/Application/Sample.entitlements
+       DEBUG_INFORMATION_FORMAT: dwarf-with-dsym
        TARGETED_DEVICE_FAMILY: 1
        DISPLAY_NAME: Sample
```

# おわり
XcodeGenを使っているとFirebaseのドキュメント通りにはできないので注意が必要です
Qiitaでの記事の作成・投稿方法

# はじめに
今回はQiitaにアカウント作成後の記事の投稿方法について、まとめます！
私自身、この記事を書いているときはまだ2投稿目です、、
自身の経験をもとに、記事の作成方法と、苦労した点をまとめていければと思います！

# 目次
[記事の作成方法](#記事の作成方法)
[苦労した点](#苦労した点)
[最後に](#最後に)

# 記事の作成方法

1.Qiitaにログイン後、「投稿する」をクリック。
![スクリーンショット 2023-03-10 19.01.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3263512/b282600f-c796-b8bf-0dbe-c76e82bbba6c.png)

2.画面が切り替わるので、記事を作成する。

左側のスペースに記述していきます。
右側にはプレビューが表示されます。
![スクリーンショット 2023-03-10 19.43.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3263512/8fef0eb8-07f3-0334-bee6-fb5ed58ce56e.png)

3.書き終えたら、右下の「Qiitaに投稿する」をクリック。
![スクリーンショット 2023-03-10 19.55.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3263512/5956458f-8391-e6d7-58af-1ff3dc95be1a.png)

**これで記事の作成、投稿が完了しました！！**

:::note warn
注意点！
記事を連続して投稿しようとすると、下記のような警告が出て、投稿できなくなります、、、
調べてみたところ、約30分ほどでまた投稿できるようになるようです！
環境によっては、連続投稿できることもあるみたいですが、、、
![スクリーンショット 2023-03-10 19.05.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3263512/9bd6c914-22a3-585d-9523-0b491a18031c.png)
:::

# 苦労した点
アカウント作成はスムーズにできたのですが、記事の記述に苦戦、、、。

マークダウン記法というもので書いていくのですが、そもそもマークダウン記法とは、、？
という状態だったため、時間がかかりました、、、。

基本的な書き方は、[「Markdown記法 チートシート」](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)という公式の記事にまとめられています。
(投稿画面の「？」からも見ることができます！)

また、[「アカウントの作成」](https://qiita.com/ken_3737/items/54340a767f77a177d84c)についてはこちらでまとめています！
(私が初めて投稿した記事です。)

# 最後に

今回はQiitaでの記事の作成・投稿方法を書かせていただきました。
マークダウン記法について、まだまだ理解は足りてないですが、これから更にいい記事が書けるよう、
勉強していきます、、、！
まだまだ見ずらい記事だとは思いますが、この記事がどなたかの参考になれば幸いです。
最後まで読んでいただき、ありがとうございました！
Ubuntu22で仮想NICを作成すると別のNodeとMACアドレスが重複する

# 背景

- ちょっと手を入れた同じAMIを使って複数Instanceを立ち上げたり、VM Cloneしたものを利用したときに起こる
- Bridge I/FやVXLAN I/Fなどを作成すると、別のNodeなのになぜか同じMACアドレスでNICが作成されてしまう
- おかげでそのNode間の通信がうまいことできなくなる

# TL;DR

- systemd v242 からMACアドレスをrandomに生成せず、一定条件で作成されたものを保持し続けるようになった
- 元ネタは `/etc/machine-id` なので、別Nodeに転用するときはこれを再作成してあげる必要があるようだ
  - 具体的にはこんな感じ
  - ```
    # 改行なし空白で /etc/machine-id を上書き
    root# > /etc/machine-id
    # machine-id を再作成
    root# systemd-machine-id-setup

    #　AMI化するならAMI化直前とかに削除しておくと、次回起動時に自動生成される
    root# rm -f /etc/machine-id
    root# touch /etc/machine-id
    ```
- もしくはMACアドレスの生成ロジックをrandomにしてあげる
    ```/etc/systemd/network/90-bridge.link
    [Match]
    # 設定するNIC名
    OriginalName=br*
    
    # デフォルトはこれがstableになったっぽい?
    [Link]
    MACAddressPolicy=random
    ```

つまり、AMI化したりVM Cloneするときはちゃんとmachine-idをリセットできるようにしましょうねってことでした

# 背景

なんやかんやあって、仮想NIC周りにMACアドレスが生成できないものがあってstableにしないといけなくなったようだ
詳しくはこれを見たけどよくわからなかったようだ
https://github.com/systemd/systemd/commit/6d36464065601f79a352367cf099be8907d8f9aa
サーバーで展開したエディタに新しいプラグインを追加する方法

新しいプラグインを追加することで、ONLYOFFICE Docsの機能を拡張し、新しい機能を追加することができます。

:::note warn
本ガイドは、ONLYOFFICE Docsのセルフホストサーバー版のみを対象としています。クラウドサービスにプラグインを追加する方法については、[こちら](https://api.onlyoffice.com/plugin/installation/cloud)のページをご参照ください。
:::

以下の手順で、数分程度で簡単に行うことができます。

１．[App Directory](https://www.onlyoffice.com/en/app-directory)ページにアクセスし、互換性があり、すぐにインストールできるプラグインがすべて配置されている場所を確認します。
２．リストから適切なプラグインを選択し、それがONLYOFFICE Docsと互換性があることを確認します。
３．今すぐインストールボタンをクリックするか、手動でONLYOFFICE [Githubページ](https://github.com/ONLYOFFICE)で最新の利用可能な対応プラグインのリポジトリを見つけることもできます。

以下はその例です。
* [Telegram](https://github.com/ONLYOFFICE/plugin-telegram)：統合されたTelegramクライアントを使用して、リアルタイムで共著者とチャットできます。
* [単語カウンター](https://github.com/ONLYOFFICE/plugin-wordscounter)：ドキュメントの選択された部分の単語、文字、段落をカウントします。
* [シソーラス](https://github.com/ONLYOFFICE/plugin-thesaurus)：ある単語の同義語と反意語を検索し、選択した単語で置き換える。

現在あるオープンソースのプラグインの例は、すべて[こちら](https://github.com/ONLYOFFICE/sdkjs-plugins)で入手できます。

４．プラグインのURLアドレスをコピーして、ターミナルを使用してダウンロードしてください。

```
git clone https://github.com/ONLYOFFICE/plugin-name 
```

`plugin-name`はプラグインのURLアドレスです（例：単語カウンターのプラグインをダウンロードするために、https://github.com/ONLYOFFICE/plugin-wordscounter）。

５．プラグインコードの入ったフォルダをONLYOFFICE Docsディレクトリにある`sdkjs-plugins`フォルダに入れます。

Linuxの場合：

```
mv plugin-folder /var/www/onlyoffice/documentserver/sdkjs-plugins/
```

Windowsの場合：

```
move plugin-folder %ProgramFiles%\ONLYOFFICE\DocumentServer\sdkjs-plugins\
```

`plugin-folder`には絶対パスのプラグインディレクトリを指定します。

６．プラグインはONLYOFFICE Docsの全ユーザーが利用できるようになります。サービスの再起動が必要な[場合](https://nodejs.org/docs/latest/api/fs.html#fs_availability)があります。

```
systemctl restart ds-converter ds-docservice ds-example ds-metrics
```

また、config.jsonファイルを通して新しいプラグインを追加することも可能です。この方法については、[開発者向けページ](https://api.onlyoffice.com/plugin/installation/onpremises)をご覧ください。

プラグインは、エディターで利用できるプラグインマネージャーで管理することも可能です。詳しくは、[こちらの記事](https://helpcenter.onlyoffice.com/ONLYOFFICE-Editors/Editors-User-Guides/AllEditors/Plugin-manager.aspx)をご覧ください。

追加したプラグインやデフォルトのプラグインを削除したい場合は、[サーバーエディターからデフォルトのプラグインをアンインストールする](https://helpcenter.onlyoffice.com/installation/docs-uninstall-plugin.aspx)ガイドを参照してください。
デスクワークで目を守るためにやっていること

健康を気にかけることも大事にしている小野です。
以前も健康についての記事を書いて、評判が良かったです。

https://qiita.com/ono-ayumu/items/2b7354b1b191de93e999

さて、今回はシステムエンジニア・プログラマーには、切っても切り離せない問題である画面の見過ぎについて。
そう、「目」についてです。

肉体には限界があるもので、使い過ぎれば壊れてしまいます。
そして、一度壊れたものは同じように戻らないことが多いです。

なので、普段の業務から「目を守る」ために実践していることをまとめて紹介していきます。
**エンジニアとして長く働いていこうと思っているなら、目を労るのは大事なことですよー。**
（今の時代、デスクワークの人も同様に目を守るために一読するの推奨しています！）

## 目を守るために実践していること

どれもちょっとしたことですが、毎日続けていると体感します。
どれだけ目を酷使して作業を進めていたのかを...

### 画面を夜間モードにしている

WindowsもMacも夜間モードと言って、ブルーライト少なめの設定で画面を表示することができます。
**毎日8時間も画面を見ていると、目がずんっと重くなりますし、開けているのも限界なことがありましたが、夜間モードにするとそれだけで目の疲れが軽減されます。**

ただし、画面が暖色っぽくなるので、夜間モードをやっていない人が見るとビックリされます。
その時はしっかりと説明して、目を守るために夜間モードを使うことをオススメしましょう（笑）

### ディスプレイから距離を取る

**近づき過ぎない。**
というのも大事です。

夜間モードほどの体感はありませんが、目の疲れは軽減します。

### 夜寝る前にホットアイマスクを利用する

ホットアイマスクを20〜40分やるだけで、かなり楽になります。
たった20分でもやっていると翌日の目のフレッシュさが全然違います。
やっていない時は目が疲れ切った状態で仕事開始するので、午前中でヘトヘトになります。。

**最近だとUSBで使えるタイプもあるので、一度買うと何回も使えて便利ですよー。**

https://amzn.asia/d/4nzImm1

### サプリメントを取る

目に良いサプリメントも最近は増えていますね。
私はサプリメントを摂取して、リフレッシュしています。

1日働くと自分が思っている以上に、体の栄養もエネルギーも使っています。
毎日ちゃんと栄養を取ることで、元気に働けますよ。

### ブルーライトカットのメガネを使う

これも夜間モードと同じで”ブルーライトを減らす”方法です。
私は両方使っています。
（だから、仕事中は世界が暖色に見えます...笑）

ただ、両方使うと、目の疲れもぐぅーんと減るので、全然疲れないですね！
個人的には、かなりオススメです。

また、特に目が悪くなければ、度を入れなくても使えるタイプもあります。
なので、今日買って、今日から使えます。

私はJINSの使っています。

https://www.jins.com/jp/jins-screen/

### スマホを見ない時間をつくる

**スマホを見過ぎかもしれませんね。**

かくいう私も見過ぎています（笑）
ツイッターとか、ついったーとか、Twitterとか、、（笑）

寝る前や、移動中など、”見ない時間”をちょっとでもいいので作ると目を休めることができますよ。

### しっかり寝る

しっかり寝ましょう。
睡眠はすべてを解決してくれます！！

https://amzn.asia/d/9qnBjoE

### さいごに

ひとつひとつはちょっとしたことですが、どれも試していると驚くほどに「目を守る」ことができます。
LaravelでClass定数を使う

定数定義をどこで行うのかという話になった際に、クラス定数を作成してそこに定義するという話題があったので実装方法を調べてみた

### Class定数の作成方法

##### App内にConstsディレクトリを作成 
　※ディレクトリ名は、何でも問題ない
```
app
 └── consts
```



その中に定数ファイルを作成 
```
NotificationConst.php 
```

```php
<?php
Namespace App\Consts; 

Class NotificationConst {
    const MAX_DISPLAY = 20; 
    const PUBLIC = '公開'; 
    const PRIVATE = '非公開';
}
```

### エイリアスの設定 

##### app.phpファイル内のaliasesに設定を記述
```
app
 └── config
        └── app.php
```
```php
<?php

return [

    'aliases' => [ 

      'App' => Illuminate\Support\Facades\App::class,
      'Arr' => Illuminate\Support\Arr::class,

      /** 省略 */

      /** 追加 */
      'NotificationConst' => App\Consts\NotificationConst::class
      
    ]
]
```

定義ファイルをエイリアスに設定したらあとは、呼び出したいファイル内で呼ぶ

##### Controllerの場合 Bladeで使用する

```php
@if($publicStatus === NotificationConst:: PUBLIC) 
    <p>{{ $title }}</p>
    <p>{{ $contents}}</p>
@endif
```

この方法で、Classを使って定数を定義出来る。
C++で連結リストを実装してみた

実装イメージは以下の通り。

![絵日記2023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/1b3af47c-c04f-5fad-4d7e-d9ce377993fb.png)


ソースファイルは以下の通り。

```list2.cpp
#include <iostream>

class List {
public:
  int data;
  List *pointer;
};

List *list;
List *list_;
List *list_header;

void push(int data){
  list_ = new List[1];
  list_->data = data;
  list_->pointer = (List *)NULL;
  List *list_next = list_header;
  while(list_next->pointer != (List *)NULL){
    list_next = list_next->pointer;
  }
  list_next->pointer = list_;
}

void show(){
  List *list_next = list_header;
  while(list_next != (List *)NULL){
    std::cout << list_next->data << std::endl;
    list_next = list_next->pointer;
  }
}

int main(){

  list_header = new List[1];
  list_header->data = 0;
  list_header->pointer = (List *)NULL;
  list = new List[1];
  list->data = 0;
  list->pointer = (List *)NULL;
  list_header->pointer = list;
  
  std::cout << "---" << std::endl;
  push(100);
  show();
  std::cout << "---" << std::endl;
  push(200);
  show();
  std::cout << "---" << std::endl;
  push(300);
  show();
}
```
コマンドラインの実行結果は以下の通り。

```
$ g++ list2.cpp
$ ./a.out 
---
0
0
100
---
0
0
100
200
---
0
0
100
200
300
```
[OutSystems]Barcode PluginのPWA対応

公式のモバイルプラグインのリストではわからないが、Barcode PluginはPWAに対応しているようなので、動作確認してみた。

# 結論（2023/03/10時点の情報）
OutSystemsドキュメントにある公式プラグインのリストには記述が無いが、Barcode Plugin 5.1.0でPWAに対応している。
使い方は、ネイティブの場合の使い方に加えて、画面にPWABarcode Blockを配置するだけ。

# 環境情報
Personal Environment(Version 11.18.1 (Build 37884))
Service Studio(Version 11.53.42)
[Barcode Plugin](https://www.outsystems.com/forge/component-overview/1403/barcode-plugin)(Version 5.1.4)

iPhone(iOSバージョン 16.3.1) 

# PWA対応公式プラグインのリストにはBarcode Pluginは含まれない
[Mobile Plugins](https://success.outsystems.com/documentation/11/extensibility_and_integration/mobile_plugins/)というドキュメントに公式プラグインのリストがあり、Supported in PWAという列で、そのプラグインがPWAでサポートされているかを示している。

2023/03/10現在サポートされているのは
- Camera
- Location
- Social Login Mobile

の3つのみ。なお上記の表内では、Barcode Pluginは「QR/Barcode scanner」と表記されている。また、このページは日本語訳があるが、翻訳が最新に追い付いていないようなので、現段階では英語で見ることをお勧めしておく。

# Barcode PluginのVersionsを見るとサポート済みとある
[ForgeのVersions](https://www.outsystems.com/forge/component-versions/1403/version/0/platform/)を見ると、Version 5.1.0 (2022/07/08) のRelease NotesにPWAサポートを追加したとある。

Pluginのプログラムを追ってみるとPWA対応のロジックは入っているので実験したところ、無事に動作した。

# 利用方法
## バーコード/QRコードを読みたい画面にPWABarcode Blockを配置
Blockは、Barcode Plugin内のBarcodePlugin/PWABarcode。
特にパラメータはないので、画面に配置するだけでよい。

Blockの実装を見ると、↓のように、Required ScriptsでJavaScriptを読み込んでいる。
Client ActionをPWAで動作させると、WebScannerというオブジェクトを介してバーコード/QRコード読み取り機能を起動しているので、ここで読んでいるスクリプトが処理の実態と思われる（コードまでは読んでいないけど）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/a00e1936-69c1-8cb5-81b0-94197d61e99f.png)

## 通常のPluginと同じようにActionを呼ぶ
Pluginは

1. Check\<Plugin名\>でプラグインが利用可能かを確認
1. 利用可能であれば、プラグインの本体となるAction (Barcode PluginではScanBarcode）を呼ぶ

という流れで操作する。このとき、画面にPWABarcode Blockを配置しておかないと、JavaScriptエラーが起きてうまく動かない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/0b7ecdbc-b1c7-9666-2736-435f15208c6d.png)
Googleデジタルマーケティング＆Eコマース：キーワード調査

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/84e33f4e-81cb-98a6-4546-f2ec06fd8b8b.png" width="800">

# キーワード調査

デジタルマーケターやeコマースアナリストとして、Webページのコンテンツを作成するよう依頼されることがあります。コンテンツを作成する前に、潜在顧客がその情報を見つけるためにGoogleに入力する用語やフレーズを把握しておくと便利です。

好まれる単語を理解することで、顧客が検索しているものに密接に関連するコンテンツを作成することができます。このコンテンツは顧客とつながり、コンテンツがつながれば、顧客が望む行動を起こす可能性が高くなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/a1975abd-97d8-54ed-340c-1481d3fd889a.png" width="600">

キーワード調査とは、人々が検索エンジンで使用する言葉を見つけるためのプロセスです。キーワード調査の方法は、唯一無二の正解があるわけではありません。ある組織に勤めていて、その組織が推奨するプロセスがあるかもしれません。

キーワードを調査する際、役立つツールがあります。これらのツールは、人々がキーワードを何回検索しているかのデータを提供します。また、あるキーワードがどの程度競合しているかというデータも得られます。

:::note info
キーワード調査は、所属する組織によって異なりますし、意見に左右されることもあります。また、キーワードの調査は現場で学ぶのが一番なのです。
:::
# キーワード・スタッフィング（Keyword stuffing）

GoogleのSEO品質ガイドラインでは、あるキーワードに関連する行為を行わないよう推奨しており、この行為をキーワード・スタッフィングと呼びます。

キーワード・スタッフィングとは、検索結果におけるサイトのランキングを操作しようとして、Webページにキーワードや数字を読み込ませる行為のことを指します。多くの場合、これらのキーワードはリストまたはグループとして表示されます。

これらのキーワードは、通常、文脈から外れており、Webページのコンテンツにとって本当に自然なものではありません。キーワードでページが埋め尽くされると、ユーザー体験が損なわれ、サイトのランキングにも悪影響を及ぼしかねません。

キーワードを適切に使用し、文脈の中で、有益で情報量の多いコンテンツを作成することに重点を置く必要があります。

キーワードの詰め込みの例としては、次のように不自然に聞こえるほど頻繁に同じ単語やフレーズを繰り返すことが挙げられます。

***「私たちのカスタムキャンドルは手作りです。カスタムキャンドルの購入をお考えの方は、カスタムキャンドルの専門店にご相談ください」***
dockerでmysqlコンテナが立ち上がらない

## エラー文　
```
[ERROR] [Entrypoint]: MYSQL_USER="root", MYSQL_USER and MYSQL_PASSWORD are for 
configuring a regular user and cannot be used for 
the root user Remove MYSQL_USER="root" and use one of the following to control the root user password:
    - MYSQL_ROOT_PASSWORD
    - MYSQL_ALLOW_EMPTY_PASSWORD
    - MYSQL_RANDOM_ROOT_PASSWORD
```

## 該当のソースコード　
```:docker-compose.yml
version: "3"
services:
  web:
    container_name:  sample_app_local
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
  
  db:
    image: mysql:5.7
    volumes:
      - mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_PASSWORD: password
      MYSQL_USER: root
    ports:
      - 3306:3306

volumes:
  mysql-data:
```

## 原因　
docker-compose.ymlファイルで`MYSQL_USER: root`を設定していたから。　
`MYSQL_USER`は通常のユーザーを作成するためのもので、rootユーザーには使用できない。　
また、rootユーザーはmysql構築時に作成されている。 

## 解決　
`MYSQL_USER: root`を削除、または`MYSQL_USER: user`を設定する。

`MYSQL_USER: user`を設定した場合、`MYSQL_PASSWORD`の設定も必要になります。
また、mysqlはrootユーザーで作成されているため、`MYSQL_USER: user`だと権限がなくアクセス時にエラーが出る。その際には権限の設定が必要になる。
## 参考サイト　
[【Docker】Mysql が立ち上がらない（ユーザ設定エラー）](https://c-a-p-engineer.github.io/tech/2021/07/05/docker-mysql/)
[MYSQL_ROOT_PASSWORDを付け足したのに解決しない](https://teratail.com/questions/g82650lt0blom7)
[Ruby on Rails 6のDocker環境構築](https://zenn.dev/yuma_ito_bd/scraps/1adb89dfe0661c)
NOFILEを削除する

# git reset --hardでマイグレーションが消えた
```
**********@mbp ***** % bin/rake db:migrate:status                  

database: ********

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20221228045452  Create users
.
.
.
   up     20230308014904  ********** NO FILE **********
   up     20230308021103  ********** NO FILE **********
```
```
*********@mbp ***** % rails db:migrate:down VERSION=20230308014904
rails aborted!
ActiveRecord::UnknownMigrationVersionError: 

No migration with version number 20230308014904.
```
これをなんとか消したい。

# IDが同じのダミーのマイグレーションファイルを作成する
```
touch db/migrate/20230308014904__hoge.rb
```
```rails db:migrate```

```
********@mbp ****** % bin/rake db:migrate:status              

database: ******_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20221228045452  Create users
.
.
.
   up     20230308014904  Hoge
   up     20230308021103  ********** NO FILE **********
```
IDが同じのファイルがダミーファイルが作成された。

```
*********@mbp ***** % rails db:migrate:down VERSION=20230308014904              
== 20230308014904 Hoge: reverting =============================================
== 20230308014904 Hoge: reverted (0.0068s) ====================================
```
# ダウンになった。
```
*********@mbp ****** % bin/rake db:migrate:status               

database: ******_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20221228045452  Create users
.
.
.
  down    20230308014904  Hoge
   up     20230308021103  ********** NO FILE **********
```
これで削除できる

すごい！


# 出典
https://stackoverflow.com/questions/16041790/what-is-the-best-way-to-resolve-rails-orphaned-migrations

https://qiita.com/r_sk00002/items/9bf321f81d3b84042694

# 感想
英語だけでは不安だったので日本語も同じようなものがあってよかった。
Qiitaのはじめかた[アカウント作成]

# Qiitaのはじめかた

はじめまして！
この度、Qiitaにアカウントを作成し、初めての投稿として、Qiitaのアカウント作成方法をまとめてみます！
これからQiitaにアカウント作成をしようと思ってる方の手助けになれば幸いです。

# アカウント登録の流れ

[Qiitaのホームページにアクセス](#Qiitaのホームページにアクセス)
[画面右上の「ユーザー登録」をクリック](#画面右上のユーザー登録をクリック)
[興味のあるタグやユーザーのフォローを行う](#興味のあるタグやユーザーのフォローを行う)

# Qiitaのホームページにアクセス

こちらからアクセスできます。
↓↓↓
[Qiitaのホームページ](http://qiita.com "Qiita Home")

# 画面右上の「ユーザー登録」をクリック

画像にある赤枠のところをクリック。
![スクリーンショット 2023-03-10 17.56.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3263512/d9081724-0a86-cc12-7746-09a46b5c5aea.png)

クリックすると、このような画面に遷移します。
ここでは、お好きな方法を選んでいただき、登録します。
![スクリーンショット 2023-03-10 18.00.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3263512/0cc16ba7-5d46-3643-8a2b-dbcc3c7b26fd.png)

# 興味のあるタグやユーザーのフォローを行う

登録の最後に、タグやフォローしたいユーザーを選びます。
私は、スクールで使用している言語を選びました！
画像は私の作りたてのマイページです。
タグやユーザーをフォローすると、マイページにも表示されます！
![スクリーンショット 2023-03-10 18.01.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3263512/a7007465-8f66-0603-fef1-127688be0a98.png)


**これで登録は完了です！！**

最後に、、、
今回は初めての投稿として、Qiitaのアカウント作成方法を記事にさせていただきました。
記事の作り方についても、別記事として書きたいと思います！

初めての投稿で、見ずらいところもあるとは思いますが、
最後までご覧いただき、ありがとうございました！
この記事がどなたかの参考になれば幸いです。
[Mac] フォルダの色をCLIで変更する方法 colormkdir

![スクリーンショット 2023-03-10 17.33.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953900/f2ea5960-ca04-9f33-7758-03afa4d0fc96.png)
初めまして、mimomimoto( www.linkedin.com/in/mimomimoto )です！
皆さんは大好きなMacのフォルダ色を好きな色に変えたいと思うときはありますか？

私はあります！！！！！！！！！


そこで、今回はCLIでMacのフォルダ色を変更可能な[colormkdir](https://github.com/mimomimoto/colormkdir)を紹介したいと思います。

# colormkdir
Macのフォルダ色を変えるにはGUIで操作するのが既存の方法ですが、毎度時間がかかるため非効率的です。[colormkdir](https://github.com/mimomimoto/colormkdir)はCLIで指定した色のフォルダを作成でき、自分専用のフォルダ色リストを管理できる優れものです。

https://github.com/mimomimoto/colormkdir

![movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953900/9be6ac53-4e0c-24f8-b478-454caabfebd2.gif)

...はい、お気づきの方もいられるかもしれませんが[colormkdir](https://github.com/mimomimoto/colormkdir)は私が作成したものです。
先ほどは優れものなどと自分で言ってしまい申し訳ありません!!!🙇


今回使用方法については割愛させていただき、githubに載せているものを見ていただければと思います。
実際使ってみると便利だと思うのでぜひ皆さん使ってくださると幸いです🙇


# 終わりに
今回、私自身初めてOSS開発を行なったため宣伝したく投稿させていただきました。OSS開発をする上で勉強になったことが多々あるため、それらはまた別の記事にしたいと思います。(自作コマンド作成・公開方法など...)
バグなどの報告はgithubのissueに投げてもらえればと思います。
Googleデジタルマーケティング＆Eコマース：SEOの事前準備

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/84e33f4e-81cb-98a6-4546-f2ec06fd8b8b.png" width="800">

# Pre-SEO work

組織のSEOを担当するデジタルマーケターとして、いくつかの事前作業を行う必要があります。このプレワークを行わずにSEOを実施すると、いくつかの問題が発生します。

- **SEOを依頼する企業や組織**
    - 実施した作業が、組織の目標に合致していない可能性があります。自分の行っている作業が、組織の目標達成に役立つものであることを確認する必要があります。
- **潜在的なWebサイト訪問者**
    - もし、あなたがやっている仕事が、訪問者とつながっていないとしたらどうでしょう？さらに悪いことに、訪問者を遠ざけてしまっていたらどうでしょう？

SEOを実施する前に事前準備をすることで、こうした状況を回避することができます。ここでは、SEOの作業を行う前に考慮すべきいくつかの要因について説明します。

### <font color="MediumBlue">あなたのWebサイトや組織の目標を知る</font>

どのようなSEO対策を行うかは、その目標によって異なります。目標を明確にすることが重要です。そして、その目標にポジティブな影響を与えることができると確信できる仕事をすることです。

マーケティングの専門家として、あなたはこれらの目標に影響を与えることができることを忘れないでください。ほとんどの経営者は、売上を上げたい、収入を増やしたいと思っているはずです。
- 例えば、あなたが作成したビジネス用のマーケティングフォームが、メール収集を優先しているとします。見込み客からメールを集めれば、売上につながることはご存じでしょう。そこで、SEOを実施する側としては、メール収集のためのコンテンツ作りを優先するわけです。

### <font color="MediumBlue">顧客をよく知ること</font>

この原則があるからこそ、以前[顧客ペルソナ][persona]を紹介しました。SEOを行う前に、あなたのコンテンツを読み、体験する人々を本当に理解する必要があります。

[persona]: https://qiita.com/mapami/items/303a9119f5245effb052

潜在顧客が、問題解決に役立つWebサイトを訪問したとしましょう。もし彼らがいくつかの文章を読んだり、つながりのないビジュアルを体験したら、ただ単純に去っていくでしょう。問題解決に役立つサイトが他にいくつもあるのですから。

さらに、訪問者の意図を知る必要があります。彼らは何を達成したいのでしょうか？直接的にコミュニケーションをとり、最終的にその目的を達成する手助けをするのです。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/980e149d-c0cb-6e95-5a6b-487534cb6484.png" width="650">

### <font color="MediumBlue">顧客向けコンテンツのブレインストーミング</font>

まず人のためにコンテンツを作るということがどういうことかを理解するためには、SEOの仕事がどういうものかを理解する必要があります。

コンテンツを作成したり、コンテンツを改善したりする際には、すでにSERPsに表示されているものを見直すことになります。GoogleのSERPsが人に見せたいと信じているもののためにコンテンツを作る習慣に陥りがちです。すでにうまくいっているのであれば、同じようなコンテンツを作ればいいだけですからね。

しかし、優れたSEOベースのコンテンツマーケティング担当者は、まずGoogleの検索結果のためにコンテンツを作成することはありません。彼らは、まず人々のためにコンテンツを作成し、次にGoogleのためにコンテンツを作成します。

これはどういうことでしょうか？それは、検索結果に表示されている情報よりも、検索者が必要としている情報を優先し、考慮するということです。不足している情報はないか？
- 例えば、写真や動画など、より視覚的に説明したほうがいいのか？検索結果の記事がすべてテキストベースだからといって、それが検索者の求めるものであるとは限りません。

### <font color="MediumBlue">競合他社をよく知ること</font>

SERPsで上位にランクインするためには、多くの場合、競合他社よりも優れたコンテンツを作成する必要があります。より良いというのは、人によって意味が異なることを忘れないでください。それは、

- テキストの代わりにビデオかもしれません。
- ポイントを説明するために長いストーリーやケーススタディを含めるなど、より深いコンテンツかもしれません。
- より短く、より簡潔なコンテンツかもしれません。

それを見極めるのがマーケッターとしてのあなたの仕事です。競合より優れたコンテンツを作るには、競合が作ったものを研究する必要があります。彼らがやったことを研究し、それをより良くするのです。全ては、理想のお客様を念頭に置きながら。
設定画面からアプリの処理を切り分ける

## 環境
- Xcode 14.2

## Settings.bundleを追加
「**File**」→「**New**」→「**File...**」から「**Settings Bundle**」を選択する
![](https://storage.googleapis.com/zenn-user-upload/bd0234c189bc-20230310.png)

## Root.plistの変更
1. Settings.bundle内にあるRoot.plistを編集する
2. Preference ItemsにToggle Switchを追加する
	3. Title、Identifierを適当に設定する
![](https://storage.googleapis.com/zenn-user-upload/e55fba683690-20230310.png)

## Configファイルを作成
1. UserDefaultに保存するソースコードを追加する
```swift:UserDefaultConfig.swift
import Foundation

@propertyWrapper
struct UserDefault<T> {
    let key: String
    let defaultValue: T

    var wrappedValue: T {
        get {
            UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        }
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

enum UserDefaultConfig {
    // UserdefaultのkeyはPreference Itemsで設定したIdentifierにする
    @UserDefault(key: "IS_STUB", defaultValue: false)
    static var isStub: Bool
}
```
上記の設定で、設定画面にパラメータが追加される
![](https://storage.googleapis.com/zenn-user-upload/5096e5cd410b-20230310.png)

## UserDefaultの値によって処理を切り分ける
例）レスポンスでStubを返すか、そのままAPIに投げる
```swift:LoginModel
import Foundation

protocol LoginModelInput: AnyObject {
    func login(loginInfo: LoginInfo) async throws -> LoginResponse
}

class LoginModel: LoginModelInput {
    func login(loginInfo: LoginInfo) async throws -> LoginResponse {
        if UserDefaultConfig.isStub {
            StubURLProtocol.requestHandler = { request in
                let response = HTTPURLResponse(
                    url: request.url!, statusCode: 200, httpVersion: "HTTP/2", headerFields: [:]
                )!
                guard
                    let jsonDataURL = Bundle.main.url(forResource: "sample", withExtension: "json"),
                    let jsonData = try? String(contentsOf: jsonDataURL)
                else {
                    fatalError("sample.json not found")
                }
                let data = jsonData.data(using: .utf8)
                return (response, data)
            }

            // URLSession を作る
            let config = URLSessionConfiguration.default
            config.protocolClasses = [StubURLProtocol.self]
            let session = URLSession(configuration: config)

            // APIClient を作る
            let client = APIClient(session: session)

            // request 投げる
            let request = LoginInfoRequest(logInfo: loginInfo)
            let response = try await client.send(request)

            return response
        } else {
            do {
                let request = LoginInfoRequest(logInfo: loginInfo)
                let response = try await APIClient().send(request)
                return response
            } catch APIError.networkError {
                fatalError("ネットワークエラー")
            } catch APIError.decodingError {
                fatalError("デコードエラー")
            }
        }
    }
}
```

## 注意点
このままだとリリースビルドをした際にも開発用のパラメータが出てしまうため、Active Compilation Conditionsを用いて、Build Phaseの一番最後にRelese Buildの際にはSettings.bundleを削除するScriptを作成する必要がある
![](https://storage.googleapis.com/zenn-user-upload/5f35b8fad4f0-20230310.png)
Reactを学んで気づいたこと

## わかったこと
Reactを学んできて、あれそうなんだ、という気づきを記事にしていく。
## 理解: モジュール化
### モジュール全体を丸々いれたい時
<ul>
    <li>名前なし（default）モジュールをimportする</li>
    <li>1ファイル1モジュールが原則</li>
    <li>ES6で標準？</li>
</ul>

```App.js
// （一部切り抜き）
import Home from "./Home";
```
<ul>
    <li>コンポーネント</li>
</ul>


```Home.js
const Home = () => {
    return(
        <>
            <h1>Home</h1>
        </>
    );
}
export default Home;
```
<ul>
    <li>App.jsにimportすると</li>
</ul>

```App.js
import Home from "./Home";
function App(){
    return(
        <div className="App">
            <Home />
        </div>
    );
}
```
こんな感じ。
### 関数ごとのimport
<ul>
    <li>{}の中に入れたい関数をimportする</li>
<ul>

```App.js
import { Home, About } from "./HomeAbout";
```
<ul>
    <li>コンポーネント</li>
</ul>

```HomeAbout.js
// 関数に名前をつけていないver
export function Home(){
    return(
        <>
            <h1>Home</h1>
        </>
    );
}

// 関数に名前をつけているver
export const About = () => {
    return(
        <>
            <h2>About</h2>
        </>    
    );
}
```
## 便利: リストの表示
### map関数
<ul>
    <li>keyとvalueを使って展開していく</li>
</ul>

```App.js
function App(){
    const fruits = [
        {   id: 1,
            name: 'banana',
        },
        {   id: 2,
            name: 'apple',
        },
        {   id: 3,
            name: 'chocolate', 
        },
];
    return(
        <ul>
            { fruits.map((fruit) => (
                <li key={fruit.id}>{fruit.name}</li>
            ))}
        </ul>
    );
}
```
<b>結果：ちゃんと展開されている</b>

・banana
・apple
・chocolate

### filter関数
<ul>
    <li>その名の通り,条件で絞りこむ</li>
</ul>

``` App.js
const fruits = [
        {
            id: 1,
            name: 'banana',
        },
        {
            id: 2,
            name: 'apple',
        },
        {
            id: 3,
            name: 'chocolate', 
        },
    ];
const UnChocolatefruits =
 fruits.filter((fruit) => fruit.name !== 'chocolate');
```

<b>結果：ちゃんと展開されている</b>

・banana
・apple
Laravel9 Eloquent ORMでCAST＆$visibleプロパティの巻

###テーブル内のデータ”E2201”を取得するときに苦労したことメモ
####データベーステーブルの全中身をJSON形式で取得
```
public function readTable()
{
$list = \App\Models\Xxxtb::all();
return response()->json(['lists' => $list]);
```
XxxtbControllerで上記JSON取得を記述し、それをXxxtb.blade.phpに出力する。超簡単！ところが
⇒Xxxtbs実際のテーブルのコード列に入っている’gkno’のデータが
22E01⇒220
22E02⇒2200
22E03⇒22000．．．．．．
22E10⇒220000000000
22E017⇒2200000000000000000
というデータとしてJSONの中に納まっている。
どうやら数値としてパース解釈されているらしい。
しかも自分で```json_encode();```とかしている訳ではない。
もちろんDBのデータ型もCHAR型。
途方に暮れた。で見つけた！
[Laravel9日本語マニュアル](https://readouble.com/laravel/9.x/ja/eloquent-mutators.html)
MODELで以下のようにしてJSON化すれば解決！

```$visible```プロパティを使用して、モデルの配列とJSON表現に含める必要のある属性を定義する。モデルが配列またはJSONに変換されると、$visible配列に存在しないすべての属性が非表示になります。
```
class GakuseiTb extends Model
{
    
    use HasFactory;
    protected $connection = 'sqlsrv2' ;
    protected $table = 'Xxxtb';
    protected $primaryKey = 'gkno';
    protected $updated_at = 'kodate';
    const CREATED_AT = Null;
    protected $visible = [
        'gkno',
        'nname',
        'ename',
        'sex',
        'nen',
        'seinenymd'
    ];
    protected $casts = ['gkno' =>'string',
                        'seinenymd'=> 'date:Y-m-d',
                        'nymd' => 'date:Y-m-d',
                        'symd'=> 'date:Y-m-d',
                        ];




    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
    }
   
}
ServiceNow カタログに任意のWebページのURL、メールアドレスを掲載する

# カタログに任意のWebページのURL、メールアドレスを掲載する
サービスカタログに、使用方法のマニュアル、ServiceNow で作られたものではない申請ページ、問い合わせ先のメールアドレスなどを掲載したいことがあります。 

Service Catalog＞Maintain Items の代わりに Content Items を選び、下記のようにしてアイテムを作成します。

- Content Type  : External Content
- Target : New Window/Tab
- URL : 飛び先の URL   (メールアドレスの場合は、mailto:に続けてメールアドレス)

![ct1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707437/2af06cc3-bee6-eb28-96f7-40b31b793788.png)

上記のアイテムはこのようにカタログに表示されます。

![ct2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707437/7332da4d-3037-af20-3a99-e90b73682a73.png)

表示できましたが、そっけなくてさびしいですね。 説明を追加してみましょう。

System UI＞UI Policies で Set fields for URL を選び、UI Policy Actions 関連リストの中の Short Description のVisible を False から True に変更します。

（ちなみに、Content Items の Content Type ごとに UI Policy が用意されています。Set fields for URL は、External Content 用の UI Policy です）

![ct3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707437/37074422-4c9b-31b2-61ae-f64042b8a823.png)

Short Description が入力できるようになりました。さっそく入力してサービスカタログでの表示を確認しましょう。
![ct3.1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707437/3a45a941-5688-b6a9-4f70-b5c566a9fd65.png)


![ct4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707437/37a689b6-eba6-3418-f19c-a3747d3688bb.png)

なお、余談ですが Short Description の代わりに Description を入力してもサービスカタログ上には表示されません。検索で使用されるだけとなります。

弊社ブログへも[同様の記事を投稿](https://alpcom.co.jp/blog/20230310/?utm_source=Qiita&utm_medium=post&utm_campaign=ysi&utm_id=20230310)しております。
【Docker】2023年最新Docker Desktopをインストールする方法

1.初めに
---
こんにちは。YoutubeやTwitchで配信しておりますアニメ、漫画、ゲーム、Vtuber大好きオタクのVtuber
久遠楽 (https://twitter.com/kuonraku0210) です。
今回はDockerを入れていきたいと思います。
最終的にはDockerにDjangoをいれてWebアプリケーションを作成したいと思っています。

2.Docker Desktopのインストール
---
* 公式サイトよりDocker Desktopをインストール
https://docs.docker.com/desktop/install/windows-install/

1.ダウンロードしたインストーラを起動するとディスクトップにDocker Desktopが作成されます。
2.Docker Desktopを起動し、画面に従いインストールします
3.この画面が表示されたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3226293/0105f7f0-fbef-4bd8-dec9-c8539bfed22b.png)

3.起動しない場合
---
Docker Desktopを起動時にこの画面が表示され、Docker Desktopを起動できない場合は下記サイトの手順を行ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3226293/fd96ac40-2e21-0ce3-503f-d3cf4c6fce4b.png)

***手順↓***

https://learn.microsoft.com/ja-jp/windows/wsl/install-manual#step-4---download-the-linux-kernel-update-package

3.最後に
---
これでDockerをインストールすることが出来たので
次はDocerにDjangoをインストールしてみたいと思います。

【宣伝】
APEXやヴァロラントなどのFPSをメインに毎日20時頃から配信をしているのでよければチャンネル登録していただければ嬉しいです。
git reset --hardをして訳のわからないことになった。

# git reset --hardをして失敗
初心者の知識ではわからないぐらい何かおかしいことが起きた。
怖い。
マイグレーションファイルは消えてしまうし、ステータスも知ることができない。
```
*********@mbp garden % rails db:migarate status
/Users/************/*******/******/config/boot.rb:4:in `require': cannot load such file -- bootsnap/setup (LoadError)
        from /Users/************/*******/******/config/boot.rb:4:in `<top (required)>'
        from bin/rails:3:in `require_relative'
        from bin/rails:3:in `<main>'
```
# `require': cannot load such file -- bootsnap/setup (LoadError)で検索
> @nicolasmlv you are using bootsnap (0.2.12) which did not include this file. We are now on bootsnap 1.1.2 (After jumping from 0.3.x which introduced bootsnap/setup).

Please run bundle update bootsnap :)

https://github.com/Shopify/bootsnap/issues/73

何いっているかわからないが、```bundle update bootsnap```を行った。
```
*********@mbp garden % bundle update bootsnap
Could not find gem 'bootsnap'.
```
# どうやらgem 'bootsnap'が必要らしい
```rb
gem "bootsnap", require: false
```
# もう一回```bundle update bootsnap```を行った。
```
*********::@mbp garden % bundle update bootsnap
Fetching gem metadata from https://rubygems.org/..........
.
.
.
An error occurred while installing msgpack (1.6.1), and Bundler cannot continue.
.
.
.
An error occurred while installing msgpack (1.6.1), and Bundler cannot continue.

In Gemfile:
  bootsnap was resolved to 1.16.0, which depends on
    msgpack
```
ダメだった。
行が多すぎて見落としているところもあるかもしれない。
困った。

# 最後にrails db:migrateを行った。
```
**********@mbp garden % rails db:migrate                               
Could not find gem 'bootsnap (~> 1.16.0)' in locally installed gems.

The source contains the following gems matching 'bootsnap':
  * bootsnap-1.4.5
  * bootsnap-1.11.1
Run `bundle install` to install missing gems
.
.
.
An error occurred while installing msgpack (1.6.1), and Bundler cannot continue.

In Gemfile:
  bootsnap was resolved to 1.16.0, which depends on
    msgpack
```
# 解決しそうな文言発見
```
* bootsnap-1.4.5
  * bootsnap-1.11.1
Run `bundle install` to install missing gems
```
どれかわからないがとりあえず```bootsnap-1.11.1```を使って検索
```
gem 'bootsnap', '~> 1.11', '>= 1.11.1'
```
# 出典
https://rubygems.org/gems/bootsnap/versions/1.11.1

# 解決 
migrateとstatusはできるようになった。
しかし
これからまたエラーが出るだろう。
パニックになった。
Tableau:日付フィルター今日の最後（23:59:59）を表示させるやつ

## ググっても出てこなかったのでここに記す。
*  業務で要求された際に調べても解決できなかったので、<br>調べたものを組み合わせて解決させたもののシェアです。


# 結論
あらかじめToday関数を用意しておきます。<br>メジャーの新しい計算フィールドで、<br>`DATEADD('second', -1, [Today] + 1 )`<br>これで指定日の23時59分59秒を取得できます。<br>（名前は「Today Last」てつけました。）<br>これでビューを開いた時に今日の最後が表示されるはずです。。。

※業務でしかTableauつかってないため画像なくてすみません。m(_ _)m

## おわりに
他にも方法あったり、なにかご意見あれば教えてください。
誰かの役に立てば幸いです。
（少なくとも「あの頃」の自分には役立つ！）

あざした。
変数名に動的にアクセスする

# 概要
数字のプロパティ名(a1やa2など)にテンプレートリテラルでアクセスするとエラーがおきてうまく行きませんでした。
たとえば以下のような書き方です。

# NGパターン
```
interface contentsModel {
  a1: string;
  a2: string;
  a3: string;
}

const contents: contentsModel = {
  a1: 'コンテンツA',
  a2: 'コンテンツB',
  a3: 'コンテンツC',
}
const num = "1"
const value = contents[`a${num}`]; // ←この書き方だとうまく行かない
```


エラー内容
```
Element implicitly has an 'any' type because expression of type '`a${num}`' cant be used to index type 'model';
```

# OKパターン
原因
・numが文字列型ではなく、``文字列を含んだ数値型``とみなされるためのようでした。

以下のように``[key: string]``を型につけて、明示的にプロパティの方を示すことによって解決できました。
```
interface contentsModel {
  + [key: string]
  a1: string;
  a2: string;
  a3: string;
}
```
RailsでLike機能を追加する手順をchatGPTに聞いてみた。

`質問1`
ruby on rails でcookieとajaxを使ってlike機能を実装する方法を教えて。

テーブルにはLikeカラムがあって、Likeボタンを押されるとそこが+1される想定。

---
Ruby on RailsでCookieとAjaxを使用してLike機能を実装する手順を以下に示します。

1、コントローラーにアクションを追加する
まず、コントローラーにLikeアクションを追加します。このアクションは、Likeをカウントするためにデータベースを更新します。

```ruby
class PostsController < ApplicationController
  def like
    post = Post.find(params[:id])
    post.update(like: post.like + 1)
    render json: { status: 'success', like_count: post.like }
  end
end
```

2、ルーティングを設定する
Likeアクションをルーティングに追加します。

```ruby
Rails.application.routes.draw do
  resources :posts do
    post 'like', on: :member
  end
end
```

3、ビューにLikeボタンを追加する
Likeボタンを追加します。以下の例では、data-post-id属性に投稿のIDを設定します。

```html
<button class="like-btn" data-post-id="<%= post.id %>">Like</button>
```

4、JavaScriptでAjaxリクエストを送信する
JavaScriptを使用して、Ajaxリクエストを送信し、サーバー上でLikeアクションを呼び出します。以下の例では、jQueryを使用しています。

```javascript
$(document).on('click', '.like-btn', function() {
  var postId = $(this).data('post-id');
  $.ajax({
    url: '/posts/' + postId + '/like',
    type: 'POST',
    dataType: 'json',
    success: function(data) {
      if (data.status === 'success') {
        // カウントを更新する
        $('.like-count[data-post-id="' + postId + '"]').text(data.like_count);
      }
    },
    error: function() {
      console.log('エラーが発生しました。');
    }
  });
});
```
以上で、Ruby on RailsでCookieとAjaxを使用してLike機能を実装する手順が完了しました。

---
`質問2`
上の機能に加えて、likeを押したことをcookieに保存しておいて、かつ画面表示にも反映するにはどうすれば良い？

---
Likeを押したことをCookieに保存して、かつ画面表示にも反映するには、以下のような手順が必要です。

1、Likeを押したことをCookieに保存する
JavaScriptを使用して、Likeボタンがクリックされた場合に、CookieにLikeしたことを保存します。以下の例では、document.cookieを使用して、CookieにLikeした投稿のIDを保存しています。

```javascript
$(document).on('click', '.like-btn', function() {
  var postId = $(this).data('post-id');
  // CookieにLikeした投稿のIDを保存する
  document.cookie = 'liked_post_' + postId + '=1';
  $.ajax({
    url: '/posts/' + postId + '/like',
    type: 'POST',
    dataType: 'json',
    success: function(data) {
      if (data.status === 'success') {
        // カウントを更新する
        $('.like-count[data-post-id="' + postId + '"]').text(data.like_count);
      }
    },
    error: function() {
      console.log('エラーが発生しました。');
    }
  });
});
```

2、CookieからLikeした投稿のIDを取得する
画面を読み込んだときに、CookieからLikeした投稿のIDを取得します。以下の例では、document.cookieとString.prototype.match()を使用して、CookieからLikeした投稿のIDを取得しています。

```javascript
// CookieからLikeした投稿のIDを取得する
var likedPosts = document.cookie.match(/liked_post_\d+=1/g);
var likedPostIds = [];
if (likedPosts) {
  likedPosts.forEach(function(likedPost) {
    likedPostIds.push(likedPost.match(/\d+/)[0]);
  });
}
```

3、画面表示にLikeした投稿のIDを反映する
取得したLikeした投稿のIDを使用して、画面表示にLikeを反映します。以下の例では、取得したLikeした投稿のIDを使用して、Likeした投稿のボタンにactiveクラスを追加して、ボタンの色を変更しています。

```javascript
// Likeした投稿のIDを使用して、画面表示に反映する
if (likedPostIds.length > 0) {
  likedPostIds.forEach(function(likedPostId) {
    $('.like-btn[data-post-id="' + likedPostId + '"]').addClass('active');
  });
}
```
以上で、Likeを押したことをCookieに保存して、かつ画面表示にも反映する手順が完了しました。
Windowsのエクスプローラからコピー＆ペーストでファイル名やフォルダ名を取得する方法

# はじめに
初投稿です。拙いところもあるかと思いますが何卒ご容赦くださいませ。
画像はありません。

# この記事の対象者
- Windowsユーザ
- ファイル名やフォルダ名をコピー＆ペースト（`Ctrl + C`, `Ctrl + V`）で取得したい人

# 前置き
元々Windowsを10年使い、その後Macを10年ほど使用し、最近Windowsユーザに戻りました。
MacではFinderから `command + C` と `command + V` でファイル名やフォルダ名を取得できていました。しかし、Windowsでやってもできない。仕方なくコマンドプロンプトを開いて `Dir /b` と打ち込んだり、Pythonでそれ用のアプリを作ったりしました。

# 問題（？）発生
ふと何かの拍子に、Windowsのエクスプローラでファイルを `Ctrl + C` してテキストエディタで `Ctrl + V` したらファイル名がペーストできました。
でも、弊チームのメンバーに情報共有したところ、「できない」の声多数。

# 原因を探る
「エクスプローラの拡張アプリをインストールしてたからか？」と思い、アプリをアンインストールして試しても、ファイル名のコピー＆ペーストができる。
自宅にある3台のWindowsすべてでできる。
はて？ 何らかのアプリのせいか？

# 共通点を見つける
3台のWindows全部でエクスプローラからコピーして、VSCodeにペーストして、できている。
ということは、VSCode？

# 解決
「できない」と言ったチームメンバーにペーストしたアプリが何か訊いたところ、「メモ帳とTeraPad」と。VSCodeは試してない！
当方ではメモ帳と、Crescent Eveにペーストしようとしてみたらできない。VSCodeではできた。
「VSCode」で試してもらったら、できたとのこと。

# もしかしたら
VSCodeのバグかもしれません。逆に、VSCodeだけに実装されているのかもしれません。

# 結論
なぜVSCodeではできるのか、よくわからない。
Pythonでアプリ作らなくても良かったかもしれない。
孤独なリモートワークをphindとGithub Copilotと乗り切る

# はじめに

人によってはオフィスに行くことが少なくなった昨今、ハマった時にさっと質問できる人もおらず思ったより時間がかかってしまった、なんてことは誰にでもあるかと思います。ChatGPTを触り始めた時、こいつを相談相手にすると色々捗るぞと思いましたが、現状開発時には他のツールをまず使うようになったので今時点（2023/3/13）の私の体制を紹介します。

## 困った時の相談役、先生: [Phind (The AI search engine for developers.)](https://www.phind.com/)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556201/9e3e4383-36f0-7b48-22b2-13b7347777d1.png" width=500>

`The AI search engine for developers.`とある通り、開発者を意識して作られています。
開発中に使っていてChatGPTと比較してみて以下の違いがあると感じました。

1. **質問に対する回答のサマリ**+**具体的なソースコードor手順**という順番で回答してくれるのでわかりやすい
2. **日本語でもレスが早い**
    - ChatGPTだと英語で入力した時と日本語の時とで、日本語はゆっくりな回答ですがこちらは日本語でも速いです
3. **出典付きで結果が返る**ので内容の正誤を確認しやすい
    - 下のサンプル画像のように回答内容の文末（赤枠部分）に出典元のリンクが付きますので、どの答えがどの出典元からの情報かわかりやすいです
     ![Screenshot 2023-03-13 at 10.43.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556201/73e49ad8-412b-a759-4088-1cc984b0cb63.png)
4. **人に共有しやすい**
    - 検索した後、URLのクエリパラメータの部分が、`search?cache=xxxxx`という形式に切り替わります。それを人に渡せば同じ回答結果をそのまま人に共有できます。コピペしなくて良いので楽です（cacheがいつexpireするかまでは未確認です）
    - 例（phindに遷移します）
        - [「PythonでMQTTブローカーにPublishするスクリプトを作りたいです。」](https://www.phind.com/search?cache=66c80d5e-46ff-4ad4-bb65-cdce2203af2d)

:::note info
ChatGPTのように文脈を理解しているので、phindの回答にしたいして追加質問をしていくこともできます。
:::

## ペアプログラミング相手: [GitHub Copilot](https://github.com/features/copilot)
こちらは使ってみたことがある方も多いかと思います。ソースコードを書いていると記述内容をサジェストしてくれます。
例えば適当に`.py`のファイルを作成し、
```python
# publish messages to the broker
```
というコメントだけを自分で書いたところ、こちら↓のソースコードが生成されました。コメントだけ羅列して書いていくだけでプログラムが書けてしまったりします。(動作検証してません、`import pika`してないのでこれだけではまず動きませんが)
```python
def publish_message(message):
    # connect to the broker
    connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
    channel = connection.channel()

    # create a queue
    channel.queue_declare(queue='hello')

    # publish the message
    channel.basic_publish(exchange='', routing_key='hello', body=message)
    print(" [x] Sent %r" % message)

    # close the connection
    connection.close()
```

### GitHub Copilotのセットアップ
一応セットアップ手順を載せます。ご興味のある方はどうぞ。

Github Copilotのサインアップ画面から登録を行います。10ドル/月かかりますが60日間のトライアル期間があります(2023/3/10時点)。
[GitHub Copilot](https://github.com/github-copilot/signup)

住所やクレジットカードなどの情報を入れてサインアップが完了すると使用できる状態になります。
私は普段VSCodeを使っているのでここから使用します。

VSCodeを開いてGitHub Copilotをインストールするだけです。
![Screenshot 2023-02-28 at 14.44.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556201/127f177c-11ff-368f-93ff-c82e8677ecd1.png)

インストールができたら、あとはファイルを開いて何かしら書き始めれば使えます。

:::note info
地味に便利だったのか、単に英文を書いてみた時にも精度の高いサジェストしてくれることです。英語のメールを書くときなどにも便利です。
:::


## どう使っているのか
ChatGPTでもphindでも言えることですが、回答の内容にソースコードの記述が一部抜けているということが日常的に起きます。そういった際に抜けをGithub Copilotが補完してくれることが多いです。

ちょっとしたものを作るのであればphindで大枠のソースコードを生成させてしまい、細かい記述の抜け漏れはGithub Copilotで埋めて仕舞えば時間をかけずに結構色々作れてしまいます。

新しいフレームワークを触る時など使ったことのない技術を使う時も、まず動くものを作らせて、それをいじりながらチュートリアルやリファレンスを見て試すということができるので一人でやっていても理解を早めることができると思います。

ただ内容を理解せずに頼って作りすぎると`作るの5分、デバッグ24時間`みたいなことになるのであくまでツールとしてですね。

https://mastodon.social/@nixCraft/109467334494967033

ぼっち作業で行き詰まることがかなり減ったので私のようにリモートで一人でやっている人には心強い味方になると思います。
ShaderGraphでエッジを整理する(UEのリルートみたいなの)

エッジにマウスカーソルをのせて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2570514/597ccaf7-594e-2a4d-7121-c83b617d34ce.png)

ダブルクリック!!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2570514/893d80ac-f3a8-de58-9b37-8b94c7af883f.png)

もしくはエッジを右クリックしてAdd Redirect Nodeでもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2570514/33f47988-e6de-b4a2-c5c7-fd5355e1a26e.png)

おわり！

これめっちゃ大事な機能だと思うのですが、公式マニュアルに載っていません。(たぶん)
一応APIリファレンスを読むとクラスはRedirectNodeとして記載があるのですが...
しかもこの機能CreateNodeメニューからはアクセスできません。
気づいてない人も結構多いのではないでしょうか?


こーゆーだいじなのはちゃんとゆっといてよね！！！！
(多分)Uipathで一番簡単なWebhookチャット投稿

#  ■１.背景
最近別の業務でUipathを触れることが多くなりました。
勉強がてら、Uipath経由でGoogle Chatを使おうとしていたのですが……
##### 「どこにも情報がない」

てかそもそもGoogle ChatのAPI情報が少ない。（Slackなら死ぬほどあるのに）
APIでチャット投げるってみんなしないのかしら……
どうにかしてGoogle WorkspaceのWebhook経由で使う方法とかないのかなぁと探すこと幾億年、ようやく見つけました。

https://www.youtube.com/watch?v=8bB7O4nqENE


動画はSlackのガイドではありますが、ちゃんとGoogleでも使えるので安心してください。


#  ■２.実践
ステップは大きく3つです。
　1. Webhookを連携先のチャットから入手する。
　2. WebAPIのパッケージを導入する。
　3. JSON形式でチャットを送信する。


---------------------------------------
#### 　▼1　Webhookを連携先のチャットから入手する
GASを触ったことあるなら「なんだ、いつものか」になりますよね。
最近仕様変更が入って、WebhookURLは画像の通り``アプリと統合``の中に格納されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3036127/581106d0-9e17-e98f-432b-d78b76e5db83.png)
Google WorkspaceでBot作ったことないと戸惑うかもしれませんが、ポップアップの``Webhookを管理``から適当な名前を付けてWebhookを保存します。うまくいくとURLが出るはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3036127/075bdaf3-44fc-4fc5-3417-840d69ba0c20.png)
後ほどこのURLをUipathで使いますので、メモ帳かなんかに残しておきましょう。



---------------------------------------
#### 　▼2　WebAPIのパッケージを導入する
UipathからWebAPIのパッケージを導入します。公式のパッケージを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3036127/1527435b-3439-7c86-40d3-f1b01691ba61.png)
ダウンロードが完了すると、``HTTP Request``が使えるようになるので、シーケンスにぶち込みます。
この時設定がごちゃごちゃとでますが、無視して閉じて大丈夫です。かわりにプロパティからいろいろ設定をいじくります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3036127/0fdb7a7d-7cf4-bc75-28b0-8b5b587c2d34.png)
↑の図の赤枠で囲った``Input``の中身を次のように変更します。
```HTTP Request in Main.xaml
Accept Format : ANY
Request Method : POST
Request URL : "1で保存したWebhookURL"
```
WebhookURLであれば実はなんでもいいので、Slack, MS Teamsなど自身の使いたいWebhookを入れてください。WebhookURLの取得方法は各自でお探しください。

---------------------------------------
#### 　▼3　JSON形式でチャットを送信する
できる人はXMLでもいいです。メッセージ本体の内容を作って送り付けます。
ここではJSON形式について詳しい説明はしませんが、フォーマットの一部だと思っていください。

```.JSON
"{'text':'textmessagehere'}"
```
↑をコピーして、``Options``の``body``に格納します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3036127/7c6db00b-1190-e3bc-814b-99369e30926e.png)



以上です。

あとはファイルを実行してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3036127/b5a32b4b-a99a-f00e-6fcf-ac3f5b1f2ffc.png)
成功ですね。ちなみに送るメッセージは変数を使って送ることもできます。事前にassignを組み込んでおけば、サブルーチンとしても利用できます。
```.JSON
"{'text':'"+string_MessageContent+"'}"
```

# ■最後に
同一スレッドの投稿なども試したかったですがわからなかったです。
cURLとかでAPIを叩きに行った方がいいかもしれませんが、RPAは脳死でやりたいので本末転倒です。（保守や引継ぎとか考えるのがだるいので……）

活用方法などがあればぜひ教えてください～
f=x*log(x/p),g=exp(f)「滋賀県立大学2023年前期第４問」をwolframalphaとsympyでやってみたい。

sympyのplotでグラフを書いてみました。

オリジナル

https://mathmathmass.exblog.jp/33038921/

# wolframで

https://www.wolframalpha.com/input?i=diff%28x*log%28x%2Fp%29%29&lang=ja



勉強中。

# sympyで
```python
from sympy import *
p=Symbol  ('p',real=True)
x=Symbol  ('x')
f=Function('f')(x)
g=Function('y')(x)
f=x*log(x/p)
g=exp(f)
print("#(1)",diff(f,x),",",diff(g,x))
print("#(2)",integrate(x*diff(g,x)/g, (x, p, 2*p)))
xk=solve(diff(g,x),x)[0]
pp=solve( Eq(xk,1),p)[0]
print("#(3)[1]",1 ,"        ,",g.subs({x:1 }))
print("#(3)[2]",xk,","        ,g.subs({x:xk}))
myGraph=plot(
             g.subs({p:2}),
             g.subs({p:float(E)}),
             g.subs({p:3}),
             0,
             (x,1,3),legend = True, show = False)
myGraph.show()
#(1) log(x/p) + 1 , (log(x/p) + 1)*exp(x*log(x/p))
#(2) 3*p**2/4 + 2*p**2*log(2)
#(3)[1] 1         , 1/p
#(3)[2] p*exp(-1) , exp(-p*exp(-1))
```

上からP=2,e,3 の順です。
![0png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/addd41bb-bcaa-f1ed-d13e-83092b658fdf.png)