OmniAICreator/Qiita-1.07M huggingface dataset:
belongs_toでdefault_scopeをunscopeする

- `belongs_to` に条件をつけることで、default_scopeをunscopeすることができます
- Rails6.0で確認

```ruby
# 古きよきdeleted_atで論理削除できるとします
class User < ApplicationRecord
  default_scope { where(deleted_at: nil) }
  has_many :articles
  has_many :comments
end

class Article < ApplicationRecord
  # Userが論理削除されていても参照できます
  belongs_to :user, -> { unscope(where: :deleted_at) }
end

class Comment < ApplicationRecord
  belongs_to :user
  # このように、default_scopeをunscopeした関連を定義することもできます
  belongs_to :user_with_deleted, -> { unscope(where: :deleted_at) }, foreign_key: :user_id, class_name: 'User'
end
```

```ruby
test "article" do
  user = User.create! nickname: 'nickname'
  user.articles.create! title: 'article_title'
  user.update! deleted_at: Time.zone.now

  article = Article.first
  # userを論理削除した後でも取得できます
  assert_equal user, article.user
end

test "comment user" do
  user = User.create! nickname: 'nickname'
  user.comments.create! text: 'comment'

  comment = Comment.first
  assert user, comment.user

  user.update! deleted_at: Time.zone.now

  comment = Comment.first
  # 論理削除後はnilになります
  assert_nil comment.user
end

test "comment user_with_deleted" do
  user = User.create! nickname: 'nickname'
  user.comments.create! text: 'comment'

  comment = Comment.first
  assert user, comment.user_with_deleted

  user.update! deleted_at: Time.zone.now

  comment = Comment.first
  # user_with_deletedを使えば、論理削除後でも取得できます
  assert user, comment.user_with_deleted
end
```

- has_many等でも同様のことができます
- こちらはactiverecordのテストケースから一部抜粋させてもらいました
  - https://github.com/rails/rails/blob/main/activerecord/test/cases/associations/has_many_associations_test.rb

```rb
class Car < ActiveRecord::Base
  has_many :bulbs
  has_many :all_bulbs, -> { unscope(where: :name) }, class_name: "Bulb"
end

class Bulb < ActiveRecord::Base
  default_scope { where(name: "defaulty") }
  belongs_to :car
end

test "test" do
  car = Car.create!
  bulb1 = Bulb.create! name: "defaulty", car: car
  bulb2 = Bulb.create! name: "other",    car: car

  assert_equal [bulb1], car.bulbs
  assert_equal [bulb1, bulb2], car.all_bulbs.sort_by(&:id)
end

```
【javascript】配列をループして処理成功した要素は削除する

この記事は移行しました！[最新の内容はこちら](https://naoqoo2.github.io/blog/javascript-%E9%85%8D%E5%88%97%E3%82%92%E3%83%AB%E3%83%BC%E3%83%97%E3%81%97%E3%81%A6%E5%87%A6%E7%90%86%E6%88%90%E5%8A%9F%E3%81%97%E3%81%9F%E8%A6%81%E7%B4%A0%E3%81%AF%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B/)をご覧ください😀


Vueなど配列データと見た目が連動（データバインディング）しているときに、
処理成功した要素だけ削除して、失敗した要素は残しておきたい。ということがありました。

ループ（forEach？Map使う？）と要素の削除（shift？deleteだとundefinedになるだけで要素は残るのか...）に試行錯誤した結果、forとspliceに落ち着いたのでそのメモ。

```js
for (let i = 0; i < this.files.length; i++) {
  const file = this.files[i];
  file.uploading = true; // 処理中だよ（見た目を変える）
  await upload(file).then(() => {
    // 処理成功したら要素を削除
    this.files.splice(i, 1);
    // 要素を削除（splice）したことで添字が詰まるので、i--しないと次の要素がスキップされてしまう
    i--;
  }).catch(error => {
    file.uploading = false; // 処理は終わったけど...（見た目を変える）
    file.error = true; // エラーになったよ（見た目を変える）
  });
}
```
ドメインコントローラーでセッションマネージャーを使う前に必要な設定

#結論
ユーザー名が`ssm-user`のアカウントを作成しておく
（アカウントのパスワードはポリシーに抵触しなければ何でも良い）

#環境
・AWSで公式のクイックスタートAMIを使用しました。
`Microsoft Windows Server 2019 Base - ami-0f3651a900e33262f`
`Microsoft Windows 2019 Datacenter edition. [English]`
※SSM Agentがデフォルトで入っています。

・インスタンスはpublic subnetに作成しました。

・IAMはSSMに必要な権限が付与されている以下AWS管理ポリシーのみアタッチしたロールをEC2にアタッチしました。
`AmazonSSMManagedInstanceCore`

・[こちら](https://soma-engineering.com/server/activedirectory/promote-domaincontroller-win2016/2018/04/24/)を参考にドメインコントローラーに昇格しました。

#事象
環境も整えたのでいざ接続してみたら画像のようなエラーが表示され、セッションが開始できませんでした。
![2021-04-08_18h58_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269716/f55d473b-93a1-b8b9-14ad-02e338d28576.png)
エラー内容は以下の通りです。

```
セッションが次の理由で終了されました。  ----------ERROR------- Unable to start shell: Failed to create user ssm-user: Instance is running active directory domain controller service. Disable the service to continue to use session manager.
```

#理由
[ドキュメント](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-prerequisites.html)には以下の記載がありました。

>ssm-user アカウントについて

>エージェントはインスタンス上にルートまたは管理者権限 (ssm-user と呼ばれる) を持つユーザーアカウントを作成します。(インスタンスでセッションが最初に開始されたときに ssm-user が作成されます。) セッションは、このユーザーアカウントの管理者認証情報を使用して起動します。

>Windows Server ドメインコントローラー上の ssm-user

>ssm-user アカウントは Windows Server ドメインコントローラーとして使用されているマネージドインスタンスに自動的には作成されません。ドメインコントローラーとして使用されている Windows Server マシンでセッションマネージャーを使用するには、ssm-user アカウントが存在しない場合は手動でアカウントを作成する必要があります。Windows Server で、SSM エージェント はセッションが開始されるたびに ssm-user アカウントの新しいパスワードを設定するので、アカウントを作成するときにパスワードを指定する必要はありません。

つまり、通常エージェントはセッション毎にユーザーアカウントを作成するけど、ドメインコントローラーだとローカルユーザーアカウントの概念が無く、セッションに使用できるユーザーが存在しない（作れない）のでエラーになってたようです。

#実践
エラーの文面通りドメインに`ssm-user`アカウントを作成するだけで、
![2021-04-07_20h07_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269716/56789aed-799e-4596-c9fe-716faa14956a.png)
無事接続できるようになりました！
![2021-04-08_19h38_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269716/6dd7c659-86f7-aea2-4216-cd0807f7f14b.png)

因みに、SSM エージェント サービスを実行するのには特段アカウントは必要無いようです。

#参考
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-prerequisites.html

https://soma-engineering.com/server/activedirectory/promote-domaincontroller-win2016/2018/04/24/
cssでぐるぐる作ってみた

# どうも7noteです。cssでぐるぐるを作ってみました。

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/af562d95-dbd0-793e-c5e4-4d4f6c04d42e.png)


固定電話の受話器のコードみたいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/3d313364-de72-054b-b26a-4100d616ce4a.png)

## ソース

```index.html
<div class="coil"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
```

```style.css
/*大きい半円*/
.coil span {
  width: 120px;
  height: 60px;
  border-radius: 60px 60px 0 0;
  border-top: 2px solid #000;
  position: relative;
  display: inline-block;
  margin-left: -40px;
}
/*小さい半円*/
.coil span::after {
  content: "";
  display: block;
  width: 40px;
  height: 20px;
  border-radius: 0 0 20px 20px;
  border-bottom: 2px solid #000;
  position: absolute;
  right: 0;
    bottom: -17px;
}
.coil span:last-child::after {
  content: none;
}
```

## 解説

大きい半円と小さい半円の繰り返しで作られています。パーツ1つだけ見るとこんななんじ。
青いほうがspanで、赤いほうがspanの疑似要素（after）です。

![parts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/6e2432cf-57b5-d006-548d-d7ac7ac5781c.png)

小さい円は大きい円の1/3くらいの大きさがベスト。
これを左右に繰り返しつつ重ねるために小さい円の直径分だけ左方向にずらす。
そして最後の1個の小さい半円は非表示にしておくことで、ぐるぐるのゴールが書けます。

## まとめ

半円同士をつなぐと変わった形をつくることができます。いろいろためしてみたいですね。
ぐるぐるの作り方はこれだけですが、もう少ししたらこれを使って他のものをcssだけで再現しようと考えているところです。おたのしみに。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
Rails-Tutorial 13章　Micropostの作成とUserとの関連付けについて

# Qiita初投稿です。
Rails-Tutorial 13章について自身のアウトプットと自分のつまづいたところの共有もかねて投稿してみました。

