備忘録」カテゴリーアーカイブ

[Vue] 親コンポーネントのデータ/メソッドを子コンポーネントから使う

前提

以下の環境で動作確認

要素 バージョン
debian 8.6
node 8.6.0
Vue 2.6.1

概要

題の通り、Vueの親子コンポーネント間でのデータとメソッドのやり取りを行う方法の備忘録。
本記事では、以下のようなVueコンポーネントの親子関係を用意し、子コンポーネントから親コンポーネントのデータ、メソッドを利用する。

  • 親コンポーネント(parent)
    — 文字列データ及びそれを書き換えるメソッドを定義
  • 子コンポーネント(child)
    — テキストボックスとボタンと持ち、親のデータの読み書きを行う

親コンポーネント

<template>
  <div>
    <child :data="data" @set="setData"/>
  </div>
</template>

<script>
  export default {
    name: 'parent',
    data() {
      return {
        data: '',
      }
    },
    methods: {
      setData(data) {
        this.data = data
      }
    }
  }
</script>

子コンポーネント(child)に、属性dataとメソッドsedDataを渡す。
:dataと@setは省略記法で、それぞれv-bind:dataと、v-on:setを省略したもの

子コンポーネント

<template>
  <div>
    <input type="text" ref="text">
    <button @click="$emit('set', $refs.text.value)">Set</button>
    <p>{{ data }}</p>
  </div>
</template>

<script>
  export default {
    name: 'child',
    props: ['data'],
  }
</script>

親コンポーネントから受け取る属性は、propsで定義しなければならない。一見面倒だが、これによって不要な属性を受け取らずに済む。

buttonクリック時に、親コンポーネントのイベントに伝搬するために、$emitを用いる。$emitの第二引数以降が、元のイベントに対する引数になる。

実行結果

画像のように、テキストボックスに文字列を入力し、ボタンをクリックすると、親コンポーネントのsetDataメソッドが実行され、dataが書き換わる。

備考

  • Vueではコンポーネントの親子関係が深くなるとバケツリレーが始まるので、Vuexを導入が推奨されるみたい
  • VuexはReactにおけるReduxのような、Vueでストアを一元化するためのフレームワーク

SinatraでFlash(1回きりのセッションデータ)を用いる

備忘録

前提

以下の環境で動作確認済み

$ ruby -v
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
$ gem -v
2.4.5
$ bundle -v
Bundler version 1.13.4

FLASHとは

直後のHTTPリクエストのみで使用するセッションデータ。
POSTでデータを登録した後にGETにリダイレクトし、登録の結果メッセージを表示するのに使ったりする

rack-flash3をインストール

gem install rack-flash3

bundlerを使う場合
Gemfileに以下を追加し、bundle install

 gem "rack-flash3"

プログラム例

‘/’ 経由で’/hoge’にアクセスした場合に、’flash data’を出力。
直接’/hoge’にアクセスしたり、リダイレクト後に再読込した場合に’no data’を出力。

require 'sinatra/base'
require 'rack/flash'

class App < Sinatra::Base

  configure do
    use Rack::Flash
  end

  get '/' do
    flash[:hoge] = 'flash data'
    redirect '/hoge'
  end

  get '/hoge' do
    if flash[:hoge]
      flash[:hoge]
    else
      'no data'
    end
  end

end

MySQLで枠線/列名を表示せずにSQLを実行する

備忘録

通常

 mysql -u root --password=pw db_name -e "select id , created_at from user"
+----+---------------------+
| id | created_at          |
+----+---------------------+
|  1 | 2016-02-14 17:39:06 |
|  2 | 2016-02-14 17:39:28 |
|  3 | 2016-02-14 17:39:33 |
|  4 | 2016-02-14 17:39:38 |
|  5 | 2016-02-18 00:07:45 |
|  6 | 2016-04-27 23:09:30 |
|  8 | 2016-05-17 22:45:14 |
|  9 | 2016-05-28 18:33:53 |
| 10 | 2016-09-03 20:59:53 |
+----+---------------------+

枠線なし

-sオプションを付与するだけ

