Quantcast
Channel: 初心者タグが付けられた新着記事 - Qiita
Viewing all 21663 articles
Browse latest View live

Moleculeに入門してみたよ

$
0
0

Moleculeってなに?

MoleculeはAnsibleロールをテストするためのツール
分子って意味らしい

pythonモジュールで実装されているので、pip install moleculeで使える
使い方もとってもかんたん、molecule test
これで、

  • プレイブックが正しい構文になっているよね、コードがある規則に基づいて記述されているよね、を確認する(lint)
  • dockerコンテナを立てて、作成したプレイブックを流す
  • ↑のコンテナにもう一度同じプレイブックを流して冪等性を確認
  • 事前に記述したテストを実行して、狙い通りの動きをしているかチェック

みたいなことをやってくれる
つまりAnsibleロールのテスト自動化ができるツール

もちろんテストの内容やmolecule test実行時の動作はカスタマイズできる

なにがうれしいのよ?

Ansibleロールは一回書いて終わりじゃなくて、何度も修正していくはず
そんな中で、何度もロールの動作が正しいことを手で確認するのは大変であることは明らか
こんなときに、Moleculeのようなテスト自動化が役に立つ

テストが自動化されていれば以下のようなうまみが得られる

  • 人間が毎回毎回手でロールの正しさを保証する必要がなくなる
  • 機械がテストをしてくれるので定義された試験項目をもれなく実施できる
    • 人間がやるとサボりが発生するのでデグレードの心配をしなければならない
    • 特にlintとか構文チェックとかって人間は毎回やらない
      • だいたい「まぁあってるやろー」→「あっ…」ってなるのがデフォなので機械的に救うのは理にかなっている

更に、ロールをGitみたいなバージョン管理ツールに入れておいて、コードに修正が入ったとき自動でテストが流れるようなパイプラインを作っておけば、コード修正時にテストを自動化するといったこともできて素敵になる

要するに、IaCをするならテストは自動化されているべきで、それをAnsibleロールにおいて実現してくれるのがMoleculeだよ、って話

Moleculeを使ってロールの開発をやってみる

ハイパー実際にMoleculeしてみようタイム

作業環境

品目バージョン
OSmacOS Catalina 10.15.2
シェルfish, version 3.0.2
Python3.8.0
Ansible2.9.2
Molecule2.22
Docker Desktopcommunity 2.1.0.5 (40693)
Docker Engine19.03.5

インストール

  • Docker Desktopを入れておく
  • 適当な作業ディレクトリにcdしておく
  • pythonの仮想環境を作ってアクティベート
    • 私はfishシェルを使っているので、bashやzshの方はsourceの部分を適当に読み替えて下さい
$python -m venv .venv
$source .venv/bin/activate.fish
  • Moleculeをインストールする
$pip install molecule
  • ロール置き場を作って移動
$mkdir roles
$cd roles

molecule initでロールの雛形を作成する

  • 今回はAnisbleもくもく会の教材になっている、httpdを構築するロールを題材にする
  • ので、ロール名はapache_vhostとして、Moleculeに用意されているロール雛形生成コマンドを実行する
    • molecule init role -r <ロール名>
$molecule init role -r apache_vhost
-->Initializing new role apache_vhost...
Initialized role in /Users/answer_d/repos/molecule_test/roles/apache_vhost successfully.
$cd apache_vhost
  • こんなかんじのディレクトリが生成される
apache_vhost
├── README.md
├── defaults
│   └── main.yml
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── molecule
│   └── default
│       ├── Dockerfile.j2
│       ├── INSTALL.rst
│       ├── molecule.yml
│       ├── playbook.yml
│       └── tests
│           ├── __pycache__
│           │   └── test_default.cpython-38.pyc
│           └── test_default.py
├── tasks
│   └── main.yml
└── vars
    └── main.yml

※ この時点ではmain.ymlの中身は空

molecule/ディレクトリに、Molecule関連ファイルが入っているので覗いてみる

molecule
└── default
    ├── Dockerfile.j2
    ├── INSTALL.rst
    ├── molecule.yml
    ├── playbook.yml
    └── tests
        ├── __pycache__
        │   └── test_default.cpython-38.pyc
        └── test_default.py
  • default/ディレクトリ
  • これはMoleculeにおいて「シナリオ」と呼ばれる、ロールのテストスイートを示す

    • デフォルトではdefaultディレクトリが作成されるが、別の名前をつけることもできる
      • default以外のシナリオを実行する場合は、molecule testコマンドの実行時に明示的にシナリオ名を記述したりする必要がある
  • Dockerfile.j2

    • Moleculeはこのファイルを使用して、ロールをテストするためのdockerイメージを作成する
    • テスト環境を生成する仕組みをMoleculeでは「ドライバ」と呼び、デフォルトはDockerであるため、このファイルが自動生成される
      • ちなみにDocker以外には、VagrantやEC2、Azureなどが選択できる
  # Molecule managed

  {%ifitem.registryisdefined%}
  FROM {{item.registry.url}}/{{item.image}}{%else%}
  FROM {{item.image}}{%endif%}{%ifitem.envisdefined%}{%forvar,valueinitem.env.items()%}{%ifvalue%}
  ENV {{var}}{{value}}{%endif%}{%endfor%}{%endif%}

  RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates iproute2 && apt-get clean; \
      elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash iproute && dnf clean all; \
      elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash iproute && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
      elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml iproute2 && zypper clean -a; \
      elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
      elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates iproute2 && xbps-remove -O; fi
  • INSTALL.rst

    • Moleculeがドライバと正常に接続できるようにするために必要なセットアップ手順が書いてある説明書
    • ただの説明書なのでなくても良い
  • molecule.yml

    • Moleculeがロールをテストするときの動作を構成したりするための設定ファイル
    • 例えばドライバをDockerから別のものに変更したい場合はこのファイルを書き換えることになる
---dependency:name:galaxydriver:name:dockerlint:name:yamllintplatforms:-name:instanceimage:centos:7provisioner:name:ansiblelint:name:ansible-lintverifier:name:testinfralint:name:flake8
  • playbook.yml
    • ロールを呼び出すプレイブック
    • Moleculeはこのプレイブックをansible-playbookで呼び出し、ドライバによって作成されたインスタンスに対して実行する
---- name:Convergehosts:allroles:-role:apache_vhost
  • test/
    • テストコードを配置するディレクトリ
    • テストツールに何を使用するかは「Verifier」の指定により変更できるが、デフォルトではtestinfraであるためこのディレクトリが生成される
    • Verifierはtestinfraのほか、Ansibleなどが選択できる
      • AnsibleをVerifierとする場合はこのディレクトリは不要で、代わりにverify.ymlを作成する必要がある

ロールを実装する

上述の教材を信頼し、何も考えず以下のように実装する、moleculeディレクトリはまだ触らない
いらんディレクトリは消しておく(meta/とか)

.
├── files
│   └── index.html
├── handlers
│   └── main.yml
├── tasks
│   └── main.yml
└── templates
    └── vhost.conf.j2
files/index.html
simple vhost index
handlers/main.yml
---# handlers file for roles/apache_vhost-name:restart_httpdservice:name:httpdstate:restarted
tasks/main.yml
----name:install httpdyum:name:httpdstate:present-name:start and enable httpd serviceservice:name:httpdstate:startedenabled:true-name:ensure vhost directory is presentfile:path:"/var/www/vhosts/{{ansible_hostname}}"state:directory-name:deliver html contentcopy:src:index.htmldest:"/var/www/vhosts/{{ansible_hostname}}"-name:template vhost filetemplate:src:vhost.conf.j2dest:/etc/httpd/conf.d/vhost.confowner:rootgroup:rootmode:0644notify:-restart_httpd
templates/vhost.conf.j2
# {{ansible_managed}}
Listen 8080
<VirtualHost*:8080>
    ServerAdmin webmaster@{{ansible_fqdn}}
    ServerName {{ansible_fqdn}}
    ErrorLog logs/{{ansible_hostname}}-error.log
    CustomLog logs/{{ansible_hostname}}-common.log common
    DocumentRoot /var/www/vhosts/{{ansible_hostname}}/

    <Directory/var/www/vhosts/{{ansible_hostname}}/>
  Options +Indexes +FollowSymlinks +Includes
  Order allow,deny
  Allow from all
    </Directory></VirtualHost>

テストを実装する

  • 想定するテストケースは以下とする(ちょっと冗長かもだけどあまり気にしない)

    • ポート8080番がオープンである
    • httpdサービスが起動しており、自動起動がオンである
    • index.htmlが取得できる(= ステータスコード200が返ってくる)
  • これを実現するtestinfraのコードとして以下を実装

    • テストケースごとに関数作ってassert文を並べるだけなので、python知らない人でも結構書きやすいはず