###Micropostの作成
```
$ rails generate model Micropost content:text user:references
```
$ rails generate modelはmodelとmigrationとtestを作成するコマンドでした。
そこにcontent:textを加えることによってText型のcontent属性を付与します。Text型は255文字までしか格納できないString型と違ってさらに長い文字列を扱えます。Text型は長い文字列を扱えるためパフォーマンスに影響するようですが今は考えなくても良いレベルの話かと思います。
![スクリーンショット 2021-04-08 18.43.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/958803/842509d5-c439-76d9-3e99-3fdc380e4909.png)
さらにuser:referencesによりuser_id属性が付与されユーザーと１対１の関係であることを表すbelongs_to　:userがapp/models/micropost.rbに追加されます。

Micropostモデルのマイグレーションファイルでもt.timestampsという行 (マジックカラム) が自動的に生成されています。これによりcreated_atとupdated_atというカラムが追加されます。
よってmicropostsのデータモデルは以下のようになります。![スクリーンショット 2021-04-08 18.53.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/958803/cee2744c-1365-3516-9eb0-27133860df87.png)

###UserとMicropostの関連付け
ここで一つのマイクロポストは一人のユーザーと関係性を持つべきであり、一人のユーザーは複数のマイクロポストとの関係性を持つべきです。
Twitterで例えると、一つのツイートのツイート主が複数人だったらおかしいですし、ツイート主が１つしかつぶやきができなかったらとんでもない欠陥を抱えているのは言うまでもないでしょう。
このことをそれぞれ
MicropostとそのUserは belongs_to (1対1) の関係性があるUserとそのMicropostは has_many (1対多) の関係性がある
と表現します。![スクリーンショット 2021-04-08 19.06.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/958803/e050f041-f180-0538-f91d-51bf6ea00dd2.png)

この関連付けを行うことにより
![スクリーンショット 2021-04-08 19.09.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/958803/ee4116b3-7362-7938-5d96-97f9e06d2bf3.png)
ではなく
![スクリーンショット 2021-04-08 19.09.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/958803/1364b777-e122-8baf-fbf9-a6364e512b4c.png)
を利用してマイクロポストを作成できるようになります。
つまり親モデルに属する子モデルのインスタンスを作成したい場合はnewではなくbuildを用います。
なおbuildメソッドはnewメソッドと同様にオブジェクトを返しますがデータベースには反映されないメソッドです。
そのほかにもmicropost.userだったらマイクロポストに紐づいたユーザーオブジェクトを返します。なおマイクロポストとユーザーは１対１の関係なのでどちらも単数系を用います。
user.microposts.find_by(id: 1)ユーザーに紐づいてidが１のマイクロポストを検索しますが、こちらは1対多の関係なのでマイクロポストは複数形です。user.microposts.createやuser.microposts.buildも同様の理由です。

なお、belongs_toとhas_manyは以下のように記述します。

![スクリーンショット 2021-04-08 19.27.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/958803/9d512ca3-bf90-9817-ae73-1ae79d85f6a8.png)

###dependent: :destroy
このようにマクロポストとユーザーを関連付けることができましたが、もしユーザが削除されても、ユーザーに関連するマイクロポストは自動では削除されません。
そのためにdependent: :destroyと言うオプションを用います。![スクリーンショット 2021-04-08 19.32.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/958803/ef788185-f00c-d66e-24ad-a16f8eda6d0a.png)

こうすることでユーザーが削除されてもマイクロポストだけが残ってしまうと言う問題を解消できます。


##最後に
ということでMicropostの作成とUserとの関連付けについてRails-Tutorialの受け売りですがまとめさせていただきました。
チュートリアルを自分で勉強していてわからなかったことやつまづいた点などを急に補足したりしたのでまとまっていない点などがあり少し見づらい点もあったかと思いますが参考になれば幸いです。
また間違っている点やミスリードを誘うような表現がございましたら教えていただきたいです。
【自動】Youtube Live の.m3u8ファイルURLを取得して QuickTime Player で再生するスクリプト

Youtube のライセンスなしの動画の HLS URL を取得する方法の記事を見かけたので、
この方法を自動化して、QuickTime Player で再生するスクリプトを作りました。

```zsh
#!/usr/bin/env zsh

VIDEO_ID="7NOSDKb0HlU"

HLS_URL="$(curl "https://www.youtube.com/get_video_info?video_id=$VIDEO_ID" | python3 -c "from urllib.parse import parse_qs; import json; print(json.dumps(json.loads(parse_qs(input())['player_response'][0])))" | jq -r .streamingData.hlsManifestUrl)"

open -a 'QuickTime Player' "$HLS_URL"
```

# 参考


