OmniAICreator/Qiita-1.07M huggingface dataset:
【Ruby】APIへxmlでリクエスト

## はじめに

現在公開されているほとんどのAPIがデータフォーマットJSONでリクエストを送るAPIかと思いますが、
稀にデータフォーマットがXMLのAPIがありますので、そのリクエスト方法をメモとして残しておきたいと思います。

## 環境

* Ruby 2.5.0

今回はRailsなどは使用せず、ピュアなRubyのみで実装を行なっていきたいと思います。

## ファイル構成

* index.rb
* hoge_api.rb

> ファイル名などは適当ですmm

## リクエスト用のクラスを作成

このクラスでxml引数にとりをAPIへリクエストを行わせます。
Rubyの標準ライブラリを使用するため、特別何かのインストールは必要ありません。

```rb
# hoge_api.rb
require 'net/http'
require 'uri'
require 'json'
require 'rexml/document'
require 'open-uri'

class HogeApi
  attr_reader :body, :code, :json

  def initialize(xml)
    # リクエストヘッダ
    headers = {
      'Content-Type' => 'application/xml'
    }

    # 環境変数にエンドポイントを設定しておく
    uri = URI.parse("#{ENV['API_URL']}")
    # xmlのAPIは仕様が古くsslに対応していないものが多いので、以下のように80番ポートでアクセス。sslに対応している場合はsslに対応するように設定を変更してください
    http = Net::HTTP.new(uri.host, 80)
    http.use_ssl = false

    response = http.post("#{uri.path}?#{uri.query}", xml, headers)
    @body = response.body # APIからのresponseのxmlをそのまま返す
    @code = response.code # ステータスコードを返す
    @json = xml_to_json(response.body) # xmlをjsonに変換したデータを返す
  end

  # xmlフォーマットのデータを扱い易いようにjsonデータに変換するメソッド
  def xml_to_json(xml)
    doc = REXML::Document.new(xml)
    hash = Hash.from_xml(doc.to_s)
    hash.to_json
  end
end
```


## 実行用のファイル

リクエスト用のxml

```xml
<?xml version='1.0' encoding='UTF-8' ?>
<foods>
  <food>
    <name>バナナ</name>
    <color>黄色</color>
  </food>

  <food>
    <name>リンゴ</name>
    <color>赤</color>
  </food>
</foods>
```

上記のようなxmlを使用します。

```rb
require 'json'
require 'net/http'
require './hoge_api' # 作成したリクエスト用のクラスを読み込み

def main
  food_name = 'アップル'
  food_color = '赤'
  # 上記のxmlデータを文字列にして変数に格納
  xml = "<?xml version='1.0' encoding='UTF-8' ?><foods><food><name>#{food_name}</name><color>#{food_color}</color></food></foods>"
  
  # HogeApiクラスでリクエストを行い、返却された結果を変数responseに代入
  response = HogeApi.new(xml)

  # 返却されたデータが必要ない場合は、以下でもいい
  HogeApi.new(xml)
end
```

以上となります。
xmlでリクエストを送る方法でわかりやすいのがなかなかなかったので、参考になれば幸いです。
macOS : Finderにある「最近の項目」をクリアする方法

# はじめに
Finderの「最近の項目」にファイルを表示したくない。
安易に消すとファイルの実体が削除になる。（ゴミ箱に入る）
ファイルは消さずに、「最近の項目」からは消したい。
その方法です。

# 環境
macOS Catalina バージョン 10.15
macOS Big Sur バージョン 11.3.1


# 手順
スクリーンショットは Catalina ですが、Big Sur でも同じです。

## 「最近の項目」から消す
1. アップルメニューの「システム環境」で「Spotlight」を選ぶ。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297484/0a8735ee-5f04-1b9d-9b57-4bfa1ab388ee.png" width="50%" />

2. 「プライバシー」タブで「+」をクリックするか、ドラッグアンドドロップでハードディスク、もしくは「最近の項目」に載ってほしくないファイルがあるフォルダを追加し、確認で「OK」する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297484/494f4108-269d-e172-8e50-ee94d66d2d4e.png" width="50%" />
　で、「最近の項目」から消える。
　載って欲しくなったら、「-」をクリックして除外しない。

## Finderのサイドバーから「最近の項目」を消す（非表示にする）
メニューの「移動」-「最近の項目」か、Shift + Command + F キーで表示できるので、非表示でも困らないと思う。

1. Finderのメニューから「Finder」-「環境設定」を選ぶ。
2. 「サイドバー」の「最近の項目」チェックを外す。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297484/f423da51-389a-afe8-f719-5941d3e4277c.png" width="50%" />

## 結論
仕方ないじゃないか。男だもの。

# 参考

[Q: Recents in Finder Go Column Can't be Deleted -> A: from Touten](https://discussions.apple.com/thread/8137012?answerId=32628149022#32628149022)
Raspberry PiにRaspbianをインストールしたら最初にすることメモ

# apt

## 一括アップデート

```
$ sudo apt update && sudo apt -y upgrade && sudo apt -y dist-upgrade && sudo rpi-update -y && sudo apt -y autoremove && sudo apt -y autoclean
```

※アップデート後に再起動させる場合は、` && sudo init 6`を追加します。

# リモートデスクトップ設定

## TightVNC Serverをインストールする

## IPアドレスを固定する

```
$ sudo nano /etc/dhcpcd.conf
```

```Ruby:/etc/dhcpcd.conf
+ interface wlan0
+ static ip_address=192.168.0.8/24
+ static routers=192.168.1.1
+ static domain_name_servers=192.168.1.1
```
リーダブルコード第3章＜誤解されない名前＞

# 最善の変数名とは

**誤解されない名前であること**

# 鍵となる考え
**変数名が「他の意味と間違えられることはないか？」　何度も自問自答する。**

例: filter()
「選択する」メソッドなのか、それとも「除外する」のかわからない。

例: clip(text,length)

下記のように「textの最後を切り落として、　...をつける」というメソッドの場合において

``` 
def clip(text, length):
・・・・
```

2通りの動作として解釈できる

- 最後からlength文字を削除する。(remove)
- 最大length文字まで切り詰める(truncate)

```
def Truncate(text, length):
```
lengthはmax_lengthにしたほうが明確になる。
しかし、max_lengthという変数名も誤解を招きやすい。

３種類の解釈ができる。

- バイト数
- 文字数
- 単語数

といった場合を想定できる（下記は文字列の場合の例）

```
max_chars
```



##限界値を含めるときはminとmaxを使う

```
X CART_TOO_BIG_LIMIT 限界値を含むかどうか曖昧
◯　MAX_ITEMS_IN_CART
```

## 範囲を指定するときはfirstとlastを使う
始端、終端を表す言葉は様々ある
start, begin , first 
stop , last , end 
範囲を表し、それぞれの言葉が始端、終端に含まれる場合にはfirst,lastが適している。

```
first 
last
max , min (意味的に正しく聞こえるのであれば代替可能)
```

## 包含/排他的範囲にはbeginとendを使う
## ブール値の名前

プール値の変数名には、頭に　is, has , can , should などをつけてわかりやすくする。

## ユーザーの期待に合わせる

getなどの、多くのメンバが慣れ親しんでいる言葉から始まるメソッドの変数名をつけるときは、特に注意する。
get*() 軽量アクセサとして広く認識されており、仮にgetを先頭にして処理の重いメソッドの関数名として定義した場合、呼び出し側の期待に沿わない使い方をされる場合がある。
そのようなメソッドに対して名前をつける場合は、具体的に処理内容がわかる変数名を定義し、期待に沿うようにする。

## 複数の名前を検討する

複数の名前を定義できる場合は、可能性のある名前を吟味し、客観的にその変数名が明確に何をするものなのかがわかりやすく、誤解が生じる可能性が低いものを選択し、定義する。

# まとめ

冒頭でも述べたが、「誤解されない名前」が最善の名前である。
呼び出し側のメソッド名に対する一般的な認識に対しても注意する。
get(),size()など（基本的に軽量なメソッドの名前として認識されている）

- 上下の限界値を決めるときは、前方に 

```
max_,min_
```
- 包括的範囲であれば 

```
first_ , last_ 
```
- 包含、排他的範囲であれば 

```
begin_ , end_ 
```
プール値に名前をつけるとき

```
is_ , has_
```
- 否定的な命名はできるだけ避ける。

```
X disable_ssl
```
MQTTのMessageを残らずMySQL(MariaDB)に保存するコマンド

#個人的なメモ

## db構造

```sql

sudo mysql -e "SHOW FULL COLUMNS FROM mqtt.msg"
+-------+---------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type          | Collation         | Null | Key | Default | Extra | Privileges                      | Comment |
+-------+---------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
| m     | varchar(1124) | latin1_swedish_ci | YES  |     | NULL    |       | select,insert,update,references |         |
| tm    | int(11)       | NULL              | YES  |     | NULL    |       | select,insert,update,references |         |
+-------+---------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
```

## コマンド

```shell
mosquitto_sub -t "#" -v | xargs -I@ sudo mysql -e "insert into mqtt.msg (m,tm)values('@',$(date +%s))"
```
上記だと、時間が固定になってしまいます。
SQLの方で持ってくるように変更

```shell
mosquitto_sub -t "#" -v | xargs -I@ sudo mysql -e "insert into mqtt.msg (m,tm)values('@',UNIX_TIMESTAMP(NOW()))"
```


## 課題

・セキュリティ的に問題有り
・トピックとMessageが分割できていない

commentいただけると嬉しいです！
Xcode11のIBに追加されたContentLayoutGuideとFrameLayoutGuideについて

## 要約
- Xcode11からIBで`UIScrollView`を使うときは`Content Layout Guide`と`Frame Layout Guide`を利用するといいかも
- iOS10以下をサポートしたい時は今までとちょっとやり方が変わったから気をつけよう

## IB + UIScrollViewは大変
例として、夏目漱石の「我輩は猫である」を表示するだけの画面を作ってみます。
ここではXcode10.2を使用しています。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186419/0566da5e-ccbe-a4c3-2a5b-4a9a29d6d409.png)