$ mysql -u root --password=pw db_name -e "select id , created_at from user" -s
id	created_at
1	2016-02-14 17:39:06
2	2016-02-14 17:39:28
3	2016-02-14 17:39:33
4	2016-02-14 17:39:38
5	2016-02-18 00:07:45
6	2016-04-27 23:09:30
8	2016-05-17 22:45:14
9	2016-05-28 18:33:53
10	2016-09-03 20:59:53

列名なし

-Nオプションを付与するだけ

$ mysql -u root --password=pw db_name -e "select id , created_at from user" -s -N
1	2016-02-14 17:39:06
2	2016-02-14 17:39:28
3	2016-02-14 17:39:33
4	2016-02-14 17:39:38
5	2016-02-18 00:07:45
6	2016-04-27 23:09:30
8	2016-05-17 22:45:14
9	2016-05-28 18:33:53
10	2016-09-03 20:59:53

使用例

ユーザのIDリストをDBから取得し、それに対して何らかの処理を行うスクリプトに標準入力で引き渡す

$ mysql -u root --password=pw db_name -e "select id from user" -s -N | script

RubyプログラマがPython3を勉強した話

概要

Rubyを使い始めて2年弱の私が、前々から気にはなっていたが使ったことのないPythonにようやく手を出したお話。
私がひと夏の間に行った、基本的な勉強についての備忘録を残す。

Pythonのバージョンについて

Pythonのバージョンは2.x系(Python2)と3.x系(Python3)が存在するが、2と3では互換性のない変更が多く含まれており、実質別言語として扱われることが多い。

既存システムの多くはPython2で書かれていること、Python3では動かない有用なライブラリが存在することなどから、単に新しいという理由でPython3を採用することはできないが、今回は以下の理由からPython3を採用する。

  • Python2は2010年以降更新されていないため
  • Python2は2020年で公式のサポートが打ち切られるため
  • Python3は現在も積極的なバージョンアップが行われており、今後は完全に3に以降する流れのため

Python3.6.2のインストール

今回は現在の最新のPythonである3.6.2を、Debianにインストールした。
インストールには、Pythonのバージョン管理ツールであるpyenvを用いることにした。インストール手順については、以下記事にまとめた

Python3.6.2をインストールして、Wikipediaをクロールするスクリプトを書く | QSのウェブ開発とか

Python3の基本の勉強

はじめに、Python3の基本的な使い方、文法などの勉強には以下ページを利用した。広く浅く、かつ丁寧にPython3の基本が書かれた良い記事だったので、自身を持ってオススメできる。

Python3基礎文法 – Qiita

Rubyなどのスクリプト言語をある程度経験している人なら、Python3の基本的な範囲については特に戸惑うこと無く馴染めると思う。

Python3のトレーニング

前項で基本的なPython3の書き方、文法は抑えられた。
しかし、まだまだPythonの感覚は掴めていないので、競技プログラミングの問題をPython3を用いて沢山解くことで、Pythonの感覚を掴むことにした。

今回は、私が個人的にもよく利用していたpaizaのスキルチェックを利用した。

paizaのスキルチェック問題は、以下の5段階の難易度がある

  • Dランク: ウォーミングアップレベル
  • Cランク: 初級レベル
  • Bランク: 中級レベル
  • Aランク: 上級レベル
  • Sランク: 超上級レベル

Aランク以上は、言語の使い方よりも、高度なアルゴリズム設計が求められる問題(そもそも解けないのが殆ど)となるので対象外とし、D,C,BランクをPython3を用いて解くことにした。

実際に問題を解いてみると、多言語ではすんなり書けることがPython3ではなかなか書けない。やりたいことをPython3で実現する方法が全然わらないのだ。そういった壁に直面するたびに、実現方法を調べては、Python節を身につけることを繰り返し、D,C,Bランク合わせて30問ぐらい解いたところである程度の理解は出来たと判断して終了した。

Python3によるWebスクレイピング

次に、Pythonと言えばWebスクレイピング/クローリングなので(偏見?)、HTTPライブラリと、XMLパーサライブラリを用いて色々遊んだ。
その中で作成した、Wikipediaをランダムにクロールするスクリプトについては、以下記事にまとめた

Python3.6.2をインストールして、Wikipediaをクロールするスクリプトを書く | QSのウェブ開発とか

Capybara(Rspec)で指定したセレクタ要素が存在しないことを検証する

以前は以下を参考にして例外を発生させて検証してたが、

