OmniAICreator/Qiita-1.07M huggingface dataset:
【C#/WPF】EventTriggerを使って、Buttonでなくてもクリック時のCommandをかけるようにする

# やりたいこと
Buttonの「Command」プロパティに、ViewModelのICommandに書いた処理をバインドして「ボタンを押したときの処理」を書いていたが、Button以外の普通のコントロール(例えばGridとか)に、「押したときの処理」を書きたい。

＝ViewModelで定義したICommandに、ボタンではないコントロールをクリックしたときの処理を書きたい。
(`ViewModelで定義したICommandに`→表現正しいのか？)

# EventTriggerを使う
    
EventTriggerを使う前に、下記の手順が必要。

- System.Windows.Interactivity.dllを参照に追加
- Microsoft.Expression.Interactionsを参照に追加
- xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xamlの上に追加

# xaml側

``` a.xaml
<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="1">このグリッドを押すと、トリガーが発火します2
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDown">
                    <!-- ViewModelのメソッドの呼び方１ -->
                    <i:InvokeCommandAction Command="{Binding func}"/>
                    <!-- ViewModelのメソッドの呼び方２ -->
                    <ei:CallMethodAction TargetObject="{Binding}" MethodName="EventFunc"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBlock>
    </Grid>
</Window>

```

# ビューモデル側

```cs
using System.Windows;
using System.Windows.Input;

namespace WpfApp1
{
    class ViewModel
    {
        public ICommand func { get; set; }

        public ViewModel()
        {
            func = new DelegateCommand(
                () =>
                {
                    MessageBox.Show("トリガー発火");
                    return;
                });
        }

        public void EventFunc()
        {
            MessageBox.Show("CallMethodAction でトリガー発火");
        }
    }
}
```
# その他の部分のコード
こちらに置いておく。
https://github.com/tera1707/WPF-/tree/master/003_EventTrigger

# memo

- トリガーには、EentTrigger以外に、
    - TimerTrigger 
    - PropertyChangedEventTrigger 
- トリガー発火時に呼ばれるActionには、下記のようなものがある。
    - CallMethodAction 
    - ChangePropertyAction 
    - ControlStoryboardAction 
    - GoToStateAction 
    - InvokeCommandAction 

[かずきのBlog](https://blog.okazuki.jp/entry/2014/12/21/205558)より。
上のサンプルでは、EventTriggerで、CallMethodAction とInvokeCommandAction を使っている。
この辺りをうまく使えば、xamlだけでいろいろなことができそう。(未検証)

# 参考
WPF4.5入門 その58「Behavior」
https://blog.okazuki.jp/entry/2014/12/21/205558

【WPF】【MVVM】イベントをViewModelのメソッドに割り当てる。２
http://pro.art55.jp/?eid=1303821

GUIのマウス/キー操作処理をコードビハインドから駆逐する
https://qiita.com/hotelmoskva_/items/13ecc724bdad00078c16
Craft CMS でダッシュボードにエントリの数を表示する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8890/3b7e6f4c-77e4-46fb-1681-7d4334a7124d.png)

このプラグインを表示できる。

> CP Element Count
> https://plugins.craftcms.com/cp-element-count
EmacsでTrampがフリーズしたときの対処法


SSH接続先の.bashrcをいじって、プロンプトの表示をいじっていたら、Emacsが急に落ちて、それ以後Trampで接続できなくなった。Tramp Modeフリーズ時の対処法はEmacs Wikiにまとまっていた。
私の場合は、Tramp hangs #6: Not recognising the remote shell promptというやつであった。

Emacs Wiki Tramp Mode <https://www.emacswiki.org/emacs/TrampMode>
NPOの人におすすめするwebサービス

#はじめに
NPOに入ってから、ひたすら（NPOだったら）無料で使えるwebサービスを探しています。今回はそんなオトクなwebサービスを書いていきますね。

