OmniAICreator/Qiita-1.07M huggingface dataset:
新プロジェクトのテストケース作成について


アドベントカレンダーの5日目当番のQAグループ @takashios です。
新プロジェクトは、従来のプロジェクトよりも進化したやり方でテストケースが作成されていますので、簡単に紹介します。


#1. ツールが新しい
元々はQAメンバー全員でTestlinkを使っていたのですが、使いにくいという声もあり廃れてしまいました。
そこで、新プロジェクトの始動を機に、便利そうなツールに変えてみました。
今の新プロジェクトではコレを使っています。

* TestRail（テストケースを書き溜めるところ。テスト実行でも使用する。レポート機能は…使いこなしたい）
* スプレッドシート（主に、テストパターン検討やデシジョンテーブルに使用）
* Redmine（Bugを報告するところ。TestRailと連携させている）


#2. テスト駆動開発
今までの仕様説明は開発チームと同じタイミングで受けてましたが、現在はテスト駆動開発に向けて、先にQAが仕様説明を受けてテストケースを作成しています。その後に開発チームに共有するやり方に挑戦しようとしています。
これにより、以下のメリットがあるのではないかと思っています。

* 仕様の疑問点を解決
* 振る舞いが未確定な動作を明確化（実装を判断するエンジニアが、その場にいたらいいなぁ）
* テスト観点から、必要な影響範囲を再確認する
* 重要なテストの優先度や粒度の調整を行う
* テストケースができているので、テストの自動化にも繋げることができそうな予感

#3. テストの種類を増やした
他プロジェクトではCPM法に近い機能テストのみでしたが、現在のところは以下の３つです。
他に必要なテストの種類があれば、随時検討して追加していきます。

* UATテスト（受入要件を満たしているかどうかをテストする）
* 機能テスト（各機能を詳細にテストする）
* APIテスト（API自体を動作テストする）


#4.テストケース完成までの工程が厚くなっている
### 従来のやり方
（できる人も弊社に存在してます）
1. 仕様説明＆確認
2. テストケース作成
3. テストケースレビュー（レビューする人：QA）

###新しいやり方
1. 仕様説明＆確認
2. テスト分析（観点の洗い出し。CPM法にならないこと。漏らさないこと。）
3. 観点レビュー(レビューする人：QA、企画)
4. テスト設計（テストパターンの作成や、デシジョンテーブル等の作成）
5. テストケース作成
6. テストケースレビュー（レビューする人：QA、企画、開発）


#5.救いの手がある
仕様説明を受けた後に工数を見積もりすると、QAの作業は開発の倍以上も時間がかかっていることがわかりました。
具体的な時間のかかる理由は以下の点です。

* 新規プロジェクトの場合は、基本的にテストケースを新しく作っていくので時間がかかる
* 影響範囲のケースも漏れなくピックアップして、修正するので時間がかかる
* テストケースの漏れがないように、自分以外の人にテストケースのレビューをしてもらうので時間がかかる