Capybaraで要素がないことをテストする方法 | 自転車で通勤しましょ♪ブログ http://319ring.net/blog/archives/2546/

以下で充分検証することができた。例外待ちしない分こちらのほうが高速。

def cant_find(selecter)
  expect(page.all(selecter).empty?).to eq true
end

GUIでgitを使っている人がCUIに乗り換えるための基礎知識

前提

本記事は以下の環境で動作確認しています

要素 バージョン
debian 8.6
git 2.1.4

また、本記事中ではリモートリポジトリとして、私用のGitHubを用いています。リモートリポジトリは以下のものを用いて、空の状態からスタートするものとします。

git@github.com:Sa2Knight/git_test.git

CUIによるメリット

SourceTreeなどのGUIツールを使う場合と、CUIでgitコマンドを叩いて利用する場合では、どちらもメリット・デメリットが存在すると思います。ここでは、CUIを使う場合のメリットにのみ触れますが、デメリットについてはCUIの利用を躊躇ってる方々の考えるとおりだと思います。(コマンド覚える必要があるなど)

※ 以下のメリット・デメリットは私の個人的な考えが多く、実際は異なる可能性もあります。

1. 作業内容を共有しやすい

これはgitに限らずCUI全般に言えることですが、CUI上での作業は全て正確に言語化することができます。ある作業内容を相手に伝えたい場合、実行したコマンドリストを送ることで全て解決します(もちろん付加情報を自然言語で与えることも重要ですが)

対してGUIでは、操作を言語化する際に曖昧な情報になりやすく、誤解を与えやすい問題があります。

2. 定型的な作業を自動化出来る

こちらもCUI全般の話ですが、GUIでの操作と比べたとき、CUIの操作は自動化を行いやすいです。例えば、pullしてaddしてcommitしてといった一連の作業は、GUIだとマウスカーソルをそれなりに動かして、何度かクリックしたりといった定形作業が発生します。(ショートカットキーを使った場合でも)

対してCUIでは、一連の処理を一つのコマンドで実行できるようにすることで、定形作業をまとめて実行することができます。

3. 使い方を検索しやすい

言うまでもなく、バージョン管理システム”git”は、CUIツールです。SourceTreeなどのGUIツールは、GUIでgitを利用できるようにしてくれる後発のソフトウェアです。

そのため、当然ながらgitの使い方について検索した場合に出てくる情報の大半はCUIのコマンドです。もちろんSourceTreeなど、GUIソフトウェア名を検索ワードに含むことでカバーは効きますが、それでもCUIに関する情報量と比べれば雀の涙程度です。

以上より、gitを利用していて何らかの問題が発生した時に、それを検索して解決できる可能性は確実にCUIのほうが早く見つかると言えます。

4. カッコいい

これに尽きます

gitのインストール

ここでは、debianにapt-getを用いてgitをインストールします。他の環境でのインストール方法については適宜ググってください。gitは特別インストールが難しいツールではないので大丈夫だと思います。

$ sudo apt-get install git

gitがインストールされていることを確認する

$ which git
/usr/bin/git
$ git --version
git version 2.11.0

gitの利用

以降では、実際に以下の手順でgitを利用してみます。
1. ローカルリポジトリの作成
2. 空のファイルを作成してコミット
3. リモートリポジトリを登録し、pushする
4. 既存のファイルを編集する
5. 既存のファイルの削除
6. リモートリポジトリの更新をローカルリポジトリに反映

また、本項では以下のコマンドを利用します

コマンド名 内容
git init ローカルリポジトリを作成
git status リポジトリの状態を確認
git remote add リモートリポジトリを追加
git add ファイルをステージング・エリアに移動
git rm ファイルをリポジトリから削除
git diff 直前のコミットと現在のファイルの差分を確認
git commit リポジトリをコミット
git push ローカルリポジトリの更新をリモートリポジトリに反映
git pull リモートリポジトリの更新をローカルリポジトリに反映

1. ローカルリポジトリの作成

以下のコマンドは、作業ディレクトリ直下で実行してください

$ git init
Initialized empty Git repository in /home/vagrant/gittest/.git/

2. 空のファイルを作成してコミット

適当にファイルを作ります。以下は、”test”と書かれたテキストファイルを作成しています。

$ echo "test" > file1
$ cat file1
test

