OmniAICreator/Qiita-1.07M huggingface dataset:
チャート式Ruby

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# 概要

Rubyの初心者向け教科書が適切なのが見当たらないので，自分で書くことにしました．これは，Ruby = TDD + English という図式が自分の中で出来上がっていて，でも，それをうまく学生に伝えることができないもどかしさからです．

プログラミングを勉強するには，「数学の問題を解くときと同じように試行錯誤しなさい」と言います．でも，その試行錯誤のやり方を本当に教えられているのか疑問です．解答を丸写しするのでなく，動作を理解するために，解答を分解して作り上げていく作業が必要になります．これを実践する手順に，欧米では，TDD(Test Driven Development:テスト駆動開発)と名が付けられたんだと思います．

日本では，写経と呼ばれますが，さらにわかりにくくなりますね．そこで，日本で昔からお馴染みのチャート式に従って，どうやって動く綺麗なコードを書くかを紹介します．


# チャート式の体裁と内容

チャート式と言った時，「たくさんの問題をずらずら解いて行くこと」と思っている研究者がいて驚きました．チャート式の本質はそこではなく，

1.  簡単なお題
2.  詳しい解法
3.  類題

です．この基本に沿って

1.  [puts](https://qiita.com/daddygongon/items/1b0f0ff3fb9d60418289) ; 出力のみ,先ずはhello worldでしょ
2.  [variable and method](https://qiita.com/daddygongon/items/c51f3e0695174bb3c508) ; method, Kent Beckの至言がある
3.  [if, case, array, each by leap year](https://qiita.com/daddygongon/items/a550bde1ed6bff5217d8) ; TDDでcaseまで
4.  [assert\_equal](https://qiita.com/daddygongon/items/f6cea87314ee26e130ea) ; gem, colorizeの継承, require, 重複実行の予防
5.  [recursive Fibonacci](https://qiita.com/daddygongon/items/1bb27b8920c201d5c520) ; recursion(再帰)をtestで
6.  [hello class](https://qiita.com/daddygongon/items/969ad5112878f6dab844) ; class化

なんかを紹介します．チャート式のもう一つの本質である「体裁」は，htmlなんで，諦めてください．


# 仕上げ問題

次のような課題が解決できるはずです．

-   [roman numerals](https://qiita.com/daddygongon/items/2d0a73a51ddab2d9da1b) ; ローマ数字
-   [google recruit](https://qiita.com/daddygongon/items/ba94b0f2a73990fc6a07) ; Googleの有名なリクルート問題


# Ruby開発周辺環境

Rubyの言語仕様を覚える前に，Rubyが足場にしているLinuxの思想に馴染んでください．CUI, option, pipe, filterなんかです．その他いくつかのRuby開発における便利ツール(ecosystemと呼ばれることも．．．議論あり)がありますので，紹介していきます．

1.  [Shell + Emacs](https://qiita.com/daddygongon/items/3ab780f22e620c3f8298) ; hello worldの，その前に
2.  [my\_help](https://qiita.com/daddygongon/items/967d715e914a8269e237) ; CUIでメモ，org-modeの使い方
3.  [bundler](https://qiita.com/daddygongon/items/14218c96df5cbcf35c62) ; scaffold(足場)構築, CoC, gem
4.  [rake](https://qiita.com/daddygongon/items/1c2d6d2895333ccf5e62) ; なんでも自動化, system
5.  [rubular](https://qiita.com/daddygongon/items/5e2de543400fe56be768) ; 正規表現, rubular
6.  [fsm](https://qiita.com/daddygongon/items/c84eaea29a14a5d05945) ; ファイルの読み込み, finite state machine(有限状態マシン)
7.  [thor](https://qiita.com/daddygongon/items/19e58f757fab197bc347) ; 複雑なCLI, Rubocop

などかな．


# 学生の作業

(これは2019年度の反省メモです，2020では改良してqiitaを使っています)学生が類題を独自に解いたかどうかをどうやって判定するかが問題になります．

-   tddのred状態を残す
-   green状態を残す
-   refactoringを晒す

というのが一つの解になるのではと期待しています．まさに，gitのlog状態．．．うーーーん．そこを残すのは．．．


## 文書作成

-   学習者自らが文書を作成するというのをやってみてください．
-   自分の書いたcodeを表示させるというやり方です．
-   卒論を仕上げるのと同じようにして，文書を書くという作業を通じて，codeを覚えていくというものです．
-   platexと違って，html outはどんな環境でもできるのでそいつを使います．=> qiitaに変更(20f)



------
 - **source** ~/git_hub/ruby_docs/chart_style_ruby/README_chart_style_ruby.org
【rails】deviseにストロングパラメーターを追加する

deviseと言うgemをインストールすると、ログイン、サインアップ機能が簡単に実装できますが、
あらかじめストロングパラメーター（パスワード、メールアドレス）が備わっています。

しかし、ログイン、サインアップをする際に、他のストロングパラメーター（名前、画像等）も欲しいことありますよね。

その場合にストロングパラメーターを追加する方法をアウトプットいたします。

※deviseの詳しい説明については
https://qiita.com/gogotakataka1234/items/0125b7d50ded8968a745
を確認ください。

#devise_parameter_sanitizerを使おう！

devise_parameter_sanitizerをメソッドを使うと、deviseで設定されているストロングパラメーターにパラメーターを追加することができる。

使い方の例

```csharp
devise_parameter_sanitizer.permit(追加したいメソッドの種類, keys: [追加したいパラメーター名])
```

例えば、サインアップ時に画像の情報を必要とする場合

```csharp
devise_parameter_sanitizer.permit(:sign_up, keys: [:image])
```

これでサインアップ時に画像をアップロードするdeviseが実装されました。
あとは、数点気をつけなければいけないことがあります。

#devise_parameter_sanitizerを使う上での注意点
①devise_parameter_sanitizerメソッドはbefore_actionに設定します

②devise_parameter_sanitizerメソッドは記述するのはDeviseのコントローラを継承したコントローラに実装する。

③devise_parameter_sanitizerメソッドを直接before_actionに記述してはいけない

あれ？①と言っていることが違う！？
実は直接before_actionに設定していはダメなんです。
基本的には「configure_permitted_parametersメソッド」のなかでdevise_parameter_sanitizerを定義します。
そしてconfigure_permitted_parametersをbefore_actionに設定するのです。

よくわからない方、例を見てみましょう。

```csharp
before_action :configure_permitted_parameters

  def configure_permitted_parameters
   devise_parameter_sanitizer.permit(:sign_up, keys: [:image])
  end
```

configure_permitted_parametersは許可するパラメーターを設定すると言う意味。


以上になります！
Oracle Cloud Infrastructure Mobile Appがリリースされたよ

# Oracle Cloud Infrastructure用のモバイルアプリがリリース！

Oracle Cloud Infrastructure用のモバイルアプリケーションがリリースされた(2020/11/03)。

* **[The Oracle Cloud Infrastructure Mobile app is now available](https://docs.cloud.oracle.com/en-us/iaas/releasenotes/changes/ff7454b7-ef34-4917-8243-19acc57be9c7/)**
* **[Oracle Cloud Infrastructure Blog: Oracle Cloud Infrastructure mobile app anytime, anywhere](https://blogs.oracle.com/cloud-infrastructure/oracle-cloud-infrastructure-mobile-app-anytime-anywhere)**
* **[Manual: Using the Mobile App](https://docs.cloud.oracle.com/en-us/iaas/Content/GSG/Concepts/mobile.htm)**

対応OSは以下のとおり。

* **Android 8 and later versions** [play.google.com/store/apps](https://apps.apple.com/jp/app/oracle-cloud-infrastructure/id1534250806)

* **iOS 11 and later versions** [apps.apple.com/us/app/oracle](https://play.google.com/store/apps/details?id=com.oracle.oci.console.ocimobile&hl=ja_JP&gl=JP)
# Androidにインストールしてみた

1. Google Playストアを起動して「Oracle Cloud Infrastructure」を検索。「Oracle Cloud」だけだと、他にも大量にヒットするので要注意。
2. Oracle Cloud Infrastructureを見つけたらインストールを開始。

![oci_mobapp01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/3eebaced-d8b6-3e9a-6cc9-042dede1c92b.png)

3.起動したら「Sign In」をタップ。

![oci_mobapp02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/fe8109fb-54c4-7f38-9890-7005fdc8235b.png)

4.画面下の「I Agree」をタップ。スクショの取りミスすみません。

![oci_mobapp03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/a02642ab-35f1-4fbd-7c39-1259e7c969bb.png)


5.テナント名を入力（画像無し）。
6.IDCSサイン・インのときは「Continue」をクリック。IAMで直接サイン・インするときはページ下部の下向き矢印をタップ。

![oci_mobapp04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/7ce4f2b0-8444-dcff-ad97-0a44e4fa643b.png)

7.ユーザー名とパスワードを入力して「サイン・イン」をタップ。

![oci_mobapp05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/048c5d0b-5160-bd67-c91f-c285d8f2c59f.png)


8.無事サイン・インできました。いままでもスマホのブラウザでサイン・インできたけれど、専用品らしくサクサク動く。少ししかさわってないけれどね。

![oci_mobapp06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/9c2b4d8b-1395-c965-fa34-4227e251a9f5.png)

# Oracle Cloud Infrastructure Mobile Appで何ができるのか？

現時点では参照専用で、作成/削除/起動/停止はできない。起動/停止くらいできると便利なんだけどなあ。純正品では無いけれど、iPhone用の[OCI Manager](https://www.oc-blog.com/iphone/)は多少の操作はできるっぽい。

Twitterには次のことができると書いてあった。

- View alarms
- Explore resources globally
- View monitoring and billing info
初心者便利ツール（アイデア検討中）

#メモ書き

素人でも最近のＩＴに参画できるために、あったらいいなと思うツール

#語学学習

情報収集に使っているサイトでは、英語で聞くことが多い
→すぐに翻訳して、回答を得たいが文策が苦手

* Deeplに投げる。 →　このサイトは文字数制限がないし、頭がいい
→改良としては、日→英→日→英ぐらいを繰り返して、アニーリングするのが良さそう
（これをWEBアプリでできるパッチ画面をつくる）

英語以外の学習
* 多国語辞書をつくる　→　日中英韓香の辞書　
→　google api（有料）→　一応完成した　→　つぎはヒアリングmp3の音声データ作成を追加すること


#親切コマンダー

これはCLIベースの悩み

* GITが出来ない
* GITIGNOREが分からない

GITが出来ない　→　コマンドを忘れる

ユースケースに遭遇　→　教えて（チャットボット）　→　親切さん登場し、ワンポイントを開設　→　チートシートが出来る　→　覚えたら合格バッジ、進級する


GITIGNOREが分からない　→　覚えられるかっ！

したいこと　→　テンプレートで生成　→　GIBO使う　※完了
見てもさっぱり？　→　AIで自然言語処理　→　全行にコメントを追加する


自分としては、チャットボットは初心者向け
AI自然言語処理　→　コメント記入は万人向け
→　将来的にはAIは、そういうところから普及していく


#その他

　ネタを思いついたら書いておく
[jQuery] シリーズ

#jQueryに関するまとめ

本家はこちら参照
https://jquery.com/


## jQueryとは
> jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript. jQueryは、高速で、小さく、機能豊富なJavaScriptライブラリです。HTMLドキュメントの走査や操作、イベント処理、アニメーション、Ajaxなどを、多くのブラウザで動作する使いやすいAPIでより簡単にすることができます。汎用性と拡張性の組み合わせにより、jQueryは何百万人もの人々がJavaScriptを書く方法を変えました。

jQueryとはJavaScriptをより利用しやすいまとめているライブラリーになります。

日々ウェブ開発するさいにちょこちょこ使っているので、まとめます。

jQueryに関する記事をまとめます（更新中）

## まずは基本の「き」
- [[jQuery] 基本の「き」](https://qiita.com/syantien/items/0c2a0873962b3ea058ea)

## 部分的にコンテンツを読み込みたいなら
- [[jQuery] [C#] [ASP.NET] loading partial view](https://qiita.com/syantien/items/7c1d1c449dc97f65330b)

## サーバーに対してリクエストを送信したいなら
- [[jQuery] Ajax](https://qiita.com/syantien/items/58dbf42be98cae9433cd)

## URLの取得、パラメターの取得

- [[jQuery] URLの取得、パラメターの取得](https://qiita.com/syantien/items/d7d9c788495ccd1d3d52)

## [Jquery] Validation

- [[Jquery] Validation](https://qiita.com/syantien/items/8928eb8aa7276c23e733)
Elastic Beanstalkでメモリとディスク残量の監視を行う

(事前にSNS側で通知を受けられるような準備はしておくこと)

.ebextensionにて以下を追加

```
packages:
  yum:
    perl-DateTime: []
    perl-Sys-Syslog: []
    perl-LWP-Protocol-https: []
    perl-Switch: []
    perl-URI: []
    perl-Bundle-LWP: []
files:
  /root/setup_alarm.sh:
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/bin/bash
      INSTANCE_ID="`wget -qO- http://169.254.169.254/latest/meta-data/instance-id`"
      REGION="`curl --silent http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region`"
      echo '*/5 * * * * root perl /opt/cloudwatch/aws-scripts-mon/mon-put-instance-data.pl `{"Fn::GetOptionSetting" : { "OptionName" : "CloudWatchMetrics", "DefaultValue" : "--mem-util --disk-space-util --disk-path=/" }}` >> /var/log/cwpump.log 2>&1' > /etc/cron.d/cwpump
      chmod 644 /etc/cron.d/cwpump
      chmod u+x /opt/cloudwatch/aws-scripts-mon/mon-put-instance-data.pl
      aws cloudwatch put-metric-alarm --region=$REGION --alarm-name WebDiskSpaceUtilization --alarm-description "Alarm when DiskSpaceUtilization exceeds 90 percent" --metric-name DiskSpaceUtilization --namespace System/Linux --statistic Average --period 300 --threshold 90 --comparison-operator GreaterThanThreshold  --dimensions Name=Filesystem,Value=/dev/nvme0n1p1 Name=MountPath,Value=/ Name=InstanceId,Value=$INSTANCE_ID --evaluation-periods 2 --alarm-actions #{SNSのARN} --unit Percent
      aws cloudwatch put-metric-alarm --region=$REGION --alarm-name WebMemoryUtilization --alarm-description "Alarm when MemoryUtilization exceeds 95 percent" --metric-name MemoryUtilization --namespace System/Linux --statistic Average --period 300 --threshold 95 --comparison-operator GreaterThanThreshold  --dimensions Name=InstanceId,Value=$INSTANCE_ID --evaluation-periods 2 --alarm-actions #{SNSのARN} --unit Percent
sources:
  /opt/cloudwatch: https://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.1.zip
container_commands:
  add-swap-space:
    command: "/bin/bash /root/setup_alarm.sh"
    ignoreErrors: true
option_settings:
  "aws:autoscaling:launchconfiguration" :
    IamInstanceProfile : "aws-elasticbeanstalk-ec2-role"
  "aws:elasticbeanstalk:customoption" :
    CloudWatchMetrics : "--mem-util --mem-used --mem-avail --disk-space-util --disk-space-used --disk-space-avail --disk-path=/ --auto-scaling"
```

IAMでRoles > `aws-elasticbeanstalk-ec2-role` の「Add inline policy」にて、下記のように設定して追加
* Service: CloudWatch
* Actions: PutMetricData と PutMetricAlarm を追加
* Resources: Specific Add ARN にて例えば下記
  * Region => ana
  * Account => デフォルトのまま
  * Alarm Name => any
* Name: CloudWatchMetricAlarm など

これでデプロイしてCloudWatchの 
* System/Linux > InstanceID でメモリ使用量などが確認できる
* System/Linux > AutoScalingGroupName, Filesystem, MountPath でディスク残量などが確認できる

Alarmで監視されていることを確認


参考: https://aws.amazon.com/jp/premiumsupport/knowledge-center/elastic-beanstalk-memory-monitoring/
.htaccessを下位フォルダに置いたらリダイレクトが利かなくなった

知ってれば当たり前、初歩的な内容なのですが。
誤った場所に .htaccessのリダイレクト処理を置いて、他のリダイレクト処理が利かなくなってしまいました。
つまり、今まで表示されていたページが表示されなくなるという障害を起こしてしまいました。

#原因
##.htaccessの影響範囲を誤って理解したため
・親ディレクトリの設定は、子ディレクトリにも有効
・一つ.htaccessを設置すると、その下にぶら下がる全ディレクトリに影響が及ぶ
ネットで検索するとでてくる.htaccessの影響範囲の説明

このことから
①上位ディレクトリでリダイレクト処理を書く
②下位ディレクトリでも別の内容のリダイレクト処理を書く
①②両方OKになるのと勘違いしていまいした。



#今回の障害事例
①redirect/test/A/Cへのアクセスはすべて　https://yahoo.co.jp　
にリダイレクトされます。
www直下の.htaccessには以下の記述がありました。

```:WWW直下の.htaccess

RewriteEngine on
RewriteRule redirect/test/A/C https://yahoo.co.jp [L,R=301]

```
②新たに
redirect/test/Bへのアクセスはすべて　https://google.co.jp へリダイレクトする処理を追加します。
www直下の.htaccessを触って真っ白になるのが嫌だったので
www/rediret/test直下の.htaccessを新たに作成し以下の記述をしました。
ネットで検索するとでてくる
「親ディレクトリの設定は、子ディレクトリにも有効」
などの言葉を誤って解釈していたのでここで悲劇が起こりました。

```:www/rediret/test直下の.htaccess
RewriteEngine on
RewriteRule B https://google.co.jp [L,R=301]
```

<b>③redirect/test/A/Cから　https://yahoo.co.jp
へのリダイレクトが利かなくなった</b>

##解決①
リダイレクト処理はwww直下の.htaccessに追記

```:www直下の.htaccess
RewriteEngine on
RewriteRule redirect/test/A/C https://yahoo.co.jp [L,R=301]
RewriteRule redirect/test/A/B https://google.co.jp [L,R=301
```
##解決②
www/rediret/test直下の.htaccessに親ディレクトリのリダイレクト処理をだぶって書く

```
RewriteEngine on
RewriteRule B https://google.co.jp [L,R=301]
RewriteRule A/C https://yahoo.co.jp [L,R=301]
```

##.htaccessのリダイレクト処理（RewriteRule）は追記ではなく上書き
今回だと、
www/rediret/test直下に.htaccessを置いて、リダイレクト処理（RewriteRule)の記述をしたので
www/rediret/test以下のリダイレクト処理は上書きされたのです。
つまり、www直下の.htaccessに記述したwww/rediret/testフォルダへのリダイレクト処理は上書きで消えてしまったのです。

これを解決するには
①www/rediret/test/.htaccessに上位ディレクトリのRewriteRuleをもう一度書く
②上位ディレクトリの.htaccessにRewriteRuleに追記する
のどちらかになります。
参考↓
[適用のされ方Apache公式サイト説明](https://httpd.apache.org/docs/current/ja/howto/htaccess.html#how)

※実は以前にも同じような依頼があって
www直下の.htaccessを触りたくなかったので下位ディレクトリに.htaccessを作成しリダイレクト処理を書いてました。
たまたまwww直下の.htaccessに該当フォルダへのRewriteRuleがなかったのでうまくいってただけのようです。
次からは要注意です。
というかサイト作成に何一つかかわっていないのに、.htaccessの作成だけ丸投げされるのは怖いです。
The Consciousness Prior【1 Introduction】【論文 DeepL 翻訳】

この記事は自分用のメモみたいなものです.
ほぼ [DeepL](https://www.deepl.com/home) 翻訳でお送りします.
間違いがあれば指摘していだだけると嬉しいです.

翻訳元
[The Consciousness Prior](https://arxiv.org/abs/1709.08568)
Author: Yoshua Bengio

前: [【Abstract】](https://qiita.com/tomato_/items/8e0dca423540ef77418f)
次: [【2 System 2 Processing and Global Workspace Theory of Consciousness】](https://qiita.com/tomato_/items/bf604cf935c6cfdf4a9b)

# 1 Introduction

本論文では, 人間が自然言語で操作するような概念のトップレベル抽象表現のための新しい種類のプライヤーを提案する. これは, 意識の一形態 [van Gulick, 2004] としてのグローバルワークスペース理論 [Baars, 1988, 1997, 2002, Dehaene and Naccache, 2001, Dehaene et al., 2017] などの現代の意識論, すなわち, ロックが定義したように, 意識とは "人間自身の心の中を通過するものの知覚", すなわち, 外部の物体や自分の中にあるものに対する意識である (Wikipediaの定義). この論文の主な貢献は, 意識的思考の要素がアテンションメカニズム (先に紹介したコンテンツベースのアテンションメカニズムなど [Bahdanau et al., 2015]) によって選択され, 脳の他の部分に伝達され, 次の意識的思考の内容だけでなく, 下流の知覚や行動にも強く影響を与えることを規定し, この理論の一側面を機械学習によって正当化することを提案していることである. この論文では, これを意識的思考を形成しうる高レベル変数の種類間の同時分布の形についての仮説と一致する計算メカニズムとして捉えている. 意識的思考は一度に非常に少数の変数を参照するだけなので, これは一度に少数の変数を含む断片に事実化された知識表現の形態に相当することを示唆している. 確率論的モデリングの観点からは, これは疎な因子グラフに相当する. 各 "因子" は, いくつかの変数間の強い依存関係をキャプチャする. 1つの変数がそのような多くの因子に参加することができるが, 各因子は, 自然言語の文の中で一緒にリンクされた単語や概念に似て, 非常に少数の変数をリンクしている.

## 原文

We propose here a new kind of prior for top-level abstract representations of concepts of the kind humans manipulate with natural language, inspired by modern theories of consciousness such as the global workspace theory [Baars, 1988, 1997, 2002, Dehaene and Naccache, 2001, Dehaene et al., 2017] as a form of awareness [van Gulick, 2004], i.e., as defined by Locke, consciousness is “the perception of what passes in a man’s own mind”, or awareness of an external object or something within oneself (Wikipedia definition). The main contribution of this paper is proposing a machine learning justification for an aspect of this theory, stipulating that elements of a conscious thought are selected through an attention mechanism (such as the content-based attention mechanism we introduced in [Bahdanau et al., 2015]) and then broadcast to the rest of the brain, strongly influencing downstream perception and action as well as the content of the next conscious thought. The paper sees this as a computational mechanism which is consistent with a hypothesis about the form of the joint distribution between the type of high-level variables which can form a conscious thought. Since a conscious thought only refers to very few variables at a time, we suggest that this corresponds to a form of knowledge representation which is factored into pieces involving a few variables at a time. From a probabilistic modeling point of view, this corresponds to a sparse factor graph. Each “factor" captures the possibly strong dependency between a few variables. Although a variable can participate in many such factors, each factor links very few variables, similarly to words or concepts linked together in a sentence in natural language.
calibreコマンドライン操作のメモ

###追記
2021年7月22日
-作業手順のレイアウト調整

## 参照
2019年03月19日に更新 kindle書籍のpdf化
https://qiita.com/keitasumiya/items/c9d0f81fd7fb96e505b3
2016年12月10日に更新 Kindle本をGoogle Booksに移動させたときのメモ
https://qiita.com/mgoldchild/items/165f63bc2e006c81bf58
calibre-ebook.com - Command Line Interface » ebook-convert
https://manual.calibre-ebook.com/generated/en/ebook-convert.html

##作業手順
```zsh:(Mac作業ディレクトリ)●/Applications/calibre.app/Contents/MacOS 
./ebook-convert [変換したいファイルのあるディレクトリ]/[変換したいAZWファイル].azw3 [出力先ディレクトリ]/[出力ファイル名].pdf \
--custom-size 200x283 \
--unit millimeter \
--preserve-cover-aspect-ratio \
--pdf-serif-family 'Times New Roman' \
--pdf-sans-family 'Courier New' --pdf-mono-family 'Courier New' \
--pdf-standard-font 'serif'  \
--pdf-default-font-size 18 \
--pdf-mono-font-size 14 \
--pdf-page-margin-bottom '20.0' \
--pdf-page-margin-left '20.0' \
--pdf-page-margin-right '20.0' \
--pdf-page-margin-top '20.0'
```

cssスタイルの追加についてはまだよくわかっていない。
`--custom-size 200x283`
ここはカバー画像解像度1005x1420から求めたアスペクト比a=1.41を使用し 200x200*aで求めている
'kindle書籍のpdf化'の設定を公式ドキュメントと照らし合わせながら貼り付けただけなので本当にただのメモ

serif,sans,mono,のフォント設定に至っては全く調べてない
PDFで表示が固定化できると記憶の整理がしやすい。いいね
自己代入演算子

#自己代入演算子（+=, -=, *=, /=）
**自己代入とは、その名の通り自分自身に代入するということです。
自己代入演算子は、通常の演算子を用いた書き方を省略して記述できます。**

例として<font color="Red">number = number + 1</font>を自己代入演算子<font color="Red">+=</font>を使った書き方に直してみましょう。

```java:【例】通常の代入演算子
number = number + 1
```

この式を自己代入演算子<font color="Red">+=</font>を使えば以下のように書き直せます。
これらは同じ意味になります。

```java:【例】自己代入演算子
number += 1
```
上記ソースコードを比較するとわかるように自己代入演算子を使った式<font color="Red">number += 1</font>は、変数<font color="Red">number</font>に1を足した値を<font color="Red">number</font>自身に代入する
という処理になります。
以下に代表的な自己代入演算子を示します。

![自己.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762918/67dbc7ed-752b-86ff-f677-bb7ca95f70da.png)

このように自己代入演算子を使うと、変数自身にある値を足したり、
引いたりすることを簡単に記述できます。

コードを省略できるためよく使われます。
どちらの記述も覚えておきましょう。

#まとめ

**自己代入演算子を使用することで、コードを省略して書くことできるため、
より見やすく書きやすくする位ことができます。**

#####以上。
再代入

#再代入
**1度値を代入したあとの変数に、別の値を再び代入することもできます。
つまり、変数の値は別の値に変更できます。**

プログラム中に何度でも変更可能であることも変数の特徴です。

以下の例を見てください。

```java:【例】irb
# 変数に代入
irb(main):001:0> value = "Hello World"
=> "Hello World"

# 変数を出力
irb(main):002:0> value
=> "Hello World"

# 変数に再代入
irb(main):003:0> value = "See you"
=> "See you"

# 変数を出力
irb(main):004:0> value
=> "See you"
```

変数の値が後から代入したものに書き換わっていることがわかります。
Rubyでは、変数にはどんな値でも代入できます。もちろん、変数に対してメソッドを使うこともできます。

代入を利用して、以下のように記述すれば、変数自身の値を利用した計算結果と入れ替えることができます。

```java:【例】irb
# 変数に代入
irb(main):001:0> number = 7
=> 7

# 変数に1を足す
irb(main):002:0> number = number + 1
=> 8
```

また、このような変数自身を利用して代入する場合には、**自己代入演算子**を用いて記述することもできます。
自己代入演算子については、次回ご説明させて頂きます。

#まとめ

**再代入とは、変数の値が後から代入した値に入れ代わるということです。**

#####以上。
CloudFunctionsでHTTPリクエストが大量に来て多額の請求がくる夢を見たのであり得るか考えた

#Googleさんから10万円の請求が来た夢を見た
そして今、目が覚めて寝れてないｗ

昨日、CloudFunctionsでLINEのMessagingAPIを使って、
送ったメッセージをそのまま返すBotを作った。

とりあえず動くものを、と作ったので、
今日攻撃されたら？という気持ちを残したまま寝てしまった。
そしたら請求書という形で夢に出た。


#頭を落ち着かせるために考える

考えた切り口は、
　・リクエストに対する料金
　・今の作りだった時に、めちゃくちゃHTTPリクエストをなげる攻撃であったとしても請求対象となるか

です。

####リクエストに対する料金
　CloudFunctionsでかかる料金は、
　・関数の呼び出し数
　　　呼び出し料金は 1 回あたり $0.0000004 の単価制。毎月最初の 200 万回までは無料。
　・コンピューティング時間
　　　関数に対してプロビジョニングされたメモリ・CPUで変わる。
　　　関数が働いた時間。
　　　割り当てられたのはこちら。
　　　256 MB　400 MHz　$0.000000463
　　　参考）128 MB　200 MHz　$0.000000231
　　　

　・ネットワーキング
　　送信データ（下り、外向き）	$0.12/GB
　　受信データ（上り、内向き）	無料
　　CloudFunctionsの指標のページを見てもネットワーキングの量の記載ないな。。。

例で参考サイトに一番安いメモリで試算した結果を書いてくれていたのでそのままパクると、
1000万回アクセスが来たとしたら今のつくりなら　
　__月7.2ドル*2（2番目に安いメモリの料金は1番安いやつの2倍）=14.4ドル__


####実際に呼び出されると請求対象か
__どんな形であれば請求対象に入る。__ように見える。
前提として、処理の流れは
　LINE→LINEサーバ Webhookの設定→CloudFunctions HTTPリクエスト
のアクセスの仕方

URLにアクセスすると関数が呼び出されるから、たたけば請求対象にはなりそう。
表示しているのは、下記の結果。
　1回成功するように普通にLINEでメッセージ送った。
　7回ぐらいエラーになるようにブラウザでURLをたたいた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737206/515caade-57b2-d98a-6f87-0f84dd4c356a.png)

#結論
結論から言うと、たぶん一晩だと死ぬほど集中的にやられないかぎりは大丈夫だったのかも。
デプロイはいつでもできるから、不安だったら関数を削除しておけばよいのだな。
寝よ寝よ。

__参考サイト__
[CloudFunctionsの料金](https://cloud.google.com/functions/pricing?hl=ja)
代入

#代入


**変数のあとの<font color="Red">=(イコール)</font>は数学の方程式のように等しいという意味ではなく、
「変数の箱の中に値を入れる」という意味です。
これを代入と言います。**

この<font color="Red">=</font>は**代入演算子**と呼びます。

ここで必ず覚えておくべき重要なポイントですが、
**「Rubyにおいて<font color="Red">=</font>が1つの式は必ず『右側の値を左の変数に代入する』という意味」**であることです。

![りんご.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762918/e92657b5-c689-26b7-5a6c-f0f6115401c4.png)

```java:【例】irb
# piという変数の中身を、円周率の3.14159であると定義する
irb(main):001:0> pi = 3.14159

# piを呼び出すと、格納された3.14159が返ってくる
irb(main):002:0> pi
=> 3.14159

# 何度実行しても、格納された3.14159が返ってくる
irb(main):003:0> pi
=> 3.14159
```

上の例で行っている処理は、「piという変数に円周率をあらわす数値3.14159を代入する」ということになります。
すると変数piの中身は、数値の3.14159となります。

そのため、数値を返す「pi」に対しては、to_iメソッドや演算子による計算など、
数値の行える動作すべてが、同じように行えます。

#まとめ

**代入とは、変数のような箱の中に値を入れること。**

#####以上。
Web系志望の未経験者に「Web系エンジニアになろう」をオススメする3つの理由

はじめまして。ニッシーと申します。
Twitter, YouTubeでよく拝見していた勝又健太さん（@poly_soft）の著書である
<STRONG>「Web系エンジニアになろう」</STRONG>が届いたので、さっそく読みました。
<FONT COLOR=blue>
この本、オススメです！
</FONT>
![Web系エンジニアになろう.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/853298/a6e2e587-3276-67bc-7cf5-60a86423ce75.jpeg)

本書のなかで、Qiitaで技術的な発信をすることを推奨していたので、
読了後にすぐアカウント作成しました。
初めての記事は、この本のレビューを書くことにします。

まだHTMLもわかりませんが（文字サイズを大きくできません！）
STRONG? FONT COLOR? br? 見出しの#??? を調べながら書いています。
温かい目でお付き合いください。
<br>
<br>
#オススメする3つの理由

###1.Web業界の厳しいリアルをハッキリと書いている
Web系エンジニアへの転職を希望する人が多くなってきている背景には、こういう誘い文句の影響もあります。
<STRONG>「時間単価1万円超え」「リモートワーク」「未経験でも転職可能」</STRONG>
昨今のコロナ禍が根深く残っているためか、私もSNSでよく見かけます。しかし、この条件で契約するには<FONT COLOR=blue>厳しいリアル</FONT>があることを勝又さんは説明しています。

<STRONG>時間単価1万円超え</STRONG>
　→　「1年や2年程度の経験で月単価100万円を安定して稼げるフリーランスエンジニアになることはほぼ不可能」

<STRONG>リモートワーク</STRONG>
　→　「キャリアの初期は、リモートワークは条件に含めないのが賢明」

<STRONG>未経験でも転職可能</STRONG>
　→　「スクールの課題をこなす程度の労力でWeb系エンジニアにジョブチェンジすることはできない」

上記以外にも、未経験者が抱きがちな幻想について、かなりバッサリと斬り捨てています。転職を志す前に知っておくべきことが、この本には詰まっています。<FONT COLOR=blue>甘く考えていると痛い目を見ることになりかねない</FONT>ので、自分のような<FONT COLOR=blue>未経験者の必読書</FONT>ではないかと思います。
<br>
<br>
###2.厳しいリアルがある前提で、転職するために必要な作業を書いている
本書の構成は、厳しいリアルを知ってもらったうえで、<FONT COLOR=blue>転職を成功させるための具体的な方法</FONT>の説明に移ります。<STRONG>何を買い、何を読み、どのような方法で学び、何を作り、どうやって面接を突破するか。</STRONG>転職するまでに必要となる作業が、非常に具体的に書かれています。

これらは勝又さん自身の経験だけでなく、勝又さんが運営する「雑食サロン」に所属する多数の人が、実際に未経験からWeb系自社開発企業に転職できている事実に基づいています。もし「Web系エンジニアになろう」と考えたら、まず転職までのロードマップを描くと思いますが、そのために必要となる前提知識や情報が、この本には網羅されています。この本を初期に読むことで、<FONT COLOR=blue>今後のロードマップを描くための情報収集が効率的になります。</FONT>
<br>
<br>
###3.Web系エンジニアに転職したあとの未来についても書いている
Web系エンジニアは<STRONG>「需要と将来性」「スキルの可搬性」「ワークスタイルの柔軟性」</STRONG>などが高いレベルで備わっていると本書に記されています。しかしながら、<FONT COLOR=blue>リスクがゼロになることはありません。</FONT>勝又さんは、Web系エンジニアに転職したあとのキャリア形成についても書いています。

・技術を磨き続ける　(幅広い技術に「分散投資」する)
・QiitaやTwitterなどで外部発信をする　(知名度を獲得するとマネタイズできるようになる)
・勉強会やイベント、LTなどで人脈形成をする　(リファラル採用の転職先を広げる)

他にもNISAやiDeCoなどの資産運用の話もあります。資産運用はWeb系エンジニアになるという主題から逸れるように見えますが、「リスクの分散」を徹底的に考え抜いている点に着目したいです。現在と将来の<FONT COLOR=blue>リスクを小さくするための選択肢の一つが「Web系エンジニアになろう」という提案</FONT>になります。
<br>
<br>
#Web系エンジニアを目指すことにしました
少し前から考えていたのですが、この本をきっかけに、バックエンドエンジニアを目指すことにしました！

私は、インフラ系SESの運用監視2年目です。（セキュリティ監視ですが、実態はWord, Excel案件です）
運用監視から脱出して開発の案件に異動or転職するために、勝又さんや #プログラミング初心者 のタグで投稿されている方々を拝見していました。良い出会いに感謝します。

読んでくださった方、ありがとうございます。
直近では OracleBronzeDBA の試験を控えているのですが、プログラミング学習もがんばります！
<FONT COLOR=gray>（まずは Qiita を自在に書けるように）</FONT>

Twitterアカウントを作りました。
よろしければ、フォローお願いいたします。

###Twitterアカウント
@nissy_gorilla53
最近話題の無限くら寿司用の料金計算アプリを作ってみた！

今回はWEBアプリを作ってみたので、そのアプリに関する紹介です！

↓作成したアプリ
[くら寿司料金チェッカー（https://jorublog.site/kurasushi-calc/）](https://jorublog.site/kurasushi-calc/ "くら寿司料金チェッカー")

僕が通っている大学のすぐ横に数か月前にくら寿司ができたので、最近研究の合間にちょくちょく無限くら寿司にお世話になってます（笑）。
ですが、その際毎回スマホの電卓アプリで料金計算をしていたのですが税込み金額が、ランチの場合は500円、ディナーの場合は1000円超えているかどうかの計算が面倒くさいと感じてました。そこで今回、タップ操作だけで手軽にくら寿司の料金計算ができるWEBアプリを作ってみました！

#概要
くら寿司の料金計算をタップ操作だけで行えるようにしたアプリです。WEBアプリなので、以下のURLにアクセスするだけで使用できます。

#作成したくら寿司料金計算用WEBアプリ
[くら寿司料金チェッカー（https://jorublog.site/kurasushi-calc/）](https://jorublog.site/kurasushi-calc/ "くら寿司料金チェッカー")


画面はこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276761/3ad42508-b56a-d31e-f2f6-766cca2d26cd.png)


#アプリの使い方
まず、最初にGoToクーポンの利用有無を選択します。
あとは、各料金のお皿の個数を＋、－ボタンか、真ん中のプルダウンメニューから選択することで、右側に各料金の小計が、上の合計料金のところには税込みと税抜きの値段が表示され、さらにGoToクーポンによる割引後の料金がその下に表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276761/1a990201-5a9b-b4e2-ad2a-83b983a0b523.png)


#最後に・・
基本的な機能だけをとりあえず付けただけなので、レイアウトやデザインは見にくいかもしれませんが良かったら使ってみてください！
改善点や不具合、追加してほしい機能等がありましたらご連絡ください。
twitter↓

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">無限くら寿司用にくら寿司の料金計算を簡単に行えるwebアプリ作ってみました！<br><br>料金計算する際に電卓で計算するのは面倒くさかったので、タップ操作だけで各料金の皿の計算ができるようにしてみました🙂<br><br>URLは↓こちらです。<a href="https://t.co/KxhbxcthlD">https://t.co/KxhbxcthlD</a><a href="https://twitter.com/hashtag/%E7%84%A1%E9%99%90%E3%81%8F%E3%82%89%E5%AF%BF%E5%8F%B8?src=hash&amp;ref_src=twsrc%5Etfw">#無限くら寿司</a> <a href="https://twitter.com/hashtag/web?src=hash&amp;ref_src=twsrc%5Etfw">#web</a> <a href="https://twitter.com/hashtag/%E3%82%A2%E3%83%97%E3%83%AA?src=hash&amp;ref_src=twsrc%5Etfw">#アプリ</a> <a href="https://twitter.com/hashtag/%E6%96%99%E9%87%91%E8%A8%88%E7%AE%97?src=hash&amp;ref_src=twsrc%5Etfw">#料金計算</a></p>&mdash; JUN@じょるブログ (@jorublog) <a href="https://twitter.com/jorublog/status/1323762631342133249?ref_src=twsrc%5Etfw">November 3, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
React+Material-UIで簡単にGridレイアウトが出来た

# 概要
* ReactのためのUIコンポーネントライブラリである[Material-UI](https://material-ui.com/)を使ったら簡単にGridレイアウトを作れたので、試したいくつかの事を書きます。
* 公式ドキュメントが非常に充実しているので、細かいことは書きません
* 最近Reactに触れた新参者なので、(特にts周り)おかしかったらすみません

# 下準備
```bash
$ npx create-react-app . --template typescript
$ npm install @material-ui/core
$ npm start
```

# ディレクトリ構成
```
src
├── components
│   ├── GridList.tsx
│   └── tileData.ts
├── img
│   ├── neko1.jpg
│   ├── neko2.jpg
│   ├── neko3.jpg
│   ├── neko4.jpg
│   └── neko5.jpg
└── App.tsx
 

```

# Instagram風? 写真のGridList
```tsx:src/components/GridList.tsx
import React from 'react';
import { Theme, createStyles, makeStyles } from '@material-ui/core/styles';
import GridList from '@material-ui/core/GridList';
import GridListTile from '@material-ui/core/GridListTile';
import GridListTileBar from '@material-ui/core/GridListTileBar';
import ListSubheader from '@material-ui/core/ListSubheader';
import tileData from './tileData';

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      display: 'flex',
      flexWrap: 'wrap',
      justifyContent: 'space-around',
      overflow: 'hidden',
      backgroundColor: theme.palette.background.paper,
    },
    gridList: {
      width: 500,
      height: 700,
    },
  }),
);

const TitlebarGridList: React.FC = () => {
  const classes = useStyles();
  return (
    <div className={classes.root}>
      <GridList cellHeight={200} className={classes.gridList}>
        <GridListTile key="Subheader" cols={2} style={{ height: 'auto' }}>
          <ListSubheader component="div">かわいいねこ</ListSubheader>
        </GridListTile>
        {tileData.map((tile) => (
          <GridListTile key={tile.img}>
            <img src={tile.img} alt={tile.title} />
            <GridListTileBar
              title={tile.title}
              subtitle={<span>by: {tile.author}</span>}
            />
          </GridListTile>
        ))}
      </GridList>
    </div>
  );
}

export default TitlebarGridList;
```

```ts:src/components/tileData.ts
import neko1 from '../img/neko1.jpg';
import neko2 from '../img/neko2.jpg';
import neko3 from '../img/neko3.jpg';
import neko4 from '../img/neko4.jpg';
import neko5 from '../img/neko5.jpg';

const tileData = [
    {
      img: neko1,
      title: 'お顔',
      author: 'yotsak',
    },
    {
      img: neko2,
      title: '眠い',
      author: 'yotsak',
    },
    {
      img: neko3,
      title: '恥ずかしい',
      author: 'yotsak',
    },
    {
      img: neko4,
      title: '細目',
      author: 'yotsak',
    },
    {
      img: neko5,
      title: 'はまり',
      author: 'yotsak',
    },
];

export default tileData;
```

```tsx:src/App.tsx
import React from 'react';
import GridList from './components/GridList';

function App() {
  return (
    <div>
      <GridList />
    </div>
  );
}

export default App;
```

# 画面イメージ

![ui.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87716/95655723-47e5-f253-bd50-58b01b97e0ec.jpeg)

ヨシ！
[ Laravel ＆ Xampp ] ローカル開発環境に便利なバーチャルドメイン設定

## `http://localhost/プロジェクト名/public` を好みのドメインに変更する

Laravel＆xamppのローカル開発で、普通に`xampp`の`htdocs`フォルダ内に`Laravel`をインストールすると、`http://localhost/プロジェクト名/public`のアドレスになると思います。

もちろん、上記のアドレスで開発もできるのですが、シンプルに`http://プロジェクト名.localhost`という感じで、フォルダ名の「public」が付かないスマートなドメインを指定してみましょう。


### 手順１
`C:\xampp\apache\conf\extra\httpd-vhosts.conf`ファイルを開き「NameVirtualHost *:80」の行を有効にする（行始めの#を取る）

### 手順２
設定１の `httpd-vhosts.conf` ファイルに以下を追加

```
<VirtualHost プロジェクト名.localhost:80>
DocumentRoot "C:/xampp/htdocs/プロジェクト名/public"
ServerName プロジェクト名.localhost
</VirtualHost>
```

＊ `プロジェクト名`の部分を環境に応じて書き換えてください。

### 手順３

`C:\WINDOWS\system32\drivers\etc\host`ファイルを開き

```
127.0.0.1 プロジェクト名.localhost
```

を追加する。

設定が完了したら、`http://プロジェクト名.localhost/` にアクセスすると、Laravelのトップページが表示されると思います。
JSON Serverで静的ファイル(画像, CSV等)を配信する方法

# JSON Serverで静的ファイルを配信する方法

## はじめに
JSON ServerでCSVファイルや画像ファイルを配信しようとして、ちょっと苦戦したのでまとめておく。
JSON Serverではpublicディレクトリに配置したものを配信することができるが、
デフォルトではルートディレクトリに存在するpublicディレクトリを参照してしまうため、
ルートディレクトリ以外にpublicディレクトリを配置したい場合、これを変更する必要がある。

## 静的ファイルを配置するデフォルトディレクトリを変更する方法
JSON Serverをモジュールとして使用し、
以下のように```jsonServer.defaults()```のオプションを指定することで、
静的ファイルのデフォルトディレクトリを変更することができる。
JSON Serverをモジュールとして使用する方法については[過去記事を参考](https://qiita.com/daiti0113/items/576805676c4094b5170c)にしてほしい。

```js:server.js
server.use(jsonServer.defaults({static: ${配置したいパス}}))
```

具体的な例として、以下のように静的ファイルを配置した場合、

```
mock
├── public
│   └── img
│       └── hogehoge.jpg
└── server.js
```


```js:server.js
const jsonServer = require("json-server")
const server = jsonServer.create()
const middlewares = jsonServer.defaults({static: `${__dirname}/public`})
const port = 3000

server.use(middlewares)

// モックサーバ起動
server.listen(port, () => {
  console.log(`JSON Server is running in localhost:${port}`)
})
```

とすれば、```http://localhost:3000/img/hogehoge.jpg```でアクセスすることができる。
teratermマクロ(telnet)でシェルスクリプトを送って実行

## Teratermマクロの定石ってどうなのよ？

さすがにコマンド1行を送信するごとにプロンプトの表示を待つコードを挟むというやり方(そうしないとリモートの状況関係なく問答無用で送信するのでうまくコマンドが実行できない場合があるのですが…)はコマンド1つ2つならともかく増えてくるとちょっとどうかと思ってくるので、
あらかじめ作成しておいたシェルスクリプトを送ってリモート側(UNIX系OSを想定)で保存し、リモート側で実行するマクロを作ってみた。
SSH接続ならSFTPを使ってファイルを送るコマンドがあるのですが、Telnetだとそんなものは存在しないようなので工夫する必要がある。

## Telnetでテキストファイルを送信するコード

```
;すでにtelnet接続に成功していると仮定

;プロンプトの内容は環境や設定によって変わるので適宜変更する
prompt = "localhost $"

;ローカルのファイルを1行ずつ読み込んでcatコマンドでリモートに書き込み
;ローカルから読み込むファイルがinput.sh、リモートに書き込んだファイルがoutput.shになっているので
;任意のファイル名に変更する。
wait prompt

fileopen fh input.sh 0

sendln "cat << TTLEOF > output.sh"

while 1
    filereadln fh buf
    if result=1 then
        break
    endif
    sendln buf
endwhile

sendln "TTLEOF"

fileclose fh

;プロンプトの表示を待ってシェルスクリプトを実行
wait prompt

sendln "sh ./output.sh"
```

teratermマクロのファイルを1行ずつ読み込むfilereadlnコマンドと、シェルのヒアドキュメントを使い終端として指定した文字列がある直前の行までの複数行の文字列をcatで出力したものをファイルにリダイレクトするという方法を利用しています。

## どういうこと？

ヒアドキュメントというのはざっくり言えば複数行にわたる文字列を文字列結合や特殊文字等を使うことなくそのまま表現するための記法のこと。

ヒアドキュメントがあれば複数行の文字列を表現するのにわざわざ```\n```のような特殊文字を使ったり、改行部分でエスケープ文字を挟んだり、諦めて1行ごとに何度も同じ処理を繰り返し使う必要はないってことです。

UNIX系OSの一般的なシェルでは

```sh
コマンド << EOF
...
複数行にわたる文字列
...
EOF
```

でコマンドへの標準入力**(重要)**として複数行の文字列を渡すことができます。文字列の終わりを判別するために終端となる文字列(ここではEOF)を決める必要があります。終端の文字列はEOFに限らず任意の文字列にすることが可能です。

これをファイルの内容をそのまま標準出力へ出力(ファイルの指定がない場合は標準入力の内容を出力)するcatコマンドに渡し、

標準出力をファイルにリダイレクトすることでヒアドキュメントの内容をそのままファイルに書き込むことができるわけです。

```sh
#2行目からEOFの直前の行までの文字列をtest.txtに書き込む
cat << EOF > test.txt
...
複数行にわたる文字列
...
EOF
```

teratermマクロ側からすればヒアドキュメントを標準入力にして任意のファイルにリダイレクトしているcatコマンド実行中の文字列送信はそのままヒアドキュメントの内容となるので、
あらかじめ決めておいた終端文字列を送信するまで送信した文字列の内容がそのままファイルに書き込まれることになります。

もっと詳しくわかりやすい解説はいくらでもネットに転がってるのでググってください。


## 応用

```
sendln buf
```

を

```
expandenv exbuf buf
sendln exbuf
```

としておくとローカル側の環境変数(例:```%ENV%```)を展開してくれるようになります。

純粋なシェルスクリプトではなくなりますが、ローカルでバッチファイルと連携している場合は設定が共通化できるので便利です。


## 注意点

### UTF-8は使えないというか事実上日本語は使えない

teratermマクロのfilereadlnコマンドはUTF-8に対応しておらず(2020年11月現在)、UTF-8のファイルを読み込もうとしてもうまく読み込んでくれません。
Shift-JISならいけるっぽいですが、リモート側がUNIX系OSなんかだとまたそれはそれで…という感じなので日本語は使えないと思っておいたほうがいいです。

### 送信するシェルスクリプト内でヒアドキュメントを使う場合は注意しよう

ファイルの書き込みにヒアドキュメントを使ってる関係上、teratermマクロ側で終端とした文字列と同じ文字列がシェルスクリプト内にあるとファイルの書き込みが途切れてしまいます。
最もありえそうなのがシェルスクリプト内でヒアドキュメントを使い終端文字列を同じものに設定した場合でしょうか。
一応上記のコードではTTLEOFとしているのでまぁ被ることはないとは思いますが、一応意識はしておきましょう。
Oculus Riftで「HDMIが接続されていません」と表示されている時やることリスト

## やること、確認すること
1. HDMI端子のPINが折れていないか
2. グラボのHDMIポートに接続しているか
3. PCのHDMIポートから抜き差ししてみる
4. Oculusヘッドセット側の端子を抜き差ししてみる  
https://support.oculus.com/help/oculus/1114691701909297?sr=2&query=cable&sid=0q9NgkhG3A9Bp1tKI
5. グラボのドライバをアップデートする
6. Oculusアプリの修復を実行する  
https://www.oculus.com/setup/#rift-setup

***以上のリストで治らない場合はサポートに問い合わせましょう***
https://support.oculus.com/

### 見逃しやすい点
初見だと4番のOculus側の端子は外せることわかんないので可能性高いかも
Bridgeで開くPhotoshopバージョンを一気に変更するAppleScript

#複数バージョンのPhotoshopをインストールしている方へ
BridgeはOSの関連付けと関係無くアプリケーションを指定できますが、複数バージョンのPhotoshop等入れている場合はよく使うバージョンを固定しておきたい、ですよね
プレリリース版がいちいち起動してたら面倒なので…

~/Library/Application Support/Adobe/Bridge 2021/Adobe Bridge Opener Preferences.xml
からsedでPhotoshopの行を探して、アプリケーション本体のパスを書き込みます。

```Applescript:
--Bridgeバージョン取得
tell application "System Events"
	set bridgeIdentify to null
	set alist to bundle identifier of every process
	repeat with i from 1 to count of alist
		set a to item i of alist
		if a contains "com.adobe.bridge" then
			set bridgeIdentify to a as text
		end if
	end repeat
	if bridgeIdentify is null then
		display alert "バージョンを取得したいので、Bridgeは起動しておいてください"
		error number -128
	else
		--フォルダ名判別。bundleIDとパス名は記憶に頼ってるので不正確です…………
		set BridgeA to ":Adobe Bridge Opener Preferences.xml"
		set BridgeB to ":AdobeBridgeOpenerPreferences.xml"
		if bridgeIdentify is "com.adobe.bridge14" then set bPath to "Bridge 2024" & BridgeB
		if bridgeIdentify is "com.adobe.bridge" then set bPath to "Bridge 2025" & BridgeB
		
		if bridgeIdentify is "com.adobe.bridge12" then set bPath to "Bridge 2022" & BridgeA
		if bridgeIdentify is "com.adobe.bridge11" then set bPath to "Bridge 2021" & BridgeA
		if bridgeIdentify is "com.adobe.bridge13" then set bPath to "Bridge 2023" & BridgeB
		if bridgeIdentify is "com.adobe.bridge9" then set bPath to "Bridge CC 2019" & BridgeA
	end if
end tell

tell application "Finder"
	activate
	
	set fileTarget to (home as text) & "Library:Application Support:Adobe:" & (bPath as text)
	try --実在判定
		fileTarget as alias
	on error
		display alert "設定ファイルがありません。Bridge環境設定「ファイルタイプの関連付け」で、PNGなどの設定を適当に変更すると、自動的に環境設定ファイルが作成されますので、もう一度このスクリプトを実行してください"
		return
	end try
	set fileTarget to do shell script "echo " & fileTarget & " | sed -e 's| |\\\\ |g'"
	--xml書き替え。app_name="Photoshop"を探して、それ以降をapp_pathで書き替える
	set app_path to (choose file with prompt "Photoshop本体を選択してください")'s POSIX path
	set nameTemp to (items 1 thru -2 of characters of app_path)
	set app_path to POSIX path of (nameTemp as string)
	do shell script "sed -i -e 's|\\(app_name=\"Photoshop\"\\).*|\\1 app_path=\"" & app_path & "\">|g' " & POSIX path of fileTarget
end tell

set Bridge to application id bridgeIdentify
if Bridge is running then tell Bridge to quit
repeat while Bridge is running
	delay 0.5
end repeat
tell Bridge
	activate
	display alert "書き替えました"
end tell

```
サクラエディタの置換がファイル拡張子によって万倍速だった件

# 概要
「いっつも高速にサクサク動くサクラエディタ先生が、今日はやけに遅いな」
と思っていたら、本当にただの仕様によって処理速度が遅くなっていたという話。
おそらく自分は今回の経験を糧に、今後同一のケースにハマることはもう無いと思うけれど、どこかの誰かのためになるかもしれないと思い備忘。

# 現象（結論）
「サクラエディタの一括置換が、拡張子を.sqlから.txtに変えたら1万倍早くなった」
※約10万行の長大ファイル。

# 詳細（やろうとしたこと）
## SQL文を丸っと変えたかった

「げっ、クォーテーションついて文字列になっててINDEX使えねえじゃん…10万行とかこれで流したら日が暮れる」

「しゃーない、サクラエディタでSQLファイルいじって数値型に変えて流すか」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/dae82ed7-c2ca-24b8-4fcb-8cdd51694363.png)

てなわけでいつもどおりサクラエディタの置換窓を開くも、クルクル…クルクル…

「1分立っても終わらないだとぉ」

## SQLファイルの場合、置換時に色々とやってるみたい

「なんでや…」

って思いながら眺めていると、よくよく見ると、WHEREに色がついていたり、クォーテーション内部が文字列で若干色が違ったり、なんか認識を持っている様子。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/496c5462-6ca4-2c49-e960-1d1fb37da8b2.png)

「もしや」と思い、ファイルの拡張子を「.sql」→「.txt」に変更してみたところ。

色がなく味気のない画面とともに一瞬にして置換終了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/752a4e16-b61a-96fa-19b9-27fca00691cb.png)


# 感想

そもそも10万行のSQLファイルを開くことが、人生の中で一体何回あるかはしらんけど。
【Windows10】ディスク使用率100%で何もできましぇん状態からのすこぶるいい加減な回復メモ

### 注意
かなりいい加減な、数打ちゃなんとか方式の解決策ですので、あしからず。
また、いわゆるところの自己責任でお願いいたします。

### はじめに
それはとても気分のいい朝だった。おろしたての真っ白なワイシャツみたいに、しわ１つない朝だった。僕は猫に缶詰の餌をやり、パンとコーヒーで簡単な朝食を済ませると、仕事に取り掛かった。（某作家風）

### これからってときによ
前置きはさておき。仕事の都合で、いつも使っているmacではなくWindowsを使わなくてはならなくなりました。
そこで、最近ほぼ使っていない6年モノのHpのノーパソを引っ張りだしました。ちなみにスペックは、
・HDD500くらい（いまちょっと忘れたわ）
・ メインメモリ8G
・intel core i3（笑）
です。OSはもともと8.1でしたが10にアップップしてあります。

起動はすんなり。さて、ではまずはGoogle Chromeをば立ち上げてと……。
……。（1分経過）
……。（3分経過）

**遅ーい！！**

てめえ何やってんだとばかりもう1回ダブルクリックしても変わらず。マシン再起動しても変わらず。
やれやれ。僕は首を振った。ラジオからは時代遅れのサイモンとガーファンクルの曲が流れていた。

### タスクマネージャーを拝見
というわけで、何が起こっているのか、タスクマネージャーを開いて見ました。
するとどうでしょう。ディスク使用率が１００%ではありませんか。

### いろいろやった
なんかぐだぐだ長くなってきたんで、こっからはさっさと書きます。
まず、こちらに書かれている対応法のうち、できるものはやってみましたが効果なし。

ディスク使用率が100％ の解決策
https://jm1xtk.dip.jp/cnt/54_hdd100/index.php

こんな情報もありました。えっと、要は「個人用設定」からウィンドウとかの透過処理をオフにしたら解決したって記事です。これで直ったらウケるーと思ったものの、やはり効果なし。

【Windows10】異常に遅い。タスクマネージャでディスク100％！？意外なところの設定変更で改善！【対処法】
https://tom2rd.sakura.ne.jp/wp/2017/01/30/post-3204/

この時点でだんだん腹が立ってきました。さっきからもう何回も再起動も試してるし。もう素敵な朝なんてどっかにいってしまい、目の前にはロバのうんこが転がってます。

### ええーいで解決した
そこで僕は、客先エンジニア時代に教わった基本に立ち返ることにしました。簡単です。
そう、「サービス」画面をもっかい開き、「なんか臭さそうなやつ」を見つけて片っ端から終了していきました（爆）
なんか一番臭そうなのは「Javaうんちゃらかんちゃら」です。これなんだっけ？ まあいいわ、終了したろ。
そんな感じで、あれこれ「要らなそう」なやつを５個くらい息の根止めてやりました。するとどうでしょう、ディスク使用率が80%、76%と減っていき……**30パーくらいになりました**。Chromeたんも無事起動。
やれやれ。

**終劇**

### まとめ
嗅覚的に、うさんくさいバックグラウンドのサービスを止めたるといいと思うよ。
apt と yumの違い

## 勉強前のイメージ

aptがdebian系とかで、yumがredhat系の感じ
yumはrpmを管理するものだけど、aptも同じ立ち位置なのかな？そんな気もする

## 調査

### apt

Debian系ではdeb形式のパッケージ管理システムを使用しています。
deb形式のパッケージのインストール・アンインストールは `dpkgコマンド` を使用します。
`dpkgコマンド` はパッケージのインストール等は可能ですが、依存関係の解決を行ってくれません。
そこで `aptコマンド` を使用することで依存関係の解決を行ってくれます。

### yum

Redhat系ではrpm形式のパッケージ管理システムを使用しています。
rpm形式のパッケージのインストール・アンインストールは `rpmコマンド` を使用します。
`rpmコマンド` はパッケージのインストール等は可能ですが、依存関係の解決を行ってくれません。
そこで `yumコマンド` を使用することで依存関係の解決を行ってくれます。

#### まとめると....

|  | Redhat系 | Debian系 |
|:-:|:-:|:-:|
| 形式  | rpm形式  | deb形式  |
| コマンド  | rpmコマンド  |  dpkgコマンド |
| 依存関係の解決  | yumコマンド  | aptコマンド  |


## 勉強後のイメージ

Raspbian とか Ubuntu しか触ったことないから、基本的にはapt-getで何でも入れてたけど、
yumと同じ立ち位置なのね。
あまり触ったことなかったから違うんかなって思ってたけど役割的には一緒だった。

※ちなみにRaspbianからRaspberry Pi OSに名前変わったらしい...知らんかった

## 参考

- [Linux × パッケージ管理 × apt? yum? rpm?](https://www.kinakomotitti.net/entry/2018/07/03/213449)
- [【初心者にもわかる】rpmとyumの違いと使い分け一通り](https://eng-entrance.com/linux-package-rpm-yum-def#rpmyum)
Herokuにデプロイする時に躓いたこと

##はじめに
ポートフォリオサイトを作るための最初の一歩として
試しに静的サイトをherokuにデプロイしてみたら少し躓いたので
備忘録として残そうと思いました。
誰かの参考になれば嬉しいです。
***

##Herokuのアカウント作成とHerokuCLIのインストール
Herokuのアカウント作成は必要な情報を入力してメール認証するだけ。
https://www.heroku.com/

つぎにHerokuアプリをターミナルから直接簡単に作成、管理できるようにするため
HerokuCLIをインストール。
https://devcenter.heroku.com/articles/heroku-cli
ターミナルから以下を入力するだけでインストールできます。

```
% curl https://cli-assets.heroku.com/install.sh | sh
```

途中でパスワードを求められるけど、これは自分のPCにサインインするときのパスワード。

インストールできたら、以下のコマンドを入力して

```
% heroku --version
```

バージョン名が出てくれば成功。

以下のコマンドを入力すると

```
% heroku login
```

ブラウザが起動してログインする。

##いざデプロイ
herokuにアプリケーションを作成するために

```
% heroku create
```
を実行。
するとherokuのダッシュボードに新しく追加されるはずです。

そして適当に

```
% mkdir sample
```
でディレクトリを作って

```php

<?php echo "hoge"; ?>
```
をindex.phpという名前で保存。
そして以下のコマンドを実行。

```
% cd sample
% git init
% git add .
% git commit -m "first commit"
% git push heroku master
```

```
% heroku open
```

でブラウザが開き、画面に「hoge」が表示されれば完了です。

##ここでエラー発生
`git push heroku master`を実行すると

```
fatal: 'heroku' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```
という文が表示されました。
どうやらgitがリモートのリポジトリを参照できていないようです。

```
% cat .git/config
```
を実行し、`[remote "heroku"]`が無ければ追加します。

```
% git remote add heroku https://git.heroku.com/アプリケーション名.git
```
これでリモートにherokuが追加されたはずです。
ちなみにアプリケーション名は、さっき`haroku create`を実行した直後の
`Creating app... done, ⬢ `以降にあるのがアプリケーション名です。

私はこれに気づかず、アプリケーション名を適当に「sample」とかにしちゃってました。
このアプリケーション名と、ダッシュボードにあるアプリケーション名が不一致のまま
`git push heroku master`を実行すると、今度は

```
remote: !	Your account [自分のメールアドレス] does not have access to sample.
fatal: unable to access 'https://git.heroku.com/sample.git/': The requested URL returned error: 403
```
という文がでます。あたりまえですよね。

対処法としては
`vim .git/config`を実行して、編集画面にします。
`i`を押すとインサートモードになるので、アプリケーション名のところまでカーソルを移動して編集します。
編集が終わったら`esc`でインサートモードを終了し
`:wq`で保存して終了です。
念のためもう一度`cat .git/config`で変更できてるか確認してみましょう。

これでもう一度pushし、やっとデプロイすることができました。
Gitコマンド（初学者の備忘録）

独学期間で使用したGitコマンドや用語の備忘録です。（随時更新）

<h2>Pull Request</h2>
あるブランチに、別のブランチをマージしてもらうための要求

　　　　　　　　　　　　　↓

追加したい機能ごとにブランチを作成し、最終的に共通のメインブランチであるmasterに取り込んでもらうことを目指す

<h1>git checkout -b login</h1>
loginブランチを作成しloginブランチ（ローカル）に移動できる
この段階ではremote上にloginブランチはありません

命名は自由ですが、客観的に分かりやすい命名を意識する。ログイン機能を一つの開発の区切りとしてブランチを切りたいのであれば「login」というように。
</br>
</br>
<h1>git checkout　ブランチ名　</h1>
任意のブランチに切り替えできる
</br>
</br>
<h1>git branch</h1>
ブランチ情報を表示することができる
（ブランチを作成していない状態だと「master」と表示されるはず）
</br>
</br>
<h1>git status</h1>
コミット前の状態を確認
</br>
</br>
<h1>git diff ファイル名 </h1>
本当に修正したファイルが正しいか確認（必要ない修正が入ってないか）
</br>
</br>
<h1>git add  app/…  db/…</h1>
（git add -Aは基本使わない、変更したファイルごとに登録することが原則）
</br>
</br>
<h1>git diff --cached　</h1>
addしたファイルが反映されているか、addしたい修正が正しくaddされているか確認（ファイルの一部分をaddするgit add -pを実行する場合に役立つ）
</br>
</br>
<h1>git commit -m “任意のコミットメッセージ”</h1>
ローカルリポジトリ側の準備が完了したことになる
</br>
commitメッセージも客観的にどのような開発機能部分（ファイルの種類等）なのか、修正したファイルであればどのような修正を施しているのかが分かる内容を心掛ける。
</br>
</br>
<h1>git log –-oneline -10 </h1>
コミットされたか、commitメッセージが正しいか
</br>
</br>
<h1>git push --set-upstream origin login</h1>
--set-upstreamは -uで省略可能。originブランチ名で参照先を示す。
</br>
このようにするとGitHub側でローカルと同じ内容のloginブランチが作成され、ローカルリポジトリのloginブランチがGitHubのloginブランチと連携するようになる
</br>
</br>
<h1>git branch -D [ブランチ名]</h1>
どんなローカルブランチも削除することができる（マージされていないブランチも含めて）
</br>
</br>
<h1>git commit –amend -m “”</h1>
直前のGit commit名を変更できる
</br>
</br>
</br>
<h2>Merge方法</h2>

Merge pull request(GitHub上)

　　　　↓

Git checkout master

　　　　↓

Git pull origin master

　　　　↓

Git log –oneline -10
（本当にマージされたか確認）

___
GitHubを初めて使用するような方は、commitやpush、mergeコマンドは毎回しっかりlogを確認してから行う方が良いと思います。少し慣れ始めたときにうっかりミスをしてしまうのでご注意を💦
reactのcomponentWillMount

## componentWillMount()
- componentが呼び出される直前に実行される
- setstateを呼び出すとstateに値が入った状態で画面描画される

```javascript

    componentWillMount(){
        const request = axios.create({
            baseURL: 'http://localhost:8080'
        })
        request.get('/describe')
            .then(res => {
                this.setState({
                    userDatas: res.data
                });
            })
    }

```
外付けNGINX環境でGitLab v13.5にアップデートすると502 Bad Gateway

# 概要
`GitLab` v13.5にアップデートしたら `502 Bad Gateway`になった。
なにが悪かったかのかを簡単にまとめる。

**先に結論**
悪いのは`GitLab`ではなく、`NGINX`のリバースプロキシ設定を変えなくてはならないのに変えなかったから。

# 発生環境
* `Ubuntu` 18.04
* `GitLab` v13.5.1 Omnibus版
    * アップデート前は v13.4.3
* `NGINX` v1.19.3
    * Omnibus版同梱ではなく、独立して動いている

# 何が起こったか？
`GitLab` v13.4.3 -> v13.5.1にアップデートしたら`502 Bad Gateway`になった。
慌てて`GitLab`の動作確認するも問題なし

```bash
$sudo gitlab-ctl status
# ここにいっぱいRUNって出てる。
```

# 原因を見つける
なんやかんやあって[GitLab v13.5リリースBlog](https://about.gitlab.com/releases/2020/10/22/gitlab-13-5-released/)見ると次の一文があった。[^1]

![スクリーンショット 2020-11-05 0.13.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240601/bf88d76a-eb1f-fa3a-54ce-c36493b38743.png)

>The default path for the Workhorse socket changed from /var/opt/gitlab/workhorse/socket to /var/opt/gitlab/workhorse/sockets/socket in 13.5. A gitlab-ctl reconfigure is required during upgrade to apply this change. If you use SELinux and have specified a custom socket path, see the upgrade documentation for some manual steps that are required.

もう一度特に重要なところを
>The default path for the Workhorse socket changed from <font color="Crimson">/var/opt/gitlab/workhorse/socket</font> to <font color="Crimson">/var/opt/gitlab/workhorse/sockets/socket</font> in 13.5.

まじでImportant

# 対策
[これが全ての答え](https://gitlab.com/gitlab-org/gitlab-recipes/-/blob/master/web-server/nginx/gitlab-omnibus-ssl-nginx.conf#L27)

`NIGNX`のリバースプロキシ設定の`conf`ファイル
よくある場所だと `etc/nginx/sites-available/GitLab.conf`とか

```diff:gitlab-omnibus-ssl-nginx.conf
upstream gitlab-workhorse {
  # On GitLab versions before 13.5, the location is
  # `/var/opt/gitlab/gitlab-workhorse/socket`. Change the following line
  # accordingly.
+  server unix:/var/opt/gitlab/gitlab-workhorse/sockets/socket fail_timeout=0;
}
```

ソケットのパスを`/var/opt/gitlab/gitlab-workhorse/sockets/socket`に変えればOK

# 参考サイト
* [Permission denied on sockets after update to "13.5.1-ce.0"](https://gitlab.com/gitlab-org/gitlab/-/issues/271623)
* https://gitlab.com/gitlab-org/gitlab-recipes/-/tree/master/web-server/nginx

[^1]: ページの1番下に書いてある。
[auto-ohin]自動で一括電子押印できるコマンドラインツールauto-ohinの紹介[電子印鑑]

# 電子押印できるコマンドラインツールauto-ohinの紹介
## 0. はじめに
毎月月末になると，pdfファイルを印刷して押印した後にスキャンするというムーブをしていました． そこで，押印したくなさすぎるが故に，電子押印をしてくれるコマンドラインツールを作りました．

リポジトリはこちら[GitHub](https://github.com/MitawaUT/auto-ohin)

## 1. インストール方法
簡単です．

```console
$ pip install auto-ohin
```

## 2. ファイルの準備

次のものを用意します．

- 押印したいpdfファイル
- 電子印鑑(透過画像(png))
- configファイル(後述)

### 2.1 configファイルの準備

押印するために必要なconfigファイルを用意します．Jsonフォーマットで書くことも可能ですが，Jsonnetにも対応しています．
例えば以下のファイルをテキストエディタで作成し，適当な名前で適当な場所に保存します．

今回は，`path/to/config.jsonnet` として保存したとして話を進めます．

```jsonnet
local root = "path/to/root/"; # 各種ファイルを格納する親ディレクトリ
local pathgen(path) = root + path;
{
    "input_path": pathgen("input.pdf"), # 押印をしたいpdfファイル名
    "save_path": pathgen("output.pdf"), # 出力ファイル名(存在している場合は書き換えられるので注意)
    "img_path": pathgen("inkan.png"), # 電子印鑑のファイル名
    "obj_pages": [1, 3], # 押印をしたいページ番号の配列です． 1から始まります．
    "position": [147, 225], # 左下を原点として[x, y]という形式で記入します．単位はmm．
    "img_size": [20, 20], # [幅，高さ]として入力します．単位はピクセル．
    "pdf_size": "A4" # 今のところ，A0~A5に対応しています．

}
```

## 3. 押印
コマンドラインで以下を実行すると，configファイルで指定した場所に押印後のpdfが作成されます．

```console 
$ auto-ohin path/to/config.jsonnet
```

## 4. 最後に

今後の展望: 引数が多いのでconfigを用意する形式にしましたが，Jsonに慣れていない人には使いづらいのでそこら辺どうにかしたいですね．アイデア募集中です．

P.S. pdfの各ページに透かしを入れたり，偶数ページのフッター位置に特定アイコンを入れたりなどの用途にも使えます．
【Laravel】複数テーブルからあいまい検索をしたい

# 画像タイトルとハッシュタグからあいまい検索したい

こういうテーブルがある

![ddcb54066c7b1a424e7ddc913ef509db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413699/10f7f0fc-8fc4-9569-492b-ad2ffbab0a03.png)

画像テーブルとハッシュタグテーブルがあり、それを中間テーブルがつないでいる。
**多対多**の関係である。
自由入力の検索フォームがあって、画像タイトルとハッシュタグからあいまい検索ができるようにしたい
（例えば『あ』と検索すれば『から**あ**げ』というタイトルの画像と『#めぐり**あ**い』というハッシュタグのつけられた画像が出てくる）。

## これでいいのか

```php:ImagesController.php
  $result = Image::whereHas('tags', function($q) use($keyword){
    $q->where('name', 'iLIKE', "%$keyword%");
  })->orWhere(function($q) use($keyword){
    $q->where('title', 'iLIKE', "%$keyword%");
  })->get();
```

- `iLike` を使って大文字と小文字を区別しないようにしている。
- `whereHas` において変数を使いたい場合は `use` で宣言しないとエラーになる。

**一応これで望んだ結果は得られる**が、どうも複雑すぎる気がする。
もっとカンタンにできないものでしょうか🤔
あとこれにユーザー名も検索対象に追加しようと考えるとどうすればいいのかもわからなかった。