molecule/default/tests/test_default.py
importosimporttestinfra.utils.ansible_runnertestinfra_hosts=testinfra.utils.ansible_runner.AnsibleRunner(os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')deftest_port_open(host):local=host.addr("localhost")assertlocal.port(8080).is_reachabledeftest_httpd_enabled_n_started(host):httpd_svc=host.service("httpd")asserthttpd_svc.is_runningasserthttpd_svc.is_enableddeftest_index(host):index=host.run("curl -LI http://localhost:8080 -s")assertindex.rc==0assert"200 OK"inindex.stdout.split("\r\n")[0]
  • プレイブックでserviceモジュールを使っている = Dockerコンテナでsystemctlを触る必要があるため、コンテナの設定を変える
molecule/default/molecule.yml
---dependency:name:galaxydriver:name:dockerlint:name:yamllintplatforms:-name:instanceimage:centos:7privileged:truecommand:/sbin/initprovisioner:name:ansiblelint:name:ansible-lintverifier:name:testinfralint:name:flake8
  • Dockerfile.j2playbook.ymlはそのままでOK

Dockerドライバを使用するため、pipでdockerをインストールする

$pip install docker

Docker Desktopだけじゃ動かなかった (なんで?)

テストを実行する

$molecule test

これでテストが実行される
実行結果を上から見ていくと…

-->Test matrix
└── default
    ├── lint
    ├── dependency
    ├── cleanup
    ├── destroy
    ├── syntax
    ├── create
    ├── prepare
    ├── converge
    ├── idempotence
    ├── side_effect
    ├── verify
    ├── cleanup
    └── destroy

defaultシナリオが実行されていて、こんな感じのステップで構成されてるよー的なやつ

lint

-->Action: 'lint'-->Executing Yamllint on files found in /Users/answer_d/repos/molecule_test/roles/apache_vhost/...
Lint completed successfully.
-->Executing Flake8 on files found in /Users/answer_d/repos/molecule_test/roles/apache_vhost/molecule/default/tests/...
Lint completed successfully.
-->Executing Ansible Lint on /Users/answer_d/repos/molecule_test/roles/apache_vhost/molecule/default/playbook.yml...
Lint completed successfully.

以下の3つのlintが実行されている

  • 作成したロールapache_vhostに対するYamllint
  • testinfraで実装したテストコードに対するFlake8
    • Flake8はpythonのlinter
  • playbook.ymlに対するAnsible Lint

create

-->Action: 'create'
    PLAY [Create] ******************************************************************

    TASK [Log into a Docker registry] **********************************************
    skipping: [localhost] =>(item=None)
    TASK [Create Dockerfiles from image names] *************************************
    changed: [localhost] =>(item=None)    changed: [localhost]

    TASK [Determine which docker image info module to use] *************************
    ok: [localhost]

    TASK [Discover local Docker images] ********************************************
    ok: [localhost] =>(item=None)    ok: [localhost]

    TASK [Build an Ansible compatible image (new)] *********************************
    ok: [localhost] =>(item=molecule_local/centos:7)
    TASK [Build an Ansible compatible image (old)] *********************************
    skipping: [localhost] =>(item=molecule_local/centos:7)
    TASK [Create docker network(s)] ************************************************

    TASK [Determine the CMD directives] ********************************************
    ok: [localhost] =>(item=None)    ok: [localhost]

    TASK [Create molecule instance(s)] *********************************************
    changed: [localhost] =>(item=instance)
    TASK [Wait for instance(s) creation to complete] *******************************
    FAILED - RETRYING: Wait for instance(s) creation to complete (300 retries left).
    changed: [localhost] =>(item=None)    changed: [localhost]

    PLAY RECAP *********************************************************************
    localhost                  : ok=7    changed=3    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0

Dockerfileからイメージを作って、Dockerコンテナを作成している
Moleculeが内部的に持つプレイブックで実行されていることがわかる

converge

-->Action: 'converge'
    PLAY [Converge] ****************************************************************

    TASK [Gathering Facts] *********************************************************
    ok: [instance]

    TASK [apache_vhost : install httpd] ********************************************
    changed: [instance]

    TASK [apache_vhost : start and enable httpd service] ***************************
    changed: [instance]

    TASK [apache_vhost : ensure vhost directory is present] ************************
    changed: [instance]

    TASK [apache_vhost : deliver html content] *************************************
    changed: [instance]

    TASK [apache_vhost : template vhost file] **************************************
    changed: [instance]

    RUNNING HANDLER [apache_vhost : restart_httpd] *********************************
    changed: [instance]

    PLAY RECAP *********************************************************************
    instance                   : ok=7    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

自分が作ったロールを先程作成したインスタンスに対して実行している

idempotence

-->Action: 'idempotence'Idempotence completed successfully.

結果からは見えにくいが、ここで冪等性の確認を行っている(idempotenceは「冪等性」という意味)
convergeで実行したプレイブックをもう一度実行し、changedステータスが返らないことを検証しているらしい

verify

-->Action: 'verify'-->Executing Testinfra tests found in /Users/answer_d/repos/molecule_test/roles/apache_vhost/molecule/default/tests/...
    ============================= test session starts ==============================
    platform darwin -- Python 3.8.0, pytest-5.3.2, py-1.8.1, pluggy-0.13.1
    rootdir: /Users/answer_d/repos/molecule_test/roles/apache_vhost/molecule/default
    plugins: testinfra-3.4.0
collected 3 items                                                            

    tests/test_default.py ...                                                [100%]

    ============================== 3 passed in 2.64s ===============================
Verifier completed successfully.

testinfraコードをインスタンス上で実行する
3件テストし、全てパスしていることが確認できる

destroy

-->Action: 'destroy'
    PLAY [Destroy] *****************************************************************

    TASK [Destroy molecule instance(s)] ********************************************
    changed: [localhost] =>(item=instance)
    TASK [Wait for instance(s) deletion to complete] *******************************
    FAILED - RETRYING: Wait for instance(s) deletion to complete (300 retries left).
    changed: [localhost] =>(item=None)    changed: [localhost]

    TASK [Delete docker network(s)] ************************************************

    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

-->Pruning extra files from scenario ephemeral directory

テストに使用したインスタンスを削除する

できた

これでわたしもMoleculer

今回は一発で成功する例を示しましたが、プレイブックに意図的に変な空白を入れてみたり、プレイブックやテストコードの処理内容を変えてみたりすることでエラーが検出できることを確認できます、興味があればやってみて下さい

おまけ

  • molecule testで実行される一部のステップだけ取り出して実行することもできる
    • molecule create: dependency, create, prepare
      • インスタンスが作成されるとこまで
    • molecule converge: dependency, create, prepare, converge
      • create+Playbookの実行まで
    • molecule destroy: dependency, cleanup, destroy
      • インスタンスの削除
  • なのでテスト自動化前提でなくて、ロールを作るだけでも結構うれしい、Dockerコンテナ上げて動作テストしながらーって手でやるとまぁまぁ手間だけど、Moleculeならいい感じにしてくれていい感じ(語彙力)

    • 作ったコンテナにログインしてくれるmolecule loginとかもある(vagrant sshみたいな感じで使える)
    • サーバの状態確認するときラクラクの楽になって便利
  • VerifierはAnsibleにすることもできる

    • testinfraだとpythonコードになってしまうので、プログラムかけないインフラマンはAnsibleをVerifierにするととっつきやすい
      • といってもtestinfraだけだったらpythonでも十分書きやすいと思われるのでぶっちゃけどっちでも良いと思う、好みとテストでやりたいこと次第で決めれば良い
    • AnsibleをVerifierにした場合でも、テスト用モジュールはちゃんとある
      • ポートチェックとかどうやるの?って思ったらwait_forモジュールとかあった、さすがです

ちなみにAnsibleをVerifierにする場合、今回作成したtestinfraと同様のテストを行うプレイブックは以下のようになる
このファイルを用意して、molecule/default/molecule.ymlでVerifierにAnsibleを使用する旨を記載するとAnsibleでテストするようになるので気になる人は試してみてクレメンス

molecule/default/verify.yml
----name:Verifyhosts:allgather_facts:falsepre_tasks:-name:get httpd statusservice_facts:-name:get index.htmluri:url:http://localhost:8080method:GETregister:responsetasks:-name:test port 8080 openwait_for:port:8080timeout:5-name:test http enabled and startedassert:that:-ansible_facts.services['httpd.service'].state == "running"-ansible_facts.services['httpd.service'].status == "enabled"-name:test httpd returns status 200 and has contentassert:that:-response.status == 200-response.content is not none

Mac Vagrant の起動 接続 終了

$
0
0

目的

  • Vagrantの基本をまとめる

起動

  • Macのterminalを用いて下記コマンドを実行する。

    $vagrant up
    

接続

  • MacのterminalからVagrantを用いて仮想マシンに接続する。
  • 下記コマンドを実行して接続を行う。

    $vagrant ssh
    

終了

  • $ vagrant ssh実行後、仮想マシンから出て、VirtualBoxを終了する。
  • 下記コマンドを実行して終了する。

    [vagrant@localhost]$exit$vagtrant suspend

React NativeでError: Activity class {APP_NAME/APP_NAME.MainAtivity} does not exist となる

$
0
0

react-nativeでandroidのアプリを作っている際に、普段は通る

react-native run-android

が通らなくなったのでその対処法メモです.

現象

普段から実機のandroid端末を使ってテストしているのですが、
実機上でビルドされたアプリをアンインストールした後にリビルドしたところ、
以下のエラーを吐くようになりました.

Error: Activity class {APP_NAME/APP_NAME.MainAtivity} does not exist.

解決法

あくまで自分の場合はですが、以下のコマンドで完全に実機上からアプリをアンインストールすることで解決しました.

adb uninstall com.APP_NAME

想定原因

今回、アプリのアンインストールがトリガーになったのですが、androidのシステム上でアンインストールを行っても、どうやら何かしらのデータは実機上に残るっぽいです(少なくとも今回の端末ではそのようです).

詳細は追っていないので正しいかどうかはわかりませんが、該当コマンドでは必要な部分のみのリビルドを行うために、中途半端に削除されたデータのせいで当エラーが発生したのではないかと思っています.

プログラミング初心者です、よろしくお願いします

$
0
0

今日からプログラミングで学習したこと+他色々投稿していく

今日からプログラミングで学習したことを淡々と投稿していきたいと思います。

気が向けば、他のことも書くかもしれません...

ひとまずデータベースとSQL、データベース設計を学びました。

ゲームをイメージしながらデータベースの内容を理解していきたい...と思いますが、

正直実際に使って覚えていけたら良いと思ってるので、

取り急ぎさらっと流す感じで今はやっていこうかと思います。

まずは定期的なアウトプットが継続できるよう頑張っていきたいです。

Siri に Slackbot が投稿した AWS 請求額を読み上げる仕事をさせる

$
0
0

はじめに

iPhone を使い始めて10年弱、 Siri が全く働いていないことに気付きました。
スマートスピーカーが流行っている昨今、自分の Siri にももっと活躍して欲しいので Slackbot が投稿した AWS 請求額を読み上げてもらうことにしました。

結果から見せるとこんな感じです。
料金を聞くと...
スクリーンショット 2020-01-14 22.12.01.png

Slackに投稿した内容を読み上げてくれました。
スクリーンショット 2020-01-14 22.12.21.png
では、作り方諸々を紹介していきます。

構成

構成はこんな感じになります。
アーキテクチャ.png

それぞれの役割を紹介していきます。

  • Siri
    • 音声呼び出しによるショートカットアプリの実行
    • Slack に投稿された AWS 請求額の読み上げ
  • ショートカットアプリ
    • SlackAPI を使用して投稿
    • SlackAPI を使用して最新の投稿を JSON で取得
    • 取得された JSON 情報から必要な内容を抽出
  • Slackbot
    • Lambda の呼び出し
  • Lambda
    • AWS 請求額の取得

処理内容

今回はショートカットアプリに重点を置いて説明していきます。
Lambda と Slackbot についてはそれぞれ以下の記事にて詳細を記載しているので参照してください。
Lambda:(Python)AWSの請求金額を取得する
Slackbot:echobotを作成し、Slackに通知する

それでは、ショートカットを作成していきます。
まず、ショートカット名を決めます。
Siri にショートカット名を呼びかけると登録しているショートカットを実行してくれます。
なので今回は『今月の料金は』というショートカット名にします。
(『AWSの料金は』としたかったのですが Siri が AWS の部分を理解してくれませんでした...)

続いて、各処理で使用する変数を定義していきます。

  • token:SlackAPI で使用する token (今回は Legacy tokens を使用しています。)
  • channel_nm:SlackAPI で投稿するチャンネル名
  • channel_id:SlackAPI で最新の投稿を取得する対象のチャンネルID
  • text:Slack に投稿する文章

変数が設定できたら、 Slack 投稿用 API の URL を作成し、実行します。
1.png
2.png
API を実行すると、 AWS 請求額取得 Lambda が実行されます。結果がSlackに投稿されるまで時間がかかるので待機させます。
3.png
待機後、 Slack の最新投稿取得APIを実行していきます。
投稿用 API の時と同様に URL を作成し、APIを実行します。
4.png
5.png
最新投稿取得 API を実行すると以下のような JSON が返却されます。

{"messages":
    [{
        "bot_id":"XXXXXXXX",
        "ts":"1579095866.000200",
        "attachments":
        [{
            "color":"36a64f",
            "id":1,
            "fallback":" ・AWS Cost Explorer: 1.04 USD\n ・Tax: 0.10 USD",
            "pretext":"01月01日から01月14日の請求額は、1.14 USDです。",
            "text":" ・AWS Cost Explorer: 1.04 USD\n ・Tax: 0.10 USD"
        }],
        "type":"message",
        "subtype":"bot_message",
        "text":""
    }],
    "has_more":true,
    "ok":true,
    "channel_actions_ts":null,
    "channel_actions_count":0}

ここから pretext の値を変数に追加していきます。
6.png
7.png
8.png
9.png
10.png
11.png
これで Siri に読み上げてもらう内容が取得できました。
最後に読み上げる文章をテキストに起こし、読み上げのアクションを設定します。
12.png
完成です。
Siri に向かって『 Hey Siri! 』と話しかけましょう!

おわりに

これで Siri が一つ仕事を覚えてくれました。
この構成を使えばもっといろいろな事ができると思います。
今回は Slack + Lambda をショートカットアプリから呼び出しましたが、 アプリの Pythonista3 から Python を実行しても面白い事ができると思います。

[Vue.js] ケバブケースとかキャメルケースとかパスカルケースとか

$
0
0

Vueでのケースの書き方って場所によって何がいいか若干悩みますよね。(私だけ?)
なので、まとめてみました。

そもそも○○○ケースって?(復習)

一言で言うと「クラス名や変数名等の名前の付け方の総称」
覚えておくべきケースをざっと説明すると。。

ケバブケース

文字と文字の区切りを-で表現するやり方。「チェインケース」とも言う。
ケバブのお肉をぶっさしている感じからきているとか。:meat_on_bone:

this-case-is-god

キャメルケース

文字と文字の区切りを大文字で表現するやり方。
よく見るやつです。ラクダのこぶですね。:camel:

thisCaseIsGod

パスカルケース

文字と文字の区切りを大文字で表現+先頭の文字も大文字にする。
それもそのはず、「アッパーキャメルケース」とも呼ばれるのだから。
これもよく見ますね。

ThisCaseIsGod

どこにどのケースを書くべきか?

基本的に下記の方針でOK

  • コンポーネントは「パスカルケース」
  • JavaScriptでは「キャメルケース」
  • HTMLでは「ケバブケース」

記述に迷う主な例を挙げたいと思います。

コンポーネントは「パスカルケース」

<template><MyComponent></MyComponent></template>

因みに、componentsに指定する際にパスカルケースであれば、ケバブケースでも記述できるが
ケバブケースで指定するとケバブケースでしか動かない。

<template><MyComponent></MyComponent><!-- OK --><my-component></my-component><!-- OK --><MyComponent2></MyComponent2><!-- NG --><my-component2></my-component2><!-- OK --></template><script>exportdefault{components:{MyComponent,'my-component2':MyComponent2,}}</script>

props 属性は「ケバブケース」 その他は「キャメルケース」

<template><MyComponent:my-data="hoge"></MyComponent></template><script>exportdefault{props:['myData'],}</script>

emitは「ケバブケース」

JavaScript内だが文字列として定義しているだけで、
カスタムイベント名として使われるためケバブケース推奨

<script>exportdefault{methods:{hogeFunc(){this.$emit('my-emit')}}}</script>

最後に

書き終わった後に気づいたのですが、とても分かりやすい記事がありました。
参考にさせていただきます。
https://qiita.com/ngron/items/ab2a17ae483c95a2f15e

Could not find matching close tag for "

$
0
0

node.jsのエラーコード

Could not find matching close tag for "<%="

意味 “<%=“. に合うタグが見つかりませんでした。

Dataikuでプラグインを利用する

$
0
0

はじめに

Dataiku Data Science Studio(DSS)とは、Dataiku社が提供するデータ分析ツールです。
Dataiku DSSをVirtual Boxを使って利用する方法では、Dataiku DSSのインストール方法を紹介しました。
ここでは、Dataiku社から提供されているプラグインをインストールする方法を紹介します。

Dataikuプラグインとは

Dataikuプラグインを用いると、Dataiku DSSに新たな機能をアドオンすることができます。
Dataiku社のPluginsサイトでさまざまな機能のプラグインが提供されています。
また、自分で独自の機能を持つプラグインを作ることもできます。例えば、他の人と共有したい機能があれば、プラグインを作って提供することができます。
プラグインの作り方はこちらを参照してください。

Dataikeプラグインを利用する

Dataikuプラグインを利用するには、プラグインをインストールする必要があります。ここでは、試しに、Reverse Geocoding/Admin mapsをインストールします。
Reverse Geocoding/Admin mapsは、逆ジオコーディングの機能を提供します。例えば、IPアドレスから都市の情報を導出したりすることができます。
image.png

インストール手順

Reverse Geocoding/Admin mapsをインストールするには次の手順で行います。

  1. Dataiku DSSにログイン後、画面右上にあるAppsアイコン(キューブの形)をクリックして、[Plugins]メニューをクリックします。 image.png
  2. 画面左上にある検索で「Reverse Geocoding」を入力すると、画面右側に「Reverse geocoding」のプラグインが表示されます。この「Reverse geocoding」の[INSTALL]リンクをクリックします。「Install Reverse geocoding」のメッセージが表示されるので[CONFIRM INSTALL]ボタンをクリックします。インストールが開始されます。 image.png
  3. インストールが完了すると、次のメッセージが表示されます。[RESTART DSS]ボタンをクリックして、Dataiku DSSを再起動します。 image.png
  4. 再起動が終わると、Reverse Geocoding/Admin mapsの機能を利用することができます。Reverse Geocoding/Admin mapsの利用の仕方はこちらを参照してください。 image.png

おわりに

Dataikuプラグインを利用すると、新しいデータ項目の追加や、時系列分析など便利な機能を利用することができます。また、独自のデータ分析処理をプラグインとして作成すると、他の方に共有することもできます。
よろしければ活用してみてください。


大学で演劇を学んでいた新入社員がUiPathのハンズオン講師をした話

$
0
0

はじめに

はじめまして。
19卒、ぎりぎり新入社員のさくももです。

表題の通り文系出身の私が、なぜIT業界に就職したのかはまたの機会に。
RPAのチームに配属されて一から勉強していたところ、初めてのお仕事がハンズオンの講師だった話をまとめてみました。
(お仕事、と言っていいのかわかりませんが、初めて任せて頂けたこと)
大学で学んできた演劇の知識や技術が生かせる場面が多かったことに自分でも驚きました。
稚拙ながら文章に残してみようと思います。

依頼は突然に

あ~の~日、あ~の~時、あ~の場所で、き~み~に会えてなかったら~♪

いきなりIT業界に飛び込んだ私が配属されたのはRPAのチームでした。
RPAという言葉も知らなかったし、ロボ、と聞けばガションガション動くものを想像しちゃいます。
一から勉強で、とにかく作って慣れる、そんな毎日が始まりました。
ひたすらUiPathの勉強、ロボを作ってみる、新人課題に挑戦する、RPAを中心に色んなIT業界のイベントに参加するなど、プロジェクトに関わることはまだなくても色んなことに何だかんだ挑戦しながら半年が過ぎました。

そんな折、上司から一通のメールがあったのです。
なんだろう、と開いてみると「内定者向けのハンズオン講師のお願い」という言葉。
——なんと!
案件にアサインされることもなく淡々と勉強に勤しんでいた私に急に舞い込んだ初仕事、ハンズオン講師。
できるかしら、と少し不安も覚えましたが正直やっと自分に任せてもらえることが出来たのでわくわくしていました。

概要

ざっと以下のような依頼内容でした。

 テーマ:RPAハンズオン
  対象:内定者(RPA未経験/IT未経験者たち)
 ツール:UiPath
所要時間:2時間程
  目的:DX領域におけるRPAを体験してもらい、自社の重点事業を知ってもらう

特に今回大事にしたいのは「体験」というところでした。
新入社員として最も内定者に近い感覚を生かし、内容や説明を考えて講師をしてほしいという話でした。
確かに内定者の時の研修もよく覚えていたので、その記憶をもとにハンズオンを考えることになったのです。

注意したこと

ハンズオンをやるに当たって話し方や立ち居振る舞いに関しては特に注意しました。
私の専攻していた「演出」の仕事の半分は「人にものを伝える」ことだと言っても過言ではありません。
戯曲から得た解釈やイメージを役者やスタッフに伝える、作りたいものを実現させていく…とにかく言葉を必要とされます。
そんな中で、話す内容だけではなく「伝え方」も非常に大事なことを学びました。
以下、演劇を通して学んだこと、加えてこの1年で感じたことをもとにハンズオンで注意してみた内容です。
ご参考までに!

①鏡の法則

「話し手が緊張していれば聞き手にもその緊張が伝わる。
緊張していても息をつめず、吐くことが出来ていれば聞き手も息を抜くことが出来る。」

緊張状態の人間は息が浅く、詰めてしまいます。それを見ている人間は不思議なことに同じような状態に陥るのです。
和やかな空気を作りたい、笑わせたいときには緊張状態とは逆で息を吐かせることが大事になります。
そのためには話し手である自分もリラックスして息を吐いていなければいけません。
「緊張している」と素直に伝えてしまうのもいいかもしれないです。

②話をさせる

「人が楽しいと感じるのは聞いているときより話しているとき。」

これは演劇というよりビジネスシーンでもよく聞く話かもしれませんが、人間の心理を利用する演劇でもいえることでした。
ハンズオンという場では受講者は話を聞く立場です。
そのため「眠くなる」「つまらなくなる」、ましてや初めて聞く難しい言葉だらけなら尚更、
「楽しい」とはかけ離れていることを前提にしなければいけないでしょう。
面接などでも応用できるのですが、一方的に話すより、コミュニケーションをとる対話のつもりでいる方が相手に好印象を残せます。
特に面接官は一日の間に何十人と見なければいけなかったりするので、疲労もたまります。
「話す」という行為にも「息を抜く」効果があります。
ハンズオンという場で受講者たちに話をさせるのも難しいと思いますが、似たことが出来ればいいのかもしれません。
・隣同士で確認し合うことをOKとする
・フォローの先輩方や講師に聞きやすい場を作る
・たまに話を振ってみる
などが考えられるでしょうか。

③基本の話し方

立ち居振る舞い、気持ちが整っていても内容が伝わらなかったら本末転倒になってしまいます。
プロの役者ほど発声練習は怠らないものです。そこまでする必要はありませんが、心がけは大事にしたいところです。

・活舌
 内容を伝えるために何より大事なことかもしれません。
 「あ」「い」「う」「え」「お」、母音はそれぞれ発声するときの口や喉の開き方、形が違います。
 子音と母音で成り立っている日本語では主にこの母音の意識をしながら話すと伝わりやすいです。

・話すスピード
 早すぎず遅すぎず。
 早すぎれば聞き取れない可能性がありますが、長く話す必要のない内容は気持ち早めていいかもしれません。
 遅すぎれば眠くなってしまったり飽きてしまう可能性がありますが、普段喋っているときより気持ち遅い方がちょうどいいかもしれません。

・声の大きさ
 声の大きさは部屋の大きさに合わせて調整します。
 個人的には自分から最も遠い人に話しかけるくらいの声の大きさを意識すると話しやすいです。

・声のトーン、身振り手振り
 これは上記の3つに対してプラスαになります。
 トーンを使い分けることで「ポイント」を抑えたり、眠くならないように面白く話せたりします。
 身振り手振りは声のトーンに対して視覚的な補助になります。

・目線
 身振り手振りの延長になりますが、目線にも注意が必要です。
 前に立つ以上、人の視線からは逃れられません。むしろ、見られていることを意識する方がいいかもしれません。
 見られていることから逃げるのではなく、
 ちゃんとコミュニケーションをとる意思があることを示すためにも相手を見て話すことは重要です。

④資料作成

「必要最低限に、しかし丁寧に」

個人的に、内定者から新入社員にかけて特に苦労したのがITの専門用語。
使っている人によっては略語を使っていたり、IT関係者同士のニュアンスの専門用語だったりが掴めず話を聞くのが難しかったのです。
そのため、なるべく専門用語は使わず、「説明」は最小限に「手順」をしっかり丁寧に書くことを心がけました。
同じ作業を繰り返すシーンでも「慣れるだろう」と思わずになるべく省略して書かないように、
ぱっと見てわかるように文字よりも画像を多用しました。

いざ、本番!

さて、ITの知識面では内定者とあまり変わらない、RPAに特化した新入社員がハンズオン講師をすることになりました。
内定者の中には私のようなIT初心者もいれば、専門的にプログラミングをしてきた人もいます。
―――大丈夫か、私!?
元来、石橋を叩きすぎるような性格なので準備は徹底していました。
それこそ台本を書く如く、話したい内容を何度も想定して書き込み、声を出してちょっと話す練習もしたり。
メイン講師として「話す」私だけではなく、詰まった受講生を「サポート」してくれる先輩方がついてくれることが何より心強い事でした。
私はとにかく全体の流れを考えて滞りなく進めるのみ!いざ行かん。

当日の内容

1.RPAとは(15分座学)
2.自社のRPA事業(15分座学)
3.ハンズオン(2時間半程)←担当
4.その他人事系の話(30分)

ハンズオンの内容

今回、内定者向けに考えた内容は以下の通り!
1.UiPathいろいろ(Studio、Robot、Orchestrator、Academy等)
2.UiPath Studio 基本操作(画面の説明、作成する、保存する等)
3.演習①【webサイトからのデータスクレイピング】
4.演習②【アプリケーションへのデータ登録】
演習①では基本をおさえるために地道に手作り、データスクレイピングなどの機能を使ってみる。
演習②では①とは違いこんな方法もあるよと示す、レコーディングや繰り返しなどの機能を活用。

リハーサルで先輩方に試していただいた際は演習①に約1時間、演習②に約30分かかり、
30分程の余裕をもってこのくらいのボリュームでいこうと決めました。

よーいドン

昨年自分が内定者だった時のことを思い出すと最初に緊張をほぐせるかどうかが大事だと感じていました。
「内定者」という立場的に、正直かなり猫も被るし真面目な姿勢をとります。
同時に普段から授業を受けている「学生」でもあるのです。
学生時代、周りを見ていても非常にわかりやすかったのですが、大抵の人は「どんな姿勢で受ける授業か」を使い分けています。
この先生は、この授業は、と各々が判断しています。
しん、としている授業もあれば、にぎやかな授業もありますよね。
先生の雰囲気や話し方が、その授業での生徒の姿勢を決めている気がします。

今回はハンズオンなので遅れないように「集中しつつ」体験重視のため「リラックスしてほしい」と考えていました。
そのため自分も同じように「集中しつつリラックスする」態度で臨むことが大事です。
――が、緊張した!
どんなに準備しても、意気込んで臨んでも緊張するものは緊張するのです!
ちょっと変なことを口走ってしまったり、準備したにもかかわらず説明をとばしてしまったり。

天の声

そんなとき、本当に有難かった救いの手。
フォローに入って下さったり、自らハンズオンに参加してくれていた先輩方。
変なことを口走れば笑ってくれる、ツッコミをいれてくれる、説明の補助をしてくれる、、、
そんなリラックスした雰囲気が内定者のみんなにもいい影響を与えてくれました。

大きな失敗もなく受講者の全員がロボを無事に完成、きちんと時間内に演習①②共に成功させることが出来たのです。

振り返り

兎にも角にも初めてのハンズオン講師を完遂しました。
後日、フォローで入って下さった先輩方と反省会も行い、下記のような振り返りに至りました。

環境

・UiPathのインストール
 :色々あって手作業で一台一台行ったためちょっと大変でした。
  多方面とのホウレンソウ大事。
・資料
 :今回は資料を印刷して内定者に配りたいと依頼されていました。
  カラー印刷のつもりで作っていましたが、当日白黒印刷だったことが判明。
  ホウレンソウ大事。
・受講者の名簿
 :人事の方が講師用に用意してくださっていたもの。
  特に面識はあるけど名前覚えてない人も多かったので非常に助かりました。
  途中、指名して確認したりコミュニケーションがとれました。
・ホワイトボード
 :口頭では説明が難しいけど資料にも書いてないようなことを説明するのに重宝しました。
  先輩が補足してくださった図に書き加えたり、便利でした!

内容

・スキル感の確認
 :今回いきなりハンズオンに入ってしまったので前置きがあった方がよかったことが反省点。
  例えば「RPA知ってる?聞いたことはある?」や「触ったことがある人」のようにスキル感の確認をしてもいいかもしれません。
  これにより、フォロー側も講師側も気を配らなきゃいけない人がわかります。
・「アクティビティ」は肝
 :すぐに作り始めてしまいましたが、その前に「アクティビティ」の概念をわかってもらうのが大事でした。
  「一つ一つの命令だよ」「これを組み立てていくんだよ」等。
・受講者に合わせたストーリー
 :「RPAはホワイトカラーなどの仕事を効率化できるよ」なんて言っても大学生にはピンときません。
  大学生が普段触れそうな実感のある例え話「申込書って書いたことあるはず、そのあとどうなると思う?」など。
・前後しない作り
 :最後に余分なシーケンスを整理する手順を入れていましたが、これに混乱して大事なアクティビティを消してしまう人がいました。
  「業務ではこのままにしないけどハンズオンはここまででいいかな」などの判断があってもいいかもしれません。
  作業が前後しない作りを心がける必要があります。
・アンケート
 :最後に簡単な感想を聞いてみること。
  RPAどうだったか、楽しかったか、大変だったか等。

おわり

しっかり準備した甲斐もあり有難いことにとても好評価を頂きました。
このあと、自分の所属するグループの勉強会に振り返りを含めてハンズオンを再度展開しました。
内定者ではなく現役バリバリエンジニアの皆様だったので、質問や進み方もまた全く違ったのが面白かったです。

2回のハンズオンを通して感じたのは、勉強を続けた先のハンズオン講師というこの「体験」は私にとっても非常に大切なものになりました。
演劇の知識から入っているのは特殊かもしれませんが、半年かけて身につけた知識を展開する場として最適だと感じました。
インプットし続けた先のアウトプット、大事。
人に伝えるために、今まで得た知識を噛み砕き、改めて成形しなおすと自分にとっても復習になります。さらに自信にも繋がります。
先輩方を見ているとエンジニアにも「ヒアリングする」「伝える」コミュニケーション力が大事なんだなと日々感じます。
技術面の勉強だけでなく、社会人としてのコミュニケーション能力も身につけていきたいと思います。

最後まで読んでいただき、ありがとうございました!

【Laravel】リレーション先で検索する方法

$
0
0

Laravelでリレーション先で検索することがあったため備忘録。

例えば下記のようなモデルがあったとします。

User.php
classUserextendsModel{publicfunctionproject(){return$this->belongsTo('App\Project');}}
Project.php
classProjectextendsModel{publicfunctionorganization(){return$this->belongsTo('App\Organization');}}

※主キーはidとします。

リレーション先で検索

Userからリレーション先であるProjectのorganization_idで絞り込みたいとします。

  • whereHasを使用する場合
UserController.php
$Users=User::whereHas('project',function($query)use($request){$query->where('organization_id',$request->organization_id);})->get();
  • whereHasを使用しない場合
UserController.php
$Users=User::whereIn('project_id',function($query)use($request){$query->from('projects')->select('id')->where('organization_id',$request->organization_id);})->get();

リレーション先のリレーションで検索

Userからリレーション先であるProjectのリレーション先のOrganizationのnameで絞り込みたいとします。

  • whereHasを使用する場合
UserController.php
$Users=User::whereHas('project',function($query)use($request){$query->whereHas('organization',function($query)use($request){$query->where('name',$request->organization_name);}})->get();
  • whereHasを使用しない場合
UserController.php
$Users=User::whereIn('project_id',function($query)use($request){$query->from('projects')->select('id')->whereIn('organization_id',function($query)use($request){$query->from('organizations')->select('id')->where('name',$request->organization_name);});})->get();

他により良い方法などありましたらご教示いただけますと幸いです。

【初心者】Vue.jsでタブメニューを作ってみた

$
0
0

最近、Vue.jsを勉強しています。
練習として、タブメニューをつくってみました。

Vue.jsの導入

以下のコードでVue.jsを導入します。
HTMLファイルのbody内に記述します。
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

JavaScriptを記述する

HTMLファイルのbody内のscriptタグ内に、以下のコードを記述します。

newVue({el:'#app',data:{active:1},methods:{change:function(num){this.active=num;}}})

変数

activeという変数を用意しています。
どのタブが選択されているのかを代入します。

関数

changeという関数を用意しています。
他のタブが選択されたときに用います。
activeに、選択されたタブの番号を代入します。

HTMLを記述する

HTMLファイルのbody内に、以下のコードを記述します。

<divid="app"><ulid="tabMenu"><liv-on:click="change(1)"v-bind:class="{'active': active === 1}">タブ1</li><liv-on:click="change(2)"v-bind:class="{'active': active === 2}">タブ2</li><liv-on:click="change(3)"v-bind:class="{'active': active === 3}">タブ3</li></ul><pv-if="active === 1">コンテンツ1</p><pv-else-if="active === 2">コンテンツ2</p><pv-else-if="active === 3">コンテンツ3</p></div><script src="https://cdn.jsdelivr.net/npm/vue"></script>

v-on , v-bind , v-if , v-else-ifを使いました。

v-on

v-on:click="change(2)"は、その要素がクリックされたとき、
関数 changeに値 2を渡して処理を行います。

v-bind

v-bind:class="{'active': active === 2}"は、
active === 2が真のとき、その要素で class="active"を有効にします。

v-if, v-else-if

v-else-if="active === 2"は、
そのすぐ上に書いてある v-if="active === 1"の続きになります。
active === 1が偽で、active === 2が真のとき、実行します。

CSSを記述する

見た目を整えます。

#tabMenu{padding:0;display:flex;list-style-type:none;}#tabMenuli{width:auto;padding:10px20px;color:black;border:1pxsolidblack;background-color:white;cursor:pointer;}#tabMenuli.active{color:white;background-color:black;transition:.3s;}

ぶっちゃけ、CSSが一番難しかったです。笑
flexboxは便利なので、使いこなせるようになりたいです。

終わりに

Vue.jsのアウトプットの練習として、タブメニューを作ってみました。
割と簡単に作ることができたので、Vueってスゴいなと思いました(小並感)
引き続き、Vueの勉強をがんばります。

初学者は教材選びが大事

$
0
0

前回のあらすじ

・新人プログラマ向けの本が分かりづらすぎて学習効率が下がってた

今日やったこと

・if文とswitch文を使って、コンピューター様とじゃんけんするプログラムを作った
(今回の教科書『いちばんやさしいJavascriptの教本』)
(学習環境 エディタ→メモ帳 ブラウザ→EDGE)

困ったこと

・エラーが2箇所出て、場所の特定に難航した
特定方法→ブラウザのコンソールツールを見つつ、前後4行くらいを教本と見比べていく
・原因その1
===記号のつけ忘れ
・原因その2
教本の誤植(プラス記号の抜け落ち)
本のHPを見て判明

感想

古めの版年に出た本を使って学習すると、誤植に振り回されるなぁと思った。
ランダムに数を生成するメソッド「Math.random()」は応用が利きそうだなァと思った。
エラーがでたとき、落ち着いて対処できるようになりたいと感じた。

次回の目標

・関数について再学習しよう

PHP 変数のデータ型を出力しよう

$
0
0

目的

  • 変数のデータ型を確認する命令var_dumpを知ったので簡単にまとめる

書き方の例

  • 下記にvar_dumpの使用方法をまとめる。
var_dump($変数名);
  • 下記にプレビューイメージを記載する。
データ型(格納されている文字列の文字数) "格納されている文字列"

【swift】userDefaultsへの書き込み・読み込みを簡易化する

$
0
0

環境

xcode 11.3
swift 5.1.3
CocoaPods 1.8.4

方針

@noby111さんの記事「Swifterを自分のアプリに組み込む方法」を参考にしていた時に以下の方法がさらっと用いられていていいなと思ったので、これだけでまとめました。

AppStatusクラスを作って、クラス変数にアクセスする方法でuserDefault内のデータにアクセスできるようにする

letappData=AppStatus()//データの入力appData.username="test user"// データの出力print(appData.username)
出力
test user

実装

AppStatus.swiftファイルを新たに作成し、以下を記述

AppStatus.swift
importFoundationimportUIKitclassAppStatus{varuserdefault=UserDefaults.init(suiteName:"app_status")!// usernameの設定varusername:String?{get{ifletusername:String=userdefault["username"]{returnusername}else{returnnil}}set{userdefault["username"]=newValue}}}extensionUserDefaults{subscript<T:Any>(key:String)->T?{get{ifletvalue=object(forKey:key){returnvalueas?T}else{returnnil}}set(_newValue){ifletnewValue=_newValue{set(newValue,forKey:key)}else{removeObject(forKey:key)}synchronize()}}}

usernameの部分と型を変更すればuserDefaulに保存可能な任意のデータ型を扱うことができる。
これ便利。

userDefaultsの使い方

ちなみに、userDefaultとはなんぞや、とかどうやって使うの、とかは以下の記事が参考になりました。

qiita : swift4 超初心者向け!"UserDefaults"の使い方とか 忘備録

qiita : UserDefaultsの使い方

Goで超簡易版Twitterを作って見ました(初心者向け)

$
0
0

はじめまして

最近Goの勉強を始めたばかりで何か開発してみようと思い、簡単なアプリを開発しました。

見た目

スクリーンショット 2020-01-16 11.57.40.png

出来る事

・フォームから投稿する事が出来ます
・投稿をデータベースに保存する事が出来ます
・保存されている投稿を表示してくれます
・投稿を消す事も出来ます

はい、それだけです。
めちゃくちゃ低レベルですが、UIからサーバーにデータを送りDBへ保存、DBのデータをビューに表示するというのは全てのアプリの基本的な部分だと思いますので、これが出来るとようやくエンジニアレベル1達成です!
僕と同じようにこれからGoの勉強を始める方の少しでも役に立てればと思い記事を投稿しました。
僕も初心者ですので間違ってる部分や至らない点があるかと思いますがご了承ください。

解説

Goの導入や基礎文法やVSCodeの使い方などは解説しません、僕より詳しい人がYouTube等で動画を出していますのでそちらで勉強した方がいいと思います(あとProgateとか)
Macでの開発ですのでwindowsの方はうまく動かない可能性もあります

まずmain.goを作ります
メインディレクトリの直下でいいと思います。

スクリーンショット 2020-01-16 12.59.20.png
この画面上でF5を押すとスタートさせる事が出来ます、その後http://localhost:8080 
にアクセスすると
スクリーンショット 2020-01-16 13.01.28.png
この画面になります
これでサーバーを建てられました。
Goでは起動させると func main() が動き出します。
なのでmain関数の中に書いてあるhttp.ListenAndServe(":8080", nil)が起動するという事ですね。
8080という数字はお好みで大丈夫です、他の数字でも動きます。
ちなみにimport "net/http"も書いてあげないと動きません。
Goでは使用したい機能(パッケージ)をimportしてあげる必要があります。
ではサーバーを起動する事が出来たのでHTMLを表示させたいと思います。

メインディレクトリの下にviewsディレクトリを作成し、その中にindex.htmlを作ります
そして適当に文字を書いてみます
スクリーンショット 2020-01-16 13.18.07.png
そしてこのHTMLファイルをmain.goから呼び出す記述を書いてみます
スクリーンショット 2020-01-16 13.32.38.png

この記述後に再起動してみて、http://localhost:8080 
をリロードしてみてください
スクリーンショット 2020-01-16 13.25.22.png
このようにHTMLの文字が画面に表示されると成功です

解説

http.HandleFuncは第一引数でURLのパスを指定し、第二引数で動かしたい関数を指定します。
今回第一引数は "/" なのでルートパスがリクエストされた時にindexHandlerという関数を呼び出しているという事です。
次にindexHandlerの中身ですが、10行目でtemplate.ParseFilesにHTMLファイルを指定しその中身を tとerrという変数に代入しています。11行目で、もしtemplate.ParseFilesに渡したHTMLが存在しなければerr変数にエラーが代入されエラーを出してくれます。
この if err != nil { log.Fatalln(err) }という記述はGoではめちゃめちゃ出てきますので、とりあえずお決まりの文という認識でいいと思います。(エラーが出た時に内容を教えてくれるよーというものです)
で、HTMLが存在すればその t変数に対してExecuteメソッドを使用するとHTMLを表示する事が出来ます。
Executeに渡している引数ですが、第一引数にResponseWriterを渡しています(これもお決まり文という認識で大丈夫です)第二引数にmain.goからHTMLに渡すデータを指定してあげる事が出来ます。
今回は何も渡さないのでnilにしておきます。

とりあえずHTMLを完成させます、こんな感じにしました
スクリーンショット 2020-01-16 14.06.20.png
次にCSSファイルを作成します。
メインディレクトリの下にresourcesディレクトリを作り、さらにcssディレクトリを作ります。その中にview.cssを作ります。こんな感じです

header{height:50px;line-height:50px;border:1pxsolidlightgray;text-align:center;color:rgb(142,168,184);background-color:rgb(249,252,252);}.tweet_view{float:left;height:100vh;width:50vw;background-color:rgb(235,243,243);padding-top:20px;}.tweet_message{background-color:white;color:gray;font-size:30px;margin:020px15px;padding:10px;position:relative;border-radius:15px;}button.tweet_delete_button{background-color:rgb(130,168,238);border-style:none;height:20px;width:20px;position:absolute;right:10px;bottom:17px;color:rgb(255,255,255);line-height:5px;padding-right:18px;cursor:pointer;}button:focus{outline:0;}.tweet_form{height:100vh;width:100vw;}textarea{background-color:rgb(235,243,243);width:450px;height:250px;margin:50px00120px;}input{width:200px;height:50px;background-color:rgb(130,168,238);color:white;position:absolute;left:68vw;top:400px}

ではリロードしてみます
スクリーンショット 2020-01-16 15.17.11.png

あれ、CSSが効いてませんね。
Goでは静的ファイルを読み出す時はmain関数内で宣言をしてあげないと行けないらしいです。
ではmain.goにcssを呼び出す記述を書きます

funcmain(){http.Handle("/resources/",http.StripPrefix("/resources/",http.FileServer(http.Dir("resources/"))))http.HandleFunc("/",indexHandler)http.ListenAndServe(":8080",nil)}

一番上にhttp.Handleという関数を追加しました。
正直自分はコードの細部は理解出来ていなんですが、とりあえずresourcesディレクトリを呼び出してくれる関数という事らしいです(なのでコピペで大丈夫です)
この記述後もう一度リロードしてみます(cm + sf + R でスーパーリロードした方がいいかも)
スクリーンショット 2020-01-16 15.29.34.png
今度はちゃんとCSSが効きました!

次はデータベースを導入します

SQLite3というDBを導入します。導入用記事はまた今度書きます(ググればすぐ出来ます)

ではDBインストール出来たのでmain.goにインポートします

packagemainimport("database/sql"_"github.com/mattn/go-sqlite3""log""net/http""text/template")varDbConnection*sql.DBfuncindexHandler(whttp.ResponseWriter,r*http.Request){t,err:=template.ParseFiles("views/index.html")iferr!=nil{log.Fatalln(err)}t.Execute(w,nil)}funcmain(){http.Handle("/resources/",http.StripPrefix("/resources/",http.FileServer(http.Dir("resources/"))))http.HandleFunc("/",indexHandler)http.ListenAndServe(":8080",nil)}

上記のようにimportした後、var DbConnection *sql.DBでDBを定義してあげます。
これでDbConnectionという名前でDBにアクセス出来ます。
では実際にDBにデータベースを作ってみます。

今回はターミナルからSQLコマンドを打ちます。メインディレクトリでsqlite3 example.sqlと打ち込んでください。
スクリーンショット 2020-01-16 16.07.43.png
こんな風になると思います、次にCREATE TABLE tweets (id INTEGER PRIMARY KEY,tweet STRING);と打ち込みます。
これはtweetsという名前のテーブルを作成し、idとtweetというカラムを作成するというコマンドです。
tweetは文字型なのでstring、idはintegerにします。
idのprimary keyとは、何もしなければ自動的に数字を割り振ってくれるというものです。

これでtweetsテーブルは作成出来ました、一応確認してみます。ターミナルで.tabelと打ち込んでください。
スクリーンショット 2020-01-16 17.09.37.png

tweetsテーブルが作成されているのを確認出来ました。

ではフォームに入力した値を実際にDBに入れてみます。

index.htmlの14行目に注目してください。

<formaction="/tweet/"method="POST"class="tweet_form"><textareaname="tweet"rows="20"cols="80"></textarea><inputtype="submit"value="speak"></form>

actionに"/tweet/"を指定してるので、ボタンを押すとhttp://localhost:8080/tweet/
というURLが走ります、なのでmain関数にそのパスが通った時に呼び出される関数を記述すればいいという訳です。

packagemainimport("database/sql"_"github.com/mattn/go-sqlite3""log""net/http""text/template")varDbConnection*sql.DBfuncindexHandler(whttp.ResponseWriter,r*http.Request){t,err:=template.ParseFiles("views/index.html")iferr!=nil{log.Fatalln(err)}t.Execute(w,nil)}funcgetPostTweet(whttp.ResponseWriter,r*http.Request){DbConnection,_:=sql.Open("sqlite3","./example.sql")deferDbConnection.Close()v:=r.FormValue("tweet")cmd:=`INSERT INTO tweets(tweet)VALUES(?)`DbConnection.Exec(cmd,v)http.Redirect(w,r,"/",http.StatusFound)}funcmain(){http.Handle("/resources/",http.StripPrefix("/resources/",http.FileServer(http.Dir("resources/"))))http.HandleFunc("/",indexHandler)http.HandleFunc("/tweet/",getPostTweet)http.ListenAndServe(":8080",nil)}

ますmain関数内にhttp.HandleFunc("/tweet/", getPostTweet)という関数を記述します。
これは先ほど説明しましたね、これで"/tweet/"というパスが通ればgetPostTweetという関数が呼び出されます。
ではgetPostTweet関数の中身な解説をします。
DbConnection, _ := sql.Open("sqlite3", "./example.sql")でデータベースを開いて読み込みます。
defer DbConnection.Close()で開いたら閉じましょう。
これもお決まり文という認識で大丈夫だと思います、openしたらdeferでcloseです
ビューから送信したデータはr変数(http.Request)として送られてくるので
v := r.FormValue("tweet")としてv変数に代入してあげます。
このFormValueの中の"tweet"とは

<textareaname="tweet"rows="20"cols="80"></textarea>

このtextareaのname属性の事ですね。
textareaに記述した投稿がtweetという名前で受け取れますよという意味ですね。

今度はv変数に投稿内容が渡せているのでこれをDBに書きこみたいです。なのでデータを書き込むSQL文を記述してあげます。
cmd := INSERT INTO tweets(tweet)VALUES(?)
それがこれですね。 
tweetsテーブルのtweetカラムに値を入れてね、というSQL文です。

DbConnection.Exec(cmd, v)で実際にデータを書きこむ事が出来ます。
Execの第一引数にSQL文を、そして第二引数に書き込む値を渡している訳です。
そして最後のhttp.Redirect(w, r, "/", http.StatusFound)ですが、この関数処理が終わった後に"/"パス(つまり元のページ)に戻ってきてねという関数です。
この処理を書かないとtweet.htmlの画面に飛んでしまうのですが、そんなもの作成していないので真っ白の世界に行っちゃいます。
では実際に投稿フォームから投稿してみたいと思います。
スクリーンショット 2020-01-16 17.10.51.png
今回は Go と投稿してみます、ボタンを押すと...
スクリーンショット 2020-01-16 17.12.04.png
またこのページがリロードされましたね。
では本当にDBへ保存されているのか確認してみます。
ターミナルでselect * from tweets;と打ち込んでください。これでtweetsテーブルの中身を確認出来ます。
スクリーンショット 2020-01-16 17.13.54.png
1|Go と保存されているのが確認出来ました。
左のidはprimary keyを設定しているので勝手に数字が振られてます。

次はこのデータを画面に表示してみます

まずはstructを作成します。

packagemainimport("database/sql"_"github.com/mattn/go-sqlite3""log""net/http""text/template")typeTweetsstruct{IdintTweetstring}

適当にこの辺りに作成します。
structとは他の言語でいうクラスのようなものです(間違ってたらごめんなさい)
DBから引っ張ってきたデータを一旦入れておく入れ物みたいなイメージですかね!
DBのデータをHTMLに渡したい時は一旦このstructに入れてからじゃないと渡せません。

次にindexHandleを編集します

funcindexHandler(whttp.ResponseWriter,r*http.Request){DbConnection,_:=sql.Open("sqlite3","./example.sql")deferDbConnection.Close()cmd:=`SELECT * FROM tweets`rows,err:=DbConnection.Query(cmd)iferr!=nil{log.Fatalln(err)}deferrows.Close()varbody[]Tweetsforrows.Next(){varbTweetserr:=rows.Scan(&b.Id,&b.Tweet)iferr!=nil{log.Fatalln(err)}body=append(body,b)}t,err:=template.ParseFiles("views/index.html")iferr!=nil{log.Fatalln(err)}t.Execute(w,body)}

先ほどと同じくDBをOpenしてdeferでCloseしまして、tweetsテーブルを探すSQL文を記述してcmd変数に入れてやってるだけですね。
投稿の時と違うのは、DbConnection.ExecではなくDbConnection.Queryになっている事です。Queryメソッドでデータを引っ張り出せるんですね。
今回はrows変数にそのデータを代入してあげます。ちなみこれもdeferでcloseしてあげる必要があります。

その後スライスのTweets型のbody変数を定義してます。
rows.Next()でなにをしてるかと言いますと、DBから引っ張って来たrows変数を一つづつ b変数に代入して行って、それをスライスのbodyへ追加してあげてる訳です。(これもお決まり文として覚えればいいです)
これでtweetsテーブルのデータをTweets structへ変換する事が出来ました。
ではこれをHTMLヘ渡します。Executeの第二引数でデータを渡せるんでしたね。

次にHTMLも編集します

<!DOCTYPE html><htmllang="ja"><head><metacharset="utf-8"/><title>Gopher Tweets</title><linkrel="stylesheet"type="text/css"href="../resources/css/view.css"></head><body><main><header>Gopher Tweets</header><divclass="tweet_view">
      {{range .}}
        <formaction="/tweet_delete/"method="DELETE"><pclass="tweet_message">{{.Tweet}}
            <buttontype="submit"value={{.Id}}name="tweet_delete"class="tweet_delete_button">-</button></p></form>
      {{end}}
    </div><formaction="/tweet/"method="POST"class="tweet_form"><textareaname="tweet"rows="20"cols="80"></textarea><inputtype="submit"value="speak"></form></main></body></html>

{{}}←これでデータを受け取る事が出来ます。詳しくはこの人の記事で

ではまた再起動して画面を見てみましょう
スクリーンショット 2020-01-16 17.50.09.png
先ほど投稿した Go という投稿が表示されてますね、今度は Hello と投稿してみます。
スクリーンショット 2020-01-16 17.51.55.png
ちゃんと投稿する事が出来ました。

次は投稿を削除してみます

今投稿の横に青いボタンがありますが、今は押しても何も変化しません。このボタンを押すと投稿が削除できるようにしてみましょう。

      {{range .}}
        <formaction="/tweet_delete/"method="DELETE"><pclass="tweet_message">{{.Tweet}}
            <buttontype="submit"value={{.Id}}name="tweet_delete"class="tweet_delete_button">-</button></p></form>
      {{end}}

これが投稿表示部分のhtmlですが、このボタンをおすと 
/tweet_delete/ パスが走り
tweet_deleteというnameで 
{{.Id}} という値が送られる訳ですね。

なので先ほどと同様にこのパスのHandlefuncをmain関数に記述します。

func deleteTweet(w http.ResponseWriter, r *http.Request) {
    DbConnection, _ := sql.Open("sqlite3", "./example.sql")
    defer DbConnection.Close()
    cmd := "DELETE FROM Tweets WHERE id = ?"
    i := r.FormValue("tweet_delete")
    var I int
    I, _ = strconv.Atoi(i)
    DbConnection.Exec(cmd, I)
    http.Redirect(w, r, "/", http.StatusFound)
}
func main() {
    http.Handle("/resources/", http.StripPrefix("/resources/", http.FileServer(http.Dir("resources/"))))
    http.HandleFunc("/", indexHandler)
    http.HandleFunc("/tweet_delete/", deleteTweet)
    http.HandleFunc("/tweet/", getPostTweet)
    http.ListenAndServe(":8080", nil)
}

はい、先ほどの投稿の時とほとんど同じですね、削除するSQL文と削除したいIDを渡して実行しているだけです。
ただ送られて来たIdはstring型で送られてくるのでInt型に変換する為にstrconv.Atoi(i)を使用しているだけです。
ではまた再起動してから、一番上のGoという投稿のボタンをクリックしてみます。
スクリーンショット 2020-01-16 18.04.24.png
ちゃんと消えました!

このままでは寂しいのでマスコットキャラのゴーファくんを表示してあげて終了です。
resourcesディレクトリ内にimagesディレクトリを作成し、その中に画像を入れてCSSにてbackground-imageで指定するだけですね。

スクリーンショット 2020-01-16 18.11.48.png
以上です。
この記事が僕と同じような初学者の方の為になれば幸いです。


Python3とFlaskのインストール[環境構築まとめ]

$
0
0

PythonのFlaskを最初から構築する機会があったので、環境構築のメモを残しておく。

pyenvを使ったPythonのインストールなどは以下で行なっていたので、最初にそれをやっていない人は以下をまずは行う。
Python 環境構築 mac windows

virtualenvのインストール

上記が終わったらvirtualenvをインストール。

※Virtualenvとは
Virtualenvは、Shell上でプロジェクト毎に個別の環境が構築出来るナイスなツールです。

pip install virtualenv

上記で動かない人はpip3で実行してみてください。自分はエイリアス設定をしているのでpipで動きます。

alias pip=pip3

flaskアプリケーションを作成する

適当なワーキングディレクトリに移動してから環境を作る。

コマンドはvirtualenv {app_name}

cd /Work/flask_app/

$ virtualenv testapp
Using base prefix '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7'
New python executable in /Work/flask_app/testapp/bin/python3.7
Also creating executable in /Users/yoshi/Work/sample_python/testapp/bin/python
Installing setuptools, pip, wheel...
done.

完了すると以下のように指定した{app_name}でディレクトリ(プロジェクト?)が作成される。

$ ll
total 0
drwxr-xr-x   6 ys  staff  192  1 16 11:02 testapp/

中身はこんな感じ

$ ll testapp/
total 0
drwxr-xr-x   6 ys  staff  192  1 16 11:02 ./
drwxr-xr-x   4 ys  staff  128  1 16 11:02 ../
lrwxr-xr-x   1 ys  staff   80  1 16 11:02 .Python@ -> /usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/Python
drwxr-xr-x  18 ys  staff  576  1 16 11:02 bin/
drwxr-xr-x   3 ys  staff   96  1 16 11:02 include/
drwxr-xr-x   3 ys  staff   96  1 16 11:02 lib/

この環境を使用するようにアクティブ化する必要があります。OS XとLinuxでは以下のコマンドを実行。

$ cd testapp
$ . bin/activate

# 上記で動かなかったら$ source bin/activate

(testapp) adminnoMacBook-Pro-4:testapp ys$

うまく起動できると({app_name})とターミナル上に出現して実行可能な状態になる。

Flaskのインストール

$ pip install Flask

Collecting Flask
  Downloading https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl (94kB)
     |████████████████████████████████| 102kB 1.8MB/s
Collecting Werkzeug>=0.15
  Downloading https://files.pythonhosted.org/packages/ce/42/3aeda98f96e85fd26180534d36570e4d18108d62ae36f87694b476b83d6f/Werkzeug-0.16.0-py2.py3-none-any.whl (327kB)
     |████████████████████████████████| 327kB 1.9MB/s
Collecting itsdangerous>=0.24
  Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
Collecting click>=5.1
  Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB)
     |████████████████████████████████| 81kB 2.4MB/s
Collecting Jinja2>=2.10.1
  Downloading https://files.pythonhosted.org/packages/65/e0/eb35e762802015cab1ccee04e8a277b03f1d8e53da3ec3106882ec42558b/Jinja2-2.10.3-py2.py3-none-any.whl (125kB)
     |████████████████████████████████| 133kB 3.4MB/s
Collecting MarkupSafe>=0.23
  Downloading https://files.pythonhosted.org/packages/ce/c6/f000f1af136ef74e4a95e33785921c73595c5390403f102e9b231b065b7a/MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl
Installing collected packages: Werkzeug, itsdangerous, click, MarkupSafe, Jinja2, Flask
Successfully installed Flask-1.1.1 Jinja2-2.10.3 MarkupSafe-1.1.1 Werkzeug-0.16.0 click-7.0 itsdangerous-1.1.0

無事に完了したか確認。

$ flask --version
Python 3.7.6
Flask 1.1.1
Werkzeug 0.16.0

Flask上で動作確認をしてみる

公式ドキュメントからサンプルプログラムを拝借。
クイックスタート¶

サンプルのPythonファイルは{app_name}の直下で大丈夫。

sample_flask.py
fromflaskimportFlaskapp=Flask(__name__)@app.route('/')defhello_world():return"Hello Flask"if__name__=='__main__':app.run()
python sample_flask.py

動くかな....

動いた!

$ python test_flask.py
 * Serving Flask app "test_flask"(lazy loading)* Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [16/Jan/2020 11:33:03] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [16/Jan/2020 11:33:03] "GET /favicon.ico HTTP/1.1" 404 -

ちゃんとTOPページへのアクセスが200になっている。ブラウザで確認してみてもちゃんと表示された。

127_0_0_1_5000_と_test_flask_py_—_未設定__ワークスペース_.png

ただ、なぜかコンソールをみると* Environment: productionをみている。開発環境なんだからこのまま本番用に使うなよって以下のように警告が出ています。(現状は問題ないけど
WARNING: This is a development server. Do not use it in a production deployment.

気になる人は以下のコマンドを実行。

$ export FLASK_APP=app_name
$ export FLASK_ENV=development

(testapp) ys $ flask run

おわり。

【RStudio】Gitに恋してバージョン管理 ~ 基礎篇 〜

$
0
0

1. 趣旨

最近になって、Rのスクリプトやプロジェクトの管理をGitで始めました。

いや~~~~~非常に便利。
僕の中ではイノベーション。
これはスクリプト書くのが楽しくなる。

ということで、「Gitって何?食べられるの?」という過去の僕に向けた超入門。
GitとRStudioとの連携については、意外と超初心者向けのサイトが少なかったので、需要あるといいなぁ~~~。

留意点

  • この記事は、RStudioでプロジェクト管理を行うための超最低限のことしか書いてません。Python等その他の環境での利用については全く考慮していません。
  • 肌感覚での理解で書いてます。厳密・正確な文言や使用法ではないかもです。
  • この記事は 僕のようなマジの初心者向けなので、Gitがある程度分かるという人は、この記事よりもコチラの記事のほうが参考になります。
    RStudioではじめるGitによるバージョン管理 - Qiita

環境

  • Windows 10 x64
  • R 3.6.2
  • RStudio 1.2.1335

2. Git × RStudioでできること

多分この記事を開いてる時点で、多少Gitやプロジェクト管理に興味がある状態のはずですが、改めて。
RStudioとGitを連携させて何ができるかと問われれば、 ずばり!バージョン管理です。具体的には、こんなことができます。

  • スクリプトの変更履歴の保存
  • プロジェクトのバックアップ・復元
  • パソコン間(ノート・デスクトップ)でのプロジェクトの同期

ね?なかなか魅力的でしょ?かくいう僕も院生フレンズに教えてもらったのですが、慣れるとプロジェクト全体のバックアップにもなるし、スクリプトを書くのがすごーく楽しくなる。

しかーし!「Gitって何だ?」という僕にとっては中々難しく、用語も沢山出てくるので、最初は全く訳のわからないままブランチ(ほらね出てきたよ、、、)を大量に切ってしまったり、いつの間にかmaster(まーた知らないコトバが出てきたよ、、、)が消えたり、それはもう散々な目に遭いました。

「愚者は経験に学び、賢者は歴史に学ぶ」なんて言いますが、愚者たる僕の経験を歴史として笑って、皆さんは賢者になってください。

Git導入前のぼく

今まではスクリプトを書き直すたびにファイル名を変更してバックアップを取ってましたが、こんな問題点がありました。

  • どれが最終版?
  • 他人が作成したコードって自分のに反映したっけ?
  • このファイル、消して良いのか?
  • そもそも何を修正したんだっけ?
  • 前のバージョンに戻りたいんだけど、バックアップしてない・・・。

こういう問題が発生すると、僕の研究へのモチベーションが一気に下がるので、どうしてもモチベーションの維持のためにラーメン二郎を食い、結果として財布は痩せて身体は太ります。
スクリプトの管理もできない奴が、モチベーションと身体と金銭まで管理できるわけがない。

Git導入後のぼく

sugee.PNG

どうですよ。このデキるオトコ感。

  • 最終版がどれか分かる。
  • 変更の概要をメモできる。
  • 変更者・日付などは自動で記録される。
  • スクリプトのどこに変更が加えられたかという変更履歴が一目でわかる。
  • コードの修正等を別プロジェクトとして管理し、反映させることができる。
    それを視覚的にも把握できる。
  • いちいちファイル名を変更していくつもファイル作ったり消したりして管理する必要もない。
  • 必要であれば、過去のバージョンに遡れる。
  • スタバで開くとカッコいい。(検証済)
  • モテる。(要検証)

さあ、僕と一緒にGitを習得する気になりましたか?

3. Gitとは何なのか

Git自体については僕が説明するより、とても分かりやすい説明を引用させていただきます。

Gitはテキストファイルなどのバージョン管理を行うためのソフトウェアであるとよく言われます。バージョン管理は、ファイルの変更内容や変更履歴を保持しておいて、あとから古い状態に切り戻したりできるようにするためのものです。
つまり、「あぁ……この文章、変える前の方が良かったなぁ……前の状態に戻したいなぁ……」となった時に、前の状態まで(変更がコミットされていれば)復元できるようにするためのものです。
- 君には1時間でGitについて知ってもらう(with VSCode) - Qiita

Git自体はRやRStudio専用というわけではなく、むしろプログラミング全般で使われる管理ソフトです。
もっと活用すると共同作業の管理なども可能ですが、今回はわかりやすさ重視のため想定利用者は自分自身だけとします。

あと細かい説明は省きますが、GitとGitHubは別モノです!
連動させることも出来ますが、設定しない限りは関係ないです。

4. Gitのインストール

こちらからダウンロード。
https://git-scm.com/

基本的に指示に従っておけばOKです。
途中、PATHに関するオプションを聞かれますので、真ん中のUse Git from the Windows Command Promptを選択してください。
git-install06.png
画像:https://zero-config.com/windows/install-git-win-001.htmlより拝借。

何かオプションなどで困ったら、こちらを参考にしてみてください。
【初心者向け】Gitのインストール方法をわかり易く解説(画面付き)

ユーザー情報の登録

! ATTENTION !
この作業は省略できません!必ずやっておいてください!
省略してしまうと、ファイルのバージョン管理ができません!

インストールが完了したら、コマンドプロンプトを起動して、次のように入力してください。
これらの情報はネット上ではなくローカルに保存されるので、GitとGitHub等と連動させない限りユーザー名もメアドも公開されないので安心してください

ユーザー名は本名以外でもOKです。

git config --global user.name "ユーザー名"
git config --global user.email メールアドレス

なお、後々GitHub等との連携を考えている場合は、ユーザー名については公開されることがある点に留意してください。
メアドについては、公開 / 非公開の選択が可能ですが、デフォルトでは公開されます。
どうしても気になる方は、捨てアドを作って登録するという選択肢もあります。

また、GitHubと連動させていることが前提ですが、メアドの非公開化については、以下を参考にしてください。
GitHubのメールアドレスを非公開に設定する - kina's tech memo

これで準備OKです。

5. RStudioと連携させよう

さあ、インストールとユーザー情報の登録が完了したらRStudioとGitを繋げましょう!
初めての方は理解のために、まずは新規プロジェクトのパターンから始めることをおすすめします。

新規プロジェクトの場合

File > New Pojectで新規プロジェクトを作成します。

一番上のNew Directoryを押すとProject Typeを聞かれるので、New Projectを選択します。

Directory nameには管理するディレクトリの名前を入力し、その親ディレクトリ(作業フォルダをどこに作成するか)を選択します。好きなように入力・選択してください。
そして、Create a git repositoryのチェックを忘れずに!

Create Projectを押して、黄色い丸のようになってればOKです!

complete.PNG

6. 「Commit」=変更を記録する

何でもいいので、スクリプトを作成して保存しましょう。
何でもいいと言われちゃうと困っちゃう可愛い子には、スーを差し上げます雑なコードを差し上げます。

iris.R
plot(iris$Petal.Length,iris$Petal.Width)result<-lm(Sepal.Length~Sepal.Width,data=iris)summary(result)

保存まで終わったら、右上のGitタブを開いてみましょう。こんな風になっていると思います。
5.PNG

この二つ並んだのアイコンはStatusと言います。左側がGitの状態、右側がディレクトリの状態を表します。
アイコンが2つ並んでいると、そのファイルがGitによる管理の対象になっていないことを意味します。
なので、Gitに「このファイルの変更を追ってください!」とお願いしましょう。

GitでいうCommitとは、簡単に言うと、Gitにファイルの変更を記録することをいいます。
近くにCommitというボタンがあるので押してみましょう。Review Changesウィンドウが立ち上がります。

キャプチャ.PNG
こんな画面が出てきたら、Stagedにチェックを入れましょう。
すると、先ほどまでだったアイコンがAになりました。
AAddedの略で、変更の追跡対象を追加することを意味します。

右上のCommit messageには、変更の記録の概要などをメモできます。
とりあえず何でもいいので書いておきましょう。日本語もOKです。

ここまで出来たら、Commitボタンを押しましょう。
コマンドプロンプトっぽいのを閉じると、先ほどまで左上にあったファイルたちが消えていれば完了です。

Statusのアイコンの詳細な意味はコチラを参照してください。

スクリプトを書き換えて変更を記録してみる

先ほど作成・保存したスクリプトを、何でもいいので一部を適当に変えて上書き保存してみてください。
僕の作った例の雑コードは、線形回帰の関数lm()の説明変数と目的変数を入れ替えてみました。

iris.R
plot(iris$Petal.Length,iris$Petal.Width)result<-lm(Sepal.Width~Sepal.Length,data=iris)summary(result)

上書き保存すると、Statusの右側(ディレクトリ側)にMアイコンが灯りました。MModifiedの略、つまり変更が加えられたということを意味します。
6.PNG

では、この変更をGitに記録させましょう。
先ほどのようにCommitを押してReview Changesウィンドウを開いてみましょう。
Review Changesウィンドウでは、どこに変更が加えられたか、一発でわかるようになっています。赤色が変更前、緑色が変更後です。

そして同じように、チェックを入れて変更の概要を記述します。
チェックを入れると、Mが右から左に移るのが確認できると思います。これは、「Commitする(変更を記録する)とGit側で管理しているファイルをModified(変更)しますよー」ということを意味します。チェックを入れただけの段階ではまだGit側には変更は記録されず、Commitボタンを押すことで初めて変更がGit側に記録されます。

ちなみに、さっきからチェックを入れているStagedとは、対象を変更の記録をGitに反映させることを意味します。「まだこのファイルの変更はGitに記録したくないんだよなー」というときは、チェックを入れなければ記録されません。チェックしたファイルの変更だけがGitに反映されます。

ではでは、押してみましょう。
先ほどのようにファイル欄がクリアになったら成功です。

7. 変更履歴を確認したい

  • いつ、どのような変更を加えたか
  • 過去のバージョンを見たい・保存したい

などを知るために、Historyを確認しましょう。
先ほど開いていたReview Changesウィンドウの左上にあるHistoryをクリックするか、RStudioのGitタブにある時計マークをクリックします。
8.PNG
7.PNG

Historyでは、

  • ファイルの過去バージョンの参照
  • 変更履歴のメタデータ(日付・作成者など)の確認
  • Commit messageの閲覧
  • 前バージョンからの変更点の確認

などが出来ます。

ウィンドウの下半分には、選択したバージョンの、ひとつ前のバージョンからの変更点が記載されます。前バージョンから変更点がない場合は載らないので留意してください。

9.PNG

もしファイル数が膨大だったり内容の変更が多い場合など、スクロールして探すのが面倒な場合は、見たいファイルをクリックするとジャンプできます。iris.Rの変更点が見たい場合は、下の画像の赤丸部分をクリックです。
13.png

8. バージョンを戻してみよう

バージョン戻しはざっくり以下の2つあります。

  • Commitを押しちゃったけど、それ以前の作業履歴まで遡りたい場合。
  • まだCommitを押してなくて、作業前の状態(直近のCommitを押した時点)まで遡りたい場合。

直近のCommitより過去まで遡りたい場合

Commitを押しちゃったけど、やっぱりCommit押す前のほうが良かった!という場合、Gitを使ってると簡単に過去のバージョンに参照できます。

戻し方は色々ありますが、ここは一番ベーシックなやり方でやってみましょう。
今回は、スクリプトファイル(iris.R)をinitial commit(最初のコミット時点)まで復元しましょう。

1. Historyで戻したいポイントを参照する

今回はinitial commitまで遡るので、その時点の履歴を参照しましょう。

10.PNG

2. 戻したいファイルのView fileをクリック

下の画像のように、過去のバージョンを閲覧できるリンクがあるのでクリックして開きましょう。

12.PNG

すると、過去の状態のものが表示されます。これを上書き保存しましょう。

14.PNG

RStudioに戻ると、スクリプトに変更が加わったことによるMが表示されたことを確認できます。あとは、これを再度Commitさせれば完了です。

15.PNG

Commit押す前で、直近まで遡りたい場合

例えば、今日の作業、失敗だったなーーー。今日の作業はなかったことにしたいなーーー。という場合。
かつ、まだ失敗した作業内容をGitに記録させてない(Commitを押していない)場合

この場合は、とても簡単で手軽です。
先ほどのスクリプトを、今度はこうしてみましょう。書いたら ファイルは上書き保存しますが、Commitはしないでください。右列にMと表示されていればOKです。

iris.R
plot(iris$Petal.Length,iris$Petal.Width)result<-lm(Sepal.Length~Sepal.Width,data=iris)summary(result)# いらないメモ

この# いらないメモを書く前の状態に戻したい場合、つまり、以下のような直近でCommitした時点のバージョンに戻したいということです。

iris.R
plot(iris$Petal.Length,iris$Petal.Width)result<-lm(Sepal.Length~Sepal.Width,data=iris)summary(result)

例のごとく、Review Changesウィンドウを開きましょう。

今回はCommitではなくRevertというボタンを押してみると、「選択したファイルの変更が失われるけどいい?(超意訳)」とお尋ねが来るので、元気よくYesを押しましょう。

16.PNG

するとあら不思議。元通りに戻りましたとさ。めでたし。

17.PNG

9. まとめ

ここまでが僕的エッセンスです。

とりあえず一人で作業をする分にはここまででも十分かなーーーと思います。
これ以降はQiitaで検索するかググればなんとかなるかも。
活用しよう、集合知。

とりあえずブランチとかプルとかブッシュとか、そういう概念を知らなくても、RStudio上でプロジェクト管理ができましたね。
かくいう僕は、GitHubとも同期させて、自宅のデスクトップとノートPCで変更を共有させてます。
そういう使い方まで書きたかったのですが、それは機会があればまた書きます。

Enjoy!

おしまい。

今後追加したいコンテンツ

余力があれば、今後この辺のコンテンツを追加したいと思います。
別記事にするかもしれません。

  • 既存のRプロジェクトをGitで管理する
  • ブランチとは何ぞ
  • GitHubとの連携
  • Push・Pullとは何ぞ

なお、この辺について知りたい方は、他の方の記事にあると思いますので、是非調べてみてください。

10. 参考文献

AWS Lightsailを使ってみた

$
0
0

はじめに

AWSのコンピューティングサービスの一つであるLightsailを試しに少しだけ触ってみたので、その記録を記事としてまとめてみました。

Lightsailの管理画面

[AWS マネジメントコンソール]にログインして、[サービス]>[コンピューティング]>[Lightsail]と進むと、Lightsailの管理画面が表示されます。
画面中央の[インスタンスの作成]をクリックすると、インスタンス作成のウィザードに入ります。

lightsail_001.png

インスタンスの作成

ロケーションの選択

  • 個人で利用するのであれば、低レイテンシーな東京リージョン(ap-northeast-1)を選択するのが良いと思います。
  • 東京リージョンを選択した場合、A/B/DのAZの中から1つを選ぶことが出来ますが、AZによる違いはないと思うので、どれを選んでも良いと思います。
    • 厳密にはAZによる違いがあるのかもしれませんが、特に記載されていませんでした。

lightsail_002.png

インスタンスイメージの選択

  • EC2のようにOS(プラットフォーム)の種類を選べるだけでなく、利用するアプリも含めてイメージ(設計図)を選択できます。
  • 独自のSSHキーペアを使う場合は、ここでキーペアをアップロードしておきます。
OSのみアプリ+OS
Windows系Windows Server 2016、
Windows Server 2012R2
SQL Server 2016 Expressのみ
※OSはWindows Server 2016のみ
Linux系Amazon LinuxやCentOS、
Ubuntuなど8種類のOS
WordPressやNginxなど14種類のアプリから1つを選択
※OSは不明(選択不可)

インスタンスプランの選択

  • 必要とするリソース(CPU、メモリ、ストレージ容量、データ転送量)に応じて、インスタンスの種類を選ぶことができます。
  • [並べ替え:]の右側にある項目名をクリックすると、リソースやコストの順にインスタンスを並べ替えて表示できます。
    • [月次料金]をクリックすると「月額料金の安いインスタンス」の順に表示されます。
    • [メモリ]などをクリックすると「メモリ量の多いインスタンス」の順に表示されます。
    • [処理中]と書かれている部分は、「サーバーの処理能力(CPU)の高いインスタンス」の順に表示されるようです。

lightsail_003.png

インスタンス名とタグの設定

  • 一意なインスタンス名を指定する必要がありますが、どのレベルでの「一意」なのかは分かりませんでした。
    • リージョン内で一意、AWSアカウント内で一意など色々と考えられますが...
  • インスタンスを識別できるように、必要に応じてタグの設定をします。
  • 全て設定が完了したら、[インスタンスの作成]をクリックします。

lightsail_004_2.png

インスタンスの利用

サーバーコンソールで接続する

  • Lightsailのトップ画面から、作成したインスタンスの名前をクリックしてインスタンスの管理画面へ遷移します。
  • 所望のインスタンス名(※ここでは Lightsail-test)をクリックして、インスタンスの設定画面へと遷移します。
  • image.png

  • 遷移先の設定画面で[SSHを使用して接続]をクリックすると、サーバーコンソールが起動してインスタンスに接続できます。

lightsail_006_2.png

独自のSSHクライアントで接続する

  • Lightsailのトップ画面の右上にある[アカウント]ボタンをクリックして、[アカウント]画面へと遷移します。
  • アカウント画面で[SSHキー]タブを開き、[デフォルトのキー]を選択して、pemファイルをダウンロードします。
    • 独自のSSHキーを利用する場合は、仮想サーバーの作成時にSSHキーをアップロードしておく必要があります。
  • あとは所望のSSHクライアントに「仮想サーバーのパブリックIP」「ユーザー名(ec2-user)」「pemファイル」の3つを設定すれば、仮想サーバーにログインすることができます。
    • インスタンスのパブリックIP(もしくは静的IP)は、インスタンスの管理画面だけでなく、Lightsailのトップ画面でも確認できます。

lightsail_010.png

lightsail_008.png

利用上の注意点

  • インスタンスを[停止]しても課金が継続されるため、課金を止めるにはインスタンスの[削除]が必要となります。
  • インスタンスを削除しても、追加したストレージや静的IPは同時に削除されないため、[ストレージ]タブや[ネットワーキングタブ]から個別に削除する必要があります。
  • インスタンスの設定画面で[ネットワーキング]タブを選択すると、ファイアウォールの設定を変更出来ますが、変更できるのはインバウンドのみとなります。

HP修正計画_宮田さんへ

$
0
0

宮田さんへ

これからこの記事に君のホームページを改良していく手順の記事のリンクをまとめていくから、読んだら連絡くれるか、この記事にいいねかコメントを残すか、記事をTweetに反応してくれ。
質問があったら適宜、連絡してください。
連絡を受けて、記事もどんどん書き直していきます。

確認した事項

進め方

とりあえず、一周は最低限の仕様を満たすことを目標とする。
後から装飾は如何様にもできるからね。

環境

ホームページは忍者ホームページを使うのでいいんだよね?
とりあえず、我もアカウント作ってサーバーを借りたよ。
我はFTPツールとしてCyberduckを使ったけど、なんでもいいからね。
宮田さんはWindowsで、我はMacを使ってるけど、WindowsPCも持ってるから分からないことがあったら早めに聞いてね。

学習記録 その22(26日目)

$
0
0

学習記録(26日目)

勉強開始:12/7(土)〜

教材等:
・大重美幸『詳細! Python3 入門ノート』(ソーテック社、2017年):12/7(土)〜12/19(木)読了
・Progate Python講座(全5コース):12/19(木)〜12/21(土)終了
・Andreas C. Müller、Sarah Guido『(邦題)Pythonではじめる機械学習』(オライリージャパン、2017年):12/21(土)〜12月23日(土)読了
Kaggle : Real or Not? NLP with Disaster Tweets:12月28日(土)投稿〜1月3日(金)まで調整
・Wes Mckinney『(邦題)Pythonによるデータ分析入門』(オライリージャパン、2018年):1/4(水)〜1/13(月)読了
斎藤康毅『ゼロから作るDeep Learning』(オライリージャパン、2016年):1/15(水)〜

『ゼロから作るDeep Learning』

ニューラルネット、そしてAI研究のブレークスルーとなったディープラーニングについて理解を深めておきたかったため、昨日から読み始めました。
p.122 第4章 ニューラルネットの学習 まで読み終わり。

1章 python入門

・基本的に今までやってたことのおさらい(Python概要、環境構築、算術平均 etc)
 本書を読み進めていくための必要な知識概要を記した章
 ちょっと理解が足りてなかった部分のみ記載

・ブーリアン(bool):True or False のどちらかを取る型
 and, or, notといった演算子を用いることができる。

クラス定義
classクラス名:
    def__init__(self,引数,):#コンストラクタ
...defメソッド名1(self,引数,):#メソッド1
...defメソッド名2(self,引数,):#メソッド2
...#コンストラクタは初期化用メソッドとも言う。

2章 パーセプトロン

・パーセプトロンとは、60年程前からあるアルゴリズム(1957年に考案)
 ニューラルネットワーク(ディープラーニング)の起源である。

・パーセプトロンは複数の信号を入力として受け取り、一つの信号を出力する。
 パーセプトロンの信号は「流すか流さないか」(1か0か)の2値の値
 複数ある入力信号のそれぞれに固有の重みを持ち、大きいほど対応する信号の重要性が高くなる。入力信号の重要度をコントロールする値。

・「入力」「重み」「出力」の他に、「バイアス」という要素がある。
 バイアスは出力信号が1を出力する度合い(ニューロン発火)を調整するパラメータのこと。

・パーセプトロンは線形であるがゆえに排他的論理和(XOR)のような分類は実現できない。(パーセプトロンの限界)
ただし、パーセプトロンは"層を重ねる"ことができるため、重ねることで非線形も表現ができるようになる。(なので上記を正確に言うと"単層"パーセプトロンの限界)

3章 ニューラルネットワーク

・理論上パーセプトロンはコンピュータも表現できるほど可能性を秘めているものの、期待する入力と出力を満たすように適切な重みを決める作業は人の手で行わなければならない。
 ただし、ニューラルネットワークはこの問題を解決するための手段の一つで、適切な重みパラメータをデータから自動学習できる性質がある。

・ニューラルネットワーク(パーセプトロン)では、入力に重みをつけ、バイアスをかけて、これら入力信号の総和を活性化関数(activation function)にかけて変換し出力している。

・活性化関数とは閾値を境にして出力が切り替わる関数で、ステップ関数や階段関数と呼ばれている。パーセプトロンではステップ関数を用いている。

・ニューラルネットワークでは、活性化関数にシグモイド関数(sigmoid function)を用いている。
 シグモイド関数はステップ関数と比較すると滑らかな曲線であり、入力に対して連続的に出力が変化する。
 この滑らかさこそがニューラルネットワークの学習の元となっている。
 重要であれば大きい値を、そうでなければ小さい値を、どんなに大きい値でも出力を0〜1の間に押し込めるという特性は共通している。

・最近はシグモイド関数のほかにReLU(Rectified LinearUnit)というものも多く用いられている。

・一番最後の出力層で用いる活性化関数はタスクによって使い分ける必要がある。
 一般的に、分類問題(どのクラスに属するか当てる)ではソフトマックス関数を、回帰問題(数字を当てる)では恒等関数を用いる。

・恒等関数は出てきた値をそのまま流す。
 ソフトマックス関数は問題に対して確率的(統計的)な対応ができるようになるのが特徴で、出力の総和は1になる。(つまり、a=0.2, b=0.5, c=0.3であれば、aの確率が20%、bの確率が50%、cの確率が30% という形でとらえることができる。)

・クラス分類における出力層のニューロンの数は、分類したいクラスの数に設定するのが一般的。(0~9の数字のどの数字に属するか当てる問題であれば10に設定)

・まとまりのある入力データをバッチ(batch)と呼ぶ。束という意味がある。
 バッチ単位で推論処理を行うことで、計算を高速化できる。

4章 ニューラルネットワークの学習

・「学習」とは、訓練データから最適な重みパラメータの値を自動で獲得することを指す。
 この学習を行えるようにするために、**「損失関数(loss function)」という指標を導入する。
 損失関数を基準として、この値が最も小さくなる重みパラメータを探し出すことが学習の目的となる。

・ニューラルネットワーク(ディープラーニング)は与えられたデータをただひたすらに学習し、パターンを発見することを試みる。
 対象とする問題に関係なく、データをそのままの生データとして"end-to-end"で学習することができる。

2乗和誤差(mean squared error):最も有名な損失関数。
 出力と正解となる教師データの各要素の差の2乗を計算し、その総和を求める。

交差エントロピー誤差(cross entropy error):上記に次いでよく用いられる損失関数。
 出力と正解ラベルを乗じたものの総和を計算する。ただし正解ラベルはone-hot表現(0か1か)で表されているため、実質的には正解ラベルが1に対応する出力の自然対数を計算するのみとなっている。

・すべてのデータを対象として損失関数を求めるのは時間がかかるため、ミニバッチと呼ばれる小さなかたまりを取り出し、このミニバッチごとに学習を行うのが基本。(統計の勉強中に似たような話を見た気がする。)

・重みパラメータを少し変化させたときに、損失関数がどのように変化するかを計算し、より小さな損失となる場所を探すのが学習の目的。
 ここで微分(勾配)という考えが出てくる。
 シグモイド関数の微分はどの場所であっても0にならないことが、この学習において重要な性質となる。

・微分とはある瞬間の変化の量を示したもの。
 微小な差分によって微分を求めることを数値微分(numerical differentiation)と呼び、こちらを主に用いる。
 微小な差hは 1e-4(10の-4乗,0.0001) がよいと言われている。
 一方、数式展開によって求めることは解析的(analystic)微分と呼ばれている。

・すべての変数の偏微分をベクトルとしてまとめたものを勾配(gradient)と呼ぶ。
 この勾配が示す方向こそが、各場所において関数の値を最も減らす方向であり、これをうまく利用して関数の最小値を探そうというのが勾配法と呼ばれている。

・勾配法を数式で表す際、1回の学習でどれだけ学習するか、どれだけパラメータを更新するか、という量ηを定める。これを学習率(learning rate)という。

・学習率のようなパラメータをハイパーパラメータという。これはニューラルネットワークが自己学習できる重みやバイアスといったものと異なり、人の手によって設定する必要がある。

・ニューラルネットの学習4手順

1 ミニバッチを選び出し、損失関数を得る。
2 勾配を求め、損失関数を減らす方向を探る。
3 重みパラメータを勾配方向に更新する。
4 1~3を繰り返す。

上記は確率的勾配降下法(SVD:stochastic gradient descent)と呼ばれる。

・損失関数とiteration(繰り返し回数)を図示することで、損失関数の推移(学習の経過)を可視化することができる。

エポック(epoch):1エポックとは単位のことで、データを全て使い切った時の回数に対応する。10,000個のデータに対して100個のミニバッチで学習する場合、100回繰り返した時点で全ての訓練データを見たことになる。
 つまり、100回 = 1エポックとなる。

Viewing all 21663 articles
Browse latest View live