新プロジェクトのチームは、1機能の開発〜テスト完了まで短いスプリントで終えるのを目標としています。
QAの作業待ちで遅れそうな状況の中でも完了まで漕ぎつけているのは、手の空いた開発のメンバーから「テスト実行やりますよ」という **救いの手** を何度も差し延べて貰えているからです。　
個人的には、**入社以来初の感動の大事件**です。チームワークって凄いですね。
今後は救いの手の為に、更にわかりやすいテストケースを作成しようと思います。　(`・ω・´)ｷﾘｯ


#6.苦しんでいるところ
それでもまだまだ未熟な部分もあり、色々苦しんでいます。
前向きに取り組んでいきたいと思ってますが、良いアイデアがあったら教えてください。

* 一箇所入力するとあちこちの値が変化するので、どこからどこまでを確認するのかを一瞬で判断をつける
* 最初に書いたテストケースと、最近書いたテストケースの語調が違うこと（酷い時には日によって違うことも。。内容には影響はなくても気になる）
* テストケースの観点が漏れてる気がする→調べてみてやっぱり…　をなくし、カンに頼らないようになりたい
* Sectionをうまく使って、テストケース個々のPreconditionsの内容が多すぎることを解決したい


#7. E2Eテストの自動化の状況
まだUIが確定していないため、準備中です。	
いつか紹介できるといいなと思います。	

---

以上です。
では、またいつかお会いしましょう。

弊社では、現在QAメンバーの募集をしております。
一緒に取り組んでいただける方は、ご一報くださいませ。
https://www.wantedly.com/companies/www-a-saas/projects
Rエラー： ‘***’ に対するパッケージもしくは名前空間のロードが失敗しました

 Rstudio使用中に遭遇したエラーとその解決方法の備忘録 _φ(･\_･　随時更新

## **エラー内容：インストールしたパッケージがロードできない**

実際は、`library("***")`実行後に以下のエラーが発生した（パッケージ名、バージョンは任意のもの）

```rout:
In addition: Warning message:
パッケージ ‘***’ はバージョン 3.3.2 の R の下で造られました 
Error:  ‘***’ に対するパッケージもしくは名前空間のロードが失敗しました
```

## **解決方法：以下のいづれかを実行**


### **1. ライブラリの場所を指定して読み込む**

```r:example1.r
find.package("shiny") 
# [1] "C:/Program Files/R/R-3.3.2/library/shiny"
library("shiny", lib.loc="C:/Program Files/R/R-3.3.2/library")
```
　これと同じことが、RStudioのUI上のパッケージ一覧表示(下図参照)から所望のものをチェックすることでも出来る。

　　　　　![rlibrary_pane.png](https://qiita-image-store.s3.amazonaws.com/0/215142/9b6dfb28-b763-7d75-5429-182594ff3311.png)
　

### **2. パッケージのアップデート/再インストール**

```r:example2.r
remove.packages("shiny") 
install.packages("shiny")
library("shiny")
```

### **3. Rstudioを再起動してパッケージを再ロード**


### **4. R上でパッケージを再インストール**

　　![image.png](https://qiita-image-store.s3.amazonaws.com/0/215142/fcb8f55a-94ea-291d-bfdf-56dc14bd11fd.png)


 上2つをやってもダメなとき、残りの2つをやってみるといいと思います。
Actions on Googleでアプリを開発/公開する際の絶妙なハマりポイント

##はじめに
Googleアシスタントアプリを開発→公開した時に躓いたポイントのまとめ。
ちなみに作ったのはこれ

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">音声アシスタントアプリ <a href="https://twitter.com/hashtag/%E4%BD%9C%E6%A5%AD%E3%83%88%E3%83%AA%E3%82%AC%E3%83%BC?src=hash&amp;ref_src=twsrc%5Etfw">#作業トリガー</a> を公開しました。<br>「始めるまでがキツい」という人に、細かく指示を出してくれます。<br>Googleアシスタントに「作業トリガーにつないで」で起動。<br>GoogleHomeと、iOS / Android にも対応してます。<br>⚠サーバーのアクセス制限で繋がらないことがあります。 <a href="https://t.co/cGQRPV30aI">pic.twitter.com/cGQRPV30aI</a></p>&mdash; 塗田一帆 (@nulltypo) <a href="https://twitter.com/nulltypo/status/935112340399202304?ref_src=twsrc%5Etfw">2017年11月27日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

このくらいシンプルな機能であれば、[Dialogflow](https://dialogflow.com/)だけでさくっと作れる。

##商標
一番最初に確認すべきところ。
「作業トリガー」は元々「やる気スイッチ」という名称にしようと思っていたが、この単語は商標登録されていた。そりゃそうか。
アプリ名を登録する段階でエラーを出してくれたので気付くことができたが、これによって最初から作り直す羽目になった。
[検索サービス](https://www2.j-platpat.inpit.go.jp/syutsugan/TM_AREA_A.cgi?0&1511837642791)を使って確認してから名前を決めたほうがいい。
もしドメインを取るならそっちも確認。

##音声認識
Googleの音声認識はかなり精度が高いが、100%ではない。
よって、同じ内容のコマンドでも**言いやすい**かつ**聞き取りやすい**単語を設定する必要がある。
また、Dialogflowは異なる言い回しでも柔軟に対応してくれるが、これが仇となる場合がある。
例えばある単語が別の単語として誤認識され、そっちに**意味的に近い**コマンドとして受け取られてしまう場合がある。

例）ユーザーの**「触った」**というコマンドが**「終わった」**と誤認識されてしまい、意図せず**アプリが終了**してしまう。

この例で言うと、「触った」を「持ってる」に変えると誤作動が少なくなった。
また、発音が近い単語をまとめてリストに入れておくと、誤認識した際に「もう一度言ってください」などと言わせることができる。

##Googleアシスタントからの呼び出し
アプリを呼び出すには「アプリ名」に加えて「特定の命令文」が必要になる。
「作業トリガー」に関しては「作業トリガー**につないで**」というフレーズを設定してある。
Google的には「〜につないで」を推奨してるっぽい。
個人的に、ちょっとダサいと思う。

##アイコンの背景色
アイコンの背景には**色**が着いていないといけない。
**透明**を使用してアイコンの形を丸くしたりはできるが、中央にシンボルマークなどがあっても、背景が**透明のみ**というのは認められていない。
また、背景色を**白、黒、ライトグレー**にすることは禁止されている。

##審査
3時間で終わる時もあれば、3日以上待つこともあった。
最終的に4度目の申請で通ったが、合計で10日くらいかかった。
あと多分土日はやっていない。

##ちなみに
他にもプライバシーポリシーの作成などで引っ掛かる可能性はあるが、基本的には親切なプラットフォームなので、ガイドラインに書いてあることを忠実に守っていれば大丈夫。
審査が通ったときはやたら賑やかな**おめでとうメール**が来るのでお楽しみに。
React-Native で iPhoneX のレイアウトに合わせる

# iPhoneX対応の個人的なまとめ
### 上下のスペースを消す
https://stackoverflow.com/questions/46316879/react-native-odd-spaces-on-iphone-x

※Target => general　=> build targetを iOS 9.0以上にする(もしくはビュー毎に設定)
https://stackoverflow.com/questions/46222000/cant-use-safe-areas-in-xcode-9-after-upgrading-minimum-deployment-target-to-ios

#### safeAreaView
https://medium.com/react-native-training/react-native-iphonex-92ff511282af
※DimensitonでScreenHeightを使っている部分は実装を考え直さないと崩れるので注意

### 端末がiPhoneXかの判定
https://github.com/ptelad/react-native-iphone-x-helper/blob/master/index.js

#### borderBottomWitdhで1以下を使わない
崩れるので
macOSでコアダンプの生成を停止する

macOS High Sierra（10.13.1）で検証しています。

macOSは、アプリケーションのクラッシュの瞬間に作業メモリのコアダンプを生成します。
これは、開発者がアプリケーションがクラッシュした理由や最後の作業環境を取得するためのアプリを探すのに役立ちます。

但し、コアダンプが大量に生成されるとSSDの領域が圧迫されるため、作業すらままならない状況に陥ります。
ワークアラウンドとして以下を実施することにより、コアダンプの削除および生成を止めることが可能です。

/cores内の全てのcoreファイルを削除するには、次のコマンドを使用します。

```bash
$ rm -f /cores/*
```

コアダンプを一時的に無効化（再起動後に元に戻ります）するには、次のコマンドを使用します。

```bash
$ sudo sysctl -w kern.coredump=0
```

コアダンプを永続的に無効化させるためには、/etc/sysctl.confを新規作成（存在していない場合）し、次の設定値を記載します。

```vim:/etc/sysctl.conf
kern.coredump=0
```
【Android】BottomNavigationをスクロール時に少しだけ隠す

## やりたいこと
スクロール時にBottomNavigationを少しだけ（文字だけが見えなくなるくらい）隠したい。

![Untitled.gif](https://qiita-image-store.s3.amazonaws.com/0/123122/a7557a42-ca59-ae5d-7b80-417252023db6.gif)

## 結論
スクロール時に一定値以上隠れないようなCustomBehaviorを作る。

## コード抜粋 & 簡単に解説
Behaviorの`onDependentViewChanged()`で少しだけ隠すような制御を入れたCustomBehaviorを作る。

```kotlin:BottomBarBehavior.kt
override fun onDependentViewChanged(parent: CoordinatorLayout, bottomBar: Toolbar, dependency: View): Boolean {
    if (defaultDependencyTop == -1) {
        defaultDependencyTop = dependency.top
    }
    var diff = defaultDependencyTop - dependency.top
    val minHeight = context.resources.getDimensionPixelSize(R.dimen.bottom_bar_min_height)
    if (diff > minHeight) {
        // ここでminHeightより隠れないようにしている
        diff = minHeight
    }
    ViewCompat.setTranslationY(bottomBar, diff.toFloat())
    return true
}
```

Toolbarの`app:layout_behavior`に作ったCustomBehaviorを指定する。

```xml:activity_main.xml
<android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:contentInsetEnd="0dp"
        android:contentInsetLeft="0dp"
        android:contentInsetRight="0dp"
        android:contentInsetStart="0dp"
        app:contentInsetEnd="0dp"
        app:contentInsetLeft="0dp"
        app:contentInsetRight="0dp"
        app:contentInsetStart="0dp"
        app:layout_behavior="rkowase.bottomnavigationcustombehaviorsample.BottomBarBehavior">

        <android.support.design.widget.BottomNavigationView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:background="?android:attr/windowBackground"
            app:menu="@menu/navigation" />
    </android.support.v7.widget.Toolbar>
```

Fragmentで使うViewは`ScrollView`だとBehaviorでスクロールイベントを受け取ることができないので`NestedScrollView`を指定する。

```xml:fragment_main.xml
<android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="@+id/constraintLayout"
        tools:layout_constraintLeft_creator="1"
        tools:layout_constraintTop_creator="1">
```

## コード
ここに置きました
https://github.com/rkowase/android-bottom-navigation-custom-behavior-sample

## 参考
AndroidのCoordinatorLayoutを使いこなして、モダンなスクロールを実装しよう - Yahoo! JAPAN Tech Blog
https://techblog.yahoo.co.jp/android/androidcoordinatorlayout/

xml - Android: remove left margin from actionbar's custom layout - Stack Overflow
https://stackoverflow.com/questions/27354812/android-remove-left-margin-from-actionbars-custom-layout
LinuxでTensorflowを使おうとするとImport Errorになる

Tensorflowをpipでinstallしていざ使おうとするとこのようなエラーが起きました。

```
ImportError: /myproject/lib/python2.7/sitepackages/tensorflow/python/_pywrap_tensorflow.so: invalid ELF header
```

検索すると他にも似たようなエラーが起きている人がいました。
https://github.com/tensorflow/tensorflow/issues/1711

原因は、どうやらLinuxにMac OS X用のパッケージをインストールしたことのようでした。

ちゃんとLinux用のものをインストールしなおしたら正常に動きました。

---
【随時更新】備忘録　laravelの基礎構文

自分用なので、参考にならないかも。
備忘録として基礎のところから、随時適当に更新していくことにする。

#コントローラーからviewに変数を渡す

```
// /hello  にアクセスした時、$msgに値を渡す
return view('hello.index',['msg'=>'フォームを入力:']);
```

```web.php
//アクセス時に$id $pass に第一引数で指定した値を渡す(必須)
Route:get('hello/{id}{pass}',function($id,$pass){...})

//パラメーターをつけない場合でも表示が出るようにする書き方（任意）
Route:get('hello/{$msg?}',function($msg = 'メッセージが格納されていないときのデフォルトメッセージ'){...})
```
Unityでスプライトアニメーションのスプライトだけを差し替える

例えばプレイヤーの衣装を変えて同じ動きをさせたいときなどに、Animatorで別ステートを用意するのは何かと不便です。

そこで、ちょっと強引ではありますが、スプライトアニメーション後に別のスプライトに差し替えることを試してみます。

```c#:AnimSpriteChange.cs
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace animSprite{
	[System.Serializable]
	public class ReplaceInfo{
		public string fromName;
		public string toName;
	}

	[RequireComponent(typeof(SpriteRenderer))]
	public class AnimSpriteChange : MonoBehaviour {
		[SerializeField] string spriteResourcePath="";
		[SerializeField] ReplaceInfo[] replaceInfo;
		SpriteRenderer sr;
		Sprite[] resSprArr;
		Dictionary<string,string> repDic;

		void Start () {
			prepare ();
		}

		void LateUpdate () {
			sprChange ();
		}

		void prepare(){
			Resources.LoadAll<Sprite>(spriteResourcePath);
			sr = GetComponent<SpriteRenderer> ();
			resSprArr = Resources.FindObjectsOfTypeAll<Sprite> ();
			repDic = new Dictionary<string, string> ();
			foreach (ReplaceInfo info in replaceInfo) {
				repDic.Add (info.fromName, info.toName);
			}
		}

		void sprChange(){
			string sprName = sr.sprite.name;
			int pos = sprName.LastIndexOf ('_');
			if (pos >= 0) {
				string pre = sprName.Substring (0, pos);
				if (repDic.ContainsKey (pre)) {
					string post = sprName.Substring (pos);
					Sprite retSpr = resSprArr.FirstOrDefault(e=>e.name.Equals(repDic [pre] + post));
					if (retSpr != null) {
						sr.sprite = retSpr;
					}
				}
			}
		}
	}
} // namespace animSprite
```
![スクリーンショット 2017-11-28 12.00.14.png](https://qiita-image-store.s3.amazonaws.com/0/59911/d1cfcb65-12ba-06f9-e44b-98a19a18f935.png)

スプライトアニメーションのあるGameObjectにアタッチして実行すると、アニメーション後 fromName_xx から toName_xx にスプライトを差し替えます。
差し替え後のスプライトはResoueceフォルダの下に入れる必要があります。

![スクリーンショット 2017-11-28 11.26.57.png](https://qiita-image-store.s3.amazonaws.com/0/59911/f413ad5b-afc7-b543-3692-ccdc640d1df7.png)

![スクリーンショット 2017-11-28 11.27.10.png](https://qiita-image-store.s3.amazonaws.com/0/59911/660376d2-be99-eefa-4bb3-82af7015411f.png)

OnAnimatorMove() で変化があった時だけ　sprChange() を呼ぶようにしていたのですが、チラつくようでしたので LateUpdate() 毎に更新しています

![スクリーンショット 2017-11-28 11.42.38.png](https://qiita-image-store.s3.amazonaws.com/0/59911/6aadc1f4-78b2-cab5-7650-5d76c5871be8.png)

![スクリーンショット 2017-11-28 11.42.54.png](https://qiita-image-store.s3.amazonaws.com/0/59911/bdf45fab-4482-cb92-605b-33b9561d9e43.png)

スプライトアニメーションの作り方は [こちら](https://qiita.com/ELIXIR/items/e58fa48680e0ebbde0ea)
404のエラーでちょっと詰まった話


## 前置き
僕自身railsエンジニアになって二ヶ月なので理解が不足している部分もありますので、そこは何卒ご了承ください。そして何かありましたらご指摘をお願いします...。

## 起こった問題
最近404のエラーで詰り、その原因が単純なエラーだったので備忘録的な感じで載せます

この前、routesのパスを色々といじっていたらとあるリンクを押しても404のエラーが出るようになりました(下記参照：名前は変えてあります)

> link_to '新規登録', new_file_path(params: { book_id: @book.id})

## 試した対処法
404のエラーは、ページが見つからないというエラーという認識だったので
### files/new.html の場所がおかしい？？
views/files/new.html
は確かにある。

### routesがおかしい？？
そもそもroutes関連のエラーではない

## 解決策
Filescontrollerのnewアクションにbefore_actionがついており、そこでエラーが起きていたのが原因だった。
エラーの内容は、存在しないparamsの値を用いてuserを持ってこようとしていたのが原因だった。

## 学べたこと
おそらく404のエラーをapplicationcontrollerで仕分けているので、それが原因？？
エラー自体は、それでも404と出てしまうということ？
いまいちしっくりはきてないですがこんな感じで理解しています。
Rustでimplの実装を複数ファイルに書く

## 発端

小ネタ。お題そのままであるが、implの中身が長くなると、分けたくなる。そのためだけに別の空structを作って処理を移譲するのはなんか躊躇う。


## implは分けられる

ところが、公式にもある通り、そもそもimplは複数のブロックに分けて書ける。

```rust:src/lib.rs
struct hyper_so_cool {
  f1: u8,
  f2: String,
}

impl hyper_so_cool {
  fn f1(self) {
    // do something wonderful...
  }
}

impl hyper_so_cool {
  fn f2(&self) {
    // do something marvelous...
  }
}

impl hyper_so_cool {
  fn f3(&mut self) {
    // do something fantastic...
  }
}
```


## ファイル分割してみる

単一ファイルの中でこの書き方をしてもあんまり意味がないので、この機能は多分ファイル分割を意識したもののはず。ほな、分けましょう。単純にモジュールに分けてみます。

```rust:lib.rs
mod struct_definition; // include struct hyper_so_cool
mod module1; // include func f1
mod module2; // include func f2
mod module3; // include func f3
```

```rust:src/struct_definition.rs
struct hyper_so_cool {
  f1: u8,
  f2: String,
}
```

```rust:src/module1.rs
use super::hyper_so_cool;

impl hyper_so_cool {
  fn f1(self) {
    // do something wonderful...
  }
}
```

```rust:src/module2.rs
use super::hyper_so_cool;

impl hyper_so_cool {
  fn f2(&self) {
    // do something marvelous...
  }
}
```

```rust:src/module3.rs
use super::hyper_so_cool;

impl hyper_so_cool {
  fn f3(&mut self) {
    // do something fantastic...
  }
}
```

`hyper_so_cool`の定義を`use`する必要があります。そりゃそうですね。


## `pub`が必要になる

さて、この状態で`cargo run`しようとすると、実はエラーが出ます。
なんと、`hyper_so_cool`が`private`なのでアクセスできないと言われます。
仕方がないので、公開します。

```rust:src/struct_definition.rs
pub struct hyper_so_cool { // pub!
  f1: u8,
  f2: String,
}
```

メソッド内ではたいていの場合、それぞれのフィールドにアクセスする必要があるでしょうから（じゃなかったらメソッドにする意味はだいぶ限定されてしまう）、これだけでは不充分で、結局全部`pub`をつける羽目になる。

```rust:src/struct_definition.rs
pub struct hyper_so_cool { // pub!
  pub f1: u8, // pub! pub!
  pub f2: String, // pub! pub! pub!
}
```

すごく釈然としない。家の鍵を自分で壊した感。Rustの場合、「ファイル分割＝モジュールを分ける」ということになってしまう（んですよね？）ので、こういうことになる。


## サブモジュールにしたら？

でもまあ、もう一歩進んで考えてみると、後からこのstructを使いたい場合、外側からは`module1` `module2` `module3`を全て`use`する必要があるので、使いにくい。普通はどうするのか、と考えると、サブモジュールである。以下のディレクトリ構成にしよう。

```
src
  hyper_so_cool
    mod.rs
    module1.rs
    module2.rs
    module3.rs
```

そしてコードは以下。

```rust:src/hyper_so_cool/mod.rs
mod module1;
mod module2;
mod module3;

struct hyper_so_cool { // no more pub!
  f1: u8, // no more pub!
  f2: String, // no more pub!
}
```

`module1.rs` `module2.rs` `module3.rs`に関しては、`src/hyper_so_cool`以下へ移動するだけで中身は変わらず。

というわけで、こう書くと各サブモジュールから親のstructへアクセスが可能になるみたいです。
これからはこう書きます。普通は自然とそうなるのかもしれないけれど、サブモジュールからのaccessibilityの話ってあんまり見たことがないので書いてみました。


## まとめ

Rustで単一structに対する`impl`を複数に分けたい場合は、サブモジュールにして、`mod.rs`にstruct定義を、それぞれのサブモジュールに`impl`を書くようにすれば、struct定義にやたらめったら`pub`をつけることを防ぐことができます。


## 追記

@termoshttさんに、コメントで教えていただきました。ありがとうございます！
`pub(crate)`を使うと、同一crate内からのアクセスだけを許すようになるみたいです。

```rust
   // pub(crate) makes functions visible only within the current crate
    pub(crate) fn public_function_in_crate() {
        println!("called `my_mod::public_function_in_crate()");
    }
```
Django入門は「 django Girls Tutorial」から手をつける

##Django Girls Tutorial について

Djangoに入門して、まず当惑するのが初心者向け日本語情報の少なさです。
Djangoは一応[公式のチュートリアル](https://docs.djangoproject.com/ja/1.11/intro/)があります。

これが非常に読みにくいです。専門用語が多く、LinuxやPython、他のフレームワークに習熟していてなんとか理解できるレベルで、初学者の心を折るには十分です。

それよりも、はじめの一歩として優秀なのが [Django Girls Tutorial] 
(https://www.gitbook.com/book/djangogirlsjapan/workshop_tutorialjp/)です。

[**Django Girls Tutorial**](https://www.gitbook.com/book/djangogirlsjapan/workshop_tutorialjp/details)

名前の通り、アメリカのPythonコミュニティで定期的に開いている女性を対象としたワークショップで、教科書として利用しているものを翻訳したものです。

明快な文章で、内容も丁寧に段階を踏んでいます。
なにしろ最初の項目が「インターネットの仕組み」です。そこからウェブサーバの仕組み、Pythonのインストール、テキストエディタのインストール、Pythonの基本知識の説明があってようやくDjangoの説明です。Djangoのひとつひとつのモジュールについてその目的を明確にし、とりあえず変更していろいろ動作を確認する構成なので個々の項目に対して理解が深まります。

内容を進めるとHerokuへのデプロイの実習まで及びます。

一般人にとってインターネットへのアプリを公開するのは非常にハードルが高いものという認識ですが、クラウド環境の整備でここまで簡単になっていることに気付く良いきっかけになりました。

非プログラマならいろいろ調べつつ読むので時間がかかりますが（私は丸３日かかりました）、項目の粒度が適切なので、今何がわからないのかが自覚しやすかったです。

Djangoのみならず、とりあえずWebフレームワークを触ってみたい人には最適の教材だと思いました。学校や新人研修でも活用できるでしょう。

##実際にやってみた後のメモ

学習を振り返ってみてメモを残します。
環境は Window 7-64bit/ Python3.6.3


#### [Pythonをインストールしよう](https://djangogirlsjapan.gitbooks.io/workshop_tutorialjp/python_installation/)

WindowsのPythonのインストーラーは、Pythonのバージョンによって、デフォルトのディレクトリが異なるようです。
現行の3.6だとユーザー領域の深い位置に配置されます。

`C:\Users\<username>\AppData\Local\Programs\Python\Python36`
  
  後々扱いにくくなるので、カスタムインストールを選び、Cドライブ直下に「Python」ディレクトリなどを作ってそこにインストールすると楽です。

  Program Files内にインストールすることもできますが、グローバル環境への変更時(pip install 等)、ターミナルを管理者モードで実行しない限りエラーになるので不便です。
※一見不便ですが、仮想環境を意識して作業する習慣がつくのでメリットとも考えられます。

####[コードエディタ](https://djangogirlsjapan.gitbooks.io/workshop_tutorialjp/code_editor/)
  Atomを含めて３つのエディタが紹介されていますが「Visual Studio Code」がおすすめです。低スペックPCでも軽快で、Django Girls Tutorial の執筆時よりもさらにDjangoにフレンドリーになっています。

####[Djangoのインストール](https://djangogirlsjapan.gitbooks.io/workshop_tutorialjp/django_installation/)

チュートリアルでは仮想環境のディレクトリをプロジェクト内に作成しています。
しかし学習中はプロジェクトを何度も削除、再作成するので、その度に仮想環境を構築するのは面倒です。プロジェクト外に作成すると学習がスムーズになります。

####[デプロイ！](https://djangogirlsjapan.gitbooks.io/workshop_tutorialjp/deploy/)

Herokuへのデプロイにあたってパッケージを４つ追加していますが、説明が無かったので調べた範囲でメモ

###### gunicorn
Python製のWSGIサーバ。WSGIとはWebサーバとアプリケーションサーバ（Django）の中間で橋渡しをするもの。herokuのWebサーバが何なのかは未調査

###### psycopg2
Postgres(データベース) への接続ドライバ


###### dj-database-url
データベースに接続するにはユーザー名やパスワードが必要です。
しかしそれを設定ファイルに直接書くと、無関係の人間に見られてしまうリスクがあります。その対策として秘密の情報は環境変数に登録し、設定ファイル内で環境変数を読み込んで使う方法が一般的になっています。
環境変数内の接続設定を読み込んでアプリケーションで使えるようにするのがこのモジュールの役割です。
Djangoアプリケーションをherokuの無料枠でデプロイすると、自動的に無料枠のPostgresデータベースが作成され、環境変数にその接続設定が登録されます。
チュートリアル内で特にデータベースの設定を行う必要が無いのはこの機能によるものです。
	
###### whitenoise
アプリケーションのソースファイルは通常Webサーバから直接公開される場所に配置しません。しかし画像ファイルなど静的ファイルは開発時にソースファイルと一緒に管理するのでデプロイにあたって分離作業をする必要があります。その作業を自動化してくれるのがwhitenoiseです。
	
##参考
- Django入門にはDjango Girls Tutorialがおすすめ
 - https://qiita.com/takechanman/items/d711e175b32f833c5e9c
RaspberryPi3でPythonを使ってLチカさせる

## 概要
Pythonを使うと超簡単にLチカができるということで試してみた

## このように配線した
![haisen_bb 2.jpg](https://qiita-image-store.s3.amazonaws.com/0/164786/1debbdc6-d7d1-fa9a-79f2-ba3eb1358905.jpeg)


## Lチカプログラム
ソースコードを[github](https://github.com/Teriyaki-0901/led-python)にアップしています。

```
git clone https://github.com/Teriyaki-0901/led-python
cd led-python
python lchika.py
```

### ソースコード

```py:lchika.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(2,GPIO.OUT)
for x in xrange(5):
    GPIO.output(2,True)
    time.sleep(2)
    GPIO.output(2,False)
    time.sleep(2)
GPIO.cleanup()
```

### 設定するところ
#### setmode
setmodeには「BOARD」と「BCM」の2種類がある。
BOARDは物理的なピン番号、BCMはGPIO3なら3といった論理番号のこと。

BOARD

```py
GPIO.setmode(GPIO.BOARD)
```

BCM

```py
GPIO.setmode(GPIO.BCM)
```

### ピン番号
上のソースコードでは、GPIO2に接続したので、接続したピンのGPIO番号に変更する
（下のソースの「2」の部分）

```py
GPIO.setup(2,GPIO.OUT)
GPIO.output(2,True)
    time.sleep(2)
    GPIO.output(2,False)
    time.sleep(2)
```
ローカル開発環境を自動でrsyncする話

PHPを始めて、ローカル環境からリモートサーバへのファイル転送（デプロイ）が億劫がだったため作成  
デプロイ先：dev-server  
ローカルPC：mac

---
## まずはデプロイ先に繋ぐssh_configの設定から。。。

~/.ssh/configを設定する

```
Host dev-server
  HostName ${ホスト]
  User ${ユーザ}
  IdentityFile ~/.ssh/id_rsa
```

コマンドラインから繋がればOK

```
$ ssh dev-server
```

---
## 手動実行編

.bashrcを書き換える

```
alias rsync_app="rsync -auvz ¥
--exclude='.git/' --exclude='.settings/' --exclude='.buildpath' ¥
--exclude='.gitignore' --exclude='.project' --exclude='vendor/' ¥
${デプロイ元dir} ${ユーザ}@dev-server:${デプロイ先dir}"
```

.bashrcを読み込む

```
$ source .bashrc
```

.bash_profileに記載が必要かも

```
if [ -f "${HOME}/.bashrc" ]; then source "${HOME}/.bashrc"; fi
```

これで手動実行は可能

```
$ rsync_app
```

-----------
## ここからは勝手にやってくれるように編

rsync用のシェルを用意（rsync.sh）  
本来ならばシェルの中で「rsync_app」を呼んでコマンド記述を省略したかったのだが、うまくいかず時間との兼ね合いで断念。。。

```
#!/bin/bash
rsync -auvz ¥
--exclude='.git/' --exclude='.settings/' --exclude='.buildpath' ¥
--exclude='.gitignore' --exclude='.project' --exclude='vendor/' ¥
${デプロイ元dir} ${ユーザ}@dev-server:${デプロイ先dir}
```

キック用のfswatchコマンドを記載したシェルを用意（fswatch.sh）

```
#!/bin/bash
 fswatch -o ${デプロイ元dir} | xargs -n1 rsync.sh &
```

コマンドラインからfswatch.shを実行
```
$ ./fswatch
```

* これでfswatchコマンドがバックグラウンドで実行される
* ${デプロイ元dir}の変更を検知  
* rsync.shが実行され、デプロイ完了
オブジェクト指向初心者向け、クラスとインスタンスの説明

```ts
// オブジェクト指向用語説明用サンプル
//
// class(クラス) :
//   データと関数 をひとまとめにした入れ物の定義(型)。
//   一般に、クラスが持つデータのことを「フィールド」、
//   クラスが持つ関数のことを「メソッド」と呼ぶ。
//   メソッドは引数で値を与えられなくても、自身のフィールドを
//   使うことができる。
//
// instance(インスタンス) :
//   クラスを実体化したもの。
//   クラスは型であり、その型を元にインスタンスを何個でも
//   生成できる。
//   オブジェクト指向プログラミングでは、インスタンスを生成して、
//   それに対して操作を行うことで処理を行う。
//
// this :
//   メソッドの中で、this という変数を使うことができる。
//   this は自身のインスタンスへの参照。 this を通して、自身の
//   メソッドやフィールドにアクセスできる。

// 商品クラス定義
class Product {
  // フィールド
  name: string;
  price: number;

  // コンストラクタ(newされたときに呼ばれるメソッド)
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }
}

// 注文クラス定義
class Order {
  // フィールド (Product(商品)型のインスタンスの配列を持つ)
  products: Product[];

  // コンストラクタ(newされたときに呼ばれるメソッド)
  constructor(products: Product[]) {
    this.products = products;
  }

  // メソッド
  totalPrice() {
    // ↓ 商品の配列から、各商品の値段(price)の配列に変換する。
    const prices = this.products.map((product) => {return product.price;});
    // ↓ 値段の合計を計算して返す。
    return this.sum(prices);
  }

  sum(prices: number[]) {
    return prices.reduce((prev, cur) => {return prev + cur;}, 0);
  }

  productNamesStr() {
    // ↓ 商品の配列から、各商品の名前(name)の配列に変換する。
    const names = this.products.map((product) => {return product.name;});
    // ↓ 商品名をコンマで連結して返す。
    return names.join(', ');
  }
}

function main() {
  // Product(商品) のインスタンスを生成し、配列に格納する。
  const products = [
    new Product('広辞苑', 4500),
    new Product('大辞林', 5000),
    new Product('吾輩は猫である', 700)
  ];

  // Order(注文) のインスタンスを生成
  const order = new Order(products);

  // Order(注文) のメソッドを使って処理する
  console.log(`total price: ${order.totalPrice()}`); // 注文に、合計金額を計算させる。
  console.log(`product names: ${order.productNamesStr()}`); // 注文が含む商品の名前を取得する。
}

main(); // ← ここからプログラムの実行が開始される。
// => total price: 10200
// => product names: 広辞苑, 大辞林, 吾輩は猫である
```
Mac「メモ」のメモリスト⇔メモ間の移動のショートカット

普段MacのメモAppが手頃なので仕事のログとして用いているのですが、
メモリストとメモ間の移動が出来ないな〜と思ってました。

公式にも載ってませんし。
https://support.apple.com/ja-jp/guide/notes/apd46c25187e/mac

たまたま押し間違えて出来たのでメモ

`cmd+Enter` です。
HTTPメソッドGetで個人情報送ってもいいんじゃないの？

タイトルの内容を思ったきっかけは社内勉強会で[体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践](https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8-%E6%B5%A9/dp/4797361190)を読んだことでした  
改めてなぜダメなのかと言われるとしっかり根拠を持って説明できないなと思い調べてみました

Getでもいいのかなと思ったパターンは以下のようなケースです

例えば、会員登録機能などで確認画面から戻るボタンで入力フォームに遷移する場合に、入力した内容をそのまま保持したままにしたい。その際にはHTTPSの場合であればGetで戻っても大丈夫なのかな？

## GetとPostの使い分けはどういう場合？
GetとPostの使い分けは以下のようなケースの場合で考えればいいようです
> - Getメソッドは参照（リソースの取得）のみに用いる  
- Getメソッドは副作用がないことが期待される  
- 秘密情報の送信にはPOSTメソッドを用いること  

> 引用：安全なWebアプリケーションのつくり方 p.35


### HTTPSでもRefererから秘密情報は漏れる

> [https: から http: へのリンクでは、 Referer: は送らない](https://wiki.suikawiki.org/n/Referer%3A#section-%E8%A6%81%E6%B1%82%E3%81%AE%E5%8F%82%E7%85%A7%E5%85%83%E3%81%AE%E6%B1%BA%E5%AE%9A)ことになっています。これを利用して、漏らしたくない URL を含むホスト全体を https で提供すれば、 http: URL への参照があっても Referer: の送信を抑制できます。 
> 引用：[Referrer を制御する](https://qiita.com/wakaba@github/items/707d72f97f2862cd8000)

> ただし、 https: のページへの Referer: は送信されてしまいます。 https: 化することで Referer: が送信されなくなったと安心してしまいがちですが、実際には対策として不完全で、危険です。
> 引用：[Referrer を制御する](https://qiita.com/wakaba@github/items/707d72f97f2862cd8000)

そのページに外部リンクがある場合、上記理由からReferrerで個人情報が流出してしまう問題からPOSTで遷移するのがよいみたいです

以下は検索機能がある画面で画像が表示されている箇所があったので、chromeディベロッパーツールから見てみると外部リンクの画像へのアクセスでReferrerから検索パラメータが付加されて送られていました

![referer.png](https://qiita-image-store.s3.amazonaws.com/0/64171/c48afec7-b3aa-411d-d90f-023b394762c9.png)


### 個人情報がアクセスログに残る
Getの場合には、パラメータに付加した個人情報がログに書き込まれてしまう為に、アクセスログの漏洩にも気を使わないといけなくなってしまうというところでリスクが更に高くなってしまう問題があるようです

> 以下は実際の Web サーバー(Apache)のアクセスログですが、GET メソッドのためパラメーターがアクセスログに残ってしまっていることが分かります。
```
192.168.11.2 - - [24/Feb/2013:07:16:48 +0900] "GET /hello.php?id=yamada&password=password HTTP/1.1" 200 105 "http://192.168.11.9/login.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17"
```
> 引用：[Webセキュリティの小部屋](https://www.websec-room.com/2013/02/24/204)

## 参考
### 文献
- [体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践](https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8-%E6%B5%A9/dp/4797361190)

### サイト
- [Referrer を制御する](https://qiita.com/wakaba@github/items/707d72f97f2862cd8000)
- [Webセキュリティの小部屋](https://www.websec-room.com/2013/02/24/204)
Hyper-V server 2016 をGUIで管理する

https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/manage/remotely-manage-hyper-v-hosts
https://yun-craft.com/software-crafts
http://yamanxworld.blogspot.com/2015/02/technical-preview-hyper-v-hyper-v.html
http://yamanxworld.blogspot.jp/2013/03/windows-server-2012-hyper-v.html
http://www.vwnet.jp/Windows/WS16TP2/HVMan/Credential.htm


この辺りを全部試してやっと繋がった。

まとめは後日やる。。
最後の「管理者でHyper-Vマネージャを起動」は罠過ぎる。。。
filter_input関数について

filter_input関数を使えば簡潔にコードを書くことができる。

<h1>filter_input関数とは</h1>
(HTMLフォームのinputタグなどから)外部変数を受け取り、フィルタリングする関数。 ユーザが入力した値などが妥当であるか調べたりするのに使います。

通常フォームから値を受け取るときにはこのように書くと思います。

```php
<?php

$id = $_GET['id'];
$name = $_POST['name'];
```

しかし、値が入っていなかったり、上手く渡っていなかった場合、Notice: Undefined index なんかが発生して、エラーになってしまいます。そのためissetを使用し、値が入っているか確認する必要性があります。

```php
<?php

if (!isset($_POST['name'])) {
  $name = null;
} elseif (!is_string($_POST['name'])) {
  $name = false;
} else {
  $name = $_POST['name'];
}
```

でも、いちいち6,7行のコードを書くのはめんどくさいですよね。
そんなときに、filter_input関数を使えば1行で書けます。

```php
$name = filter_input(INPUT_POST, 'name');
```

めちゃくちゃ楽。。。
Python でファイルを受け取るコマンドを書くときは argparse の type=open が便利

小ネタ。

Python 3 標準モジュールの argparse では、引数を設定する際に `type=int` のように型を指定できて便利なのだけど、 `type=open` を指定するとファイルオブジェクトとして引数の値を取得できて、わざわざ `open(filepath)` する必要がなくなるのでさらに便利。

## サンプルコード
``` python:filelen.py
#!/usr/bin/env python3

"""ファイルの行数を数えるコマンド"""

import argparse

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('file', type=open, help='テキストファイル')

args = parser.parse_args()

print(len(args.file.readlines()))
```

``` console
$ ./filelen.py -h
usage: filelen.py [-h] file

ファイルの行数を数えるコマンド

positional arguments:
  file        テキストファイル

optional arguments:
  -h, --help  show this help message and exit
```

``` console
$ chmod +x filelen.py
$ ./filelen.py foo.txt
74
```

## 任意の関数でも可
https://docs.python.jp/3/library/argparse.html#type

> `type=` には1つの文字列を引数に受け取って変換結果を返すような任意の呼び出し可能オブジェクトを渡すことができます

`int` や `open` はこれを満たす呼び出し可能オブジェクトなので `type=` に渡すことができる、ということらしい。

そのため、文字列を任意の値に変換する関数を用意しておいて `type=` に渡すのでも良い。
[solr tips] explainの内容を整形する

# デバッグ
検索時のscoreの内訳を見たい時にdebugQueryを付けると思いますが、
デフォルトだとexplainの内容がindentされず、手元のエディタにコピペして整形してました。

# debug.explain.structured
https://wiki.apache.org/solr/CommonQueryParameters#debug.explain.structured
該当のパラメータを付与することで、explainの内容を構造化して見やすくしてくれます。
今更ながらこんな便利なパラメータがあることを知りました。（つかデフォでこのパラメータ有効にしてくれても良いと思うけど）
最近の私的 Golang 開発環境

あらかじめ予防線を張っておくと [Go 言語]の開発環境で「これ！」という正解はない。特にチームで開発している場合は，チームの流儀に従うのが最善だと思っている。なので，この記事は「こういうやり方もあるよ」という参考程度に見ていただけるとありがたい。

## GOPATH の構造

皆さん御存知の通り，環境変数 `GOPATH` は [Go 言語]パッケージや開発環境を指定するものだが，実は複数のパスを指定できる。Windows 環境ならこんな感じにセミコロン（`;`）で区切って指定する。

```
SET GOPATH=C:\path\to\go-packages;C:\go-wkspace
```

Linux 等ならこんな感じにコロン（`:`）で区切ればいいだろうか。

```
export GOPATH=/usr/local/go-packages:~/go-wkspace
```

`GOPATH` に複数のパスを指定した場合， `go get` コマンドで導入した（依存関係を含む）パッケージ群は最初に指定したパスの配下に格納される。上の例なら `go-packages` フォルダがそれに該当する。

今回はこれを利用する。

## [Go 言語]ツールチェーンを分離する

つまり開発に必要で `go get` コマンドで導入するツール群（ここでは仮に「[Go 言語]ツールチェーン」と呼ぶことにする）は `go-packages` フォルダに集約させ，自身の開発環境は `go-wkspace` フォルダ配下で行うようにするのである。もちろん導入した [Go 言語]ツールチェーンに `PATH` を通しておくのも忘れずに。

```
SET PATH=%PATH%;C:\path\to\go-packages\bin
```

この方法なら [Go 言語]ツールチェーン導入時に依存関係で導入されるパッケージ群によって開発環境が汚染されるのを防ぐことができる。

## 開発で使う外部パッケージは [dep] で管理する

じゃあ自身が作るパッケージが依存している外部パッケージはどうやって管理するのかというと， `go get` コマンドではなく， [dep] を使う。 [dep] で管理するパッケージを追加するには，以下のようにすればよい。

```
$ dep ensure -add github.com/pkg/errors
```

もしくは `Gopkg.toml` ファイルを直接いじって `dep ensure` で更新するか。

```toml:Gopkg.toml
[[constraint]]
  name = "github.com/pkg/errors"
  version = "^0.8.0"
```

これで外部パッケージは `vendor` フォルダ以下に一括管理できる。

## 利点と欠点

このやり方の利点は「プロジェクトごとに環境を切り替えなくていい」ということに尽きる。自身の開発環境は（上の例で言うところの） `go-wkspace` フォルダ配下に集約されるため「[GOPATH 汚染](http://text.baldanders.info/golang/gopath-pollution/ "GOPATH 汚染問題 — プログラミング言語 Go | text.Baldanders.info")」みたいなことは一切気にしなくてよくなる。

また開発環境の管理に使用するツールとその手順が少ないのも利点に挙げていいかもしれない。 [dep] は事実上の公式ツールなので，余程のことがない限りなくなることはないだろう（go コマンドに組み込まれることはあるかもしれないがw）。

欠点は利点の裏返しで，自身の開発リポジトリがどうしてもモノリシックな構成になってしまうことである。複数のプロジェクトを同時に抱えている場合は，そのプロジェクト同士の関係管理が煩雑になりがちである。

もっともモノリシックなリポジトリ構成は近年見直されつつあるようなので，運用次第では帳消しにできる欠点ではある。それに今はプロジェクト環境の分離は docker などで仮想環境ごとやっちゃうのが主流みたいだし。

## 参考

- [GOPATH 汚染問題 — プログラミング言語 Go | text.Baldanders.info](http://text.baldanders.info/golang/gopath-pollution/)
- [Glide から Dep への移行を検討する — プログラミング言語 Go | text.Baldanders.info](http://text.baldanders.info/golang/consider-switching-from-glide-to-dep/)
- [ATOM で Go — プログラミング言語 Go | text.Baldanders.info](http://text.baldanders.info/golang/golang-with-atom/) : この記事で紹介している [go-plus](https://atom.io/packages/go-plus) がバックグラウンドで自動的に [Go 言語]ツールチェーンを導入・更新するので `GOPATH` の指定を動かしづらいというのも正直に言ってあった
- [Travis CI でクロス・コンパイル（GoReleaser 編） — プログラミング言語 Go | text.Baldanders.info](http://text.baldanders.info/golang/cross-compiling-in-travis-ci-with-goreleaser/) : この記事の後半で [Travis CI](https://travis-ci.org/) で [dep] を使う方法をしれっと紹介している 
- [モノリシックなバージョン管理の利点 | プログラミング | POSTD](http://postd.cc/monorepo/)

[Go 言語]: https://golang.org/ "The Go Programming Language"
[dep]: https://golang.github.io/dep/ "dep · Dependency management for Go"
VCRとrequest specを併用したときに詰まったことのメモ

# なにこれ？
VCRでRailsの外部API呼び出しを行っているときに、詰まったことと解決方法のメモ

# 問題

Request specを使ったときにController(やModel)側でAPI callがあったときにエラーが起きる

```ruby
RSpec.describe "Hoge", type: :request, vcr: true do
  describe 'GET /hoge' do
    subject do
      get '/hoge'
      response
    end
    it { is_expected.to have_http_status 200 }
  end
end
```

この時エンドポイント `/hoge`でエラーが起こる

# 解決方法

VCR.use_cassetteを使ってない場合、APIコール時にexample.descriptionを取りに行き、取れずに失敗している。

## 応急的には

```ruby
RSpec.describe "Hoge", type: :request, vcr: true do
  describe 'GET /hoge' do
     subject do |example|
      VCR.use_cassette example.description do
        get '/hoge'
      end
      response
    end
    it { is_expected.to have_http_status 200 }
  end
end
```

で動いた。

## 場当たり的ではない対策はちょっと考える。
(VCRのリポジトリ上で既知で無いならPR、既知ならきっと良いやり方があるはず)

# もっと良い方法募集中
Oracle Client を「ちゃんと」アンインストールする

Oracle Universal Installer でアンインストールを試みると

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29454/60959381-ea01-b041-b463-bfc7a71e66e4.png)

というメッセージが出る。これにしたがって、削除バッチ `deinstall.bat` を実行する時の注意点は３つ

- 管理者権限でバッチファイル(`deinstall.bat`)実行する
     - 「コマンドプロンプト(管理者)」で実行する
     - 管理者モードにならないと、まったく削除できない
- うっかり c:\app\denki\… ディレクトリをカレントディレクトリにしない
     - カレントディレクトリにするとフォルダー削除に失敗する。実害はないが、エラー終了するので気持ち悪い
- ODBC の設定などは、アンインストールする前に削除しておく
     - アンインストール後は ODBC の設定の削除は出来なくなる

以上
Phaser タッチイベント　優先順位

Button.input.priorityID

priorityIDは、入力イベントが発生したときに優先するゲームオブジェクトを決定するために使用されます。 たとえば、複数のスプライトが重なっている場合、デフォルトでは、表示リストの一番上にあるものに入力イベントの優先順位が与えられます。 これは、priorityID値を制御することでこれを止めることができます。 値が大きいほど、入力イベントとみなされる重要性が高くなります。
Phaser Button

pendingDestroy : boolean

ゲームオブジェクトは、pendingDestroyが次のロジック更新時にdestroyメソッドを呼び出すようにフラグが設定されていることです。 次の更新時に破棄するオブジェクトにフラグを付けることができるように、これを直接設定することができます。

これは、ボタンや他の入力イベントなどの独自のコールバックの1つからオブジェクトを破棄したい場合に非常に便利です。
How to rename network interface on CentOS 7

## How to rename network interface on CentOS7/RHEL7

 eg. eth1 -> eth0 and eth0 -> eth1

```
/sbin/ip link set eth0 down
/sbin/ip link set eth1 down

/sbin/ip link set eth0 name eth10
/sbin/ip link set eth1 name eth0
/sbin/ip link set eth10 name eth1

/sbin/ip link set eth0 up
/sbin/ip link set eth1 up
```

cf. https://unix.stackexchange.com/questions/205010/centos-7-rename-network-interface-without-rebooting/219277

:smiley:
NAO Flasher USBを作成する

NAOの初期化、Factry Resetを行ないたい場合に必要なUSBの作り方をメモします。

##準備するもの
Softbank Robotics developerサイト（　https://developer.softbankrobotics.com/jp-ja/ ）からダウンロードするもの
> 【ナビゲート】
「ダウンロード」→「NAO V5 & V4」→「SystemImage-NAOqi OS ExternalDownlosdLink」→「Sign in」→「Resources」→「Software」→「MY ROBOTSのNAOをチェック」

・1-Upgrading your NAO の NAOQI OSの**”2.1.4 atom system image”**
・8-TroubleShooting の **"2.1.0 Flasher Mac 64"** 　※今回はMACで作成する

>　【ダウンロードファイル】
**”2.1.4 atom system image”**：opennao-atom-system-image-2.1.4.13_2015-08-27.opn
**"2.1.0 Flasher Mac 64"**：flasher-2.1.0.19-mac64.tar.gz


・USBメモリ（スティックタイプ　２G以上）


##USB作成手順
手順１）USBメモリを挿す

手順２）ダウンロードした”flasher-2.1.0.19-mac64.tar.gz”を解凍し、*flasher*を起動する
MACの場合には、ターミナルからsudoで実行する
![nao-flasher01.png](https://qiita-image-store.s3.amazonaws.com/0/76385/e6d8c56b-6434-0164-44f0-c24df11685c7.png)

手順３）Browseボタンを押し、ダウンロードした”opennao-atom-system-image-2.1.4.13_2015-08-27.opn”を選択する
![nao-flasher02.png](https://qiita-image-store.s3.amazonaws.com/0/76385/6ddde696-5576-9a20-6f06-e5675aa7d538.png)

手順４）今回、工場出荷時の状態まで初期化したいので**Factry reset**のチェックをする

手順５）Writeボタンを押す
![nao-flasher03.png](https://qiita-image-store.s3.amazonaws.com/0/76385/c4877a03-e4cf-24f4-b509-36bce45b2427.png)
もし、エラーが出て書込みされない場合、MACのディスクユーティリティを実行してUSBメモリのマウント解除をして、再度実行する


##NAOの初期化
これで出来上がったNAO FlasherのUSBメモリを使ってNAOを初期化します

１）NAOの電源が切れている状態で頭の後ろカバーを外し、USBメモリを挿す
２）NAOの電源を長押し（スイッチの回りが青く点滅）でＯＮにする
３）しばらく更新をしているので起動が完了するまで待つ
４）起動したら、NAOとLANケーブルでパソコンを直結する
５）NAOのIPアドレスを聞く（ここではNAOは英語で話します）
６）NAOのIPアドレスをパソコンのブラウザから接続する
７）ブラウザに設定画面が表示してしたら画面に従い設定を行う
Nuxt.jsでモジュールモードのVuexストアのmutationにコンポーネントからアクセスする

vuexの使い方で少しハマったのでメモ。

## Vuexストアの作成
Nuxt.jsにvuexストアを追加します（モジュールモード）。
https://ja.nuxtjs.org/guide/vuex-store/

フォーム画面を追加して、そのフォーム画面用のストアを作ったとします。
画面のvueファイルとstoreのディレクトリ構成はこんな感じ。

```
pages
	┣ index.vue
	┗ myform.vue
store
	┣ index.js
	┗ myform.js
```


## フォームの入力値をvuexで管理する
`myform.js`では、stateの初期値とmutationを定義します。

```javascript:myform.js
export const state = () => ({
  keyword: '',
});

export const mutations = {
  updateKeyWord(state, value) {
    state.keyword = value;
  },
};
```

`myform.vue`では、インプットを作成し、双方向算出プロパティ（v-model）で`myform.js`のstateと紐付けます。`myform.js`内で定義したmutationをsetter経由で呼び出します。
参考：https://vuex.vuejs.org/ja/forms.html

```javascript:myform.vue
<template>
  <v-form ref="form">
    <v-text-field
      label="キーワード"
      :counter="10"
      required
      v-model="keyword"
    ></v-text-field>
  <v-form>
</template>

export default {
  name: 'myform',
  computed: {
    keyword: {
      get() {
        return this.$store.state.myform.keyword;
      },
      set(value) {
        this.$store.commit('search/updateKeyword', value);
      },
    },
  },
}
```
ちなみにこのフォームのコンポーネントは[vuetify](https://vuetifyjs.com/components/forms)のものを利用しています。

## ハマりどころ
### mutationの呼び出し方
下記のように、`storeモジュールのファイル名`/`mutationの関数名`で呼び出してやる必要があります。

```javascript
this.$store.commit('search/updateKeyword', value);
```

### 双方向算出プロパティを入れ子にできない（未解決）
適切な表現になっているかはわかりませんが、stateを入れ子状の構造にして、対応するmutationや双方向算出プロパティも合わせたいなと思っていましたが、出来ませんでした。

```javascript:myform.js
export const state = () => ({
  params: {
  	keyword: '',
  },
});

export const mutations = {
  params: {
  	updateKeyWord(state, value) {
   	  state.keyword = value;
    },
  },
};
```

```javascript:myform.vue
<template>
  <v-form ref="form">
    <v-text-field
      label="キーワード"
      :counter="10"
      required
      v-model="params.keyword"
    ></v-text-field>
  <v-form>
</template>

export default {
  name: 'myform',
  computed: {
    keyword: {
      get() {
        return this.$store.state.myform.params.keyword;
      },
      set(value) {
        this.$store.commit('search/updateKeyword', value);
      },
    },
  },
}
```
こんな風にしたかったですが、`v-model`の部分でundefinedとなってしまいました。。

2017/12/22 追記
名前空間を使うとうまくいきそう
https://vuex.vuejs.org/ja/modules.html
Rails5版 OR クエリ構築するマン

# 注意

6.2版はこちら

https://qiita.com/ighrs/items/6f18e290fa52d5158051

# 概要

* [Rails 4.2 で Arel を使って OR クエリを構築する](/QUANON/items/d6772127ffc0e7b78759)
* [rails 4.2.8->5.0.2の時に実施した手順メモ](/zenpou/items/950432bae246063786e8)

Rails4 時代に使っていた `where.or` 記述を Rails5 でも活用する

# 理由

Rails5から #or が実装されたため静的な条件なら `where.or` が無くても困らない

```ruby
User.where.or(User.fuga, User.hoge) #=> Rails4#where.or
User.fuga.or(User.hoge)             #=> Rails5#or
```

ただし動的な条件の場合、Rails5#or だけでは可読性が落ち、毎回記述したくない

```ruby
User.where.or(*or_conditions)  #=> Rails4#where.or

first_condition = or_conditions.shift #=> Rails5#or
or_conditions.inject(first_scope) do |merged_scope, scope|
  merged_scope.or(scope)
end
```

# 実装

余り複雑にするとRailsのVerUpでまた困るので引数のハッシュ対応は削除しました

```ruby
ActiveRecord::QueryMethods::WhereChain.include(Module.new do
  def or(first_scope, *scopes)
    or_scope = scopes.inject(first_scope) do |merged_scope, scope|
      merged_scope.or(scope)
    end

    @scope.merge!(or_scope)
    @scope
  end
end)
```

```ruby
or_conditions = [User.where(id: 2), User.where(id: 3)]
User.where(id: 1).where.or(*or_conditions).where(id: 4).to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE `users`.`id` = 1 AND (`users`.`id` = 2 OR `users`.`id` = 3) AND `users`.`id` = 4"
```

# 参考

* [Rails5で順序依存なくSQLを組み立てる_ORクエリ編](0f6313aedf86190e2431)
* [Rails5で順序依存なくSQLを組み立てる_scope編](6269b5391edb94d2dc23)
Elasticsearch.Netで検索条件を動的に生成

開発メモ

　環境：ASP.NET MVC5

商品検索を想定
メーカーの指定がある場合は、検索キーワードに足して検索を行う。

#モデルクラス
```C#
    public class SearchViewModel
    {
        public string Keyword { get; set; } //検索キーワード
        public IList<SearchModel> ResultItems { get; set; }//検索結果
    }

    public class SearchModel
    {
        public string Item_name { get; set; }//商品名
        public int Price { get; set; }//金額
        public string Maker_name { get; set; }//メーカー名
    }
```
#アクション
```C#
        public ActionResult Search(SearchViewModel model, string makerName, string lowerLimitPrice, string upperLimitPrice)
        {   
            //クライアントを生成
            connectionSettings = new ConnectionSettings(new Uri("127.0.0.1"));
            elasticClient = new ElasticClient(connectionSettings.DefaultIndex("hoge"));

            IList<SearchModel> hits = new List<SearchModel>();

            // 検索条件
            var condition = new QueryContainer();
            var search = new SearchDescriptor<SearchModel>();
            search.Type("fuga");
            search.Size(100);//100件取得
         

            //検索キーワードをセット
            if (!string.IsNullOrEmpty(model.Keyword))
            {
                var tq1 = Query<SearchModel>.Term(p => p.Item_name, model.Keyword);
                var tq2 = Query<SearchModel>.Term(p => p.Maker_name, model.Keyword);

                //商品名かメーカー名でヒットするようにshould(OR)でセット
                condition = tq1 || tq2;
            }


            if (!string.IsNullOrEmpty(makerName))
            {
                // メーカー名の条件を生成
                var tq3= Query<SearchModel>.Term(p => p.Maker_name, makerName);

                //メーカー名をmust(AND)で追加
                condition = condition && tq3;
            }


            //価格帯をセット
            if (int.TryParse(lowerLimitPrice, out int lowerLimit) && int.TryParse(upperLimitPrice, out int upperLimit))
            {
                //下限～上限
                var rg = Query<SearchModel>.Range(r => r.Field(p => p.Selling_price).GreaterThanOrEquals(lowerLimit).LessThanOrEquals(upperLimit));
                condition = condition && rg;
            }
            else if (int.TryParse(lowerLimitPrice, out lowerLimit))
            {
                //下限～
                condition = condition && Query<SearchModel>.Range(r => r.Field(p => p.Selling_price).GreaterThanOrEquals(lowerLimit));
            }
            else if (int.TryParse(upperLimitPrice, out upperLimit))
            {
                //～上限
                condition = condition && Query<SearchModel>.Range(r => r.Field(p => p.Selling_price).LessThanOrEquals(upperLimit));
            }


            //検索条件をセット
            search.Query(q => q.Bool(b => b.Must(condition)));


             // 検索結果をリストにセット
            try
            {
                var response = elasticClient.Search<SearchModel>(search);

                foreach (var hit in response.Hits)
                {
                    hits.Add(hit.Source);
                }
            }
            catch
            {
                return null;
            }　

            model.ResultItems = hits;

            return PartialView("_SearchResult", model);
        }
```
git graph

[alias]
    graph = log --graph --date-order -C -M --pretty=format:\"<%h> %ad [%an] %Cgreen%d%Creset %s\" --all --date=short

これを$HOME/.gitconfig　かetc/gitconfig に追加しておくとgit graphが使える。

commitをrebaseしたい時、ブランチがどんな構造になっているか把握したい時など便利。




引用元:http://wp.pxdesign.jp/2014/08/23/git-hierarchy-structure/
[Xcode][macOS]ビルド成功後にシミュレータが起動しない場合の対処法

## 事象

Xcodeでビルド成功するもシミュレータが起動しない場合。
Xcode真ん中上部のテキストバーに"finished running"が表示され、停止（■）ボタンがグレーアウトされる。
今回の記事は、macOSアプリにて確認。

## 原因
プロビジョニングプロファイルが正しく設定されていないため。

## 対処法
* プロビジョニングプロファイルがdebugのものになっているか確認する。
* Automatically manage signingを使用しても良い。

## 参考文献
https://stackoverflow.com/questions/10337100/finished-running-on-iphone

## 備考
これまでプロジェクトを作り直して対処していたがプロビジョニングプロファイルの設定ミスが根本的な原因でした。
TypeScriptにおけるEnumと定数Mapの違い

もしあなたがReduxアプリを書いているなら、次のようなケースに遭遇するかもしれません。

```
// @actions.ts
export type Actions = {
  readonly type: Action
}

export enum Action1 {
  FETCH_DATAS = 'FETCH_DATAS',
  RECEIVE_DATAS = 'RECEIVE_DATAS',
}

export const Action2 = {
  FETCH_DATAS: 'FETCH_DATAS',
  RECEIVE_DATAS: 'RECEIVE_DATAS',
}



// @reducers.ts
import {Actions, Action1, Action2} from './reducers'
...
```

**Action1, 2**は一見等価のように見えますが、次のような明確な違いがあります。

```
Action1.FETCH_DATAS = 'FOO' // Error
Action1.FOO = 'FOO' // Error
Action2.FETCH_DATAS = 'FOO' // NOT Error
Action2.FOO = 'FOO' // Error
```

つまり「enumの方が**不変性（Immutable）の保存**において優れている」と言え、個人的には「**enumの使用を推奨**」しています。
Rails5.1で順序依存なくSQLを組み立てる_ORクエリ編

#　Rails5.2で解決済み【追記】

[Avoid duplicate clauses when using #or #29950](https://github.com/rails/rails/pull/29950)
で修正されており、取り込まれた5.2で解決しました

# 前提

[Rails5で順序依存なくSQLを組み立てる_scope編](6269b5391edb94d2dc23)
本記事では 上記記事にある scope 内の `unscoped` に関する説明は省略します

# 概要

Rails5 で ActiveRecord に or クエリが導入されましたが適当に作ってると危ない
定義順に生成されるため「前条件はOR内」「後条件はOR外」になります

```ruby
User.where(id: 1).where(id: 2).or(User.where(id: 3)).where(id: 4).to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE (`users`.`id` = 1 AND `users`.`id` = 2 OR `users`.`id` = 3) AND `users`.`id` = 4"
```

これを 「2 or 3」 に限定したい場合はどうすれば良いでしょうか

# 後方定義

ORの挙動が周知されていればこれでも大丈夫でしょう

```ruby
User.where(id: 2).or(User.where(id: 3)).where(id: 1).where(id: 4).to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE (`users`.`id` = 2 OR `users`.`id` = 3) AND `users`.`id` = 1 AND `users`.`id` = 4"
```

しかし順序依存はスコープで発生すると大変です
せっかくスコープで定義したのに、使う時に内部実装を考慮しなくてはいけません

```ruby
class User
  scope :hoge1,  -> { where(id: 1) }
  scope :hoge23, -> { where(id: 2).or(unscoped.where(id: 3)) }
  scope :hoge4,  -> { where(id: 4) }
end

User.hoge23.hoge1.hoge4.to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE (`users`.`id` = 2 OR `users`.`id` = 3) AND `users`.`id` = 1 AND `users`.`id` = 4"

User.hoge1.hoge23.hoge4.to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE (`users`.`id` = 1 AND `users`.`id` = 2 OR `users`.`id` = 3) AND `users`.`id` = 4"
```

# merge

merge で範囲を限定させるとSQLが括弧で括られ独立します

```ruby
User.where(id: 1).merge(User.where(id: 2).or(User.where(id: 3))).where(id: 4).to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE `users`.`id` = 1 AND (`users`.`id` = 2 OR `users`.`id` = 3) AND `users`.`id` = 4"
```

順序依存がなくスコープを利用する際に、順番を意識する必要がありません

```ruby
class User
  scope :hoge1,  -> { where(id: 1) }
  scope :hoge23, -> { merge(unscoped.where(id: 2).or(unscoped.where(id: 3))) }
  scope :hoge4,  -> { where(id: 4) }
end

User.hoge1.hoge23.hoge4.to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE `users`.`id` = 1 AND (`users`.`id` = 2 OR `users`.`id` = 3) AND `users`.`id` = 4"

User.hoge23.hoge1.hoge4.to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE (`users`.`id` = 2 OR `users`.`id` = 3) AND `users`.`id` = 1 AND `users`.`id` = 4"
```

# 参考

* [Rails5 の or クエリがバグを誘発しそうで超怖い](http://monmon.hatenablog.com/entry/2016/08/04/135935)
* [ActiveRecordの #or を使うときは、こう考えると良さそう](http://nisshiee.hatenablog.jp/entry/2017/07/03/180056)
Rails5.1で順序依存なくSQLを組み立てる_scope編

#　Rails5.2で解決済み【追記】

[Avoid duplicate clauses when using #or #29950](https://github.com/rails/rails/pull/29950)
で修正されており、取り込まれた5.2で解決しました

#　概要

自身参照scopeの場合、Relationの繋ぎ方(順序)によってはSQLの重複が発生した
意図しない挙動になるのでなるべく避けたい

# 具体的な挙動

実際に自身参照scopeが必要な場合は複雑なものになるが検証のため以下を用いる

```ruby
class User
  scope :fuga, -> { where(id: where(type: 'fuga')) }
end
```

scope前に条件がある場合はscope内の自己参照部分にもその条件が入る(id=1の重複)

```ruby
User.where(id: 1).fuga.to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE `users`.`id` = 1 
    AND `users`.`id` IN (
        SELECT `users`.`id` FROM `users` 
        WHERE `users`.`id` = 1 AND `users`.`type` = 'fuga'
    )"
```

scope後に条件がある場合はscope内の自己参照部分にはその条件が入らない

```ruby
User.fuga.where(id: 1).to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE `users`.`id` IN (
        SELECT `users`.`id` FROM `users` 
        WHERE `users`.`type` = 'fuga'
    ) AND `users`.`id` = 1"
```

条件が重なるだけで出力結果に違いはないが順序依存で重複の有無が変動する

## 問題か否か

例えば重いサブクエリの場合は重複が問題になるかもしれない

```ruby
User.large_subquery.fuga.to_sql #=> 遅くなるかも
User.fuga.large_subquery.to_sql #=> 通常
```

例えば大量データのテーブルならindex次第で重複が有効かもしれない

```ruby
User.cutdown_subquery.fuga.to_sql #=> 速くなるかも
User.fuga.cutdown_subquery.to_sql #=> 通常
```

ただ、上記のような順序依存があるのが好ましくないと感じる
作った当時は調整できても後で修正する時に事故になる危険性があり保守性が落ちる
調整が必要ならその調整が崩れないように宣言しておくほうが安心する

```ruby
# データが多く高速化のためサブクエリにも適用しておく必要がある
scope :cutdowned_fuga, -> { where(id: cutdown_subquery.fuga) }
```

# 順序依存を無くす方法

引き継がないことを定義すれば良い

```ruby
class User
  scope :fuga, -> { where(id: unscoped.where(type: 'fuga')) }
end
```
そうすれば順序を問わず重複しない

```ruby
User.where(id: 1).fuga.to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE `users`.`id` = 1 AND `users`.`id` IN (
      SELECT `users`.`id` FROM `users` WHERE `users`.`type` = 'fuga'
    )"

User.fuga.where(id: 1).to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE `users`.`id` IN (
        SELECT `users`.`id` FROM `users` WHERE `users`.`type` = 'fuga'
    ) AND `users`.`id` = 1"
```

# 注意: 間違えやすい方法

クラスから呼び新しいRelationにすれば良いと考えやすい

```ruby
class User
  scope :fuga, -> { where(id: User.where(type: 'fuga')) }
end
```

実際には前条件が付いてしまう、同じRelationキャッシュを使っている？

```ruby
User.where(id: 1).fuga.to_sql
=> "SELECT `users`.* FROM `users` 
    WHERE `users`.`id` = 1 AND `users`.`id` IN (
        SELECT `users`.`id` FROM `users` 
        WHERE `users`.`id` = 1 AND `users`.`type` = 'fuga'
    )"
```

# 参考

残念ながら見つかりませんでした
`unscoped` で調べても `default_scope` の解除方法しか出てこない...