git statusコマンドを実行すると、リポジトリ内の現在の状態を確認できます

$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	file1

nothing added to commit but untracked files present (use "git add" to track)

Untracked filesは、まだリポジトリに追加されていないファイルのことです。コレに対して、git addコマンドを用いて、file1をリポジトリに追加します。

$ git add file1

もう一度git statusを実行すると、file1がリポジトリに追加され、Changes to be comittedの下にfile1が表示されていることが確認できます。この場所をステージング・エリアと呼びます。

 git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   file1

$

コミットすることができるのは、ステージング・エリアにあるファイルのみです。つまり、現状の場合file1のみがコミット対象のファイルです。コミットは、git commitコマンドで行うことができます。

$ git commit -m "初めてのコミット"
[master (root-commit) 32cd62b] 初めてのコミット
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file1

これで初めてのコミットが完了です。-mオプションを指定することで、”初めてのコミット”など、コミットコメントを記述することができます。-mを省略した場合、vimなどのエディタが立ち上がり、コミットメッセージの記述を求められます。

コミットが完了したことを、コミットログを閲覧することで確認することができます。コミットログの閲覧には、git logコマンドを用います。

$ git log
commit 32cd62bb013c5f8fe7021789ebb68d6a618fab9e
Author: Sa2Knight <shingo.sasaki.0529@gmail.com>
Date:   Sun Apr 23 20:15:53 2017 +0900

    初めてのコミット

“初めてのコミット”がコミットログに書き込まれていることが確認できます。

commit 32cd62bb013c5f8fe7021789ebb68d6a618fab9e

は、コミットハッシュと呼び、全てのコミットを一意に識別するための文字列です。

3.リモートリポジトリを登録し、pushする

ここでは、空のリモートリポジトリ

git@github.com:Sa2Knight/git_test.git

を登録し、ローカルリポジトリの内容をpushします。

リモートリポジトリの登録にはgit remote addコマンドを用います。

git remote add origin git@github.com:Sa2Knight/git_test.git

originはリモートリポジトリに付けた名前です。特にこだわりがなく、一つしかリモートリポジトリを使わない場合はoriginにする慣習があるっぽいです。

登録されているリモートリポジトリの一覧は、git remote -vコマンドで確認できます。

$ git remote -v
origin	git@github.com:Sa2Knight/git_test.git (fetch)
origin	git@github.com:Sa2Knight/git_test.git (push)

前項でコミットした内容をリモートリポジトリにpushします。git pushコマンドを用いてpushします。

$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 239 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:Sa2Knight/git_test.git
 * [new branch]      master -> master

masterはリモートリポジトリのブランチ名です。ブランチについて詳しくない方はとりあえずmasterと入れるものと思ってください。

4.既存のファイルを編集する

既存のfile1の内容を、”test”から”test2″に書き換えます。

$ echo "test2" > file1
$ cat file1
test2

リポジトリの状態を確認すると、file1がChanges not staged for commitの欄に表示されていることが確認できます。

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   file1

no changes added to commit (use "git add" and/or "git commit -a")

modifiedと書かれているとおり、ファイルの内容が前回のコミット時から変更されているが、ステージング・エリアに移動していないファイルを表します。

ここで、前回のコミット時と現在でファイルがどう変わったのか、git diffコマンドで確認することができます。

$ git diff file1
diff --git a/file1 b/file1
index 9daeafb..180cf83 100644
--- a/file1
+++ b/file1
@@ -1 +1 @@
-test
+test2

“- test”となっている部分は”test”という行が削除されたことを表し、逆に”+ test2″となっている部分は、”test2″という行が追加されたことを表します。

前項の手順で、ステージングエリアへの移動、コミット、プッシュを行いますが、やることは同じなので割愛します。

5.既存のファイルの削除

先程から利用していたfile1を削除します。

$ rm file1

リポジトリの状態を確認すると、今度はdeleted: file1と表示されています。

$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	deleted:    file1

no changes added to commit (use "git add" and/or "git commit -a")

これは、リポジトリに存在するファイルがディレクトリに存在しない状態を表します。リポジトリからも削除する場合は、git rmコマンドを用いて、ステージング・エリアに移動します。

$ git rm file1
rm 'file1'
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	deleted:    file1

あとはコミット、プッシュを行うだけです。