この画面は、`UIScrollView`と`ContentView`(`UIView`)、2つの`UILabel`で構成されています。
<img width="351" alt="02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186419/d2e6767f-e2ff-2315-ad2b-93cb8e3ba55b.png">

`UIScrollView`をAutolayoutを使って組む場合、以下の制約が必要です。

- `UIScrollView`自身の位置
- `UIScrollView`の中身のサイズ
- `UIScrollView`の中身の固定された横/縦幅

この制約を満たすために、以下の手順でConstraintを設定しています。

1. `UIScrollView`の上下左右を`UIViewController`の`View`に合わせる
2. `ContentView`の上下左右を`UIScrollView`に合わせる
3. `ContentView`の横幅を`UIViewController`の`View`に合わせる(`Equal Widths`)
4. `ContentView`にオブジェクトを追加して高さを確定させる

慣れれば大したことはないのかもしれませんが、`UIScrollView`が持つフレーム領域とコンテンツ領域が混ざって扱われているので、後からStoryboardをみた時どこがどうなってるんだっけ？？と混乱すると思います。

## ContentLayoutGuideとFrameLayoutGuideの登場
Xcode11から、ScrollViewの中に[Content Layout Guide](https://developer.apple.com/documentation/uikit/uiscrollview/2865870-contentlayoutguide)と[Frame Layout Guide](https://developer.apple.com/documentation/uikit/uiscrollview/2865772-framelayoutguide)が追加されました。
名前の通り、`Content Layout Guide`は`UIScrollView`の中身、`Frame Layout Guide`は`UIScrollView`のフレーム領域を示します。
以下の画面を見ると、中身とフレーム領域が明確に分けられていることがわかります。
<img width="375" alt="03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186419/cbca063c-7e9f-1a27-7dac-0aaf8622061d.png">

これらはiOS11から追加された機能でしたが、IB上では扱えず、コード上でUIを組み立てる時しか恩恵を得られませんでした。
Xcode11ではScrollViewの中に追加されており、IBで`UIScrollView`を扱う人でも使えるようになりました。

さて、先ほど作った画面を`Content Layout Guide`と`Frame Layout Guide`を使うように直すとこうなります。
<img width="486" alt="04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186419/4e453afd-74ca-39fa-bf3b-6bc79475126f.png">

1. `UIScrollView`の上下左右を`UIViewController`の`View`に合わせる
2. `ContentView`の**上下左右を`Content Layout Guide`に合わせる**
3. `ContentView`の**横幅を`Frame Layout Guide`に合わせる(`Equal Widths`)**
4. `ContentView`にオブジェクトを追加して高さを確定させる

手順としては大きく変わっていないのですが、今まで`ContentView`を`UIScrollView`や`UIViewController`の`View`に合わせていたところを、それぞれのLayout Guideに合わせることで役割が明確になりました。

## iOS10以下もサポートしたいんだけど。。。
残念ながら、`contentLayoutGuide`と`frameLayoutGuide`はiOS11からの機能なので、iOS10以下で実行するとクラッシュします。
その場合は従来と同じ方法で実装する流れになりますが、Xcode11では上記の方法の

>3 . `ContentView`の横幅を`UIViewController`の`View`に合わせる(`Equal Widths`)

これをやろうとすると、そもそも`Equal Widths`の項目がなくなっています(バグ？)

<img width="227" alt="05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186419/a54069b0-6674-88d1-6940-07f585af525f.png">

一時的な解決策として、Viewに対してではなく**ViewのSafeAreaに向ける**と項目が出てきますので、そっちを使っています。


## 参考
[Scroll View Layouts With Interface Builder](https://useyourloaf.com/blog/scroll-view-layouts-with-interface-builder/)
Raspberry Pi 4でDockerをインストール

多分同じように詰まる人がいると思うので共有


```bash:環境情報
uname -a
Linux raspberrypi 4.19.75-v7l+ #1270 SMP *** armv7l GNU/Linux
```


パッケージは最新化しておく。

```bash:いつもの
sudo apt update
sudo apt upgrade
```




dockerは素直に入った。

```bash:dockerのインストール
sudo curl -fsSL https://get.docker.com/ | sh

docker -v
Docker version 19.03.4, build 9013bf5
```

docker-composeが少々躓いた。
まず、公式のインストール方法ではディストリビューションが用意されておらず、9KBのゴミデータしか取得できない。

```bash:こちらは失敗
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
```

なので、pipでインストールする

```bash:pip
sudo pip install docker-compose
```

だが、本環境だと、２つの点で躓いた。

ffi.hが見つからないエラー
https://stackoverflow.com/questions/31508612/pip-install-unable-to-find-ffi-h-even-though-it-recognizes-libffi

```bash:解消法
sudo apt install libffi-dev
```

ssl_match_hostnameモジュールが見つからない
https://github.com/docker/docker-py/issues/1502

```bash:解消法
sudo cp -r /usr/local/lib/python2.7/dist-packages/backports/ssl_match_hostname/ /usr/lib/python2.7/dist-packages/backports
```

上記を実施したあとに再度、docker-composeをインストールし直す。

```bash:再インストール
sudo pip install docker-compose
docker-compose -v
docker-compose version 1.24.1, build 4667896
```


以上。
Dir関数のファイルを取り出す順番について

# Dir関数は必ずしも昇順でファイル名を返すわけではない

VBAのDir関数はファイル名の昇順で指定フォルダ内のファイル名を返すと思われている方は多いと思います

実際に試してみるとそのようになりますし、Office TANAKAさんも以下のように書かれています

> 引用
>
>ディスクのフォーマットによって異なります。最近主流のNTFSでフォーマットされているディスクでは、ファイルが保存された順番(タイムスタンプ)にかかわらず、ファイル名の順番(昇順)で返ります。
>
>[Office TANAKAファイルの操作[ファイルの一覧を取得する]](http://officetanaka.net/excel/vba/file/file07.htm)

記事によればフォーマットの形式によって取得される順番が異なるそうです

しかし、公式ドキュメントでDir関数を調べてみると以下のように書いてあります

> 引用
>
> ヒント
ファイル名は特定の順序で取得されるわけではないため、必要に応じて、返されたファイル名を配列に格納し、その配列を並べ替えます。
>
>[Dir関数(Visual Basic for Application)|Microsoft Docs](https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/dir-function)

公式ドキュメントの内容からするとDir関数は必ずしも昇順でファイル名を返すとは限らないといえると言えるでしょう
React HookでオブジェクトをuseStateではなくuseReducerで管理する

### 概要

[setState](https://ja.reactjs.org/docs/hooks-reference.html#functional-updates)でオブジェクトを管理していて起きた予期せぬ動作について調べてみたので記事として残しておきます。

### TL;DR

`React Hook`において、`useState`で複雑なオブジェクトを扱うのは最適解ではないので`useReducer`を使用する。

[フック API リファレンス](https://ja.reactjs.org/docs/hooks-reference.html#usestate)より引用

> クラスコンポーネントの setState メソッドとは異なり、useState は自動的な更新オブジェクトのマージを行いません。

> 別の選択肢としては useReducer があり、これは複数階層の値を含んだ state オブジェクトを管理する場合にはより適しています。

`useState`ではプリミティブ型、またはプリミティブ型からなるオブジェクトを扱い、それ以外のオブジェクトには`useReducer`を使用する。

### 詳細

`Next.js`で`div`要素、`input`要素にダブルクリックでトグルさせるコンポーネントを作成していました。

コンポーネントの設計として下記の様なステートを

```tsx
type ElementState = {
    selected: boolean
    element: JSX.Element
}

const [elementState, setElementState] : [
    ElementState,
    React.Dispatch<React.SetStateAction<ElementState>>
] = React.useState<ElementState>({
    selected: false,
    element: <div onDoubleClick={onDoubleClick}>
        {text}
    </div>
})
```

ダブルクリックイベントハンドラでトグルしたかったのですが

```tsx
const onDoubleClick = () => {
    if (elementState.selected) {
        setElementState({
            selected: false,
            element: <div onDoubleClick={onDoubleClick}>
                {text}
            </div>
        })
    } else {
        setElementState({
            selected: true,
            element: <input
                onDoubleClick={onDoubleClick}
                defaultValue={text}
            />
        })
    }
}
```

`elementState.element`は更新され、`elementState.selected`が更新されずトグルが実現できませんでした。

リンク[^1]を参照した所`useState`では複雑なオブジェクトを更新するのには向かず、それらを処理したい場合には`useReducer`を使用するという結論を得ました。

少し話は逸れますが、なぜ片方のプロパティが更新され、他方は更新されないのか？という点については結論はまだ出ていません。

今回の扱うオブジェクトは`boolean`と`JSX.Element`からなるオブジェクトです。
あくまで推測ですが、プリミティブ型とオブジェクト型が混合している場合、動作が未定義になるということかもしれません。

試しに`string`、`boolean`の場合で試してみた場合、期待通りプロパティは全て正常に更新されました。

上記のような予期せぬ動作は`useReducer`を使用することで回避できます。

まずは`reducer`を定義し

```tsx
interface State {
    element: JSX.Element
    selected: boolean
}

const reducer = (state: State, selected: boolean): State => {
    if (selected) {
        return {
            selected: false,
            element: <div onDoubleClick={() => dispatch(false)}>
                {text}
            </div>
        }
    } else {
        return {
            selected: true,
            element: <input
                onDoubleClick={() => dispatch(true)}
                defaultValue={text}
            />
        }
    }
}
```

`reducer`を登録し、`state`と`dispatch`を生成してあげれば大丈夫です。

```tsx
const [state, dispatch] : [
    State,
    React.Dispatch<boolean>
] = React.useReducer(reducer, {
    selected: false,
    element: <div onDoubleClick={() => dispatch(state.selected)}>
        {text}
    </div>
})
```

`reducer`の概念は処理の流れを決定するデザインパターンだと認識していましたが、`React Hook`では複雑なオブジェクトを扱う場合は`useReducer`に従えということなのでしょうか。

[^1]: [関数型の更新](https://ja.reactjs.org/docs/hooks-reference.html#functional-updates)、[useStateの設定メソッドがすぐに変更を反映しない](https://codeday.me/jp/qa/20190620/1054141.html)、[React の Hooks で state に Object を使う](https://diary.app.ssig33.com/407)、[React Hooks use State with Object](https://stackoverflow.com/questions/54150783/react-hooks-usestate-with-object)
年末まで毎日webサイトを作り続ける大学生 〜2日目 空白削除システムを作る〜

##はじめに
初めまして。
年末まで毎日webサイトを作っている者です。
今日はテキストから空白を削除してくれるシステムを作りました。
扱う技術レベルは低いですが、同じように悩んでる初心者の方の参考になれば幸いです。
今日は2日目。(2019/10/20)
よろしくお願いします。


##サイトURL
https://sin2cos21.github.io/day2.html

##やったこと
テキスト文から空白を除いてくれるシステムをJavaScriptで作りました↓

![スクリーンショット 2019-10-20 23.50.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/29dcfbbc-8950-7fdb-3367-9a6cde11c0e7.png)

##こだわったところ
入力欄をtextareaにすることで文章をそのままコピペすれば、改行・空白を取り除けるようにしました。
replaceメソッドを使って空白を取り除いています↓

```javascript

 <script>
        function deleteBlank() {
            target = document.getElementById("output");
            text = document.forms.form1.input_text.value;
            text2 = text.replace(/\s+/g, "");
            target.innerText = text2;
        }
    </script>
```

htmlの方ではformとtextareaを使っています。クリックすると関数呼び出しします↓

```html
        <form action="" name="form1">
            <textarea id="input_text" name="form1_text1" class="input_form"></textarea>
            <br>
            <br>
        </form>
        <div id="output" class="text_output">
        </div>
    </div>
    <input type="button" value="変換" onclick="deleteBlank();"> <br>
```

##感想
一括で空白が削除できるのはいいですね。
今度ぜひ削除パターンにバリエーションを作ってみたいです。（特定の文字の前後だけは削除しないとか）
~~と、そういえばgithubの方がうまくいっていなくて今僕のgitpages見れないかと思います。
早急に見れるようにしますので今しばらくお待ちください。~~

追記 2019/10/21
サイトは見れるようになりました。
リポジトリを削除したり何やらして、githubに直接ファイルをアップロードしました。
ソースツリー or コマンドを使って送ろうとすると “You must verify your email address.”とerror が出ます。
根本的には解決してないので今後も原因追求に努めたいと思います。
MISRA compliance 2016とは

# MISRA compliance 2016とは

## はじめに

[MISRA compliance 2016](https://misra.org.uk/LinkClick.aspx?fileticket=w_Syhpkf7xA%3D&tabid=57)を読む機会があったので、勉強のためまとめる。
あまり解説してる人とかが居なくて参考にするものが無かったので間違ってる箇所があるかもしれない。
＃詳しい人居たら指摘もらえると助かります。
それにしてもこのコンプライアンス文書自体はpdf公開されてるけど、肝心の規約(MISRA-Cとか)自体は買わないと見れなかったりするし、MISRAは普及させようとしているのだろうか…。

## 概要

MISRAのコーディング規約を運用するためのガイドライン。
要は、単にMISRA対応してるよ！というだけだと、チェックはしてるけど直さなかったり、チェックしてないものもの実はあったりで対応がバラバラになるので、それを統一したやり方でやることで、第三者に説明できるようにするためのもの。
(と理解した。)

## 要求されるもの

### GEP(Guideline Enforcement Plan)：ガイドライン施工計画

対象となる各規約(MISRA C 2012等)について、どのように準拠していくか(解析ツール、コンパイラ、マニュアルレビュー等)をまとめたもの。
ツールを利用する場合は下記の情報を記載する必要がある。

* ツールのバージョン
* コンフィグ
* 実行オプション
* ツールが規約への違反を摘出可能なことを示すエビデンス(ツールが公表してる情報とかかな？)
  
また、マニュアルレビューが必要な項目については、レビューの手順も記載する必要がある。

### GRP(Guideline Re-categorization Plan)：ガイドライン再分類計画書

対象となる各規約について、Mandatory(必須)/Required(必要)/Advisory(推奨)/Disapplied(非適用)の各カテゴリに再分類した結果をまとめたもの。
Advisoryに限ってはDisappliedに再分類可能だが、他は全て厳しくする方向にしか再分類できない。

| 再分類前カテゴリ | 再分類後カテゴリ |
| - | - |
| Mandatory | Mandatory |
| Required | Mandatory/Required |
| Advisory | Mandatory/Required/Advisory/**Disapplied** |

### Investigating Messages

規約への準拠をチェックする(ツールの実行など)過程で得られた情報。
以下のカテゴリに分類される。

1. 正しく違反を検知したもの(Correct diagnosis of a violation)
  →直すべきもの。逸脱するする場合は逸脱報告書に記載する必要あり。
2. 違反の可能性があるもの(Diagnosis of a possible violation)
  →良く確認して違反であればそれなりに処置し、違反でないならそれを示す必要あり。
3. 誤って違反と検知されたもの(False diagnosis of a violation)
  →何故それが誤りかを示す必要あり。可能であればツール等の開発元の同意を得ること。(それは無理じゃね…？)
4. 違反ではない本当の問題(Diagnosis of a genuine issue that is not a violation)
  ※これどういう事だろう？ツールで摘出されるけど、コーディング規約的には実はOKで、でも本当にバグってるもの？

### Deviation Permits：逸脱許可

プロジェクトとして、逸脱可能なユースケースを事前に定義したもの。
Deviation Permitsを作成することより、Deviation Records(逸脱報告書)の作成を簡素化できたり、
開発者が個別にDeviation Recordsを作成することによる、品質のばらつきを抑止できる。
以下を記載する。

* 識別ID
   Deviation Permitsを一意に識別するID。例えば{プロジェクト名}_{規約名}_{ユースケース番号}_{リビジョン}とか
* ユースケース
   例えば"xxxな書き方はやっちゃだめ"と言う規約に対して、"XXXの場合に限り、使用して良い"とか
* 逸脱を許容する背景
   逸脱するメリット(例えばリソースの効率が良いとか、メンテナンスし易いとか)と、デメリット(規約で縛っているからにはリスクがあるはず)をまとめる
* 逸脱する場合の要求事項
   デメリットに対する処置(リスクを低減・解消する施策)をまとめる

### Deviation Records：逸脱報告書

規約違反をそのままに(逸脱)するためのもの。
以下を記載する。

* 違反している規約名
* 違反が許容される状況の説明
  後述する理由で、コードを修正出来ないことの説明
* 逸脱する理由
   逸脱の正当化を参照
* コンテキストと問題の説明
   規約違反の内容と、それが発生している前後関係の説明
* リスク評価手順と、守るべき注意事項の要求
   逸脱することで発生するリスクをどう低減・解消するかの説明

#### 逸脱の正当化

逸脱する場合は、以下のいずれかの理由に該当しなければならない。

* Code quality
  ISO/IEC 250101に規定されている以下の製品品質特性に影響が出る場合
  * Function suitability
  * Performance efficiency
  * Compatibility
  * Usability
  * Reliability
  * Security
  * Maintainability
  * Portability
* Access to hardware
  コンパイラ固有の拡張機能など、標準の言語機能では提供されないローレベルのハード制御に関わる場合
* Adopted code integration
  Adopted code(プロジェクトとして受け入れを許容している、開発スコープ外のコード)とのインタフェースに関わる場合
* Non-compliant adopted code
  そもそもMISRA compliance 2016非準拠のAdopted codeに対する指摘の場合

### GCS(Guideline Compliance Summary)：ガイドライン準拠要約

規約への対応状況をまとめたもの。
各規約に対して、以下のいずれかを記載する。

* 準拠(違反も逸脱も無い)
* 逸脱あり
* 違反(Advisoryはこれも認められる)
* 非適用(再分類の結果やらないとしたもの)
GithubにSSH接続できるようにする

今回はGithubにSSH接続できるように設定していきます。

####①なぜ？
Http形式やHttps形式などGithubで使える通信規格は何種類かあります。
一般的にはHttp形式やHttps形式が有名ですが、なぜSSH形式なんでしょうか？

**SSHプロトコルを使うと、リモートサーバーや各種サービスへの接続や認証が可能になります。SSHキーを使うと、GitHubとの接続のたびにユーザー名やパスワードを省略できます。**

Https形式だと例えば、pushするたびにユーザー名とパスワードが必要になり、かなりの手間がかかります。

SSHの設定をすれば、パスワードによる認証を一切無効にして、鍵での認証のみにするといったことがよく行われます。

####②鍵とは？
鍵とは「公開鍵」と「秘密鍵」です。ここでは簡単に解説してみます。

公開鍵と秘密鍵の２つの鍵を作ります。公開鍵は一般に公開するためのもの、秘密鍵は自分だけのものとします。

公開鍵で鍵をかけたものは、秘密鍵でしか開けられません。逆もまたしかりで、秘密鍵で鍵をすると公開鍵でしか開けられません。

**Githubに登録する際には、自分の手で２つの鍵を作ります。秘密鍵は自分で保持し(他の人に見られてはいけません)、あらかじめ通信する相手、ここではGitHubに登録します。**

GitHub側とクライアントPC側、双方がこれらの鍵を使って認証や暗号化通信を行います。

####③Githubに登録する手順

まずは、公開鍵と秘密鍵のペアを作成します。

```
$cd ~/.ssh
```

鍵を入れるフォルダに移動します。

```
$ssh-keygen -t rsa
```

そして、鍵を生成します。

パスワードを聞かれたらエンターを押すと、「id_rsa」(秘密鍵)と「id_rsa.pub」(公開鍵)の2つの鍵が生成されます。

```
Your identification has been saved in (特定のパス)/.ssh/id_rsa_github.
Your public key has been saved in (特定のパス)/.ssh/id_rsa_github.pub.
The key fingerprint is:
SHA256:【略】 your_email@example.com
The key's randomart image is:
+---[RSA 4096]----+
...(snip)...　　　　　　
+----[SHA256]-----+
```

そして、公開鍵をGithubにアップします。

https://github.com/settings/ssh

で公開鍵の設定が出来ます。

「New SSH Key」をクリックし、登録画面に移動します。

<img width="761" alt="スクリーンショット 2019-10-20 19.11.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239560/69b94732-a0c6-30e9-b7dc-0db202a916af.png">


「Title」に公開鍵名、「Key」に公開鍵の中身を入れます。

ファイルの中に羅列された文字列をコピペしてアップロードします。

なお、鍵の中身のクリップボードへのコピーは下記コマンドで行えます。

Macの場合
```
$ pbcopy < ~/.ssh/id_rsa.pub 
```

Windowsの場合
```
$ clip < ~/.ssh/id_rsa.pub
```
これでペーストできるようになります。

もしできなければ、下記コマンドでKeyを確認できるので(長い文字列が表示されるはず)、コピペでも問題ありません。

```
$ vim ~/.ssh/id_rsa.pub
```

入力後は「Add Key」ボタンで登録したら完了です。

####④接続確認
下記コマンドで確認します。

```
$ ssh -T git@github.com
```

「Hi (account名)! You've successfully authenticated, but GitHub does not provide shell access.」と返ってきたら成功です！


手順としてはそこまで大変ではない上に毎回手間がかかる入力が省けるので、ぜひ試してみてください!

####参照
[Githubヘルプ](https://help.github.com/ja/articles/connecting-to-github-with-ssh)
ワーシャルフロイド法で求めた最短経路を復元する

自分用おぼえがき。

[AtCoder Beginner Contest 143](https://atcoder.jp/contests/abc143)にて、ワーシャルフロイド法を用いて解く問題が出ましたが、そこで経路を復元すると回答が求まるんじゃないかと思って調べました。
実はこの問題では、経路復元では正しい回答は求まらなかったわけですが、せっかく調べたので供養の意味も込めて書き残しておきます。

# 前提

ワーシャルフロイド法自体はわかっているものとします。

# 方法

ワーシャルフロイド法で操作するグラフの操作前の状態を保存しておき、操作後の距離が入っているグラフと照らし合わせて経路を辿っていけばよいです。

```cpp
// gが最短経路算出後のグラフ
// hが最短経路算出前のグラフ
vector<int> restore_path (int start, int end) {
    vector<int> p;
    int curr = start;
    while (curr != end) {
        // nは頂点数
        for (int i = 0; i < n; i++) {
            // (curr)---h[curr][i]---(i)---g[i][end]---(end)
            // と
            // (curr)-----------g[curr][end]-----------(end)
            // が一致すれば、iは最短経路に含まれる頂点である
            if (i != curr && h[curr][i] + g[i][end] == g[curr][end]) {
                curr = i;
                p.push_back(i);
                break;
            }
       	}
    }
    return p;
}
```

# 参考

こちらのブログ[ワーシャル-フロイド法の経路復元](http://zeosutt.hatenablog.com/entry/2015/05/05/045943)を参照させていただきました。
【作成中】PIC16F1827 I2Cスレーブとして設定

#環境
・PIC16F1827
・MPLAB X IDE v5.25
・Arduino nano互換機（テスト用I2C Master）

#参考にさせて頂いたサイト
http://kimamanilab.cocolog-nifty.com/blog/2016/05/pici2c-5dbb.html

#Configuration Bit の設定
私がよく使う設定を流用。

```c:main.c
// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = ON        // Watchdog Timer Enable (WDT enabled)
#pragma config PWRTE = ON       // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = HI        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), high trip point selected.)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)
```

#PICの初期化
内部クロックGPIOの初期化。

```c:main.c
/void main(void)
    OSCCON = 0xF2;  /* 内部クロック:8MHz */
    ANSELA = 0x00;
    ANSELB = 0x00;
    TRISA = 0x00;
    TRISB = 0x00;
    PORTA = 0x00;
    PORTB = 0x00;

    ...
```

#I2C初期設定
今回はスレーブモード、7bitアドレスモードで初期化。

```c:main.c
    SSP1CON2 = 0x01;            /* クロックストレッチ有効 */
    SSP1CON3 = 0x00;            /* データホールド有効 */
    SSP1ADD = I2C_ADDR<<1;      /* スレーブアドレスの設定 */
    SSP1STAT = 0x00;            /* ハイスピードモード/ SM Bus無効 */
    SSP1CON1 = 0b00110110;      /* I2Cスレーブモード/7bitアドレスモード */
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321914/489fc991-5aac-c5ce-70dd-47169c718d0c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321914/c79d43d6-320c-e64b-6815-6bfd1bdb9a29.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321914/08928526-5a12-5f5b-435c-ae9195430bef.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321914/97bb8737-d6f1-8b9a-83b3-9c9b3012e144.png)
テーブルの定義を変更する（主キー制約の変更）

#ALTER TABLE～DROP CONSTRAINTとALTER TABLE～ADD CONSTRAINTを使用する
　テーブルを作成したのちに、テーブルの主キー制約を変更したいことがあると思います。そのときには、**ALTER TABLE～DROP CONSTRAINT**（主キー制約の削除）と**ALTER TABLE～ADD CONSTRAINT**（主キー制約の追加）を使用します。この記事ではPostgreSQLでの主キー制約の変更方法を簡単に説明します。

#実行方法
　もともとの主キー制約を削除し、そのあとに主キー制約を追加します。以下にtestテーブルの列aの主キー制約を削除し、列aとbの主キー（複合キー）の制約を追加する例を示します。
##(1)テーブルの作成
　CREATE TABLEを使用してtestテーブルを作成しておきます。列aを主キーに設定しました。

```
postgres=# CREATE TABLE test (a int PRIMARY KEY, b int, c int);
CREATE TABLE
```

##(2)主キー制約の削除
　ALTER TABLE～DROP CONSTRAINTを使ってtestテーブルの列aの主キー制約を削除します。
　以下のように主キー名を指定しなければいけないのですが、主キーを作成するときに自分で名前を付けていなければ、**テーブル名_pkey**でOKです。もし、自分で名前を付けたが、忘れてしまった場合には(4)の方法で確認することができます。

書き方：**ALTER TABLE テーブル名 DROP CONSTRAINT 主キー名;**

```
postgres=# ALTER TABLE test DROP CONSTRAINT test_pkey;
ALTER TABLE
```

　列aの主キー制約は削除されていますが、NOT NULL制約は削除されていないため、削除したい場合は、ALTER TABLE～ALTER COLUMN～DROP NOT NULLを使用し、以下のように削除します。

書き方：**ALTER TABLE テーブル名 ALTER COLUMN 列名 DROP NOT NULL;**

```
postgres=# ALTER TABLE test ALTER COLUMN a DROP NOT NULL;
ALTER TABLE
```

##(3)主キー制約の追加
ALTER TABLE～ADD CONSTRAINTを使ってtestテーブルの列aとbに主キー制約を追加します。

書き方：**ALTER TABLE テーブル名 ADD CONSTRAINT 主キー名 PRIMARY KEY(列名);**

```
postgres=# ALTER TABLE test ADD CONSTRAINT test_pkey PRIMARY KEY(a, b);
ALTER TABLE
```

##(4)主キーが変わったか確認する
　最後に列aとbが主キーになっているのかを確認します。メタコマンド\dを使用します。
 実行結果の一番下に「Indexes:"test_pkey" PRIMARY KEY, btree (a, b)」と書いてあり、列aとbが主キー（test_pkey）となっていることが確認できます。

**書き方：\d テーブル名**

```
postgres=# \d test
                Table "public.test"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 a      | integer |           | not null |
 b      | integer |           | not null |
 c      | integer |           |          |
Indexes:
    "test_pkey" PRIMARY KEY, btree (a, b)
```
#まとめ
　基本的にはテーブルを最初に設計するときにしっかりと主キーを決めることが重要ですが、主キーを変更したいときには**ALTER TABLE～DROP CONSTRAINT**と**ALTER TABLE～ADD CONSTRAINT**を使用しましょう。
　ちなみに、**外部キー制約の変更**や**チェック制約の変更**も似たような操作で行えます。constraintは英語で「制約」を意味します。
　読んでくださりありがとうございます！
fmf.Sprintfはどんな型でもString型に合体する


### サンプル
- lengthなどはint
- spirintfでまとめつつStringにしている

```golang
package main

import "fmt"

func main() {
	type sample struct {
		length    int
		Height int
	}

	p := new(sample)
	p.length = 13
	p.Height = 666

	str := fmt.Sprintf("長さ:%d 高さ:%d", p.length, p.Height)
	fmt.Println(str)
}

```

結果

```
長さ:13 高さ:666
```
【FileMaker】部分一致の動的値一覧

受注管理のAppを作成していて、「取引先名の一部で入力候補を表示することってできますか？」とリクエストがあったので、作ってみました。

#ポイント
動的値一覧の作り方は色んな記事がありますが、部分一致の動的値一覧の記事を見たことがなかったのでまとめました。
最初はグローバル格納のフィールド「取引先リスト_g」を値一覧のフィールドに指定しようとしたのですが、索引設定できないため指定できず、マルチキーフィールドとして利用しました。
あとは一般的な動的値一覧と同じです。

# できあがりイメージ

「山田」と入力して検索ボタンをクリックすると、会社名に「山田」が含まれる取引先の候補をドロップダウンリストで表示します。
![無題０.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316038/52351ddb-40f1-fdb1-a17e-d134053cdcfa.png)

# どう処理しているのか

### 検索ボタン
![無題5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316038/8ae3e80a-cc50-9adc-d87e-32ab091c067f.png)

### スクリプトの中身
取引先マスターで検索して、結果を値一覧に表示しています。
※フィールド「取引先リスト_g」はグローバル格納。これがマルチキーフィールドになります。

![無題6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316038/7ef59861-585a-b252-8ff9-8a1909c84ce7.png)

スクリプトだけでは完結できないので、冒頭に出てきたマルチキーフィールドと動的値一覧の設定が必要です。

# 実装

## グローバル格納のフィールドを用意する
取引先マスターにグローバル格納のフィールドを追加します。
![無題4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316038/46dd9809-1848-56ac-b3f1-54fda0e64536.png)

####追記　2020/09/03
赤枠上の「取引先リスト」という集計フィールドも追加が必要です。

## テーブルオカレンスの追加とリレーションシップ設定
取引先マスターの自己リレーション。
動的値一覧用のテーブルオカレンスを追加して、マルチキーと取引先名をつなげる。
![無題3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316038/e58b843f-6d26-70fa-2354-3948e790dc49.png)

## 値一覧を新規作成
動的値一覧になります。
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316038/e55d192a-0177-f6ec-d156-958e968beae5.png)

関連レコードのテーブル指定忘れずに。
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316038/d411d481-8f84-38d6-7322-6908ca1d2115.png)

## ドロップダウンリストを設定
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316038/c3748885-1569-0efb-fe27-412220d60e05.png)

## スクリプト作成し、検索ボタンにスクリプトを設定
冒頭の画像のとおり（割愛）
(Windows) Bashが管理者として実行されているか判定する（ついでにプロンプトに表示する）

Windowsのコマンドライン環境として[Cmder](https://cmder.net/) とそれに同梱されているBashで作業をしていて，タイトルにあることがやりたくなったのでメモ代わりに初投稿です．

# 方法
バッチファイルでの方法(参考: https://commandprompt.noyokan.com/command/ck_admin.html, https://amksystem.com/cmd/cmd7/) と同様にWindowsの管理者権限を必要とするコマンドの返り値や出力で判定できる．（正規の方法はないんだろうか？）

今回は`openfiles`を使ってみる．外部コマンドなのでbashからでも呼べる．

```bash
openfiles > /dev/null 2>&1
IS_ADMIN=$?
```
これで`IS_ADMIN`に管理者権限の有無が入る．（若干紛らわしいが管理者として実行されている場合が`0`）
`$?`がバッチファイルでいう`%ERRORLEVEL%`相当の特殊変数．

# プロンプトに表示する
操作している端末が管理者として実行されているのかすぐ分かるように表示したかったというのが今回の動機．
管理者として実行されている場合にはプロンプトにその旨を表示するようにする．
`.bashrc`に次を書く．

```bash
openfiles > /dev/null 2>&1
IS_ADMIN=$?

_PS_ADMIN=''
if [ $IS_ADMIN -eq '0' ]; then
        _PS_ADMIN='(as Admin)'
fi

PS1='\[\033]0;$MSYSTEM:${PWD//[^[:ascii:]]/?}\007\]\[\033[32m\]\u@\h \[\033[33m\]\w\[\033[36m\]`__git_ps1`\[\033[0m\] \033[31m$_PS_ADMIN\033[0m\n'
```
これで管理者として実行されている場合のみデフォルトのプロンプトに加えて赤字で(as Admin)と表示されるようになる．

# おわりに
もっとましな方法やまともな書き方があったらご教授ください．
Ubuntu/ROS アップグレードメモ

#はじめに
ROSとUbuntuのバージョンは以下のようにリンクしています。（LTSは長期サポート版)

| ROS | Ubuntu |
| :--: | :--: |
| Melodic Morenia | 17.10 or 18.04 LTS | 
| Kinetic Kame | 15.10 or 16.04 LTS |
| Indigo Igloo | 13.10 or 14.04 LTS |

リンクしていない組み合わせを選択することは基本的に不可能です。
(例えば Ubuntu 16.04 で ROS Melodic を動かすことはできない)

#環境
|     | 前 | 後 |
| :-: | :--: | :--: |
| Ubuntu | 16.04.6 LTS | 18.04.3 LTS |
| ROS | Kinetic | Melodic |

#本題
##バックアップを取る
これ大事
`/home`以下くらいはコピーしておきましょう。

##ROS Kineticを消す
###パッケージ削除
```
sudo apt remove ros-kinetic-*
```

###
```
cd ~/catkin_ws
rm -rf build devel
```

###環境変数を削除
`~/.bashrc`に記述されている

```shellscript:.bashrc
source /opt/ros/kinetic/setup.bash
source ~/catkin_ws/devel/setup.bash
```
を削除する

##Ubuntuのアップグレード
1時間半位かかりました。
余裕のあるときにやりましょう。

###パッケージの更新
```
sudo apt update
sudo apt full-upgrade 
```
###アップグレード

```
sudo apt install update-manager-core
sudo do-release-upgrade
```

この後、何度か選択肢が出現するので自分の環境に合わせて処理を進めてください。
[y]か[ENTER]を押していればいいと思う

最後の方にデスクトップマネージャーをgdm3にするかlightdmにするか聞かれます。
後から変えられるので自分の好きな方を選んでください。
(lightdmは16.04、gdm3は18.04のデフォルト)


##ROS Melodicのインストール

[追記]
ROSのインストールがうまくいかない場合は
/etc/apt/sources.listに下のコマンドを追記してください。

```shell:sources.list
deb http://archive.ubuntu.com/ubuntu bionic restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu bionic-security restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu bionic-updates restricted universe multiverse
```

[ROS wiki](http://wiki.ros.org/melodic/Installation/Ubuntu)に書かれている通りにインストール

```
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

sudo apt update
sudo apt install ros-melodic-desktop-full
apt search ros-melodic

cd /etc/ros/rosdep/sources.list.d
sudo rm 20-default.list
sudo rosdep init
rosdep update

echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
source ~/.bashrc

source /opt/ros/melodic/setup.bash

sudo apt install python-rosinstall python-rosinstall-generator python-wstool build-essential

cd ~/catkin_ws/src
catkin_init_workspace
cd ~/catkin_ws
catkin_make
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc
```


#参考サイト
https://qiita.com/hirotatsuuu/items/e2e47b033dba95bfcf80
契約について（請負契約、準委任契約、派遣契約）

##はじめに
契約についてしっかり知識を身に着けようと思ったので、個人的な備忘録として残しているため、簡潔ではありません。

##1.契約とは
>二人以上の当事者の意思表示が合致することによって成立する法律行為のこと
>出典元：[Wikipedia](https://ja.wikipedia.org/wiki/%E5%A5%91%E7%B4%84)

だそうです。
契約を結んでいない限り、**法的な拘束力**がないので、お金を貰う約束をしても、法律が私達を守ってくれないんですねぇ。法律が守ってくれないとなると、お金を貰えるかどうかは、道徳の領域ですね。もちろん、「法律が守ってくれるから」とノーガード戦法も良くないですよね。法律は手段ですね。
法律っていう拘束力を発揮してもらうために契約は必要なんですね。

##2.契約が結ばれたことになるのはいつ？
契約は、**紙面に限らず口頭も含め「当事者の合意」**があればいいそうです。契約書や覚書って法律上の要件では必須ではないんですね。
契約書が必要な理由は、様々な理由がありますが省きます。

##3.契約の形態　
IT業界には請負契約、準委任契約、派遣契約をよく聞くので取り上げます。

契約が力を持つ内容を各フェーズに記載すると

|フェーズ  |契約が力を持つ内容  |
|---|---|---|
|作成中  |①受注側がやらなくてはいけないこと<br>②契約期間中の発注側の権限（指揮命令権）<br>③完成責任の有無|
|納品  |④契約完了による報酬の支払い  |
|納品後  |⑤瑕疵担保責任の有無  |
に分かれます。

各契約形態でどのように異なるのでしょうか。
##①受注側がやらなくてはいけないこと
　請負　・・・仕事の完成
　準委任・・・業務の処理
　派遣　・・・労働の従事

##①.1 仕事の完成
内容が抽象的すぎて、腹落ちしにくいですね。。
仕事の完成は、システムの完成ですね。
システムの完成には瑕疵担保責任がつきます。
瑕疵担保責任は、納品したら、システムがリプレースするなり、無くなるなり、しない限り、永遠なんでしょうか。
いえ、瑕疵担保責任を背負うのも、契約時に期間を決めます。リリースから3か月など。

##①.2 業務の処理
業務の処理は、「善良な管理者の注意義務」だそうです。つまり人依存。
発注側の権限が弱く、指揮命令系統は受注側にあります。
発注側の立場からしたら不安でいっぱいですね。発注側はその不安をどこで取っているのでしょうか。
とは言っても、実態はお金を出している側が力が強い。むしろ、しっかりコントロールすることが腕の見せ所です。コントロールも、お金やスケジュールだけでなく、システム・業務的観点でコンサルタントのようにファシリテートしていく必要があります。

##①.3 労働の従事
派遣は、完成の責任のない請負ですね。発注側の言うことを聞かなくてはいけないけど、仕事の完成責任はないんですね。

##余談
転職先の配属プロジェクトでは顧客とやり取りしている発注側に癖があり、元請の立場だった人間として「それはどうなん？」と思うことが多々。。今後戦う場面があるかもしれないので、しっかり整理しようと思ってこの記事を書きました。
各契約を差分のある項目でマトリクスを作成するのが一般的だと思うのですが
マトリクスはぱっと見キレイに見えますが、理解となると、追体験や論理の疑問点を自分なりに埋めていくことの方が理解が深まると考えています。
マトリクスや簡潔な説明は、正しい資料に見えて、前後関係が見えず、実務に活かせくなります。資格のみだったら問題ないですが、顧客に説明するときに「なんで？」攻めをされてもしっかり回答できるようにする必要があると思います。
fsharpでshift_jis(というかcp932)のファイルを読み込む

# Summary

fsharpでのファイルの読み込み

ファイルがcp932(shift_jis)

## 結論

```
nuget System.Text.Encoding.CodePages
```

### 確認コード

fecn=cp932, ff=dos, filename=foo.csv

```csv
ハイツⅠ
ハイツⅢ
浜﨑
```

filename=foo.fsx

```fsharp
#load @"./.paket/load/net48/main.group.fsx"
open System
open System.Text
open System.IO
open System.Collections.Concurrent
open System.Text.RegularExpressions

// csvFolderというフォルダーの中にあるcsvファイルを対象とする
let sourceDir = (Path.Combine( Directory.GetCurrentDirectory() , "csvFolder"))
Directory.EnumerateFiles(sourceDir, "*.csv")
|> Seq.iter ( fun fp -> 
    
    // コードプロバイダーにコードページプロバイダーを登録（これでCP932が使えるようになる）
    Encoding.RegisterProvider(CodePagesEncodingProvider.Instance)

    // cp932としてファイルからデータを読み込むリーダーを作成
    System.IO.Directory.SetCurrentDirectory( Directory.GetCurrentDirectory())
    use cp932reader = new StreamReader ( (Path.Combine( Directory.GetCurrentDirectory() , fp)) , Encoding.GetEncoding (932))

    // 改行コードが混じってると嫌なので一応変換しながら読み込む
    let file_lines = Regex.Replace( cp932reader.ReadToEnd() , "\r\n" , "\n" )

    // リーダーを閉じる
    cp932reader.Close()

    // 読み込んだデータをutf8で出力する
    file_lines |> Seq.iter stdout.Write

    )

```

出力結果

化けてない！（正しく取り込めてる！）

```
ハイツⅠ
ハイツⅢ
浜﨑
```


### おまけ

文字コード？を見る方法

１；ターミナルで見る

```
(ins)$ echo '浜﨑' | od -Ax -tx1
0000000    e6  b5  9c  ef  a8  91  0a                                    
0000007
```

２：vimでみる（一文字のみ）

```
任意の文字の上で g8

浜|﨑
g8
-> ef a8 91
```
Pythonを実行ファイル形式にする方法

>あくまでも個人用の備忘録

# はじめに

Pythonスクリプト(.py)から実行ファイル(.exe等)を生成する手段としてPyInstallerを使用した.

#実行環境

| | |
| --- | --- |
| OS | Windows 10 Home |
| Python | Python 3.6.9 :: Anaconda, Inc. |
| | pip==19.2.3 |
| | PyInstaller==3.5 |

# インストール方法

```
pip install pyinstaller
```

pipでインストール可能.

# 実行方法

```
pyinstaller filename.py option1 option2 ...
```

実行後のディレクトリ構成は以下のようになる.

```
├─filename.py       #Pythonスクリプト
├─filename.ico      #アイコン用ファイル(アイコンを設定する場合のみ用意する)
├─filename.spec
├─build
│  └─filename
├─dist
│  └─filename.exe
└─__pycache__
```

中間ファイルも生成される. 実行ファイルはdist下に生成される.

# オプション(一部)

|  | オプション | 概要 |
|---|----|---|
| 単一ファイル化 | --onefile | 関連するファイルを1つにまとめてバイナリ化 |
| コンソール非表示 | --noconsole | コンソール表示をしないようにする |
| Windowsバイナリ生成 | --windowed | 異なるプラットフォームでもWindowsのバイナリを作成 |
| icon設定 | --icon=filename.ico | アプリケーションのアイコンを設定 |

# 実行ファイルにリソースを埋め込む

実行ファイルのアイコンは上記のオプションだけで設定できるが, タイトルバーやタスクバーにアイコンを表示するためには別途設定が必要である.

- Pythonスクリプト(.py)に以下のコードを追加する

```python
import os
import sys

def icon_path(filename):
  if hasattr(sys, "_MEIPASS"):
      return os.path.join(sys._MEIPASS, filename)
  return os.path.join(filename)
```

ファイルの展開先のパスが取得できる.

- タイトルバーやタスクバーのアイコンを設定しているコードを書きかえる

```python
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon

if __name__ == '__main__':

	app = QApplication(sys.argv)
	app.setWindowIcon(QIcon(icon_path('filename.ico'))) #ココ
	window = ExWindow()
	sys.exit(app.exec_())
```

例としてPyQt5を使用している.

- 実行ファイル作成

```
pyinstaller filename.py --onefile --noconsole --icon=filename.ico
```

- filename.specを書きかえる

```python
# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['filename.py'],
             pathex=['path'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
a.datas += [('filename.ico', '.\\filename.ico', 'DATA')] #コレを追加
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='filename',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=False , icon='filename.ico')
```

- 以下のコマンドを実行

```
pyinstaller filename.spec
```

これで実行ファイルのみでタイトルバーやタスクバーにアイコンが表示されるようになる.

# 注意点
生成される実行ファイルは作成元OSにのみ対応するので, Windowsで動く実行ファイルを作成するためにはWindowsが必要である.

# 参考
[Pythonスクリプトを単一実行ファイルにする方法](https://qiita.com/hirohiro77/items/466e411fa41f144c8b2a)
[PyInstallerで実行ファイルにリソースを埋め込み](https://qiita.com/firedfly/items/f6de5cfb446da4b53eeb)
ネットワークスペシャリスト 午後Ⅱ 解答【令和元年度・2019年度】

# ネスぺ 午後Ⅱ 解答 (2019/10/20 23:30)
本日受験したNWの午後Ⅱ。問Ⅰのみ。
ひとまず自分の実際の解答。

## 問1 クラウドサービスへの移行
自己採点：62～79/100点

### 設問1
(1)↓
ア：PC
イ：FW
カ：IP-PBX

(2)↓
ウ：REGISTER
エ：SIP UA
オ：200 OK

(3)↓
1：スマホからIP-PBXへのSIP通信
2：スマホから ~~IP-PBXへの~~ 本社のIP電話機へのRTP通信

### 設問2
(1)↓
キ：MPLS
ク：ハブアンドスポーク
ケ：Y-BBR

(2)支店～Y-VPN～本社

(3)Y-GWが設置されている支店と、そうでない支店があるから

### 設問3
(1)本社のスマホ

(2)本社のIP電話機の保留

(3)(16),(17)

(4)本社のIP電話機は、(23)中のSDPの情報に従って保留音を出す

### 設問4

(1)L3SWに新環境の内部LAN、X-VNW、Y-VNWと接続するVLANを設定し、それらと現行環境の通信を禁止する

(2)↓
C：IP-PBXの切り替え
D：SIPサーバとの通信

(3)↓
設置場所：本社
変更内容：PCに新環境のプロキシサーバのIPアドレスを設定する定義情報を配布させる

(4)↓
サ：b2
シ：b3

(5)↓
時点：全拠点のPCの切り替えが完了した時点
機器：L2SW、BBR
IBM Cloud Node-RED JSON形式のフローデータの読み込ませ方

IBM Cloud上で使えるビジュアルプログラミングツールNode-RED。ここではフローエディタ上でJSON形式のフローデータの読み込ませる方法をを説明します。

ころころUIは変わりますので、これは以下時点の情報です:
2019年10月20日

#0. IBM CloudでNode-REDフローエディタを開く
IBM Cloud上でNode-RED Cloud Foundry アプリをまだ作成していない場合は、[IBM CloudでNode-REDの立ち上げ方](https://qiita.com/nishikyon/items/46c15bc392e6274dd41d)を参考に作成して、Node-REDフローエディタを開いてください。

ダッシュボードから開く場合は以下のようにします:
0.1: ダッシュボードの[リソースの要約]からリソースの表示をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/52b9bdb9-8204-e76e-e658-22c529d83639.png)

0.2: `Cloud Foundry Apps`の文字をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/9446557d-7e40-0566-1f5d-9fbf973f0147.png)

###0.3: Node-REDフローエディタを開きたいNode-RED Cloud Foundry アプリの名前をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/c6858f2f-4c28-383f-d6b2-a3d231ab1124.png)

0.4: アプリURLにアクセスをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/2d56c89c-e0dd-fc13-2f7a-a2e23b28686e.png)

Node-REDの画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/c8a3344e-2407-548f-fa36-c2c557d26747.png)

0.5: `Go to your Node-RED flow editor`をクリックします、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/97b3c98f-dfff-695b-238e-4d7cd8eedc3d.png)

0.6:設定したユーザ名とパスワードを入れて、ログインをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/3f9c174b-d093-4e9b-196e-21fd8aa91c29.png)

0.7:  Node-REDフローエディタが立ち上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/c563622f-fe26-e901-fab7-2b47ce136643.png)

#1. 右上の三本線のメニューをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/5f561d46-9dd9-f265-59f6-abb8e48fdcdd.png)

#2. 「読み込み」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/9c47e5c8-ff65-1df2-3929-3a4c75bf2015.png)

#3. ファイルを指定して読み込み
「読み込むファイルを選択してください」をクリックして、読み込ませるJSONファイルを指定します。またはビンクのエリアに読み込ませるJSONデータをコピー&ペーストします。
読み込み先を「現在のタブ」(デフォルト)または「新規のタブ」を指定し、「読み込み」をクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/e01433cc-8e89-842c-3eee-66b25a338967.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/d0e5713c-a1b7-9620-641d-8d2ea6c58136.png)

#4. フローが読み込まれます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/b952450a-2d59-80dd-8e81-6f999cfd3569.png)

以上です。
Next.js 9.1: srcディレクトリとpublicディレクトリがサポートされました

Next.js 9.1がリリースされたので変更内容をざっくりまとめました。
詳しい内容は[Nextjs.orgのブログ](https://nextjs.org/blog/next-9-1)で公開されています。

## まとめ
### 新機能
* `src`ディレクトリのサポート
* `public`ディレクトリのサポート

### プレビュー（フラッグ有効で利用化）
* Built-in CSSのサポート
* 静的なエラーページ
* Module / Nomodule

## `src`ディレクトリのサポート
Next.js 9.1からはpagesディレクトリを`src`ディレクトリにも設置できるようになりました。

今まではルートディレクトリにしかおけず、`src/pages/`を有効化するにはNext.jsのルートディレクトリをまるごとsrc/に変更する手法が使われていました。（`next dev src/`のようにしていた）
9.1からはこういった対応が不要で、src/pages/ディレクトリにおいたファイルが認識されるようになりました。

## `public`ディレクトリのサポート
静的ファイルを置くディレクトリが`static/`から`public/`に変更になりました。
`favicon.ico`を`public/favicon.ico`に設置すると、`example.com/favicon.ico`で配信されるようになります。

従来は`static/favicon.ico`に設置したファイルは`emample.com/static/favicon.ico`で公開されており、ドメインルートでファイルを配信するのに一手間必要でした。この一手間が減り、より直感的な仕様になりました。

## Built-in CSSのサポート
Next.jsでは同じくZeit製のCSS in JSライブラリである「styled-jsx」の利用が推奨されています。
しかし、Next.js中でCSSのインポートを行う、「next-css」パッケージが半分以上のNext.jsプロジェクトで利用されているらしく、その結果build-inでサポートしようという動きがあるそうです。

## 静的なエラーページ
Next.jsのエラーページは内部的に`/_error`と呼ばれており、`src/_error.js`にReactコンポーネントファイルを作成することでエラーページのカスタマイズが可能です。
エラーページを動的にレンダリングをする必要はないので、静的化を行っています。

## Module / Nomodule
Next.jsはいわゆるモダンなJSでコードを書き、実際のブラウザではBabelを使ってトランスパイルされたコードが実行されます。
このコードはサポートするブラウザすべてで動作するJSファイルですが、モダンブラウザではトランスパイルが必要ない場合があります。
module/nomoduleパターンでは古いブラウザにはポリフィル付きのES5コードを提供する一方で、モダンブラウザにモダンJSを配信するために、信頼できるメカニズムを提供します。
この機能は実世界でのデータを収集するため、複数の大規模Next.jsアプリケーションで本番環境でのテストを行っているそうです。詳細は近々共有されるようです。

## 改善されたBundle Splitting
Next.jsでビルドを行うといくつかのJSファイルが生成されます。その中に含まれるcommons.jsには各ページ間で利用されている共通のモジュールが挿入されます。
今までのこの共通のモジュールの判定は比率ベースで行われており、すべてのページの50%で使われているモジュールがcommons.jsに含まれていました。しかし、今回新しく複数のJSファイルに分割することで最適化されたBundle Splittingが行われるようになるようです。

こちらもmodule/nomoduleの変更と同じく現在テスト中とのことで、結果は後々公開されるようです。
.Net Core 3.0 SDKをUbuntu18.04へインストール手順メモ

Microsoft Keyの登録  

```bash
wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
```

.NET SDKのインストール

```bash 
sudo add-apt-repository universe
sudo apt-get update
sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install dotnet-sdk-3.0
```

インストール確認

```bash
dotnet --version
3.0.100
```
DockerでPhoenixFrameworkのプロジェクトを作成してエラーが出た話

Dockerのコンテナ内にElixirやPhoenixFrameworkをインストールして

`docker-compose run web mix phx.new sample`

のような感じでDockerにマウントしたディレクトリに新しくプロジェクトを作ると、

下のメッセージが表示されました。

``` sh
We are almost there! The following steps are missing:

    $ cd sample
    $ cd assets && npm install && node node_modules/webpack/bin/webpack.js --mode development
```

nodeのインストールを失敗しているので、手動でインストールする必要があるみたいですが、
とりあえず、このコマンドを実行せずにプロジェクトのサーバーを起動すると、
やはり画像が表示されず、崩れた画面が表示されました。
サーバーのログにも下のようなエラーが出力されてたので、`npm install`が成功しないと、
まともに表示できないみたいです。

```
[error] Could not start node watcher because script "/app/sample/assets/node_modules/webpack/bin/webpack.js" does not exist. Your Phoenix application is still running, however assets won't be compiled. You may fix this by running "cd assets && npm install".
```


原因を調べてみたところDockerでマウントしたディレクトリで`npm install`するとエラーになるみたいです。
`npm install` する時にシンボリックリンクを作成しようとして、失敗しているようでした。

マウントしていないディレクトリで`npm install`するか、
ホストでnodeをインストールして`npm install`する必要がありそうです。
【Rails】ユーザー登録機能が動作しない

##開始タグ
ユーザー登録実装中に、データベースに登録できなくて詰まったのでメモ。

##道中
色々な参考サイトを探してみるも明確な答えにたどり着けず、とりあえず「ry-byebug」のgemでデバッグして見た。

```ruby:
  def create
    @user = User.new(name: params[:name], pass: params[:pass])
    @user.save
    binding.pry
    redirect_to("/dashboard/index")
  end
```
すると以下のエラーが。

```
Started POST "/users/create" for 172.21.0.1 at 2019-10-20 13:31:02 +0000
Cannot render console from 172.21.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"AGAzaEa5VNEyv9sRn/kzQORFEDBs8CsBuxAPeH+7xB8ZM/qOfevgOKQLlmJH4mAHaDb6XEWhPWh2zHFPsMuVhA==", "name"=>"usertest", "pass"=>"passtest"}
Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms)


  
ActiveModel::UnknownAttributeError (unknown attribute 'username' for User.):
  
app/controllers/users_controller.rb:9:in `create'
```
`username`なんてないはずなのだが・・・と思い調べてみると、同じような現象が起きている方の投稿を発見。

[ActiveModel::UnknownAttributeErrorの意味｜teratail](https://teratail.com/questions/111861)

もう一度db:migrateを行えば解決したようですので、試してみる。
※Dockerを使用しています。

```
docker-compose run web bundle exec rake db:migrate
```
再度登録作業を行ったら、無事データベースに登録されました。

試しにフォームのinputのname属性を変更して再度登録してみました。

user→username
pass→password

```ruby
<%= form_tag("/users/create") do %>
  <input type="text" name="username" placeholder="ユーザーネーム" class="form_inp inp_text">
  <input type="text" name="password" placeholder="パスワード" class="form_inp inp_text">
  <div class="btn_area">
    <input type="submit" value="登録する" class="btn btn01 darkblue">
    <!-- /btn_area -->
  </div>
<% end %>
```
すると再度エラーが出ました。
そこでもう一度db:migrateすると、無事登録できるようになりました。

なるほど、そういえばname属性を`username`に変更していたな・・・。
一度送信を行ったあと（失敗しても）にinputのname属性を変更してしまうとエラーになってしまうようで、「name属性を変更してしまったこと」が原因だった。

##閉じタグ
今後、name属性の変更はなるべく行わないようにしよう。
データベースへの登録に困った際は「db:migrate」を試してみよう。
時間かかってしもうた・・・。
はじめてのDjango

#はじめに
未来電子テクノロジーでインターンをしているErika-Mです。

最近Djangoについて学び始め、<a href=https://djangobrothers.com>DjangoBrothers</a>や<a href=https://tutorial.djangogirls.org/ja/>Django Girls</a>というサイトでDjangoについてチュートリアルを進めてみました。

そこで今回は、Djangoがどのようなものなのか書いていきます。

#Djangoとは

Pythonをもとに作られた、Webフレームワークのことです。
Webフレームワークというのは、Webサービスでよく使われる、ユーザー登録や投稿機能などの機能を簡単に作れるようにしたものです。

また、Djangoは拡張性や柔軟性が高く、セキュリティが強いのが特徴となっています。

#Djangoでブログ管理サイトをつくろう

ざっくりと流れを見ていきましょう。
詳しく知りたい方は、<a href=https://djangobrothers.com>DjangoBrothers</a>や<a href=https://tutorial.djangogirls.org/ja/>Django Girls</a>を参照してください。

###PythonとDjangoの環境構築

まずは、Pythonをインストールします。
そして仮想環境を作り、その仮想環境の中でDjangoをインストールします。
仮想環境を作ることで、異なる言語を使う複数のプロジェクトを切り替えながら作業できるのです。

###プロジェクトをつくる
Djangoのプロジェクトをつくります。
プロジェクトとは、アプリケーションというWebサービスに必要な機能を実現するための部分をまとめたものです。
さらに、ユーザー情報やブログ記事などのたくさんのデータを管理するためのデータベースをつくります。

###アプリケーションで機能をつくる

アプリケーションのディレクトリをつくり、Djangoプロジェクトに登録します。
さらに、アプリケーション内にテンプレート（HTMLファイル）を配置し、HTMLファイルを表示させるためにViewをつくります。
このViewというものによって、ユーザーからのリクエストをもとに、HTMLファイルを返します。
それから、ユーザーがURLを打ち込んだ時に、HTMLファイルがブラウザに表示されるようURLの設定を行います。

###ブログモデルをつくる

ブログモデルという設計図をつくり、マイグレートという作業によって、データベースの設計図をデータベースに反映します。
続いて管理者のみが使えるAdminページをつくります。
あとは、トップページを表示させたり、記事の詳細をつくったりすれば完成です！


#まとめ

今回は、Djangoの特徴と簡単なブログ管理サイトの作り方について書きました。
最後までつくり上げると達成感があるのでぜひ挑戦してみてください。