#MammothProject
https://mmth.pro/
プロジェクト管理ツールです。タスク管理で使える感じ。
こんな感じで、NPOは無料で使用可能です。
ページは[こちら](https://mmth.pro/pricejp)
![Screenshot 2019-04-24 at 21.54.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172695/610d04a3-af7d-5c8a-c524-59b3bba21de7.png)


弊法人の場合は、名前とリンクを送ったらさくっとOK貰えました。ありがとうございます。


#Scrapbox
https://scrapbox.io/
マニュアルを気軽に作成できるナレッジ共有ツールです。
覚えることが多いNPO界隈、これは重宝しています。

そんなサービスですが、こちらはそもそも申し込む必要すらありませんでした。
以下ページで画像のように選択すると、早速作れます。
https://scrapbox.io/projects/new
![Screenshot 2019-04-23 at 20.42.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172695/47c7c34c-ea06-7ef4-b971-7030049c07fd.png)

#Cybozu
https://www.cybozu.com/jp/
こちらは無料ではなくて割引のサービスとなります。
グループウェアと、業務アプリもkintoneも付随しているのでそれなりにシステムがつくれる感じのサービスですね。

以下ページに割引についての詳細な記載があります。
https://npo.cybozu.co.jp/?_ga=2.173235875.1697481090.1556019857-808964701.1535967889

#終わりに
取り急ぎメモりましたが、またオトクなwebサービスを見つけたら加筆修正していきますね。
皆さんもオトクなサービスを見つけたらぜひ教えてください。
collapse ページ表示時選択済みにする


#html

```html
<div id="sidebar-container" class="sidebar-expanded d-none d-md-block">
            <ul class="list-group">

<a href="#submenu101001" data-toggle="collapse" aria-expanded="false" class="bg-dark list-group-item list-group-item-action flex-column align-items-start">
    <div class="d-flex w-100 justify-content-start align-items-center">
        <span class="fas fa-universal-access fa-fw mr-3"></span>
        <span class="menu-collapsed">XXX</span>
        <span class="submenu-icon ml-auto"></span>
    </div>
</a>
<!-- Submenu content -->
<div id='submenu101001' class="collapse sidebar-submenu">
    <a href="/kokyakus/" class="list-group-item list-group-item-action bg-dark text-white">
        <span class="menu-collapsed"><i class="fas fa-ellipsis-v"></i> XXX</span>
    </a>

......

```
#jQuery

```Javascript
$(function(){
  var path = location.pathname;
  var paths = path.split('/');
  path = '/' + paths[1];

  $('.sidebar-submenu a').each(function(index, element){
    if($(element).attr('href').indexOf(path) > -1){
      var menuid = $(element).parent().attr('id');
      $(element).addClass('text-warning');

      $('#sidebar-container a.list-group-item').each(function(index, element){

        if($(element).attr('href').indexOf(menuid) > 0){
          $(element).click();
          return false;
        }
      });
      return false;
    }
  });
});

```
jQuery カレンダーで年月だけ選択したい

#ブツブツ
カスタマイズしたjsが見つかったりしたのですが、バージョン３に対応してないとか。
bootstrapではあるが、チーム内でカレンダーはjQueryに統一すると言ったもんだから今更例外を注込むには面目なし。
下記で頑張ってみるか。

jQuery UI Month Picker Plugin
https://kidsysco.github.io/jquery-ui-month-picker/
Outlook 2016のデータファイルを既定のフォルダから動かすのにはまった

## やりたかったこと
Outlook 2016のデータファイルをOneDriveでクラウドに同期させたかった。

## 試行錯誤の記録
1. ジャンクションポイントかシンボリックリンクでデータファイルのあるフォルダをOneDriveの同期フォルダの下に持ってくる。
  - リンクは作れるものの、ファイルが同期される気配なし。
  - 昔のバージョンだと出来たのか？
2. あきらめてOutlookのデータファイルをOneDriveのフォルダ配下に移動させようとする。
  - ググるとOutlook 2010の記事でデータファイルを複数登録し、移動先のデータファイルを既定に設定することで切り替えることで移動させる記事がいくつか引っかかるものの、Outlook 2016では電子メールに紐付いているため「配信先フォルダ」は変更不可。
  - マイクロソフトのフォーラムを探しておそらく同じ内容のトピックをいくつか見つけるものの、Outlookのカテゴリのボランティア・モデレータがわけのわからない情報量のない回答しかしておらず、全く役に立たない。
  - 「配信先フォルダ」関係の言葉でググっていたところ、以下の記事を見つける。
  - https://support.microsoft.com/ja-jp/help/2752583/you-cannot-change-the-location-of-the-offline-outlook-data-file-ost-in
  - Outlook 2013以降のバージョンだとデータファイルの場所はプロファイルの作成時のみにしか指定出来ないと書いてある。
3. プロファイル作成時にデータファイルにpstファイルを指定しようとする。
  - ostファイルでないと受け付けないと怒られる。
  - ostファイルからpstの変換はググると引っかかるものの、pstからostへの変換はなさそう。
  - 一応、マイクロソフトのフォーラムを見たところ、ボランティア・モデレータがわけのわからない回答を（略
4. ostファイルの説明を読むと、IMAPだとほとんど使っていないように読み取れる記述を見つける。
5. 単純に新規に任意のフォルダに作ったostファイルにpstファイルをインポートすれば良いのではないかと気付く。(正解)

## まとめ
Outlook 2016でデータファイルを任意のフォルダに移動させるための手順は以下の通り。

1. Windows 10の場合、Windowsシステムツールの下にあるコントロールパネルからMail(Microsoft Outlook 2016)を選択する。歯車マークの「Windowsの設定画面」からは辿り着けません。
2. [リンク先](https://support.microsoft.com/ja-jp/help/2752583/you-cannot-change-the-location-of-the-offline-outlook-data-file-ost-in)の手順でプロファイルを新規作成し、任意のフォルダの下のostファイルを指定します。ファイルがない場合は新規作成されます。
3. 作成したプロファイルでOutlookを起動し、インポート機能でpstファイルを取り込みます。
エンベデッドシステムスペシャリスト合格に向けた学習進め方メモ

# 目的
（少し前ですが）H30春にIPAのエンベデッドシステムスペシャリストに合格しました。

- [エンベデッドシステムスペシャリスト試験(ES)](https://www.jitec.ipa.go.jp/1_11seido/es.html)

勉強を開始したのがH29でしたが、当時はサイトを見ても勉強法があまり載っておらず、
載っていたとしても元々ハードに慣れた方が多く、ソフト出身の自分には勘所が分からず、
とりあえず参考書を購入するがどう進めればよく分からなく遠回りする等苦労した覚えがあります。

また、H31.4時点でも、[応用情報技術者ドットコム](https://www.ap-siken.com/)系の姉妹サイトにはES試験について特に相談場所がなく、
現在でもネット上に知見が十分に溜まっていないようにも感じています。
このような背景もあり、自分なりの知見をメモとして記載します。

ただ、進め方は個々によって異なると思いますので、
ご参考までにお願い致します。

# 本記事に記載している事/記載していない事

- 記載している事

学習するため準備する事、進め方

- 記載していない事

具体的な問題の解き方　→ 本の解説参照
傾向と対策　→ こちらも本の解説参照

# 準備
参考書は下記３冊を用意します。

①[翔泳社 情報処理教科書 エンベデッドシステムスペシャリスト](https://www.amazon.co.jp/dp/B07G77V315/ref=cm_sw_r_tw_dp_U_x_7tWUCbXMBPWSJ)
②[アイテック 徹底解説エンベデッドシステムスペシャリスト本試験問題](https://www.amazon.co.jp/dp/4865751491/ref=cm_sw_r_tw_dp_U_x_9xWUCb9506XS3 )
③[アイテック エンべデットシステムスペシャリスト「専門知識+午後問題」の重点対策 ](https://www.amazon.co.jp/dp/4865750975/ref=cm_sw_r_tw_dp_U_x_2vWUCbBG8BA3N)

過去問は合計６年分用意します。（IPAのサイトからダウンロードします）
一部の過去問は参考書にも掲載されている+解説も載っており、それがあればダウンロード不要です。
解説がある事が最も重要で、他に解説が乗っている本があれば迷わずそちらを選びます。


これを下記ステップで解き進めます。

Step1.本①の各章と目次をざーっと眺めて範囲を確認する。流し読みでOK。(600ページ全て深堀りする必要はない)
Step2.本②③+過去問のAM2を解く。初回はボロボロと思うが、なぜ間違ったか明確にできればOK。
Step3.本②③+過去問のPM1を解く。初回はボロボロと思うが、なぜ間違ったか明確にできればOK。※1
Step4.本②③+過去問のPM2を解く。長文についていけなければ解答見ながらでもOK。自分なりのいつもの解答パターンを見いだすのが重要。
Step5.ここで本①に戻る。読み直すと大体分かってきてる事に気付くと思うが、分からない/苦手な部分まだ３割程あると思うので見える化する。
Step6.本②③+過去問のPM2対策が重要、step.3〜5.で気付いた苦手な部分の復習を繰り返す。※2
Step7.本番二週間前頃〜は得意な分野を伸ばす

各step.は厳しそうだと思ったら適宜戻ってやり直す。

※PM1/PM2は過去問のうち自分の得意/興味がある部分からとっかかる。映像とかネットワークとか。
※例えばソフト系問題が得意→ハード系問題見直す。等

# AM1 50分
応用情報の過去問を6回分ほど解けばOK。詳細は省略。

# AM2 40分
過去問６年分ほど解けばOK。
４択問題は、正解以外の問いが何を意味しているか確認する。
実感的に過去問からの出題が５割程占めている感じがある。
１問１分〜程で解答したいところ。

# PM1 90分
過去問６年分解いて、７割は取れるようになりたい。
大体、1.仕様、2.詳細設計、について問われる問題が２問出る。
問１個目(共通)　35分
問２個目　55分　程度の配分で解きたいところ。
PM2解ければPM1解けるので、時間がない時はPM2を重点強化してPM1は対策優先度下げる。
計算問題が解ければ安心できるOK

# PM2 120分
過去問６年分解いて、７割は取れるようになりたい。
大体、1.仕様、2.詳細設計、3.仕様変更に伴う設計変更時の課題、が出題される感じ。
3.が最後の砦で、1.2.で７割獲得し、3.で６割下回った場合でも救われるようにしたい。
1. 40分
2. 45分
3. 35分　程の配分で解きたいところ。
問１問２は得意な方を選択する。
文章記述問題の解答の99%は本文から答え見つけ出す必要があり、日頃の業務等から推測される答えは試験上はNGになる事が多い。

# 学習期間

1月上旬〜4月試験日までの約3.5ヵ月
　平日：0時間
　土日：2-3時間+α　※時間区切りではなく問題の進め方にそって問題解けたら終了みたいに進めていた

■内訳
Step1.　1週間
Step2.+Step3.　1.0ヵ月
Step4.　1.0ヵ月
Step5.　1週間
Step6.　0.5ヵ月
Step7.　2週間

# まとめ
エンベデッドシステムスペシャリスト合格に向けた学習進め方メモを記載しました。
問題の内容には、身近な組込み装置（ドローン、オーディオ、映像会議システム、etc）が題材のものも多く解けると楽しいです。
資格持っている事が必ずしも開発スキルに直結する訳ではないと思いますが、自己のスキルの棚卸し手段の１つとして学習するのも良いのではないでしょうか。

テクニックで解いて終わりでは寂しいので、
取得後は、折角なのでarduinoで電子工作すると楽しいと思います。


# 参考
・[エンベデッドシステムスペシャリスト試験(ES)](https://www.jitec.ipa.go.jp/1_11seido/es.html)
・[組み込みエンジニアでなくても週末にArduinoを使って遊ぶ](https://qiita.com/seigot/items/958d3f2817a4bdac8754)
passwordの暗号化の方法

##Model##
```erb
$ rails g model User  password_digest
$ rails db:migrate
```
- password_digestカラムを作る

```rb
class USer < ApplicationRecord
  has_secure_password
end
```
#####has_secure_passwordを有効にする#####

- パスワードを暗号化して保存
- password_confirmationをフォームに追加
- 確認メソッドのauthenticateを提供

##Gemfile##

```erb
gem "bcrypt", "~> 3.1.7"
```
- コメントを外す

```erb
$ bundle install
$ rails s
```
Prism.UnityでNavigationAsyncしてもページのViewModelが生成されない問題への対処

## 概要

* 自前でアプリのメニュー＋Frameを準備して、そのFrameからNavigationServiceを生成するケース
* メニュー部分とFrame部分で別々のDataContext（ViewModel）を扱う必要があるが
* FrameのDataContextがnull以外だとNavigationService側の実装が「もうViewModel注入済みやな」と判断してViewModelが生成されない
* 結論：自前FrameからNavigationServiceを生成する場合はDataContext伝播に気を付けよう

## 環境
Uno.Prism.Unity.Uno 7.1-pre4
（本家のPrism.Unity.Windowsと同じなはず）

## 問題: NavigationAsyncしても xxxPageViewModelが生成されない

Prism.Unityでは自前定義のFrameに対してNavigationServiceを都度生成することができます。アプリで複数のFrameでページ表現を別々に管理したり、あるいは複数ウィンドウで別々のFrameをもたせてそこでページを管理する場合に活躍します。（ページナビゲーションのパラメータ渡しがやりやすいだとか、ページVMの注入を自動で紐づけてくれるだとか）

そこで以下のようなNavigationServiceを作ってみると…

```csharp

// PrismApplicationを継承したAppクラス内として読んでください

public static IPlatformNavigationService NavigationService { get; private set; }

public override void OnInitialized()
{
    // アプリのルートUIを作成
    var layout = new ApplicationCoreLayout();
    NavigationService = Prism.Navigation.NavigationService.Create(layout.MyFrame, Gestures.Back, Gestures.Forward, Gestures.Refresh);
    Container.GetContainer().RegisterInstance<INavigationService>(NavigationService);
    Window.Current.Content = layout;
    Window.Current.Activate();
}
```

ApplicationCoreLayoutはアプリ側で作成したNavigationView等Frame x:Name="MyFrame"を持っていて、MyFrameと紐付いたNavigationServiceを作成してDIコンテナに登録しています。

このとき、ApplicationCoreLayoutもMVVMでやりたいので、DataContextに対して`ApplicationCoreLayoutViewModel`を設定します。そうすると**ApplicationCoreLayout.DataContextがMyFrameのDataContextに伝播します**。

それだけなら問題ありませんが、MyFrameで読み込まれる**「××Page」にまでMyFrameのDataContextが伝播してしまう**ことが問題になります。

Prism.UnityのFrameFacadeによるViewModelのDIは**「`Page.DataContext`がnullならページナビゲーション向けのViewModelをDIするよ」**と判断しているため、Page.DataContextがFrameから伝播してしまっていると**ViewModelがページに設定されない（ViewModelがそもそも生成されない）**ことになります。

（実際の処理は Prism.Windows/Navigation/FrameFacade.cs の`OrchestrateAsync` を参照のこと） 


## 解決：Frame.DataContext = null を明示的に設定

この問題を回避するにはFrame.DataContext = nullを明示的に設定するだけで十分のようです。

```xml
<!-- Frame内のPage.DataContextにDataContextを伝播させないようnullを明示的に設定
     Prism.Unityの -->
<Frame x:Name="MyFrame" DataContext="{x:Null}" />
```

これでOK。

以上、Frameが絡むDataContext伝播で事故った話でした。

あと [Uno Platform](https://github.com/nventive/Uno#uno-platform---the-uwp-bridge-for-ios-android-and-webassembly) がすごそうなんでよかったらチェックして見てね。UWPアプリをC#+Xamlで作ったらAndroidとiOSもアプリが出来る！（XamarinベースでUWPのUIを各プラットフォームでエミュレートしてるっぽい）
メールを送信する時に使うmb_send_mail関数について紹介！

## mb_send_mail関数とは
- メールを送信するときに使う関数

## mb_send_mail関数の書き方

```
mb_send_mail($to, $subject, $message, $header);
```

### パラメータ（引数）
```
$to – 宛先
$subject – 件名
$message – 本文
$header(オプション) – ヘッダー（「From」や「Cc」など追加したいヘッダーを指定します）
```

## コード例

```
//宛先
$to = "to-waka@e2info.com";

//件名
$subject = "お問い合わせありがとうございます";

//本文
$message = "この度は、お問い合わせ頂き誠にありがとうございます。";

//差出人
$header = "From: from-waka@e2info.com " . "\r\n";

mb_send_mail($to, $subject, $message, $header);
```

### 戻り値
メールの送信に成功した場合はtrueを、失敗した場合はfalseを返します。
※宛先にメールが届いたかどうかではないので、注意してください。

## CCを指定する場合

- CCを指定する場合には、$headerに追加します。
- 複数の$headerを追加する場合は、差出人のメールアドレスを代入している部分で\r\n（改行）をします。

### コード例
```
//宛先
$to = "to-waka@e2info.com";

//件名
$subject = "お問い合わせありがとうございます";

//本文
$message = "この度は、お問い合わせ頂き誠にありがとうございます。";

//差出人
$header = "From: from-waka@e2info.com " . "\r\n";

//CC情報を設定
$header .= "Cc: cc-waka@gmail.com";

mb_send_mail($to, $subject, $message, $header);
```
[Rails]herokuへのアプリ公開手順メモ

##対象者
プログラミング初学者、Ruby on Rails初学者。
こちらの記事は
・初学者の自分の知識整理
・同じような初学者向けにわかりやすく解説する
ことを目的としております。

##herokuとは
herokuとは**PaaS**(Platform as a service)の一つです。
通常サービスを本番環境にアップする為には
サーバ、OS、実行環境などが必要ですがそれらを簡単に提供してくれるのがPaaSです。
ユーザーはアプリケーションを乗せるだけでインターネット上に
サービスを公開することができます。

##前提条件

・公開するRailsアプリを準備している
・Railsアプリはローカル環境で問題なく動いている
・herokuアカウントを作成済み

##手順
###heroku CLIをインストール
https://devcenter.heroku.com/articles/heroku-cli
こちらからheroku CLI(command line interface)をインストールしましょう。
これでターミナルでherokuコマンドが使用できるようになります。

###herokuへログイン
herokuにログインします。CUIでそのまま入力したいので-iをつけています。

```
$ heroku login -i
Email: yourEmail
Password: *******
```

###heroku側でのアプリ作成
githubにレポジトリを作るようなイメージ

```
$ heroku create app_name
https://app_name.herokuapp.com/ | https://git.heroku.com/app_name.git
```
app_nameは省略すれば自動的にuniqueな名前が割り当てられます。
この時点でherokuという名前でremoteレポジトリに登録されているので
git remote -vで確認しておきましょう。
登録されてない場合は

```
$ git remote add heroku https~~
```

としてremoteに追加します。

###herokuへプッシュ

```
$ git push hreoku master
```
masterブランチをherokuへpushします。

**※ここでDBがRails初期のsqlite3のままだとエラーが出ますので
 postgreSQLかMySQLへ変更しましょう。**


###db:migrate

ローカル環境と同じようにdb:migrateをしましょう

```
$ heroku run rails db:migrate
```



##まとめ

sqlite3がrails内部で起動されるので便利なのですが
一方でherokuに対応していません。
その為Rails Tutorialさんの手順にあるように
**test, development環境ではsqlite3**
**production環境ではpostgresql**
を使うのが最適なのかな、と思っています。
LaravelでSQL Server使用時、datetime2を使いたい場合

# 困った！
LaravelでSQL Server使用時、created_atやupdated_at、またその他のカラムで日付データをdatetime2型を指定しなければならない！でもInsert/Update処理がうまくいかない！よくわからないエラーが出る！
あとなんか知らんけどdebugbarも動かない！

ネットで近い情報を調べると
```protected $dateFormat = 'Y-m-d H:i:u';```
にしろとかいう情報もあるけど、やってもだめだ！

# datetime2って？
正確に書くとdatetime2(7)。
`YYYY-MM-DD hh:mm:ss[.fractional seconds]` という形式の日時の型。
小数点以下は***7桁***で、精度は***100ns***です。
2019-04-23 19:41:12.1234567 みたいな感じです。

簡単にいうと「マイクロセコンドではありません！」
ですので、uの指定じゃ不足です。

#じゃどうすればいいの？
modelで、
```protected $dateFormat = 'Y-m-d H:i:u0';```
を指定！（末尾の0で桁を合わせる）

これで解決したよ。
Railsアプリ内にマークアップのプレビュー環境を作る

RailsでのWebアプリ作成時、マークアップのプレビュー環境どうしてますか？
一般的なのは、HTMLコーダーとRailsエンジニアが居て、HTMLコーダーにHTMLをばーっと書いてもらってそれをRailsエンジニアがErb化して…みたいな流れと思われます。

ですが

* コーディング環境との差異を限りなく少なくするために、Railsと同じ静的ファイルを使ってマークアップしてもらいたい
* headerとかの共通パーツ、 `layouts/*.html.erb` 使って共通化してほしい
* Rails上でCSS, JSの簡単な修正を行う時に一々マークアップ環境立ち上げて修正してそのファイルをRailsにコピーして…とかが嫌だ
* <img>とかをViewヘルパーに書き換えるの面倒くさい。。。

みたいなお気持ちになると思います。
そこで、簡単に以上を解決できる方法をご紹介します。

## マークアッププレビュー用の環境をRails内に作る
作りましょう。

### マークアッププレビュー用のcontroller, routesを実装する

まずはcontroller, routesから実装します。

```app/controllers/markup_preview_controller.rb
class MarkupPreviewController < ApplicationController
  def home
    page_name = params[:page_name]

    if page_name.nil?
      path = "#{File.expand_path('../../views/markup_preview', __FILE__ )}/"

      @page_list = Dir.glob(path + '*')
                     .map { |file_name| file_name.sub(/\.html\.erb/, '').sub(/#{path}/, '') }
                     .select { |file_name| file_name != 'home' }
                     .sort
    else
      render "markup_preview/#{page_name}.html.erb"
    end
  end
end
```

```config/routes.rb
Rails.application.routes.draw do
  get 'markup_preview', to: 'markup_preview#home'
end
```

こんな感じです。

少し気遣いがあり、viewファイルを作るごとにroutes.rbを書いてもらうのはなんだか面倒なので、 `/markup_preview` にアクセスした時、自動で `app/views/markup_preview` にある `erb` ファイルをリストで表示するような作りになっています。

### erb一覧表示用のviewを作る
その一覧表示用のviewを最後に作りましょう。

```erb:app/views/markup_preview/home.html.erb
<h2>マークアップ ページ一覧</h2>

<ul>
  <% @page_list.each do |page_name| %>
    <li>
      <a href="/markup_preview?page_name=<%= page_name %>"><%= page_name %></a>
    </li>
  <% end %>
</ul>

```

装飾したい人はcssとか適当につければよいでしょう.

## 使い方
1. `app/views/markup_preview` 内にerbファイルを作ってもらう。
2. 以上！

## 〆
たったこれだけの実装で簡単にRailsアプリ内にマークアップ環境を作ることが出来ました。
冒頭で挙げたような問題点も解決できていて、いい感じですね。
ぜひご活用ください。
破線のCSSジェネレータを作りました。

![Chromeで見た画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360068/52c0b043-1404-ca6a-ec3a-3897cb15249e.gif)
こんな感じのやつです。
**(20/03/17)縦横切替えができるようになりました！**

# できあがったもの
[こちらからどうぞ！](https://kackie.github.io/html_tool/dottedLine/)

# 操作方法
各レンジと色を変更してお好みの形に調節してください。
変更に応じて`.elm{}`内のスタイルが連動して書き換わるので、コピーして使ってください。
`input type="color"`を使用しているので、ChromeかFirefoxで見ていただけると嬉しいです！

# 感想
破線のスタイルって手書きするの面倒くさいですよね。デザイン無視してborder-style:dottedでシンプルに作ってしまうこともしばしばあります（スミマセン）。
自分で使う用にと最初はSassのmixinで作ろうかとも思ったのですが、せっかくなので勉強中のVue.jsでジェネレータ化してみました。
v-modelを使ってこんな感じの簡単なインターフェースをさくっと作れてしまうのはやはり便利ですね。

カラーコードをRGB形式に変換するのに下記記事を参考にさせていただきました。
どうもありがとうございました。
[Vue.jsでカラーコードからRGB値にサクッと変換する方法](https://www.webcreatorbox.com/tech/vuejs-hex-rgb)
MatrixFlowで機械学習を手軽に試した話

## MatrixFlowとは
`MatrixFlow`を利用すると、AIをノンプログラミングで導入出来る。

公式のHPは⇒[こちら](https://www.matrixflow.net/)。
2019/04/10（水）にサービスが開始され、[atmarkitでも取り上げられた](https://www.atmarkit.co.jp/ait/articles/1904/11/news035.html)。
そのせいか開始直後はサーバが重く、データのアップロードや学習が思うように進まなかったが、04/23時点では落ち着いた模様。

主な特徴としては下記が挙げられる（公式HPより抜粋）。
　- ノンプログラミング：ドラッグ＆ドロップだけで機械学習・深層学習のモデルを構築
　- あらかじめ用意されている定番の機械学習・深層学習のレシピが使用可能
　- AutoFlow(オート・フロー)：最適なアルゴリズムとパラメータの組み合わせを簡単に探索

類似サービスとしては`GoogleCloud AutoML`や`Neural Network Console`があるが、それらとの比較については確認中。

## 使い方
公式HPにリンクが貼ってある[ここ](https://ai.matrixflow.net/signin)からアカウントを新規作成してログイン。
ログイン後の画面が下記。
![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269083/6797549e-c5c3-2c28-36cb-22579ed73985.png)
推論完了までに「データ管理」～「推論」の6STEPあり、それぞれについて記載。

####データ管理
サンプルとして、「タイタニック生存者」と「ボストンの住宅情報」がデフォルトで用意されている。
自分で用意したものを使用したい場合には、「新規追加」からローカルにあるファイルをアップロードする。
※無償版はCSVのみ対応しており、データ容量の上限は300KB。
不要なデータの削除も行える。

####前処理・データ解析
管理対象となっているデータについて、学習／推論をする為の前処理をしたり解析をしたり出来る。
前処理とは、
　- 学習／推論をする為に数値以外のデータを数値データへ修正
　　例：生存結果の「生」「死」をそれぞれ「0」「1」とする
　- 欠損値の修正
などを指す。
前処理を施したデータを保存し直すこともできる。
データ解析では、
　- データ数・最大値・最小値・平均値といった値を算出
　- ヒストグラムを表示
などが出来る。


####レシピ管理
様々なアルゴリズムを組み合わせて「レシピ」として管理出来る。
SVM、ランダムフォレスト、SGDなど、大抵の有名所がデフォルトで用意されている。
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269083/8b34a7cd-4773-c8e2-5811-7df28e507ba7.png)
「ブロックタイプ」で使用したいアルゴリズムを選択し、下のスペースにドラッグ＆ドロップ。
「エッジ追加」で先行関係を付けられる。
※無償版は、自分で作成したレシピの保存や、用意されているレシピの編集は不可

####学習・モデル管理・推論
管理してあるデータとレシピを使って学習を実施し、その結果を「モデル」として管理出来る。
推論したいデータをアップロードし、管理されているモデルで推論を実施する。

## 試したこと
デフォルトで用意されているデータ（タイタニック生存者）とレシピ（分類-AutoFlow-）を用いて学習を行った後、テストデータを適当に作成して「チケットクラス」「兄弟・配偶者数」「親または子の数」から生存結果を推論させた。
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269083/bdda7d91-a199-6082-c1b3-dfc0e7fd30b0.png)
ここまでで約1時間程。手軽に機械学習で推論を行えた。
社内のAI施策でもPoCの一環で利用する予定。
clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [mysql2.bundle] Error 1

## 環境
- ruby 2.3.3
- rbenv 1.1.2
- bundler 2.0.1

# 概要

railsでサーバーを立てようとすると下記のエラーが出ました。  

```
$ rails s
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1
```
これの原因と対応です。


# パスの確認
ググるとみなさんパスを確認しておられたのでそれを確認

```
$ which bundle 
/usr/local/opt/ruby/bin/bundle
$ which ruby
/usr/local/opt/ruby/bin/ruby
```
rbenvを見て欲しいのに見てくれてませんorz

# 原因

rbenvにあるbundler2.0.1とかruby2.3.3を使って欲しいのに、パスが通っていないせいでbrewでinstallしたruby2.6.2を見に行っていた

# 解決策

ちゃんとrbenvの中のパスを通してあげればいいのですが面倒だったので
[^1]
見てるとこ消せばrbenvを見に行くよね？🔪🔪🔪
ということで

```
$ brew uninstall ruby
```

力づくで申し訳ない。。。
確認すると、

```
$ which ruby
/Users/u-sho/.rbenv/shims/ruby
$ which bundle
/Users/u-sho/.rbenv/shims/bundle
```

となっており、成功！[^2]
パスが通ったので

```
$ bundle install
```

# 結論
パスを通そう

# 参考記事
https://qiita.com/nakanowax/items/fe07e8ccd1721befebeb

[^1]: ~/.bashrcファイルや~/.bash_profileファイルにパスを通してあげると良いたぶん
[^2]: u-shoは私のユーザー名
OculusGoからWindows共有フォルダ(sambaサーバ, UNCパス)のファイルに書き込む方法


OculusGoでDebug.logを読み込む際にWindowsでSMB経由でログはきたいなと思ったので備忘録。
たぶんみんなADBでログ取るやろうからいらんやろうけど実機デバッグはいろんな方法があったほうが良いと思うので。
こっからDebug.logを模したスタティッククラス作るんやろうけど取っ掛かりにどうぞ。

ほとんど@culageさんの記事がベースになった。
Qiitaマナーとか何も知らないのでマナー違反なら消します。

環境: Unity 2018.3.12f1 (64-bit) Personal 

## 事前準備

あらかじめ Assets/Plugins に
https://jcifs.samba.org/src/
からダウンロードした「jcifs-1.3.19.jar」をコピーしておく。

## コード

以下のコードで、\\192.168.XXX.XXX\share\test.txt の最終行に書きみ込むことに成功した。

```c#

try{
	string user   = "user";
	string pass   = "pass";
	string server = "192.168.XXX.XXX";
	string path   = "share/test.txt";
	string smb = "smb://" + user + ":" + pass + "@" + server + "/" + path;
	using (AndroidJavaObject sfws = new AndroidJavaObject("jcifs.smb.SmbFileOutputStream", smb,true)) {
		byte[] data = System.Text.Encoding.UTF8.GetBytes("test go OK!!\n");
		sfws.Call("write",data);
		sfws.Call("close");
	}
} catch (System.Exception ex) {
	Debug.Log(ex.ToString());
}  
```

## 参考にしたURL

OculusGoからWindows共有フォルダ(sambaサーバ, UNCパス)のファイルを読む方法
https://qiita.com/culage/items/a8cb03c53c8ef1215e8b
DockerのRedmineでファイルがアップロードできない問題の対処

Docker でセットアップした Redmine にファイルがアップロードできなくなったので調べたところ、SSL 対応のために導入した Nginx が直接的な原因だった。

## client_max_body_size
Nginx はデフォルトでのファイルのアップロードサイズは `client_max_body_size` のデフォルト値で1MBに制限されている。 [^client_max_body_size] [^custom-nginx-configuration] [^nginx-proxy]

```nginx:conf.d/custom_proxy_settings.conf
client_max_body_size 1g;
```

[^client_max_body_size]: ["`Default: client_max_body_size 1m;`" - client_max_body_size - Module ngx_http_core_module ](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size)

[^custom-nginx-configuration]: https://github.com/jwilder/nginx-proxy/blob/master/README.md#custom-nginx-configuration

[^nginx-proxy]: [jwilder/nginx-proxy upload limits? · Issue #981 · jwilder/nginx-proxy](https://github.com/jwilder/nginx-proxy/issues/981)

## docker-compose.yml
`jwilder/nginx-proxy` に作成した `conf.d/custom_proxy_settings.conf` をマウントする。

```yml:docker-compose.yml
services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    restart: always
    privileged: true
    ports:
      - 80:80
      - 443:443
    volumes:
      - /srv/ssl_proxy/certs:/etc/nginx/certs:ro
      - /srv/ssl_proxy/htpasswd:/etc/nginx/htpasswd
      - /srv/ssl_proxy/conf.d/custom_proxy_settings.conf:/etc/nginx/conf.d/custom_proxy_settings.conf:ro
      - nginx-proxy:/etc/nginx/vhost.d
      - nginx-proxy:/usr/share/nginx/html
      - /srv/ssl_proxy/log:/var/log/nginx
      - /var/run/docker.sock:/tmp/docker.sock:ro
```

## コンテナの再起動
```bash
docker-compose up -d
```
[Rails] has_manyおよびbelongs_toへのdependent: :destroyの設定について

# 問題

`User has_many Cup(s)`といった関連のなかで、
`Cup.destroy`をしたところ`User`までも消えてしまった。

理由については本記事を見てもらえればわかるが、
`dependent: :destroy`の付与について時折迷うことがあったので
備忘録として残しておく。

# 対処
以下のような関連があるとする。

<b>User</b>
`User has_many Cup(s)`

<b>Cup</b>
`Cup belongs_to User`

この関連に対し、`dependent: :destroy`を以下のように設定していた。

```ruby:
Class User < ApplicationRecord
  has_many :cups, dependent: :destroy
end
```

```ruby:
class Cup < ApplicationRecord
  belongs_to :user, dependent: :destroy
end
```

この状態で`Cup`（のインスタンス）を`destroy`したところ、
そのユーザまでもが削除されてしまった。

<br>

そこで下記のように`belongs_to`から`dependent: :destroy`を
消去したところ、`Cup`を消してもそのユーザは残ったままになった。

```ruby:
Class User < ApplicationRecord
  has_many :cups, dependent: :destroy
end
```

```ruby:
class Cup < ApplicationRecord
  belongs_to :user
end
```

# :dependentの付与の仕方
`has_many`、`belongs_to`どちらに`dependent: :destroy`をつけるか迷う時があるが、上記より、

`dependent: :destroy`を<b>指定したクラス</b>が消えた場合に、
`dependent: :destroy`を<b>設定したモデル（のインスタンス）</b>がdestroyされる

ということになる。

# 具体例
```ruby:
class Cup < ApplicationRecord
  belongs_to :user, dependent: :destroy
end
```

このコードでは、

`dependent: :destroy`を<b>指定したクラス</b>：`Cup`
`dependent: :destroy`を<b>設定したモデル（のインスタンス）</b>：`user`

となるので、`Cup`が消えると`User`が消えることになる。

<br>

```ruby:
Class User < ApplicationRecord
  has_many :cups, dependent: :destroy
end
```

このコードでは、

`dependent: :destroy`を<b>指定したクラス</b>：`User`
`dependent: :destroy`を<b>設定したモデル（のインスタンス）</b>：`cups`

となるので、`User`が消えると`Cup(s)`が消えることになる。


<br>

おわり
Enviro pHATで室温を計測してSlackに投げる


弊社オフィスでは最近「暑い」とか「寒い」などの声が聞こえるようになったので、これを設置して温度を定期的に計測してみることにしました。

# 使うもの

ささっと始めたかったので用意したものはこれだけです。秋月電子通商でもスイッチサイエンスでも買えます。

- Enviro pHAT
- Raspberry Pi

### [Raspberry Pi Zero WH ](https://www.switch-science.com/catalog/3646/)

これがないと始まりません。Raspberry Pi Zero WHは安いですが、HDMI変換アダプタやUSB-OTGケーブルがないとまともに使えません。**初めて使う方はこれではなく普通のRaspberry Pi 3Bを使うことをお勧めします。**

### [Enviro pHAT](https://www.switch-science.com/catalog/3218/)

Enviro pHATは簡単に言うといっぱいセンサーが乗ったpHATです。

- 気温センサー
- 気圧センサー
- 加速度センサー
- 照度センサー

これら４つのセンサーが搭載されており、他にもA/DコンバータやLEDが搭載されています。このpHATははんだ付けが必要なのでご注意を。

# Enviro pHATの準備

[pimoroni/enviro\-phat](https://github.com/pimoroni/enviro-phat)

Pimoroniの製品には大抵pythonライブラリがあります。これを使うとラクにセンサーを扱えるので、このリポジトリをクローンします。
プロジェクト内にあるexampleディレクトリには簡単に動作を見られるスクリプトが用意されています。実行してみます。

<img width="565" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69399/80cf3ac0-6ec3-5bcc-0df0-f26bba5e2ba7.png">

気温がドワーッと流れてきたら正常に動いています。もし動かない場合はPythonのセットアップが正しく行われているかなどをチェックしてみてください。

温度センサー自体の温度やRaspberry Pi本体の温度を拾っているのか、8度ほど高く取得されてしまいました。（下のコードにはありませんが）今回は妥協案として空気清浄機に表示されていた温度表示を基準値として誤差の補正をしました。

# 温度をSlackに投げるようにする

適当にPythonで書きます。

```python:slack_post.py
#!/usr/bin/env python

import time
import json
import requests

from envirophat import weather, leds
SLACK_WEBHOOK = "https://hooks.slack.com/services/**************"

celsius = str(round(weather.temperature(),1))

payload_dic = {
    "text": "Temp:" + celsius ,
    "username": "(なんか名前決める)",
    "channel": "#(なんかチャンネル名決める)",
}
req = requests.post(SLACK_WEBHOOK, data=json.dumps(payload_dic))
```

`SLACK_WEBHOOK` には各ワークスペースから設定できるSlackのIncoming WebhooksのURLを貼り付けます。


# 動かす

![temp-test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69399/66bc6df7-dcaa-4b2f-a651-aeaa8f1d11a5.png)

Slackのチャンネルに投稿されたらOKです。温度表示をして結局は人間がエアコンの操作パネルまで行かないといけないのが残念ですが、早めに温度変化に気づけるようになりました。
PDF文書の空白ページをどうやって削除しますか

日常の仕事生活ではよくPDFを使いますが、PDF文書の中には一ページか何ページかの空白の文書があります。多くの人はこれらの空白のページをどうやって削除するか分かりません。ここでは、無料コントロール [Free Spire.PDF] (https://www.e-iceblue.com/Introduce/free-pdf-component.html)を使って、PDFドキュメントの空白ページを削除する方法を紹介します。

空白のページは通常、何も含まないページとして定義されます。Free Spire.PDFはPDFページが絶対的に空白かどうかを検出する方法を提供している。しかし、いくつかの「空白ページ」は実際に白い画像を含むことができます。IsBank()方法を使って、空白とは見なされません。これらの白を検出するには、空白ページではないので、カスタムメソッドIsImageBlank()が作成されました。

追加する名前空間が必要です：

```
using Spire.Pdf;
using System.Drawing;
using Spire.Pdf.Graphics;
```


完全コード：

```
namespace PDF
{
    class Program
    {
        static void Main(string[] args)
        {
            // PDF文書を読み込む
            PdfDocument pdf = new PdfDocument();
            pdf.LoadFromFile("Sample.pdf");

            //ページを巡回
            for (int i = 0; i < pdf.Pages.Count; i++)
            {
                //空白ページかどうかを判断する
                if (pdf.Pages[i].IsBlank())
                {
                    //空白のページを削除
                    pdf.Pages.RemoveAt(i);
                }
                else
                {
                    //空白のページでない場合は、ページを画像に変換します
                    Image image = pdf.SaveAsImage(i, PdfImageType.Bitmap);

                    //画像が空白かどうかを判断します
                    if (IsImageBlank(image))
                    {
                        //画像が空白の場合、対応するPDFページを削除します
                        pdf.Pages.RemoveAt(i);
                    }
                }
            }
            
            pdf.SaveToFile("Result.pdf", FileFormat.PDF);      
         }
        public static bool IsImageBlank(Image image)
        {
            Bitmap bitmap = new Bitmap(image);
            for (int i = 0; i < bitmap.Width; i++)
            {
                for (int j = 0; j < bitmap.Height; j++)
                {
                    Color pixel = bitmap.GetPixel(i, j);
                    if (pixel.R < 240 || pixel.G < 240 || pixel.B < 240)
                    {
                        return false;
                    }
                }
            }
            return true;
        }
    }
}
```
サンプルドキュメント：
![Sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/a1f6ba28-307e-49f9-4cb7-85be1a60d339.png)
効果図：
![Result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/b08a8129-fe15-ca18-b0aa-d623338d8c16.png)
UbuntuにAnacondaをインストールしたらterminalに(base)と表示される

# `(base)`という表示
Ubuntuに[Anaconda](https://www.anaconda.com/distribution/)をインストールして端末を起動すると、

```
(base) aqua@aqua-VirtualBox:~$ 
```

という具合で頭に`(base)`という見慣れない表示がされるようになってしまいました。

## 解決策
```
$ conda config --set changeps1 False
```

と設定し、端末を再起動することで表示されないようになるようです。

## 参考
https://askubuntu.com/questions/1026383/why-does-base-appear-in-front-of-my-terminal-prompt
コンピュータ構成要素　〜まとめ〜No.1

# プロセッサ

- パイプライン制御
１命令を複数のステージに分けて処理を実行する
命令には、命令読出し (フェッチ)、解読(デコード)、アドレス計算、オペランド呼出し、実行 
の６つがある

パイプライン処理時間を求める公式
(I＋D−1)＊P

I：実行する命令数
D：パイプラインの深さ(分割するステージ数)
P：パイプラインのピッチ(ステージごとの実行時間)(ex 1サイクル）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337110/49c5c945-829b-6148-56ad-7006dcab65d2.png)
図1.1 パイプライン処理

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337110/bb9e2cfc-c3f9-7c7a-86b5-7c2a92d5eb53.png)
図1.2 スーパースカラ、スーパーパイプラインの図

コンピューターの命令は、命令部とアドレス部(オペランド)から構成されています※。このうちアドレス部では命令の処理対象となるデータのメモリ上の位置を指定しますが、この指定方法には次に挙げる6種類があります。
1. 直接アドレス指定
アドレス部の値をそのまま有効アドレスとする。

2. 間接アドレス指定
アドレス部の値で主記憶上のアドレスを指定し、そのアドレスに格納されている値を有効アドレスとする。

3. 指標(インデックス)アドレス指定
アドレス部の値にインデックスレジスタの値を加えたものを有効アドレスとする。

4. 基底(ベース)アドレス指定
アドレス部の値にベースレジスタの値を加えたものを有効アドレスとする。

5. 相対アドレス指定
アドレス部の値にプログラムカウンタの値を加えたものを有効アドレスとする。

6. 即値アドレス指定
アドレス部の値を有効アドレスではなく、そのまま演算対象データとする。

# ポインタ
1. スタックポインタ
サブルーチン呼出し時に，戻り先アドレス及びレジスタの内容を格納するメモリのアドレス

2. プログラムカウンタ
次に読み出す機械語命令が格納されているアドレス

3. 命令レジスタ
メモリから読み出された機械語命令

4. ステータスレジスタ
割込みの許可状態，及び条件分岐の判断に必要な演算結果の状態

# 並列処理におけるプロセッサアーキテクチャ

1. SISD(Single Instruction Single Data)
単一の命令で単一のデータを処理する最もシンプルな方式

2. SIMD(Single Instruction Multiple Data)
単一の命令で複数のデータを処理できる方式。pentiumプロセッサで採用されている。

3. MISD(Multiple Instruction Single Data)
複数の命令で単一のデータを扱う方式。理論上は存在するが実装例はない。

4. MIMD(Multiple Instruction Multiple Data)
複数の命令で複数のデータを扱う方式で、複数のプロセッサを搭載した並列コンピュータ環境が該当する。OSやコンパイラがMIMDに対応している必要がある
Rails - Modelでlink_to などの Helper を使う時

（自分用のMEMO書きとなります。）

includeしてあげると使用できるようになる。

```
class Comment < ActiveRecord::Base
  include ActionView::Helpers::UrlHelper


  def hoge
    user.notices.create(
      content: ActionController::Base.helpers.link_to('hogehoge', path)
    )
  end

end
```

のような形で使用できる。
Ubuntu18.04でLXDとコンテナ用DNSの設定

# 環境

* Ubuntu18.04 

## Server 設定

事前に最低限 update ＆ upgrade はやりましょう

```
apt-get update
apt-get upgrade
```

#### /etc/sysctl.conf

```sh
user.max_user_namespaces = 3883
fs.inotify.max_queued_events = 1048576
fs.inotify.max_user_instances = 1048576
fs.inotify.max_user_watches = 1048576
vm.max_map_count = 262144
net.ipv4.ip_forward = 1
```

#### /etc/security/limits.conf

```
*               soft    nofile          1048576
*               hard    nofile          1048576
root            soft    nofile          1048576
root            hard    nofile          1048576
*               soft    memlock         unlimited
*               hard    memlock         unlimited
```

一旦再起動するのが無難です

```
reboot
```
設定内容の詳細は以下を確認してください。
https://github.com/lxc/lxd/blob/master/doc/production-setup.md

### LXD 初期設定

今回はサクッと設定するので silent install

```
lxd init --auto
```

### Container 作成、login、update

```sh

# container 作成
lxc launch ubuntu:18.04 container01
# container login
lxc exec container01 /bin/bash

# 以下は container 内でのcommandです
vi  /etc/systemd/resolved.conf
+DNS = 127.0.0.53 8.8.8.8
:wq
systemctl restart systemd-resolved
apt-get update
apt-get upgrade

# container から抜ける
exit
```

#### ホスト側Ubuntu内からcontainer名.lxd でアクセスできるようにする

以下のURLの内容そのままですが...
参考：https://blog.simos.info/how-to-use-lxd-container-hostnames-on-the-host-in-ubuntu-18-04/


##### lxd-br0.sh 作成

```bash
#!bin/bash

set -eu

LXDBRIP="$(ip addr show dev lxdbr0| grep -Po 'inet \K[\d.]+')"
sudo systemd-resolve --interface lxdbr0 --set-dns ${LXDBRIP} --set-domain lxd
echo -e "auth-zone=lxd\ndns-loop-detect" | lxc network set lxdbr0 raw.dnsmasq -
lxc network show lxdbr0
echo "All done.. try command"
echo "dig [container_name].lxd @${LXDBRIP}"
```

##### 実行

```
bash -x lxd-br0.sh
```

##### dig 確認

```
; <<>> DiG 9.11.3-1ubuntu1.5-Ubuntu <<>> container01.lxd +noall +answer
;; global options: +cmd
container01.lxd.        600     IN      A       10.127.173.47
```

##### PING 確認

```
root@ubuntu-bionic:~# ping -c 1 container01.lxd
PING container01.lxd(container01.lxd (fd42:b79:f367:b587:216:3eff:fe6f:a54c)) 56 data bytes
64 bytes from container01.lxd (fd42:b79:f367:b587:216:3eff:fe6f:a54c): icmp_seq=1 ttl=64 time=0.058 ms
```

DNSのサービス化は省略。
Nginx等でProxy等を用意すれば、Container別にアクセスを分けることができます。
SSHのProxyは...~~鍵認証ができないけれど~~ sshpiper が良いかと。
https://github.com/tg123/sshpiper
※ 2019/05/13 普通に見落としていました。鍵使えるようです。
mekstr様、情報ありがとうございます。
https://github.com/tg123/sshpiper#how-to-do-public-key-authentication-when-using-sshpiper
git stashが溜まってどれが古いのかわからなくなったのでメモ

コミット前の変更を保存するために、stashを繰り返してstashが溜まるときがありますよね。
その時の溜まり方がこんな感じになり、どれが最新でどれが古いのかわからなくなりますよね。
いちいちコミットIDからどれが最新なのかみるのも面倒なのでメモです。

```
stash@{0}: WIP on branch_name: a83681d6 直前のコミットA
stash@{1}: WIP on branch_name: c8e433k2 直前のコミットA
stash@{2}: WIP on branch_name: b1df90k2 直前のコミットA
```

結論、stash@{0}が一番直近でstashしたもの。
stash@{2}が一番古いstashです。
VirtualBox+Vagrant+centOS-7.3+Windows10で環境構築

##インストール

####VirtualBoxをインストール
 https://www.virtualbox.org/wiki/Downloads

####Vagrantをインストール
https://www.vagrantup.com/downloads.html




##仮想マシンの準備
####利用するBOXのダウンロード
コマンドプロンプトを立ち上げて以下を実行。

```
vagrant box add bento/centos-7.3  --provider virtualbox
```

##Vagrantfileの作成
任意のフォルダを作り以下をコマンドプロンプトで実行

```
> mkdir mycentos
> cd mycentos
> vagrant init bento/centos-7.3
```
実行したディレクトリに設定ファイル Vagrantfile ができるので確認。

##Vagrantfileの変更
作成された環境設定ファイル Vagrantfile ファイルを編集します。
以下の部分のコメントを外す

- IPアドレスの設定

```
 config.vm.network "private_network", ip: "192.168.33.10"
```

##仮想マシンの起動
コマンドプロンプトで実行

```
vagrant up
```


##ログイン
 SSHでログイン

putty
https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html


```
アドレス：192.168.33.10
ポート：22
ユーザ名：vagrant
パスワード：vagrant
```

##仮想マシンの停止
```
vagrant halt
```
VirtualBoxで確認すると「電源オフ」と表示されます。



##参考
https://eng-entrance.com/virtualbox-install
https://eng-entrance.com/linux-vagrant-install
SQL Serverをbatでサイレントインストール

# この記事の目的
Windowsのcmdを用いて、SQL ServerをGUIなしでインストールします。
仮想環境やDockerであればいいのですが、物理環境に同じ設定で何度もインストールするのは苦行以外の何物でもありませんよね。
Powershellでの自動化は別記事があったので、ここではbatでの自動化を記載します。

# 前提
以下の組み合わせで確認しました。

* Windows Server 2012 / SQL Server 2012
* Windows Server 2016 / SQL Server 2016

# 準備

### SQL Server
当然ですが、SQL Serverのインストールメディアかisoファイルが必要です。
isoは仮想ドライブにマウントします。

### iniファイル
残念ながら1回はSQL ServerのインストーラーをGUIで実行する必要があります。(インストールを完了する必要はありません)
SQL Serverのサイレントインストールを行うには設定内容が記載されたiniファイルが必要です。
以降のサイレントインストールはこのiniファイルの内容通りにセットアップします。
このiniファイルはGUIでのインストール中にエクスポートすることができます。
手作業で作ることもできますが、エクスポートした方が安全かと思います。
以下、エクスポートの手順です。

1. SQL Serverのインストーラーを起動します。
1. 「インストールの準備完了」までセットアップの項目を進めます。
1. 「インストールの準備完了」まで進んだら「構成ファイルのパス」に記載されたパスのiniファイルを取得します。このマシンにSQL Serverをインストールするのでなければ「キャンセル」を押して構いません。

* 注意  
Expressエディションだとただインストーラーを実行しただけではiniファイルを取得できません。  
以下のコマンドでインストーラーを実行する必要があります。[^1]  
`SETUP.exe /UIMODE=Normal /ACTION=INSTALL`

# 実行
batファイルのサンプルは後述しますが、実行するコマンドは以下だけです。
`D:\Setup.exe /QA /ConfigurationFile="xxx\ConfigurationFile.ini"`
Setup.exeのパスはDVDドライブのドライブ名によって適宜変更してください。
ConfigurationFile.iniのパスも適宜変更してください。(フルパスの方がいいと思います)

* 注意
SQL Server 2016はSQL Server Management Studioがバンドルされていません。  
上記コマンドではインストールされないため別途インストーラーをダウンロードしてインストールする必要があります。

# サンプル

対話があるのであまりサイレントではない気もしますがサンプルです。
※ 実行はご自身の責任で行ってください。
※ 記法が正しくない、または効率的でない可能性が多分にあります。  

```
@echo off

setlocal

set /p configfile="Configurationファイルのフルパスを入力してください。  : %configfile%"
if not exist %configfile% (
  echo Configurationファイルが存在しません。確認の上、再度実行してください。
  goto END
)

set /p exe="Setup.exeのフルパスを入力してください。D:\Setup.exeであれば何も入力せずにEnterキーを押してください。  : %exe%"
if "%exe%"=="" (
  set exe="D:\Setup.exe"
)
if not exist %exe% (
  echo Setup.exeが存在しません。確認の上、再度実行してください。
  goto END
)
echo.
echo プロダクトキーが正しいことを確認の上次に進んでください。
echo.
set /p ans="SQL Serverのインストールを実施します。よろしいですか？ (Y/n)  : %ans%"
if NOT "%ans%"=="Y" (
  echo 中断します。再度実行してください。
  goto END
)
%exe% /QS /ConfigurationFile=%configfile%
if NOT %ERRORLEVEL% == 0 goto FAILURE

echo.
echo 完了しました。
goto END

:FAILURE
echo.
echo エラーが発生しました。
echo エラー内容を確認の上、再度実行してください。

:END
pause
exit 0
```

[^1]: https://docs.microsoft.com/ja-jp/sql/database-engine/install-windows/install-sql-server-using-a-configuration-file?view=sql-server-2017
go get対象がgithub.comにある時に、新パッケージへのリダイレクトを自動追跡してgo getする

こんなシェル関数を.bashrcなりに設定して読み込んで使えばOK

```sh
function go-get {
  local opts=" "
  local pkg=""

  while true
  do
    if (( $# > 1 ))
    then
      opts="${opts}${1} "
      shift
    elif (( $# == 1 ))
    then
      pkg=${1}
      shift
    else
      break
    fi
  done

  cmd="go get${opts}$(curl -Ls -o /dev/null -w %{url_effective} https://${pkg} | sed -e 's/https:\/\///g')"
  echo ${cmd}
  eval ${cmd}
}
```

curlの処理は

- `-L` でリダイレクトを追跡
- 取得結果は不要なので、 `-o /dev/null` で捨てて、
- `-w %{url_effective}` の部分でリダイレクト先のURL表示を指定

という事をしている。このcurlの処理結果が `https://<指定したパッケージ>` という文字列になるので、この文字列からsed等で`https://`を除去すれば新パッケージが取得できる。

## 使用例
[github.com/go-delve/delve](https://github.com/go-delve/delve) は旧パッケージパスが `github.com/derekparker/delve` だった。ブラウザでアクセスしたらリダイレクトしてくれるが、`go get` で旧パッケージパスを指定するとエラーになる

```sh
$ go get -u github.com/derekparker/delve
can't load package: package github.com/derekparker/delve (以下略
```

上記シェル関数を使った場合、その新パッケージに差し替えてgo getする　※オプションやパッケージの指定の仕方は`go get`と同じでOK

```sh
$ go-get -u github.com/derekparker/delve
go get -u github.com/go-delve/delve
: (以下略
```

## See
[linux \- Get url after curl is redirected \- Stack Overflow](https://stackoverflow.com/questions/3074288/get-url-after-curl-is-redirected)
VScodeの拡張機能でサーバーにアクセスする

#はじめに
emacs嫌だ!!
VScodeで書きたい!!となったのでなんとかサーバーにSSH接続する方法を探しました.
すると<img width="620" alt="b5f8a1320489644818fc899b2c21740c.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175691/02daf407-25dc-4dca-3b30-f382ba8d5de7.png">
というものを発見したのでやってみた
(参考記事: https://qiita.com/informationsea/items/5c9f05c81a41fb885460)

#SSH FSのインストール
拡張機能で検索しインストール, リロードする．

すると....
<img width="174" alt="cb8905e251f9f63771481529ba3723a3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175691/1cfc7d71-aa26-decf-abd0-201817a8413d.png">
右下らへんにこんなの出る.
この余白で右クリックして **Create a SSH FS configuration**を選ぶ. 

すると....
<img width="663" alt="114afb0eae14f755eafb314db1d88a93.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175691/70c41585-e0b9-f046-082f-668db66ff9ca.png">
こんなのでる. 
名前は自分がわかるものならばなんでもよさそう．
LocationはGlobalとWorkspaceが選べる. 迷ったらGlobal??

決まったらsave

すると....
<img width="808" alt="e74948ef102c0e6dcaf7497dafd1d16d.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175691/3cc4d8e0-9ed0-5912-c60f-bb6cddaaa6da.png">
こんなの出る. 

#設定
save後に出てきたやつのうち以下のものを設定した. 
SSHで接続する感じです.  

Name: 自分がわかるものを
label: UI上に表示される名前, サーバーの名前にすると分かりすい気がする
HOST: 接続先のサーバーのアドレス
Root: ルートディレクトリを指定
Username: サーバーにログインするユーザー名を指定
Private key: キーのあるディレクトリを指定(絶対パス)
Passphrase: key設定時にパスワードを決めているならPromptに

サーバーに接続できるとrootディレクトリがワークスペースとして使えます. 
便利!!!
Vivadoインストール時に"generating installed device list"で止まるときの対処

#結論
installed device listは手動で生成できるのでハングアップしたインストールプロセスはキルしてしまおう

```bash
<installRoot>/Vivado/2018.3/bin/vivado -nolog -nojournal -mode batch -source <installRoot>/.xinstall/Vivado_2018.3/scripts/xlpartinfo.tcl -tclargs <installRoot>/Vivado/2018.3
```

##効果がなかった(けど役に立つかもしれない)トラブルシュート
https://hyem2.tistory.com/entry/install-vivado
https://www.reddit.com/r/FPGA/comments/ai2ite/vivado_installation_hanging/

#引用元

Installing Vivado 2018.3 on Fedora 28
https://forums.xilinx.com/t5/Installation-and-Licensing/Installing-Vivado-2018-3-on-Fedora-28/m-p/929648/highlight/true#M24600

AR# 60118 Install - Trouble shooting the Vivado Installation (v2014.1 and later)
https://www.xilinx.com/support/answers/60118.html

AR# 60111 Install - "Add Design Tools or Device" does not let me add only post Installation Options
https://www.xilinx.com/support/answers/60111.html
オブジェクト指向の設計原則まとめ

オブジェクト指向プログラミングでの設計原則を学んだので整理します。
これらにより柔軟性や再利用性の向上が図れ、全てのデザインパターンはこれらに沿っているとのこと。


# Liskov Substitution Principle (リスコフの置換原則)
- 説明
	- 親クラスのオブジェクトは、子クラスのオブジェクトによって置換可能でなければならない
		- 親クラスの機能を、子クラスでも必ず使えるようにしなければならない
		- そのためには、親クラスの機能は、十分に一般的なものでなければならない
- メリット
	- 親クラスを使っているクライアントコードへの影響を抑えられる
	- これを守ることで、次のOpen-Closed Principleも守ることができる

# Open-Closed Principle (オープン・クローズドの原則)
- 説明
	- クラスは拡張に対してOpenであり、変更に対してClosedであるべき
	- 以下のときに設計・実装が完了したと考えられ、クラスはClosedだと認識される
		- 正しく機能することが確認されている
		- 全ての属性・動作がカプセル化されている
		- クラスやインスタンスが、システムの動作を害する原因となっておらず、安定していると確認されている
- メリット
	- 予期しない変更を防ぎ、安定性を保つ
	- 拡張が可能（例：そのクラスを継承）

# Dependency Inversion Principle (依存性逆転の原則)
- 説明
	- クライアントがクラスを使用する際に、低レイヤーの具象クラスを直接使うのではなく、高レイヤーの汎化階層にアクセスし、具象クラスへのアクセスを間接化すべき
- 例
	- インターフェースが具象クラスの動作を汎化し、クライアントはインターフェースのみにアクセスするようにする
- メリット
	- システム内を疎結合にし、変更に対して柔軟、再利用が容易になる

# Composing Object Principle (Composition over inheritance / 継承より合成)
- 説明
	- 継承ではなく集約（合成）によって機能拡張を実現する
- 例
	- 実現したい機能を持ったクラスを継承するのではなく、そのオブジェクトをプロパティとして使用する
- メリット
	- 継承よりも疎結合にできる（継承で拡張すると、親クラスのプロパティ・メソッドを全て継承することになるため）

# Interface Segregation Principle (インターフェース分離の原則)
- 説明
	- インターフェースを小さく分割し、インターフェースを実装したクラスに対して不必要なメソッドの実装を強いらないようにする
- メリット
	- 不必要な依存関係をなくし、疎結合を実現できる

# Principle of Least Knowledge (最小知識の原則 / Law of Demeter / デメテルの法則)
- 説明
	- あるメソッドから呼び出すメソッドは、以下に属するものに限定する
		- 1. 同一オブジェクト内
		- 2. そのメソッドの引数
		- 3. そのメソッド内で生成したオブジェクト
		- 4. 同一オブジェクトのインスタンス変数
	- したがってメソッドのチェーンは避ける
- メリット
	- 不必要なクラス間のアクセスをなくし、疎結合を実現できる

# 感想
これまで実装でやりがちだったこと（メソッドのチェーンなど）もアンチパターンだと指摘されていて、なぜそれがダメなのか理由が分かった。今後取り入れて実装していきたい。

# 参考
[Coursera Design Patterns](https://www.coursera.org/learn/design-patterns)
LaravelのerrorsやoldをJavaScriptで扱いたい

Laravelのエラーメッセージやold値をJavaScriptやそのフレームワークなどで扱うのに何かいい方法ないかなと色々試行錯誤した結果辿り着いた一つの答え
これがアンチパターンなのかどうなのかは感知しません

はじめの試行

```html
<script>
var laravelErrors=@php print(htmlspecialchars_decode($errors))@endphp;
</script>
<script src="{{ asset('js/app.js') }}" defer></script>
```
最初はこれでいいかな…なんて思ってたのだけれど
TypeScriptを使った場合にどうしてもGlobal変数名の未定義警告TS2304がどうしても消せない状況になったので抜本的変更をしようと思い立った

方針とか問題点とか
・グローバル変数渡しは辞める
・まずbladeで@phpを使うのも辞めたい
・bladeで使ってる$errorsやold()がそもそもどういう仕組みなのかも調べ直す
・bladeの{{}}を使うとダブルクォーテーションとかがHTMLエンティティ化してしまうのでなんか面倒
・SCRFトークンみたいにmetaタグにぶち込もう
・タグの値にJSONの文字列入れるのなんか嫌だなぁ…

ってことでとりあえず$errorsやold()はどこからとってきてるのか調べてみた
→どうやらsessionから取ってきてるみたいなのでコントローラーで

```php
view('hoge',['sessions'=>json_encode($request->session()->all())])
```
とかで無理やり取ってきて表示してみたら確かにどっちも入ってた

どうやら

```php
$request->session()->get('_old_input');
$request->session()->get('errors');
```
で取れる模様_old_inputにはpasswordなどの値は返ってこないようなので全取得しても特に問題はなさそう

ってことで↓こんな感じでbase64に加工してbladeに渡してみる事にした
CSRFトークンは送っても無駄っぽいので予め除外
ちなみに'e30='は{}でパースしたら空のオブジェクトになるbase64文字列

```php
public function index(Request $request)
{
	$empty_object='{}';
	$b64_empty=base64_encode($empty_object);//'e30='
	$meta_olds=$request->session()->get('_old_input');
	if($meta_olds!==null) unset($meta_olds['_token']);
	$meta_olds=($meta_olds===null)?$b64_empty:base64_encode(json_encode($meta_olds));
	$meta_errors=$request->session()->get('errors');
	$meta_errors=($meta_errors===null)?$b64_empty:base64_encode($meta_errors);
	return view('hoge',[
		'meta_olds'=>$meta_olds,
		'meta_errors'=>$meta_errors,
	]);
}
```
これを受けてbladeではこんな感じにmetaに刺す

```html
<meta name="laravel-olds" content="{{$meta_olds}}">
<meta name="laravel-errors" content="{{$meta_errors}}">
```

あとは
受け側のJavaScriptで以下のように取り出せばよさそう
※metaタグに最低限'e30='が入ってればatobでもJSON.parseでもエラーにはならない

```js
var errors = JSON.parse(atob(document.head.querySelector('meta[name="laravel-errors"]').content))
```

TypeScriptの場合.contentがないみたいなエラーが出るのでHTMLMetaElementにキャストすればOK

```ts
var errors: object = JSON.parse(atob((<HTMLMetaElement>document.head.querySelector('meta[name="laravel-errors"]')).content))
```
IE11 で mkdocs の脚注のジャンプに失敗する場合の解決策

# tl;dr

Python Markdown を 3.1 以上に更新して mkdocs.yml に次のような設定を追加する。

```yaml
markdown_extensions:
  - footnotes:
      SEPARATOR: _
```

# 経緯

公式の [footnotes](https://squidfunk.github.io/mkdocs-material/extensions/footnotes/) を IE11 で開いて、例に含まれるリンクをクリックするとページが再読み込みされて動作しない、という相談を受けた。ほかのブラウザは問題なかったので IE だけで起きる不具合であることはわかったが、無視するわけにはいかない。

原因は皆目見当がつかなかったが URL のフラグメント部分（上の例で `#fn:1`）につく `:` がいかにも怪しかったので Python Markdown を調べていくと、つい半年くらい前に [SEPARATOR という設定項目が追加された](https://github.com/Python-Markdown/markdown/pull/728)とあった。デフォルトのコロンから適当な文字列に変更したら動作するようになった（僥倖）。

ただ、オプションを設定しないと期待通りに動作しないのが気持ち悪かったので issue[^1][^2] で相談した結果、次のような結論を得た。

- この部分にコロンを使えるのは [RFC3986](https://tools.ietf.org/html/rfc3986#section-3.5) に沿っている。
- 前述のコミット以前からコロンを使っていたが、不具合報告はこれが初めてである。 IE11 は EOL を待つだけなので、ライブラリ側は現状のままで気にする人が設定するのがベストではないか。
- 前述の例を含め、設定しないと問題が出る場合があるので Python Markdown に関する依存関係は近いうちに更新してくれる（バージョンが古いと `SEPARATOR` オプションの解釈に失敗するエラーが出る）、かも。

[^1]: https://github.com/squidfunk/mkdocs-material/issues/1083
[^2]: https://github.com/Python-Markdown/markdown/issues/819
SCSS/CSSで基本カラーを設定して効率よくまとめる

SCSS/CSSには様々なカラーコントロール機能がありまして、この機能を利用すればカラーバリエーションの作成やカラー修正など効率的に行うことが出来るようになります。

本ページは昨日の自分が見たら助かると思うように簡単にまとめました。（ご意見、ご指摘等ありましたらご連絡ください！）

#共通のSCSSファイルを作成する

カラー設定は他のSCSSファイルから共通して使用すると効率が良いです。なのでカラー設定用のSCSSファイルを最初に作成します。

共通の変数は「_variables.scss」というファイル名にします。
「＿」で始まるファイルはコンパイルされません。

```scss:_variables.scss
 $base-color:#536A97;
```
とりあえず変数「$base-color」という変数を一つ作成しました。

#変数を使用する

先ほどカラー設定した変数を使用してみましょう。

```scss:base.scss
 @import"_variables.scss";
```
```
h1{
   color;$base-color;
}
```
適当なファイル（base.scss)を作成したら、カラー設定した「_variables.scss」をインポートします。
あとは使いたい場所に「＄base-color」を記述するだけです。
ここではh1プロパティに設定した変数を使用してみました。
これをコンパイルすると下記のようになります。

```scss:base.scss
 h1{
   color:#536A97;
}
```
一つだけだとあまりありがらみがないですが、例えば下記のように複数のプロパティに同じカラーを設定した場合、「$base.color」のカラーを変更するだけで全てのカラーが反映されますので、修正が楽に行えますね。

```scss:base.scss

h1 {
    color: $base-color;
    font-size: 32px;
}
h2 {
    color: #fff;
    background-color: $base-color;
}
section {
    border: solid 1px $base-color;
}
```
【Facebook API】新規登録をFacebook for developersで連携

<img width="1500" alt="スクリーンショット 2019-04-23 16.27.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319526/c95c5c7e-e5a2-8fca-77e2-b05061a6c1df.png">



参考にした記事：

https://ruby-rails.hatenadiary.com/entry/20140804/1407168000

https://qiita.com/RYOSUKE310/items/2f9ec73aaecd4d80f997