6. リモートリポジトリの更新をローカルリポジトリに反映

今度は、リモートリポジトリ側が誰かによって更新されたとします。ここでは、リモートリポジトリにfile2というファイルが追加されたことを想定して、git pullコマンドを用いてpullします。

$ git pull origin master
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:Sa2Knight/git_test
 * branch            master     -> FETCH_HEAD
   9cc3229..0d3c678  master     -> origin/master
Updating 9cc3229..0d3c678
Fast-forward
 file2 | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 file2

pull後、追加されたfile2が存在することが確認できます。

$ ls file2
file2

その他のコマンド

以下のコマンドは本記事では使用しませんでしたが、覚えると非常に役立つコマンドです。興味があればどんどん調べて使ってみてください。コマンドは私が使うもののみで、実際は他にもう少しあります。

コマンド名 内容
git checkout ファイルを直前のコミット時の状態に戻す
git stash ファイルの変更状態を一時的に保存する
git reset リポジトリの状態を特定のコミット時に戻す
git branch リポジトリのブランチに関する操作を行う
git merge 複数のブランチを統合する
git rebase 複数のコミットを統合する

AngularJSの専門用語整理その2

まさかの続き(前回)

digestサイクル

  • AngularJSがデータ双方向バインディングを実現するために、UIとモデルの差異を検証するサイクル

式(Expressions)

  • Angular式とか呼ばれてる
  • {{ 式 }} の形式でビューで展開できるJavaScriptの式っぽいもの
  • JavaScriptっぽいだけで別物
  • 全ての評価はデフォルトでスコープのプロパティに対して行われるので
  • undefinedをオブジェクトとして参照できる(無論結果は全てundefined)
  • フィルタが使える

$parse

  • Angular式を関数に変換するサービス
  • 対象のスコープを指定して関数を実行できる
    var getter = $parse('user.name');
    var context = {user:{name:'sasaki'}};
    console.log(getter(context)); // sasaki
    

$watch

  • 特定のオブジェクトやプロパティの変更を監視し、変更後に任意の処理を行わせるサービス
    $scope.hoge = 'foo';
    $scope.$watch('hoge' , function(oldValue, newValue) {
      console.log('hogeの内容が' + oldValue + 'から' + newValue + 'に変わりました');
    });
    
  • 関数を指定して、その戻り値の変化も検知できる
    $scope.$watch(function() {
      return $location.path();
    }, function() {
      console.log('パスが変わりました');
    });
    
  • watchはdigestサイクルの中で定期的に行われる

$apply

  • UIとモデルの値を同期させるサービス
  • digestサイクルの中で呼び出されるが、手動で呼び出すことも可能
  • 特にjQueryなどによってUIの値を直接書き換えた場合など、digestサイクルで検知できない場合に手動で同期させる必要がある

$inject

  • AngularJSにおける依存性注入のためのサービス
    コンストラクタ’My’に対して、依存するオブジェクト$scopeを注入してコントローラを作成する

    var My = function(s) {
      s.msg = 'Hello, AngularJS!';
    };
    My.$inject = ['$scope'];
    angular.module('myApp').controller('myController', My);
    

PHPでタイマー制御

【内容】
特定の期間内、処理を変更する。

【用途】
稼働中のサービスでメンテナンスを行う時や、
深夜等の業務時間外に処理を変更したい場合。

//規定期間開始の年月日・時間
$s_time_stamp = mktime(15,0,0,12,30,2016);
//規定期間終了の年月日・時間
$e_time_stamp = mktime(10,0,0,1,4,2017);
//現在時間の取得
$now_time = time();
//2016年12月30日 15時0分0秒~2017年1月4日 10時0分0秒の間、true側の処理を行う
if ($now_time >= $s_time_stamp && $now_time <= $e_time_stamp) {
  //規定期間内の処理

}else{
  //規定期間外の処理

}

ほぼ同じ内容で、トリガーとする日時以降か以前かで処理を分ける場合は下記の通り。

//規定時間を設定(下記の場合は、2017年2月20日 0時0分0秒以降の処理)
$trigger_time_stamp = mktime(0,0,0,2,20,2017);
//現在時間を設定
$now_time = time();
if ($now_time >= $trigger_time_stamp) {
  //規定時間後の処理

}else{
  //規定時間前の処理

}