[【手動】Youtubeの動画の.m3u8ファイルURLを取得する](https://qiita.com/TaigaNatto/items/384318fb73b4f4712f6e)

記事を公開してくださった方、ありがとうございました！
mimemagicが無くてbundle installができない!!

#概要
本日、EC2で自動デプロイの設定を行い、実行しようとしたらこんなエラーが!!

```
bundle stdout: Nothing written
bundle stderr: Your bundle is locked to mimemagic (0.3.5), but that version could not be found
in any of the sources listed in your Gemfile. If you haven't changed sources,
that means the author of mimemagic (0.3.5) has removed it. You'll need to update
your bundle to a version other than mimemagic (0.3.5) that hasn't been removed
in order to install.
```

#起きていたこと
Railsの一部であるactivestorageが依存しているmimemagic gemが、ライセンス関連の問題でrubygems.orgから取り下げられました。これにより、mimemagic <= 0.3.5に依存しているRailsアプリがbundle installに失敗するようになっていた。

#解決策
```
-gem 'rails', '~>  6.0.3.5'
+gem 'rails', '~>  6.0.3.6'
```

#参考
https://hackmd.io/@mametter/mimemagic-info-ja

https://qiita.com/suzuki_sh/items/84806ce231ed9b0f2e6d
バッチファイルで10個以上の引数を扱う

Y子です。
「 __バッチファイルの引数は9個まで__ 」縛りをなんとかしよう、というお話です。
~~わたしその縛り最近知りましたけどね~~
今回は、（用途はさて置き）縛りを回避する方法をがんばってひねり出します。

# 概要
バッチファイルの引数が10個以上でも、すべての引数を読み取れるようにします。
バッチファイルにドロップするファイルが10個以上でも、すべてのファイルを処理対象にします。

# コード
## 　挙動の確認
まず、引数取得変数（「`%数字`」形式の変数）の挙動を確認してみます。

```bat:argument_multi_test1.bat
@echo off

echo 0=%0 1=%1 2=%2 3=%3 4=%4 5=%5 6=%6 7=%7 8=%8 9=%9 10=%10 11=%11 12=%12
```

引数に、`a`から`l`まで12個のアルファベットを与えると…

```bat
> argument_multi_test1.bat a b c d e f g h i j k l

0=argument_multi_test1.bat 1=a 2=b 3=c 4=d 5=e 6=f 7=g 8=h 9=i 10=a0 11=a1 12=a2
```

まず`%0`には、バッチファイルのファイル名（`argument_multi_test1.bat`）が格納されます。これだけ特別ですね。
`%1`～`%9`には、1番目から9番目までの引数`a`～`i`が格納されます。

一方、10番目以降の引数`j k l`がどこかへ行ってしましました。
`%10`は`a0`と表示されているので、どうやら`%1`と`0`に分割して解釈されてしまうようです。
`%11`～`%12`も、`%10`と同様に`aナントカ`という形になりました。
つまり、引数は10個以上設定しても怒られないものの、値が正しく取得できるのは9個まで、ということになります。

## 　shiftコマンドを試す
ここで、引数の順番をずらしてくれる __`shift`__ コマンドを試してみます。
先ほどのバッチファイルに、2行追加します。

```bat:argument_multi_test2.bat
@echo off

echo 0=%0 1=%1 2=%2 3=%3 4=%4 5=%5 6=%6 7=%7 8=%8 9=%9 10=%10 11=%11 12=%12
shift
echo 0=%0 1=%1 2=%2 3=%3 4=%4 5=%5 6=%6 7=%7 8=%8 9=%9 10=%10 11=%11 12=%12
```

```bat
> argument_multi_test2.bat a b c d e f g h i j k l

0=argument_multi_test2.bat 1=a 2=b 3=c 4=d 5=e 6=f 7=g 8=h 9=i 10=a0 11=a1 12=a2
0=a 1=b 2=c 3=d 4=e 5=f 6=g 7=h 8=i 9=j 10=b0 11=b1 12=b2
```

なんと`shift`後は、さっきはファイル名が入っていた`%0`に、1番目の引数`a`が格納されました。
`%1`以降もひとつずつズレて格納され、さっき取得できなかった10番目の引数`j`は、`%9`として取得できました。
これはもしかして、`echo %1`と`shift`を無限に繰り返せば、すべての引数を表示できてしまうということでは！？

## 　えぐい数の引数を扱えるようにする
ということで、引数が尽きるまで無限に繰り返すやつを作ってみました。

```bat:argument_multi.bat
@echo off

:label_top

rem 引数がなければ、最後に飛んで終了する
if "%~1"=="" (
  echo 引数がありません
  goto :label_bottom

rem 引数があれば、出力してシフトし、最初に戻る
) else (
  echo %~1
  shift
  goto :label_top
)

:label_bottom
pause
```

さっきと同じ引数を与えてみます。

```bat
> argument_multi.bat a b c d e f g h i j k l

a
b
c
d
e
f
g
h
i
j
k
l
引数がありません
続行するには何かキーを押してください . . .
```

12番目の引数`l`まで、全部出力されました！
では、このバッチファイルに、たくさんのファイルをドロップしてみると…

```bat
C:\work dir\test01.txt
C:\work dir\test02.txt
C:\work dir\test03.txt
C:\work dir\test04.txt
C:\work dir\test05.txt
C:\work dir\test06.txt
C:\work dir\test07.txt
C:\work dir\test08.txt
C:\work dir\test09.txt
C:\work dir\test10.txt
C:\work dir\test11.txt
C:\work dir\test12.txt
引数がありません
続行するには何かキーを押してください . . .
```

ドロップしたすべてのファイルのフルパスが表示されました。すてきです。
てことは… __[昨日のアレ](https://qiita.com/koiwaiwaiko/items/119efa7a50b2f96d4045 "バッチファイルで拡張子「.zi_」「.zi」「.ex_」「.ex」をリネームする(PPAP)")__ をアレすることができますね…ふむふむ。

# おわりに
無限ループって、夢がありますよね。
ちょっと間違うと __悪夢__ になりますが！

ではまた！よい夢を！
GitとGitHubの連携をしてみよう

#GitとGitHubの連携をしてみよう
##Gitを始めてみよう

新しいパソコンを買ったのでGitをインストールしてGitHubと連携したい。
毎回、方法を忘れて調べるのでメモとして記載しようと思います

利用するパソコンは
- macbook air 2020
- バージョン: 11.2.1
- OS: Big Sur

とりあいずGitが入っているか確認

```ターミナル
git --version
```

```ターミナル
xcode-select: note: no developer tools were found at '/Applications/Xcode.app', requesting install. Choose an option in the dialog to download the command line developer tools.
```
google翻訳によると
>xcode-select：注：「/ Applications / Xcode.app」にインストールを要求する開発者ツールが見つかりませんでした。 ダイアログでオプションを選択して、コマンドライン開発者ツールをダウンロードします。

ということなので言われるがままインストールします。

インストールが完了したのを確認して
再度

```ターミナル
git --version
```

以下のような結果が出たら、Gitが正常に動作しています

```ターミナル
git version 2.24.3 (Apple Git-128)
```

##GitとGitHubの連携をしてみよう

GitHubのアカウントがない方は
[GitHub](https://github.com/"GitHub")の公式サイトからSign upしてアカウントを作成しましょう

アカウントをすでに持っている人は
使用しているパソコンがsshキーを持っているか以下のコマンドで確認

```ターミナル
ls ~/.ssh
```

sshキーがない場合は

```ターミナル
ls: /Users/UserName/.ssh: No such file or directory
```

sshキーがある場合は

```ターミナル
id_rsa		id_rsa.pub
```

と表示されると思います

sshキーがなかった場合は以下のコマンドでsshキー生成します

```ターミナル
ssh-keygen -t rsa
```

いろいろと聞かれますがReturnキーを押していれば大丈夫

sshキーができているはずなので以下のコマンドで確認

```ターミナル
cat ~/.ssh/id_rsa.pub
```

GitHubと連携させるために
[SSH and GPG key](https://github.com/settings/keys/"SSH and GPG key")にアクセスして

New SSH keyをクリック、
自分がわかりやすいタイトルとターミナルで確認したsshで始まるsshキーをコピぺします。

![git_add_ssh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077136/412fcaed-3cbf-e961-1ec5-3222ad6dc2ab.png)


あとはAdd SSH keyを押せば連携完了です

###参考にさしていただいた記事
[macでgitとgithubを連携させる](https://qiita.com/Lassieena/items/db7f4cf8d9b236643dd8"macでgitとgithubを連携させる")
【Swift】UserDefaultsのリセット方法


UserDefaultsのリセット周りのプロパティが結構変わっていて、ググる度にエラーが出て変換しまくっていたので、2021年4月現在のUserDefaultsのリセット方法をここに記します。

# バージョン
Xcode: v.11.3
Swift: v.5.3.2

# tl;dr

これでリセットできます。

```swift
let appDomain = Bundle.main.bundleIdentifier
UserDefaults.standard.removePersistentDomain(forName: appDomain!)
```

# 解説

「これでリセットできる！」では芸が無いので、一つ一つ意味を調べていきます。

```swift
let appDomain = Bundle.main.bundleIdentifier
UserDefaults.standard.removePersistentDomain(forName: appDomain!)
```

## Bundle 

Appleの[公式ドキュメント](https://developer.apple.com/documentation/foundation/bundle)によると、バンドルクラスは

> A representation of the code and resources stored in a bundle directory on disk.

と書かれており、意訳すると

**一つのディレクトリにまとめられたコードやリソースを代表するもの**と言えると思います。

つまり

プロジェクトファイル内のファイル・画像やBundle identifierなどの要素にアクセスするときに使うクラスらしいです。

### main

また、この`main`は

**現在実行中のファイルを返す**らしく、今回はその中から`bundleIdentifier`を取得してるということみたいです。

その他にも、info.plistの中身やローカライゼーションの情報が取れるみたいです。

```swift
		let main: Bundle = Bundle.main
		print(main.bundleIdentifier) // プロジェクトのbundleIndentifier
		print(main.infoDictionary) // info.plistの中身
		print(main.preferredLocalizations) // ["en"]
```

## removePersistentDomain(forName:)

`UserDefaults.standard`はおなじみとして、`removePersistentDomain(forName:)`はあまり馴染みがな人が多いと思います。

これも[公式ドキュメント](https://developer.apple.com/documentation/foundation/userdefaults/1417339-removepersistentdomain/)によると、

> Removes the contents of the specified persistent domain from the user's defaults.

と定義されていて、意訳すると

指定されたuserDefaultsの永続的なドメインの中の要素を消すメソッドということらしいです。

なんでbundleIdentifierを渡すと消せるの？とおもって調べてみた所結構闇が深そうだったので、別の記事にまとめます。

# 終わりに

これでいちいちコピペしなくと済みそうです。Swift(Xcode)ってプロパティ名に変わったときに表示してれるのが良いですよね。すこ


# 参考文献

- [Bundle | Apple Developer Documentation](https://developer.apple.com/documentation/foundation/bundle)

- [removePersistentDomain(forName:) | Apple Developer Documentation](https://developer.apple.com/documentation/foundation/userdefaults/1417339-removepersistentdomain/)
docker-compose buildしても環境変数が反映されない場合の解決方法と原因

環境構築時に少しハマったのでメモ

# ハマったこと

※環境変数は`.env`ファイルで管理しているものとします。

```sh:.env
# 環境変数
# ※変更前
# HOGE="hoge"
# ※変更後
HOGE="fuga"
```

上記のように、環境変数を変更し、ビルドしてコンテナ再起動しても、変更が反映されない。

```sh
# イメージ再作成し、
docker-compose build
# コンテナを再起動
docker-compose restart
# その後、コンテナに入って
docker-compose exec sample_app bash
# 環境変数を確認しても、変更が反映されていない
echo $HOGE
hoge

# キャッシュなしでイメージ再作成しても、
docker-compose build --no-cache
# 変更が反映されない
echo $HOGE
hoge
```

# 解決方法
```sh
# upでコンテナを再作成することで、 （-d はデーモン実行のオプションなので、付けなくてもOKです）
docker-compose up -d
# 変更が反映された
echo $HOGE
fuga

# おまけ：イメージとコンテナの更新を同時に行いたい場合は、buildオプション追加すればOK
#  （-d はデーモン実行のオプションなので、付けなくてもOKです）
docker-compose up --build -d
```

# 原因
コンテナが更新されていなかったのが原因でした。
`build`, `start`ではコンテナが更新されないので、環境変数の変更が反映されなかったようです。
`up`でコンテナを再作成することで、変更が反映されたというわけですね。

オプションの違いについては、以下の記事がとても分かりやすいのでおすすめです。

https://qiita.com/tegnike/items/bcdcee0320e11a928d46
Railsバージョンアップ時の LoadError: Unable to autoload constant ActiveStorage::Blob::Analyzable のエラー対応

## 現象
Railsのライセンス問題対応のためv5.2.2.1からv5.2.5に更新したら、capで以下のエラーがでました。

参考：Railsのライセンス問題
https://github.com/rails/rails/releases/tag/v5.2.5

```
02:15 whenever:update_crontab
      01 /usr/local/rbenv/bin/rbenv exec bundle exec whenever --update-crontab XXXX 
      01 bundler: failed to load command: whenever (/var/www/XXXX/shared/bundle/ruby/2.4.0/bin/whenever)
      01 LoadError: Unable to autoload constant ActiveStorage::Blob::Analyzable, expected /var/www/XXXX/shared/bundle/ruby/2.4.0/gems/activestorage-5.2.5/app/models/active_storage/blob/analyzable.rb to define it
      01   /var/www/XXXX/shared/bundle/ruby/2.4.0/gems/activesupport-5.2.5/lib/active_support/dependencies.rb:511:in `load_missing_constant'
      01   /var/www/XXXX/shared/bundle/ruby/2.4.0/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/core_ext/active_support.rb:43:in `load_missing_constant'
      01   /var/www/XXXX/shared/bundle/ruby/2.4.0/gems/activesupport-5.2.5/lib/active_support/dependencies.rb:195:in `const_missing'
      01   /var/www/XXXX/shared/bundle/ruby/2.4.0/gems/activestorage-5.2.5/app/models/active_storage/blob.rb:21:in `<class:Blob>'

```
（一部伏せ字に改変してます）

## 解決法

検索してでてくる解決方法では、エラーがとれずハマってしまたったのですが、
近い環境を再現して、同様のrakeコマンドを発行したら、以下のエラーが原因であることがわかりました。

```
Caused by:
Gem::LoadError: can't activate aws-sdk-s3 (~> 1.48), already activated aws-sdk-s3-1.46.0. Make sure all dependencies are added to Gemfile.
```

Gemfile内のaws-sdk-s3 のバージョンを指定したら解決しました

```
- gem 'aws-sdk-s3'
+ gem 'aws-sdk-s3', '1.48'
```
Aamazon WorkSpaces(仮想デスクトップ)を使って Windows 10 での動画検証


動画プレイヤーの開発していた場合に、動画の再生テストを `Windows 10` の`Edge`または`IE11`上で確認したい場合があります。
BrowserStack というサービスを使えば、いろんな端末・OS・ブラウザでテストは可能なのですが、1分ほどでセッションが途中で切れてしまい長時間配信の確認には向いておりません。
今回は [Amazon WorkSpaces](https://ap-northeast-1.console.aws.amazon.com/workspaces/home?region=ap-northeast-1
) の仮想デスクトップサービスを使って、よりリアルな環境に近い Windows 10 環境を構築し確認する方法です。

## 前提条件

- AWSアカウントを持っていること

## AWS WorkSpace の環境を構築する

### WorkSpace 画面へ遷移

![workspace-launch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/8c5fcf33-c278-f9ca-e6d2-8e05248b42c7.png)

`今すぐ始める` をクリックします。


### 高速セットアップを選択

![workspace-start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/9a06f30f-c57a-fcca-6cd6-46e3b37693d2.png)

最短でセットアップしたいので、`高速セットアップ` を選択します。


### Windows 10の選択とユーザーの登録し起動

いろんなバンドルやタイプがあるので、その中から今回は無料利用枠対象の Starndard with Windows 10 を選択します。

![workspace-bundle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/61cbe241-0e0b-7f0a-d618-587c5dec20d1.png)

また、この後で必要な、ユーザーの情報を入力します。

- ユーザー名 - ログインするためのユーザー名
- 名
- 性
- E メール - ユーザー情報更新のために後ほどメールが送られます。

`起動する` をクリックします。
構築には、20分ほどかかります。

### 起動確認

ステータスが `Available` に変われば構築は完了です。
![workspace-list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/1edd3ebc-37c3-3450-c8b8-9b56b9b98d8d.png)


## ユーザー登録

### パスワード登録

仮想デスクトップ環境が有効化されると、構築時に登録したメールアドレスへメールが届きます。
ユーザーの認証情報が表示されますので、パスワードのみ入力し更新します。

![workspace-mail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/5949c9f8-91c6-ca09-7113-c60edb9e0f09.png)

## クライアントのインストール

今回は Mac を使用してますので、 `MacOS X` のクライアントをダウンロードしインストールします。

![workspace-client-install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/cc913d22-215f-9fbf-3934-bb0f5b0d7129.png)

## WorkSpace クライアントを立ち上げる

下記の画面が表示されます。

![workspace-login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/884d6161-f0ab-8522-51cc-4217d011d45a.png)

### 動作確認

下記の画像のように、EdgeやIE11のブラウザを立ち上げて、動作確認できます。
スリープ状態にすることはできませんが、Windows PCと遜色なく使用可能です。

![workspace-player-test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/257076c6-c33e-4ec9-f2e9-bffd639a28e1.png)

> 注意:Edgeブラウザはデフォルトでインストールされておりませんので、インストールする必要があります。

## WorkSpaceのストップ

また、次回も使えるように、ストップします。
ストップ忘れ防止のために、AutoStop というタイマーをセットすることも可能です。

## まとめ

動画の確認だけでなく、他のWebアプリケーションが Windows 上で動作確認のテストをすることも可能です。
また、他のユーザーを追加することも可能なので、チーム内で活用することできます。
M1 mac Dockerで「ERROR: Service 'mysql' failed to build」のエラー

Dockerで
「ERROR: Service 'mysql' failed to build」
のエラーが出た

AppleSiliconを乗せているM1 Macのみに該当するエラー
まだM1のプラットフォームに合わせたMySQLが無く、
エラーが出る。

以下対処法

```docker-compose.yml
version: "3"
services:
  mysql:
    platform: linux/x86_64 
```

**platform: linux/x86_64**
を追加
コントローラーからPay.jpに金額を送る記述。

class OrdersController < ApplicationController

  before_action :authenticate_user!
 
  def index
    @order_address =OrderAddress.new

    @item = Item.find(params[:item_id])
    # if current_user == @item.user
      # redirect_to_root_path              #(出品者がurlを入力しても遷移できない記述。後から役立つはず)
  
  end


def create
    # binding.pry
    @order_address = OrderAddress.new(order_params)
    
    @item = Item.find(params[:item_id])
    if @order_address.valid?
      pay_item
  
      @order_address.save
       redirect_to action: :index
    else

      render action: :index
    end

  end

private

  def order_params
    params.require(:order_address).permit(:post_num, :shipment_source_id, :city, :address, :build_name, :phone_num).merge(user_id: current_user.id,  item_id: params[:item_id],  token: params[:token])
  end

  def pay_item
    Payjp.api_key = "sk_test_秘密鍵"  
    Payjp::Charge.create(
      amount: @item.price,  
      card: order_params[:token],    
      currency: 'jpy'              
    )
  end

 
end



create内にpay_itemを記述。

下にpay_itemの内容を定義する。
ここで秘密鍵の内容を記述する。
金額はitemsテーブルから引っ張ってくるので、@item.priceとする。
【初心者向け】サーバー構成の違いまとめ (SSR/SPA/サーバレス)


Crewという会社でCTOをしてます、いぬっくすと申します。
こちらは会社で新人エンジニア向けに作った資料の一部になります。

初心者の方には分かりづらい、ブラウザからサーバーにどうやって情報が流れていくのか、5種類の構成について説明していきたいと思います。

- 静的サイトの構成
- 一般的なWEBサービスの構成
- フレームワークのSPA構成
- フレームワークのSSR構成
- サーバーレス構成

# 静的サイトの構成
HPやLPなど、静的なサイトの構成になります。

![lp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226439/46129908-ea5f-9090-9141-8cfb002fa8b5.png)


メリット

- 他に比べてシンプルな構成
- ホスティングサービスなどにアップすれば自分でサーバーを用意する必要がない

デメリット

- サイト情報を変更したい時は、直接HTMLを変更しないといけない


# 一般的なWEBサービスの構成
昔から使われている、一般的なWEBサービスの構成です。

![ssr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226439/08c9e667-3e55-2576-e92d-e2bdf3cfe821.png)


メリット

- DBの情報を変更すれば、動的に表示を切り替えられる

デメリット

- ページ遷移時は必ずサーバーにリクエストを行うため、サーバーの負荷が高い
- フロントエンドとサーバサイド(のエンジニア)で分業がしにくい<br>
=> 開発者全員が自前DBを用意したり、Dockerの知識が必要だったり


# フレームワークのSPA構成
Nuxt.jsやNext.js等のフレームワークを用いたSPA構成です。
例えば、WEBサーバーにNuxt.js、APIサーバーにNode.jsなどのアプリケーションを配置します。

WEBサーバーは静的ファイル(HTMLや画像など)だけを返却すればよいので、ホスティングサービスに代替することも可能です。

![nuxt_spa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226439/4c7a000a-a281-f972-f0ab-2db8ca1ffe84.png)


メリット

- フロントエンドとサーバサイドで分業がしやすい
- リッチなページ遷移が可能
- スペックの低いサーバーでもある程度の負荷に耐えられる

デメリット

- WEBサーバーとAPIサーバーの両方の管理が必要
- 初期表示が遅くなる場合がある
- パソコンスペックによって動作が遅くなる場合がある
- meta情報やOGP画像が反映されない場合がある

# フレームワークのSSR構成
Nuxt.jsやNext.js等のフレームワークを用いたSSR構成です。
SPAとの違いは、初回のレンダリングのみサーバー側で行い、次のページ遷移からはSPAで動作するハイブリット構成になります。

![Nuxt_ssr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226439/4cf020a4-bb88-4d6c-c741-a3fa74eb15ab.png)


メリット

- SPAと違い、初期表示が遅くならない
- SPAと違い、metaやOGPが反映される

デメリット

- パソコンスペックによって動作が遅くなる場合がある
- SPAに比べ、フロントエンドに専門の知識が必要
- WEBサーバーとAPIサーバーの両方の管理が必要
- WEBサーバーにも、ある程度のスペックが必要になる


## サーバーレス構成
ちまたで「サーバーレス」と叫ばれている構成です。Nuxt.jsやNext.jsなどのフレームワークを用いてサイトを表現し、HeadlessCMSなどのクラウドサービスからデータを取得します。

様々なクラウドサービスが出てきたことにより、自分でサーバーを用意せずにサービスのリリースが可能になりました。「ホスティングサービス」「CMSサービス」は多種多様な選択肢があります。

以下ではSPA構成の図ですが、ホスティングサービスによってはSSRすることも可能です。

![less.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226439/035ecede-dbc1-429d-1ff4-9715112a96e0.png)

メリット
・サーバーを自前で用意する必要がなく、管理が簡単
・フロントエンド(エンジニア)のみでサービスのリリースが可能
・サービスは無料枠があるため初期は費用をかけずにリリース可能

デメリット
・やりたいことが増えると、サーバーの構成が複雑になっていく
・ホスティングサービス、CMSサービスの制約によっては出来ないこともある
・サービスのユーザー数が増えるとサーバーを作るよりも費用が多くなる場合がある


# 補足
上記ではSSRとSPAを対比して記載していますが、これらは別ものです。

- SPA（Single Page Application）
サーバーへの初回のリクエストで大元となるHTMLを取得し、ページ遷移はJavaScript側で制御を行うアプリケーションを指します。
ページ遷移が従来のものに比べスムーズで、リッチな表現が可能になります。

- SSR（Server Side Rendering）
サーバー側でHTMLのレンダリング処理を行うことを指します。「一般的なWEBサービスの構成」もSSRになります。

### ホスティングサービス
静的なファイルを返却してくれるウェブサービスを指しています。GithubPageやGitlabPage、Netlifyなどが例に挙げられます。
ただ、ホスティングサービスの中にもSSRに対応しているサービスもあり…利用者としてはとても喜ばしいですが、教える方としてはとても複雑になっており教えにくいのが現状です。


# 終わりに
これらの構成は、プロジェクトの仕様や、参加するエンジニア数と知識量、かけられるお金(運用費)によって選ぶ必要があります。

また、Nuxt.jsやNext.js等のフレームワークはSSR/SPA以外にも魅力的な機能が多くあります。静的なサイトにおいても、これらのフレームワークを用いることで開発がとても楽になります。
それぞれの出来ること、メリット・デメリットを理解して技術を選定していきましょう。


閲覧いただきありがとうございました：）

こちらの記事が少しでもためになった方がいればフォローお願いします。
https://twitter.com/iminux
z88dkの始め方(PC-88版)

#セットアップ
先ずは
[z88dkの始め方](https://qiita.com/Stosstruppe/items/02f8f2bf650b20c22c16)
を参考にz88dkをセットアップする。

* z88dkディレクトリ例）C:\etc\z88dk
* 開発用ディレクトリ例）C:\Projects\z88dk

#Cプログラムのビルド
開発用ディレクトリに以下のファイルを用意する。

* 開発用バッチファイル

```dev.bat
@echo off
path %path%;C:\etc\z88dk\bin
set ZCCCFG=C:\etc\z88dk\lib\config
cmd
```

* サンプルプログラム

```hello.c
//zcc +pc88 hello.c -create-app
#include <stdio.h>
void main()
{
	printf("\nhello, world\r\n");
}
```

開発用バッチファイルを起動し、以下のコマンドを実行すると`a.t88`ファイルが作られる。

```
zcc +pc88 hello.c -create-app
```

#X88000での実行例
メニューから「イメージ」→「テープイメージ」を選択し、`a.t88`ファイルを開く。
機械語モニタの`r`コマンドで読み込み`g8a00`で実行。
エントリポイントはデフォルトで`8a00`。
![hello.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257554/d7a18e2f-5066-5f2a-7fa6-1955398aa488.png)
初期定義ファイルで終了コードが`ret`になっている場合挙動がおかしくなる。
`rst $38`に置き換えると正しく機械語モニタに復帰する。
念のため`C:\etc\z88dk\lib\target\pc88`をディレクトリごとコピーして`pc88.org`などにしておく。

`C:\etc\z88dk\lib\target\pc88\classic`

```monitor.asm
start1:
        ld      sp,0
		
        ld      a,$FF		; restore Main ROM
        out     ($71),a
        ;ret
        rst     $38
```
v-forの特定の要素だけクリックイベントを発生させる

###クリックイベントに引数を持たせる

クリックイベントに引数を持たせ、methodsでクリックイベントを書く時に条件を指定する
以下の例だとv-forで回した画像が"メニューバーアイコン"の時だけ新たにメニューを表示することができる

##開発環境

+ Mac OS
+ Node.js v12.13.1
+ npm 6.12.1
+ Vue CLI 3.9.0
+ vue 2.6.2
+ Mac OS

##実装方法
クリックイベントにv-forの値を持った引数を持たせる　

```js
@click="toggleShowNav(navIcon.alt)
```

```html:html
<nav class="header__main__nav">
  <a :href="navIcon.url" class="header__main__nav__link" v-for="navIcon in navIcons" :key="navIcon" @click="toggleShowNav(navIcon.alt)">
    <img :src="navIcon.imgsrc" :alt="navIcon.alt" class="header__main__nav__icon">
  </a>
</nav>
<div :active="showNav"> //画像altが「メニューバーアイコン」のアイコンをクリックした時にだけ表示させる
  テキストテキスト
</div
```

methods内で条件分岐する。
この場合は引数の値（画像のalt）が「メニューバーアイコン」だった場合のみ

```js:js
export default {
  name: 'Header',
  data: function() {
    return {
      showNav: false,
      navIcons: [
        { 
          url: "#",
          imgsrc: "https://placehold.jp/20x20.png",
          alt: "検索",
        },
        { 
          url: "#",
          imgsrc: "https://placehold.jp/20x20.png",
          alt: "ショッピングカート",
        },
        { 
          imgsrc: "https://placehold.jp/20x20.png",
          alt: "メニューバーアイコン",
        },
      ],
    }
  },
  methods: {
    toggleShowNav(navIcon) {
      if (navIcon === "メニューバーアイコン") {
        this.showNav = !this.showNav;
      }
    },
  }
}
```

参考サイト：
[vue.jsで特定の要素にtoggleClassを付けたい
](https://teratail.com/questions/152225)
vue-slide-up-downのインストール

##この記事について
ナビゲーションをスライドで表示するプラグインの実装方法
スクリプト部分どう書くか迷ったので備忘

配布元：[vue-slide-up-down](https://www.npmjs.com/package/vue-slide-up-down)

##開発環境

+ Mac OS
+ Node.js v12.13.1
+ npm 6.12.1
+ Vue CLI 3.9.0
+ vue 2.6.2
+ Mac OS

##実装方法
上記のサイトのインストール方法に則って実施
Vueプロジェクトのディレクトリでインストールする

```:ターミナル
npm i vue-slide-up-down
```

main.jsに以下を追記

```js:main.js
import SlideUpDown from 'vue-slide-up-down'
Vue.component('slide-up-down', SlideUpDown)
```

vueファイルに記載

```vue:home.vue
<button @click="toggleShowSlide">
  ボタン
</button>
<slide-up-down :active="showSlide" :duration="300">
  テキストテキスト
</slide-up-down>

<script>
export default {
  data: function() {
    return {
      showSlide: false,
  methods: {
    toggleShowSlide {
      this.showSlide = !this.showSlide;
    }
  }
}
</script>
```
JSのオブジェクトの中の配列の長さを取り出す

##この記事について
オブジェクトの中に作った配列の取り出し方に手こずったため備忘

##オブジェクトの中の配列の長さを取り出す

```js:js
sales: [
    {
    data: "01",
    links: [
        {
        url: "linkA",
        shop: "shopA",
        },
        {
        url: "linkB",
        shop: "shopB",
        }
    ],
    },
    {
    data: "02",
    links: [
        {
        url: "linkA",
        shop: "shopA",
        },
        {
        url: "linkB",
        shop: "shopB",
        },
        {
        url: "linkC",
        shop: "shopD",
        },
        {
        url: "linkD",
        shop: "shopD",
        }
    ],
    }
]
```

```js:js
let last = 0;
for(let i = 0; i < this.sales.length; i++) {
  last = this.sales[i].links.length
  console.log(last)
}
```

#参考記事
[javascriptでobjectの中の配列を展開する書き方](https://qiita.com/macotok/items/f89d64825478b3e685c4)
ページごとに表示タイトルを変化させる方法

#目次
<b>①結論</b>
<b>②provideメソッドとyeildの使い方</b>

##①結論
ヘルパーメソッドを使用し、各ビューファイルでprovideメソッドを使用し、application.html.erbに共通で持たせれるようにする

##②provideメソッドとyeildの使い方

```php:index.html.erb
  <% provide(:title, "ホーム") %>
```

```php:application.html.erb
  <%= full_title(yield(:title)) %>
```

```php:任意のhelper

  def full_title(page_name = "") 
    base_title = "AttendanceApp"
    if page_name.empty? 
      base_title 
    else 
      page_name + " | " + base_title 
    end
  end
```
この記述を行うことで、ページごとにprovideメソッドを使用し、タイトルに表示させたい文字を代入することで、ページごとにタイトルを変更することができる。
Flex justify-content: space-betweenで最後の行を左寄せにする

## 目的
Flexboxで5カラムの要素を並べたい時、最後の要素が５に満たない時、レイアウトが崩れてしまう。

これを
![Flexbox](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1263973/a12b6460-4d3b-5648-3752-fe8e8fd8e80b.png)
こうしたい
![Flexbox](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1263973/5d0e945b-7dae-1361-a904-a6c9bf6cff55.png)

##書き方

```html:html
<ul class="flex">
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
// 空のボックスを用意する
  <li class="flex__item--empty"></li>
  <li class="flex__item--empty"></li>
  <li class="flex__item--empty"></li>
  <li class="flex__item--empty"></li>
</ul>
```

```scss:scss
.flex {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  &__item {
    width: 18%; /* 横幅を指定する */
    &--empty {
      width: 18%; /* 空の要素にも同じ横幅を指定する */
    }
  }
}
```

##追記　justify-content: flex-start；　で揃える方法
メリット：不要なHTMLを書かずに済む
サンプルコード：https://codepen.io/Maro1027/pen/abwqvZK

```html:html
<ul class="flex">
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
  <li class="flex__item">Sample</li>
</ul>
```

```scss:scss
.flex {
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
  &__item {
    background: orange;
    width: calc((100% - 80px) / 5); 
    height: 140px;
    margin-right: 20px;
    &:nth-child(5n) {
      margin-right: 0px;
    }
    &:nth-child(n+6) {
      margin-top: 20px;
    }
  }
}
```



###参考サイト
[Flexbox で全体を中央に配置しつつ最後の行を左揃えにする](https://qiita.com/QUANON/items/e14949abab3711ca8646)
[Flexboxのjustify-contentで最後の行を左寄せにする方法](https://blog.webcreativepark.net/2016/08/15-125202.html)
Citrix Provisioning Servicesとコンピュータ名について

Citrix Provisioning Servicesでゲストを展開すると、大文字で設定したコンピュータ名が展開後は全て小文字になっていることに違和感を感じたことないでしょうか。
PVSでゲストを作成するウィザード内で大文字で設定したにも関わらずどうしても小文字になってしまいます。
いろいろ調べていると起動したOSが謎なレジストリキーを参照しています。

そのキーが`HKLM\System\CurrentControlSet\Services\Bnistack\Parameters` にある`TcpipHostnameNoConversion`。
この値は`0`が設定されており、デフォルトの動きは大文字と小文字が逆になるようです。少し意味不明なカンジがするのですが・・・。
このキーに`1`をセットするとウィザード内で指定したコンピュータ名がそのまま登録されるようになりました。
勝手に変換されるとなんとなく気持ち悪い気がしますよね(あくまでも個人的な感想です)。
たぶん、意味があって変換されているんでしょうね。

```
キー：HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Bnistack\Parameters
値：TcpipHostnameNoConversion
種類：REG_DWORD
データ：1
```
【Android】定期購入プランの切り替え

###はじめに

サブスクリプションプランを複数用意したいことってよくあると思うのですが、例えば月間契約と年間契約で料金と期間のみ異なるプランの時、ただ二つ用意するだけでは重複購入ができてしまいます。
そんなときGoogleBillingLibraryではプランの切り替え(アップグレードやダウングレード)ができます。
[公式ドキュメント](https://developer.android.com/google/play/billing/subscriptions?hl=ja#change)に詳しく書いてあるので迷うことは少ないかと思いますが、備忘録も兼ねて書いておこうと思います。
課金実装については触れず既に複数プランが用意してある前提で進みます。

###環境

```xml:環境
Kotlin 1.3.61
GoogleBillingLibrary 3.0.3'
```

###追加する部分

追加するコードはとても少なく以下の通りです。

```kotlin:BillingActivity.kt

private fun showBillingDialog(skus: List<String>, scope: CoroutineScope, activity: Activity){

         //省略

         val params = BillingFlowParams.newBuilder()
                    .setOldSku(purchase,purchaseToken)//ここと
                    .setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION)//ここを追加
                    .setSkuDetails(skuDetails[0])
                    .build()

         //省略
    }

```

.setOldSku()に現在購入中のアイテム名とpurchaseTokenを渡します(後述します)。
.setReplaceSkusProrationModeは[公式ドキュメント](https://developer.android.com/google/play/billing/subscriptions?hl=ja#change)を参考に切り替えモードを決めます。
<details>
<summary>切り替えモード「DEFERRED」について</summary>
公式は同じ階層での契約期間の変更(月単位から年単位など)時に「DEFERRED」を推奨している感じですが、「DEFERRED」の場合、購入の流れが正常に行われても実際に購入されるのは現在購入中プランの更新時であり、それまでの間は再度他のプランへの変更はできず、他のプランの購入フローに入ろうとするとレスポンスコード5でエラーとなります。
また、ユーザーの購入操作と実際の購入のタイミングに差異があるため、購入ができたのかどうかが分かりづらいような気がしますし、承認をどうするべきかもよく分かりません。
なので個人的には「IMMEDIATE_WITHOUT_PRORATION」が無難かなあと思います。
</details>

基本的にはこれだけで自動的にプランのアップグレードやダウングレードができるのですが、このままだと新規で購入する場合におかしなことになってしまいます。
なのでif文などで適当に分けます。

```kotlin:BillingActivity.kt

private fun showBillingDialog(skus: List<String>, scope: CoroutineScope, activity: Activity){

         //省略

         val params:BillingFlowParams
            if (purchase == "none" || purchase == skus[0]){//現在購入中のアイテムがないor現在購入中のアイテムと同じ
                params = BillingFlowParams.newBuilder()
                    .setSkuDetails(skuDetails[0])
                    .build()
            }else{//現在購入中のアイテムがある時はアップグレードorダウングレード
                params = BillingFlowParams.newBuilder()
                    .setOldSku(purchase,purchaseToken)
                    .setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION)
                    .setSkuDetails(skuDetails[0])
                    .build()
            }

         //省略
    }

```

purchaseというStringにはpurchaseQuery()時に現在購入中のアイテム名を入れるようにしていて、購入中のアイテムが無ければ"none"としています(この辺は仕様によって色々やり方が変わると思いますが一応以下の感じです)。
購入中のアイテムがある場合は、ついでにpurchaseTokenも保持しておきます。

```kotlin:BillingActivity.kt

private fun purchaseQuery(){
        val purchaseResult = billingClient.queryPurchases(BillingClient.SkuType.SUBS)
        if (purchaseResult.responseCode == BillingClient.BillingResponseCode.OK){
            val purchases = purchaseResult.purchasesList
            if (!purchases.isNullOrEmpty()){//購入中のアイテムがあるとき
                purchases.forEach { p ->
                    purchase = p.sku
                    purchaseToken = p.purchaseToken
                }
            }else{
                purchase = "none"
            }
        }else{
            //error
        }
    }

```

###おしまい

かなり雑な説明になってしまいましたが参考になれば幸いです。
仮想IPとXenAppとMulti NIC

RDS環境で仮想IPを利用する場合、アプリケーション単位で仮想IPを利用するのかセッション単位で仮想IPを利用するのかを設定することになります。
この設定はRDS関連のポリシーで設定することになるのですが、セッション単位で仮想IPを利用する環境で複数のNICを利用する場合には注意が必要です。
システムのデフォルト設定では複数にNICを搭載したサーバーではセッション単位で仮想IPが利用できません。
複数のNICを搭載した環境で仮想IPを利用する場合、次のレジストリを設定してください。

```
キー：HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\TSAppSrv\VirtualIP
値：AllowPerSessionInMultiNIC
種類：REG_DWORD
データ：1
```
lメソッドについて

#目次
<b>①lメソッドとは</b>
<b>②lメソッドの使い方</b>

##①lメソッドとは
日付や時刻をローカライズするメソッドのこと

##②lメソッドの使い方
前提として以下のような記述があるとする。

```php:config/locales/ja.yml
ja:
  date:
    formats:
      default: "%Y/%m/%d"
      long: "%Y年%m月%d日(%a)"
      short: "%m/%d"
  time:
    formats:
      default: "%Y/%m/%d %H:%M:%S"
      long: "%Y年%m月%d日(%a) %H時%M分%S秒 %z"
      short: "%m/%d "

```
lメソッドを使うことで、表示したい形で表示することができる。

```php:
 <%= l(day) %>
```

上記のように記述することで、ビューにデフォルトで"%Y/%m/%d %H:%M:%S"のように表示される。
日付だけ表示させたい時にはdefaultではなく、shotのような形式で表示したいとする
この場合以下のような記述する。
formatオプションを付けると、書式を切り替えることができる。


```php:
 %= l(day, format: :short) %>
```
【Rails】他のコントローラーのアクションをrenderする方法


「users_controllerのshowアクションから、posts_controllerのshowアクションをrenderしたい…」

みたいな時ってどうしたら良いのか…。
というのを結構長いこと検索してしまったのですが、[Railsガイド](https://railsguides.jp/layouts_and_rendering.html)に書かれていたのでメモ👇

>あるコントローラのアクションから、まったく別のコントローラの配下にあるテンプレートを使用して出力することは可能でしょうか。（中略）パスにスラッシュ/が含まれていると、Railsによってこのビューは異なるコントローラの配下にあると認識されます。異なるコントローラのテンプレートを指定していることをより明示的にしたい場合は、以下のように:templateオプションを使用することもできます 

```Ruby
#明示的に書く場合
render template: "products/show"

#templateは省略可
render "products/show"
```
「IDDD本から理解するドメイン駆動設計」輪読会まとめ

株式会社ミライトデザインでは毎週、社内の技術力アップのために社内勉強会を行っています。

業務に関連することであればジャンルは様々ですが、今回はCodeZineさんの「IDDD本から理解するドメイン駆動設計」の輪読会を行いました。
[IDDD本から理解するドメイン駆動設計連載一覧：CodeZine（コードジン）](https://codezine.jp/article/corner/655)
こちらの記事を読むには会員登録が必要ですが、メールアドレスを登録するだけで無料で読むことができました。

「IDDD本から理解するドメイン駆動設計」は書籍「実践ドメイン駆動設計」の内容を要約してくれているものになります。
[実践ドメイン駆動設計 (Object Oriented SELECTION) | ヴォーン・ヴァーノン, 髙木 正弘 |本 | 通販 | Amazon](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9%A7%86%E5%8B%95%E8%A8%AD%E8%A8%88-Object-Oriented-SELECTION-%E3%83%B4%E3%82%A1%E3%83%BC%E3%83%B3%E3%83%BB%E3%83%B4%E3%82%A1%E3%83%BC%E3%83%8E%E3%83%B3/dp/479813161X/ref=asc_df_479813161X/?tag=jpgo-22&linkCode=df0&hvadid=295706574430&hvpos=&hvnetw=g&hvrand=14793800068119922147&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009318&hvtargid=pla-525785668462&psc=1&th=1&psc=1)


本稿は輪読会を行って出てきた疑問点や、気になったところなどを議事録にまとめたものになります。


議事録では「IDDD本から理解するドメイン駆動設計」に書かれている内容が前提となっています。
「IDDD本から理解するドメイン駆動設計」と合わせて読んでいただければ、理解のヒントになることがあるかもしれません。

---
### 1. DDDへの誘い
[【ミライトデザイン社内勉強会#10】「IDDD本から理解するドメイン駆動設計」輪読会~1章「DDDへの誘い」~ - Qiita](https://qiita.com/tkek321/items/4a2b62db7219a510dedd)

### 2. ドメイン
[【ミライトデザイン社内勉強会#11】「IDDD本から理解するドメイン駆動設計」輪読会~第2章「ドメイン」「サブドメイン」「境界づけられたコンテキスト」を読み解く~ - Qiita](https://qiita.com/tkek321/items/71096b6404ab2091f9b1)

### 3. コンテキストマップ
[【ミライトデザイン社内勉強会#12】「IDDD本から理解するドメイン駆動設計」輪読会~第3章「コンテキストマップ」~ - Qiita](https://qiita.com/tkek321/items/69080f47d8ae94766557)

### 4. アーキテクチャ
[【ミライトデザイン社内勉強会#13】「IDDD本から理解するドメイン駆動設計」輪読会~第4章「アーキテクチャ」~ - Qiita](https://qiita.com/tkek321/items/00686c0dd823d690e2ad)

### 5. エンティティ
[【ミライトデザイン社内勉強会#14】「IDDD本から理解するドメイン駆動設計」輪読会~第5章「エンティティ」~ - Qiita](https://qiita.com/tkek321/items/cf4f49b8f994e6b85651)

### 6. 値オブジェクト
[【ミライトデザイン社内勉強会#15】「IDDD本から理解するドメイン駆動設計」輪読会~第6章「値オブジェクト」~ - Qiita](https://qiita.com/tkek321/items/e30cedab379f431ceb79)

### 7. ドメインサービス
[【ミライトデザイン社内勉強会#16】「IDDD本から理解するドメイン駆動設計」輪読会~第7章「ドメインサービス」~ - Qiita](https://qiita.com/tkek321/items/2990c4a3533d9550b3a3)

### 8. ドメインイベント
[【ミライトデザイン社内勉強会#17】「IDDD本から理解するドメイン駆動設計」輪読会~第8章「ドメインイベント」~ - Qiita](https://qiita.com/tkek321/items/6cd7d5f15718119b34a4)

### 9. モジュール
[【ミライトデザイン社内勉強会#18】「IDDD本から理解するドメイン駆動設計」輪読会~第9章「モジュール」~ - Qiita](https://qiita.com/tkek321/items/2e89db963bd51e25fa1d)

### 10. 集約
[【ミライトデザイン社内勉強会#19】「IDDD本から理解するドメイン駆動設計」輪読会~第10章「集約」~ - Qiita](https://qiita.com/tkek321/items/248a4203c40b96fcfa84)

### 11. ファクトリ
[【ミライトデザイン社内勉強会#20】「IDDD本から理解するドメイン駆動設計」輪読会~第11章「ファクトリ」~ - Qiita](https://qiita.com/tkek321/items/f68548663aa63c7cf100)

### 12. リポジトリ
[【ミライトデザイン社内勉強会#21】「IDDD本から理解するドメイン駆動設計」輪読会~第12章「リポジトリ」~ - Qiita](https://qiita.com/tkek321/items/7f58a3aa26b325331345)

### 13. 分散システム設計
[【ミライトデザイン社内勉強会#22】「IDDD本から理解するドメイン駆動設計」輪読会~第13章「分散システム設計」~ - Qiita](https://qiita.com/tkek321/items/ecaaf790124e0b0213bf)

### 14. アプリケーション
[【ミライトデザイン社内勉強会#23】「IDDD本から理解するドメイン駆動設計」輪読会~第14章「アプリケーション」~ - Qiita](https://qiita.com/tkek321/items/4a34bdd74c891cfa47eb)
whereメソッドを使った複数のカラムの検索のかけ方

一つのカラムの検索しかできずに試行錯誤してみてできましたので投稿させていただきます！

# textカラムからのみの検索の場合

```ruby:tweet.rb
def self.search(search)
    if search != ""
      Tweet.where('text LIKE(?)', "%#{search}%")
    else
      Tweet.all
    end
  end
```

# text titleカラム両方からの検索の場合

```ruby:tweet.rb
def self.search(search)
    if search != ""
      Tweet.where(['text LIKE ? OR title LIKE ?', "%#{search}%", "%#{search}%"])
    else
      Tweet.all
    end
  end
```

思ったより簡単でしたのでぜひ試してみてください。
jQuery スクロール

animateを用いた記述

```
$(function () {
  // 上に戻るボタンの初期化
  let topBtn = $('#scrollTop');
  topBtn.hide();

  // ある程度スクロールされたら、上に戻るボタンを表示する
  $(window).scroll(function () {
    if ($(this).scrollTop() > 200) {
      topBtn.fadeIn(); // フェードインで表示
    } else {
      topBtn.fadeOut();  // フェードアウトで非表示
    }
  });

  // クリックで上に戻るボタン
  topBtn.click(function (event) {
    event.preventDefault();
    $('body,html').animate({
      scrollTop: 0
    }, 500);
  });
});
wordpress5.7で、中身がスペースのみのpタグが発生し余計な余白ができる現象に対処

Wordpressを5.7に更新すると、文節の間の余白がやたら大きく出るように。
どうも余計なpタグが発生している。
しかも内部に `&nbsp;`。（空のpタグもある。）
エディタの方にはないのになぜ。。

空のpタグはcssで、スペース入りのものはjsで対処。

```scss:scss
// 	wordpress5.7での余白対応。
p:empty::before{
	content: "";
}
```
```js:javascript
// wordpress5.7で発生したスペースのみのpタグを削除する。
// IE対応のため、forEachではなくforを使用する。
const paragraphs = document.querySelectorAll('.entry-content p')
for (let ii = 0; ii < paragraphs.length; ii++) {
	if (paragraphs[ii].innerHTML === "&nbsp;"){
		paragraphs[ii].remove()
	}
}
```


参考
- [Wordpressを5\.7に更新したら記事に変な余白が…空のPタグのCSSスタイルに::beforeが付いた時の戻し方。 \- ソロ学](https://sologaku.com/6685/)
- [JavaScript &nbsp; なスペースのあるHTMLの扱い \- かもメモ](https://chaika.hatenablog.com/entry/2019/07/15/083000)
- [querySelectorAll\(\)で取得した要素をeachで回す５つの方法 \- 動かざることバグの如し](https://thr3a.hatenablog.com/entry/20190304/1551701684)
エクセルでシードを指定して疑似乱数を発生させる

　エクセルにはrand関数という関数があり、セルに「=rand()」と入力するだけで0以上1未満の乱数を返してくれます。
　乱数を発生させるこの関数は非常に便利ですが、一つ欠点があるとすれば、<b>計算を行うたびに乱数が変化してしまい、再現性がない</b>ところにあります。プログラミングであれば、乱数にシード値を設定して、疑似乱数(乱数のように見えるが、該当のシード値を入力すれば同じ乱数(っぽいもの)を返してくれる)を発生させることで、分析の再現性を担保できます。その機能はエクセルのrand関数には残念ながらないので、マクロで作ってみることにしました。

```visualbasic
Sub Giziransu()
    Dim f As Single
    Dim num As Long
        For num = 1 To 10
            f = Rnd(-num) ' シード値を -num にする
            Debug.Print (f)
            f = Rnd
            Debug.Print (f)
            Cells(num, 1).Value = f
        Next num
End Sub
```
　4行目では、「For num = 1 To 10」と書いていますが、これは乱数を10個発生させることを意味しています。もっとたくさん発生させたい場合は数字を増やしましょう。
　9行目の「Cells(num, 1)」は1Aセルから乱数の入力をしていくことを意味しており、もし1Bセルから始めたければ「Cells(num+1, 2)」、2Aセルから入力したければ「Cells(num, 2)」としましょう。
【2021年度】プログラミング入門 Webアプリ　3章のdbで躓いたはなし

# 前置き
初投稿です
学習段階で躓いたところなどをメモしていく（予定な）ので、おかしいところがあったらコメントで指摘しまくってくれると嬉しいです

# 本題
## 発生した問題
途中でデータベースにアクセスする際に

```shell
su postgres
ユーザ 'postgres' のパスワードエントリがありません
```
となってしまいう問題

## 解決策

教材ではコンテナに接続する際に

```shell
docker-compose exec app bash
```
となっているが

```shell
docker-compose exec db bash
```
で接続するとうまくいきます

## 解決中の思考メモ
1. ユーザーがない？？？（linuxのユーザーについてよくわかってない）
2. 環境変数がないらしい
3. でも`docker-compose.yml`で定義しているぞ・・・？
4. このappとdbでもしかして別物・・・？
5. `docker-compose exec app bash`のappをdbにしたらなんか行けた
【Laravel】リレーション先のレコード有無をwhereの条件として指定する。

自分用のメモとして残します。

たまに使うのですが、ど忘れすることがあるのでメモ。


# ■やり方
以下は`table_a`は`table_b`とリレーションしていることを前提。
## リレーション先のレコードがある場合。
```php
$query->has('table_b');
//条件を付けるときはwhereHasで絞り込む
```
## リレーション先のレコードがない場合。
```php
$query->doesntHave('table_b');
//条件を付けるときはwhereDoesntHaveで絞り込む
```


# ■最後に
Eloquentやっぱ便利や。。
iPhone の充電の減りが早い時の対処法

iPhoneのバッテリーは消耗品なので、確かに長く使っていると充電の減りが早いなと感じることは多いですが、そこまで、使っていないのに、iPhoneの異常に充電の減りが早いなと思っている人は、消耗していること以外の原因が考えられます。そこで今回は、iPhoneユーザーの方で、異常に充電の減りが早い方に向けて、原因や対処法をご紹介していきます。
原因1、 自動ロックを設定しているのに、自動ロックされない
まず、１つ目の原因として考えられるのが、自動ロックされないという不具合が起きているため、充電の減りが早いという理由です。しかし、これに対して正式な対処法は残念ながらありません。ここでは、iPhoneの充電の減りが早い時の比較的治りやすい対処法を２つほどご紹介します。

対処法1 「自動ロック」の設定を確認する
①iPhoneの「設定」を選択
②「画面と明るさ」を選択
③「自動ロック」を選択
④7段階の中から、自分の最適な自動ロック時間を選択。この時、設定が「なし」になっていると、自動ロックがかからないので、充電の減りが早いです。

iPhone のほとんどは、デフォルトの状態だと自動ロック時間が30秒になっています。しかし、何かの拍子にここが、「なし」になってしまい、充電の減りが早いと感じることがあるので、iPhone ユーザーの人で、充電の減りが早い人はしっかりと確認してみてください。

対処法2 iPhoneを強制終了する
これは、どんな不具合が起きても一度は試して欲しい対処法です。iPhone の場合は、
① 「音量を上げるボタン」を押して、すぐに離す
②　「音量を下げるボタン」を押して、すぐに離す
③Appleのりんごマークが表示されるまで、側面の「スリープボタン」を長押しする。

以上の方法で、強制終了することが出来るので、試してみると、もしかしたら、充電の減り方が変化するかもしれません。

iPhone ユーザーの方で、充電の減りが早いと感じる方は、上記のように自動ロックの設定を確認したり、強制終了をしてみることも重要ですが、まず、手動でしっかりとロックする癖をつけると、充電の減りが早くなる原因が、自動ロックが原因であることが少ないので、しっかり確認する癖をつけましょう。

原因② 低電力モードになっていない
先ほど紹介した方法でも治らない場合は、この低電力モードになっていないことが原因かもしれません。低電力モードにすると、バッテリー消費の大きい動作を制限してバッテリー持ちが改善されます。iPhone 8で充電の減りが早い人は、ぜひ低電力モードを試してみてください。

対処法　iPhone を低電力モードにする
①iPhone の「設定」を選択
②「バッテリー」を選択
③「低電力モード」のスライドバーをオンにする。
yarn install で出会った「error An unexpected error occurred: "ENFILE: file table overflow」を解決したよ

## 事象
`yarn install`していたら、以下のエラーに出会った。

```
error An unexpected error occurred: "ENFILE: file table overflow ...
```

## 環境
Mac OS 11.2.3 (Big sur)
node v14.16.1

## 対処方法
nodeがどうとかyarnがどうとかでなく、Macの制限が原因みたい。
で、以下のコマンド実行

```
$ echo kern.maxfiles=65536 | sudo tee -a /etc/sysctl.conf                             
Password:
kern.maxfiles=65536

$ echo kern.maxfilesperproc=65536 | sudo tee -a /etc/sysctl.conf
kern.maxfilesperproc=65536

$ sudo sysctl -w kern.maxfiles=65536      
kern.maxfiles: 12288 -> 65536

$ sudo sysctl -w kern.maxfilesperproc=65536
kern.maxfilesperproc: 10240 -> 65536

$ ulimit -n 65536
```

その後、無事に`yarn install`完了！！！
よかった！！

## 参考サイト

- [Error: ENFILE: file table overflow on MacOS Sierra](https://github.com/reactioncommerce/reaction/issues/1938)
Gitで管理したいけど、載せたくないものが含まれている時は環境変数を使ってみる

# きっかけ
入力フォームを送信すると、自分のメールアドレスに通知がくる簡易アプリを作成していました。
個人のメールアドレスがコードの載ったままGitHubに載せていたのですが、***「個人情報だから載せない方がいいよ」***とご指摘を頂きました。

そこで、***「Gitで管理したいけど、載せたくないものが含まれていたらどうすればいいのだろう？」***と考えたのがきっかけです。

#環境変数を使う
環境変数を登録しておき、コード内で変数を読み込めば、隠したい部分は変数になります。

〇〇〇@gmail.comを隠したい場合、環境変数emailを登録しておけば、コードには「email」しか乗らないわけです。

#環境変数の登録

コントロールパネルから環境変数を登録します。

![Inkedスクリーンショット 2021-04-09 155453_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1044070/d95efe19-04c2-11a0-796c-c37abcdedc65.jpeg)



>参考：https://www.atmarkit.co.jp/ait/articles/1805/11/news035.html

~~bushで`$ export 変数="登録したやつ"`にすればOK！~~
~~例）`$ export email="〇〇@gmail.com"`~~

>~~参考：https://qiita.com/fuwamaki/items/3d8af42cf7abee760a81~~

#Javaで環境変数をつかってみる
```java
		String hoge = System.getenv("email");
		System.out.println(hoge);
```
>参考:https://eng-entrance.com/java-basic-environment-variable


無事にメールアドレスを隠すことができました。