OmniAICreator/Qiita-1.07M huggingface dataset:
【Hubot】チャットからHubotとJenkins経由でEC2インスタンスのステートを操作する

![Flowchart.png](https://qiita-image-store.s3.amazonaws.com/0/67591/29137321-20ff-8128-7399-9b637d8c8b37.png)

#はじめに

AWS CLIの勉強がてらにやってみた内容です。

１　チャットツールでJenkinsのジョブの実行を唱える

２　HubotがJenkinsにジョブを実行しろと伝達

３　Jenkinsがジョブに登録されたインスタンスを破壊(Terminate)するコマンドを実行



遠隔で手軽にサーバの操作ができるのは便利です。
チャットツールは「slack」でも「Hipchat」でも「chatwork」でもどれでもいいです。
（chatworkでやりました）


#Hubotの設定

Jenkinsと連携させなければいけません。
とは言ってもスクリプトを書く必要はありません。

『hubot-scripts.json』を修正します。

```json:hubot-scripts.json
["jenkins.coffee"]



```
次にJenkins連携用の環境変数を設定します。

```

export HUBOT_JENKINS_URL=YourJenkinsUrl
export HUBOT_JENKINS_AUTH=xxxxxx:xxxxxx

```

「HUBOT_JENKINS_AUTH」にはコロン区切りでJenkinsのユーザー名とパスワードを入力してください。

これでHubotの設定は以上です。


#Jenkinsのジョブ設定

本筋から外れるので、詳しく説明しませんが、Jenkinsが動くサーバでAWS CLIをインストールしてコマンド操作ができる状態にしておきます。

さらに、

『AWSマネジメントコンソール』
↓
右上メニュー『Security Credentials』
↓
『Access Keys (Access Key ID and Secret Access Key)』

から「Access Key ID」と「Secret Access Key」を控えておく。

で、ジョブ作ってシェルスクリプトを書きます。

![スクリーンショット 2015-04-02 15.36.29.png](https://qiita-image-store.s3.amazonaws.com/0/67591/746b92a0-747b-2be1-a05b-9c892a085aab.png)

```


export WORKSPACE
sh -x ${WORKSPACE}/instart.sh

```

保存する。

実行ファイルでさきほどの「Access Key ID」と「Secret Access Key」を記入ます。

```normal:XXXX.sh

#!/bin/bash -xe

aws configure set aws_access_key_id AWSアクセスキーID

aws configure set aws_secret_access_key AWSシークレットアクセスキーID

aws ec2 terminate-instances --region=ap-northeast-1 --instance-ids=インスタンスID

```

Jenkins側もこれで以上です。

#chatworkで実行

あとは禁断の台詞を唱えるだけです。

![スクリーンショット 2015-04-02 16.47.40.png](https://qiita-image-store.s3.amazonaws.com/0/67591/6107a93c-5fc7-0d4b-5c0e-b6eee191f4ee.png)

うまくいけば、破壊に成功しているでしょう。


#最後に

アメリカの核戦略ミサイルの発射プロセスに似てます。
めちゃくちゃ単純に解釈すると

大統領(ユーザー)が命令
↓
補佐官・取り巻き（Hubot）がシークレットコードを送信
↓
SSBNの士官連中(Jenkins)が受け取ったシークレットコードを基に協議・合意
↓
発射
カスタムチェックの作り方 - Detector / Detector2

社内共有用に英語化する前の下書き

# どっちのインタフェース使うの？
カスタムチェックを作ろうと FindBugs の既存のチェックを調べてみると Detector 系と Detector2 系の二種類があることに気が付く。
どちらを使うべきなのだろうか？

## 結論
Detector を使え

## 全体像
どうやら FindBugs 2 以降、Detector2 が処理の中心で、Detector 系のチェックは DetectorToDetector2Adapter というアダプターを介して処理されるようになった模様。

しかし、便利なクラス、メソッドは全部 Detector 側にあり Detector2 側には移植されていない。
そのため、お手軽に何らかのバグを検出してレポートしたいなら素直に Detector を使った方がいい。
新しいインタフェースができたら積極的に乗りかえていくべきだよね、と Detector2 系に突っ込むと（特にまっとうなレポートを作ることが）難しくて頭を抱えることになる。
【メモ】Vagrantのsynced_folderへのアクセスがめっさ遅くなった

# 前提

Mac: 10.10.2
Vagrant: 1.7.2
Guest Additions: 4.3.16

# 本文
```rb
vm01.vm.synced_folder "~/Vagrant/vm01/", "/var/apps", owner: 'vagrant', group: 'vagrant', mount_options: ['dmode=777', 'fmode=777']
```

こう書いてて、ansibleとかで/var/apps以下にフォルダ作ったりとかするときにめっさ遅くて泣きたくなったので調べたら以下の記事を発見した

https://coderwall.com/p/uaohzg/use-nfs-to-speed-up-your-vagrant

どうやらnfsの方が速いとのことだったので、nfsにしてみた。(ホストでnfsdが必要っぽいのでWindowsだとそのまま使えないかも)

```rb
vm01.vm.synced_folder "~/Vagrant/vm01/", "/var/apps", :nfs => { mount_options: ['dmode=777', 'fmode=777'] }
```

これだと権限まわりがちょっとアレな感じになってしまったので、さらに調べたら以下のにたどり着いた

http://stackoverflow.com/questions/23798498/vagrant-synced-folder-options

http://www.rubydoc.info/gems/vagrant-bindfs/0.2.4/frames


nfsでマウントしたゲスト側のディレクトリをさらにバインドしてんのかな？

```rb
vm01.vm.synced_folder "~/Vagrant/vm01/", "/host_mount", :nfs => { mount_options: ['dmode=777', 'fmode=777'] }
vm01.bindfs.bind_folder "/host_mount","/var/apps", :owner => "vagrant", :group => "vagrant", :'create-as-user' => true, :perms => "u=rwx:g=rwx:o=rwx", :'create-with-perms' => "u=rwx:g=rwx:o=rwx", :'chown-ignore' => true, :'chgrp-ignore' => true, :'chmod-ignore' => true
```

とりあえずこれですっごく速いってわけではないけど、ものすごい遅いってわけではなくなったので、一旦これでいくことにした
Amazon Linux AMI 2015.03でLAMP環境を作成する

2015.03時点のyum packageの最新バージョンをインストールします

# Amazon Linux のアップデート

```
# yum update -y
```

# Apache 2.4

## インストール

```
# yum install -y httpd24
```

## 起動

```
# service httpd start
```

# MySQL 5.5

## インストール

```
# yum install -y mysql55 mysql55-server
```

## 起動

```
# service mysqld start
```

## セキュリティ設定 mysql_secure_installation コマンド実行

1. プロンプトが表示されたら、root アカウントのパスワードを入力します。
1. 現在の root パスワードを入力します。デフォルトでは、root アカウントにはパスワードが設定されていないので、Enter を押します。
1. 「Y」と入力してパスワードを設定し、安全なパスワードを 2 回入力します。
1. 「Y」と入力して匿名ユーザーアカウントを削除します。
1. 「Y」と入力して root ログインを無効にします。
1. 「Y」と入力してテストデータベースを削除します。
1. 「Y」と入力して権限テーブルを再ロードし、変更を保存します。

```
# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MySQL to secure it, we'll need the current
password for the root user.  If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): 初回起動時はそのままENTER
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.

Change the root password? [Y/n] y
New password: 安全なパスワードを入力
Re-enter new password: 安全なパスワードを入力
Password updated successfully!
Reloading privilege tables..
 ... Success!

以下は全部 y を入力でいい

Remove anonymous users? [Y/n] y
 ... Success!

Disallow root login remotely? [Y/n] y
 ... Success!

Remove test database and access to it? [Y/n] y
 ... Success!

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MySQL
installation should now be secure.

Thanks for using MySQL!

ここまで表示されればOK
```

# PHP 5.6

## インストール

### php5.6

```
# yum install -y php56
```

### その他モジュール等（各環境で必要な物を選択すると良いでしょう）

```
# yum install -y php56-dba php56-mbstring php56-mcrypt php56-opcache php56-pdo php56-tidy php56-mysqlnd php56-dbg
```

# 起動設定、ファイル設定

## chkconfigで再起動時にhttpd,mysqldを立ち上げる

```
# chkconfig httpd on
# chkconfig mysqld on
# chkconfig iptables off
# chkconfig ip6tables off
確認
# chkconfig
```

## ルートディレクトリ設定

* www グループをインスタンスに追加し、そのグループに /var/www ディレクトリの所有権を与え、グループの書き込み許可を追加します。
* www グループのメンバーがページを更新できます。

```
# groupadd www
# usermod -a -G www ec2-user
# chown -R root:www /var/www
# chmod 2775 /var/www
# find /var/www -type d -exec sudo chmod 2775 {} +
# find /var/www -type f -exec sudo chmod 0664 {} +
```

## テストページ作成
```
$ echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
```

## LAMP ウェブサーバーをテスト

テストURLにアクセスしてページ表示
```http://ec2-XXX-XXX-XXX-XXX.ap-southeast-2.compute.amazonaws.com/phpinfo.php```
~~僕が考えたさいきょうの~~Railsの独自config/*.yml 読み込み処理

ガイド読むの大事。
https://guides.rubyonrails.org/v4.2/configuring.html#custom-configuration

```config/hoge.yml
default: &default
  message: "hoge"

development:
  <<: *default

production:
  <<: *default
  message: "foo"

```

```config/application.rb
module XXXX
  class Application < Rails::Application
    ...
    config.x.hoge = ActiveSupport::InheritableOptions.new(config_for(:hoge))
    ...
  end
end
```
```rb
# bin/rails console development
Rails.application.config.x.hoge.message
# => "hoge"

# bin/rails console production
Rails.application.config.x.hoge.message
# => "foo"
```

# 以下、車輪の再発明　(はずかしい！)


initializersに定義しといて

```config/initializers/load_config.rb
def load_config(key, filepath)
  yml = YAML.load_file filepath rescue nil
  abort "No such file #{filepath}" unless yml

  config = yml[Rails.env]
  abort "No such environment #{Rails.env} on #{filepath}" unless config

  Rails.application.config.send(
    "#{key}=".to_sym,
    ActiveSupport::InheritableOptions.new(config.deep_symbolize_keys)
    )
end

load_config :hogeconf, Rails.root.join('config', 'hoge.yml')
```

ファイル置いて

```config/hoge.yml
default: &default
  message: "hoge"

development:
  <<: *default

production:
  <<: *default
  message: "foo"

```

実際に使う

```rb
# bin/rails console development
Rails.application.config.hogeconf.message
# => "hoge"

# bin/rails console production
Rails.application.config.hogeconf.message
# => "foo"

```

~~本当にさいきょうかは知らない~~
BaaSのリストアップ

# 大手会社
* [Parse(facebook)](https://www.parse.com/)
* [Kinvey](http://www.kinvey.com/) 
* [Azure Mobile Services(microsofrt)](http://azure.microsoft.com/ja-jp/services/app-service/mobile/)
* [Cloud Endpoints(google)](https://cloud.google.com/endpoints/)
 * [旧Mobile Backend Starter](https://cloud.google.com/cloud/samples/mbs)
* [Mobile Native Push Notiﬁcation(Amazon)](http://aws.amazon.com/sns/)
 * [cognito](http://aws.amazon.com/jp/cognito/)
* [salesforce Platform Mobile Services](http://www.salesforce.com/platform/mobile/)
* [CloudKit(Apple)](https://icloud.developer.apple.com/dashboard/)

# Players in Japan
* [アピアリーズ](http://www.appiaries.com)
* [Kii Cloud](http://jp-cloud.kii.com/)
* [Nifty Cloud Mobile Backend](http://mb.cloud.nifty.com)
* [appC cloud](http://app-c.net)
* [Fairy](http://www.idcf.jp/nativeapps/)

# その他
* [appery.io](http://appery.io)
 * 旧Tiggzi
* [shephertz](http://api.shephertz.com)
* [kumulos](http://www.kumulos.com)
* [applicasa](http://www.applicasa.com)
* [anypresence](http://www.anypresence.com)
* [apiomat](http://www.apiomat.com)
* [appacitive](http://www.appacitive.com)
* [CloudMine](https://cloudmine.me/)
* [QuickBlox](http://quickblox.com)
* [mobeelizer](http://mobeelizer.com)
* [Appcelerator Cloud Services](http://www.appcelerator.com/cloud/)
* [Buddy](http://www.buddy.com)
* [iknode](http://www.iknode.com)
* [dreamfactory](http://www.dreamfactory.com)
* [fatfractal](http://fatfractal.com)
* [netmera](http://www.netmera.com )
* [apigee](http://developers.apigee.com)
* [sencha](http://www.sencha.com/space/)
* [feedhenry](http://www.feedhenry.com)
* [Pankia](http://pankia.com/)
* [baasday](http://www.baasday.com)
* [stamplay](https://stamplay.com/index/2?utm_expid=86132196-6.9WydCmKETdWxF7Qg84k0SQ.2&utm_referrer=http%3A%2F%2Fqiita.com%2Fcognitom%2Fitems%2Fead2837115bc900a0acc)
* [backbeam](http://backbeam.io/)
* [backendless](https://backendless.com/)
* [http://www.telerik.com/backend-services](http://www.telerik.com/backend-services)
* [urbanairship](http://urbanairship.com/)


# realtime service
* [firebase](https://www.firebase.com/)

# source code
* [app-pot](http://app-pot.jp/)
* [Helios.io](http://helios.io/)
* [deployd](http://deployd.com/)
* [hoodie](http://hood.ie/)
* [baasbox](www.baasbox.com)
* [openmobster](http://code.google.com/p/openmobster/)
* [LoopBack Framework](https://strongloop.com/node-js/loopback-framework/)
* [usergrid](http://usergrid.incubator.apache.org/)


# shutdown
* [StackMob](http://www.publickey1.jp/blog/14/baasstackmob5paypal.html)
* [proxomo](http://www.proxomo.com)
* [goinstant](http://www.instigatorblog.com/goinstant-is-gone/2014/10/22/)

# 分類
* enterprice
 * [feedhenry](http://www.feedhenry.com/)
 * [anypresence](http://www.anypresence.com/)
* gaming
 * [applicasa](http://www.applicasa.com)
* O2O/engagement 
 * [netmera](http://www.netmera.com ) 
* advertising
 * [appC cloud](http://app-c.net)
MOGOK + Route53 + さくらのメールボックス で Rails アプリを公開する

Rails で作成した Web サービスを、お手軽に公開したい。
サーバの構築とか運用はしたくないので、全てクラウドのサービスにお任せしたい。

---

**Web + アプリケーション + DB**
> **MOGOK ( PaaS ) を利用**
Heroku と Sqale と迷ったが、サービスイン後のスケールを考慮し、IIJ さんの PaaS、Mogok を選択。


**DNS**
> **AWS Route53 を利用**
ドメインは お名前.com なり、バリュードメインなり、ムームードメインなりお好きなトコロで取得しておく。

**メール (SMTP, POP)**
> **さくらのメールボックス を利用**
独自ドメインでのメールアドレス作成 + 送受信がしたい。
Rails の ActionMailer からも さくらのメールボックスの SMTP サーバを利用してメールを送信する予定。
メール送信のみなら SendGrid や AWS SES が良いかも。

---

## 1. Mogok ユーザ登録 + 初期設定

[MOGOK]
(http://mogok.jp/)
※ 個人ならば heroku 同様、無料で利用可能なプランあり


ユーザ登録後のマイページメニューより「アプリケーション登録」を行う。

作成が完了すると、メニュー 「アプリケーション管理」のアプリケーション一覧へ、作成したアプリケーションが表示される。
ここの URL を 後ほど Route53 の設定で利用する。


## 2. さくらのメールボックス ユーザ登録 + 初期設定

[さくらのメールボックス]
(http://www.sakura.ne.jp/mail/)
※ 2週間のお試し後、年間 1,029 円かかる

ユーザ登録後のサーバコントロールパネルで、初期ドメインを確認しておく。
あわせてメニュー 「サーバ情報の表示」より、ホスト名を確認しておく。
この初期ドメインとホスト名を、次の Route 53 の設定で利用する。


## 3. AWS ユーザ登録 + Route53 設定 + S3 設定

[AWS - Amazon Web Services]
(http://aws.amazon.com/jp/)
※ 無料枠の範囲内で 12ヶ月間、無料でのお試し利用が可能

PaaS を独自ドメインで利用する際、ネイキッドドメインを設定する事はできず、www.独自ドメインでアクセスする事となるため、その設定を行う。

S3 へバケット作成、独自ドメインへのアクセスは、このバケットへ。
バケットへアクセスされた際に redirect で www.独自ドメイン へとばす。


### 3.1 S3 の設定

S3 の管理画面より「Create Bucket」を選択。
Bucket Name へ、独自ドメインを入力 ( hogehoge.com 等 ) 。
Region は Tokyo を選択。
「Create」ボタンを押下し、バケット作成。

一覧の該当バケットのリンク ( hogehoge.com 等 ) をクリック。
右上の「Properties」ボタンを押下し、設定を変更する。

「Static Website Hosting」をクリック、Redicrect all requests to another host name へチェックを入れ、Redirect all requests to へ、www.独自ドメインを入力 ( www.hogehoge.com 等 )。
「Save」ボタンを押下し、編集を完了。


### 3.2 Route53 の設定

Route53 の管理画面のメニューより「Hosted Zones」を選択、「Create Hosted Zone」ボタンを押下、Domain Name へ、独自ドメインを入力 ( hogehoge.com 等 ) 。
「Create」ボタンを押下し、Hosted Zone を作成。

一覧の該当ゾーンのリンク ( hogehoge.com 等 ) をクリック。
「Create Record Set」ボタンを押下し、以下、DNS の各レコードを作成。

※ デフォルトで作成されている NS レコードは、後の DNS サーバの切り替えで利用するので覚えておく。


|設定項目|設定する値|
|:--|:--|
|Name|www|
|Type|CNAME|
|Value|hogehoge.ruby.iijgio.com|
※ hogehoge.ruby.iijgio.com は MOGOK で作成したアプリケーションの URL

|設定項目|設定する値|
|:--|:--|
|Type|A|
|Alias|Yes|
|Alias Target|S3 で作成したバケット名が表示されるので、それを選択|

|設定項目|設定する値|
|:--|:--|
|Type|MX|
|Value|10 hogehoge.sakura.ne.jp|
※ hogehoge.sakura.ne.jp は、さくらのメールボックスの初期ドメイン名

|設定項目|設定する値|
|:--|:--|
|Type|TXT|
|Value|"v=spf1 a: www1000.sakura.ne.jp -all"|
※ www1000.sakura.ne.jp は、さくらのメールボックスのホスト名

|設定項目|設定する値|
|:--|:--|
|Name|mail|
|Type|CNAME|
|Value|hogehoge.sakura.ne.jp|
※ hogehoge.sakura.ne.jp は、さくらのメールボックスの初期ドメイン名


## 4. DNS サーバの切り替え

取得したドメインの管理会社 ( お名前.com、 ムームードメイン、バリュードメイン ... ) のコントロールパネルより DNS サーバの切り替えを行う。

**ムームードメインの場合**

コントロールパネルへログイン -> メニュー 「ドメイン管理」の「ネームサーバ設定変更」を選択。
該当ドメインの「ネームサーバ設定変更」ボタンを押下。
GMOペポバ以外のネームサーバを使用するにチェックを入れ、ネームサーバ 1 〜 4 へ、Route53 の NS レコードの Value を登録。


## 5. MOGOK へ独自ドメインの追加

下記 MOGOK の公式ドキュメントを参考に、ドメインを登録する。

[MOGOK Documents ドメイン管理メニュー]
(http://mogok.jp/documents/webui_custom_domain)

※ CNAME の設定は、Route53 の設定で既に完了している。


## 6. さくらのメールボックスへ独自ドメインの追加

下記 さくらのメールボックス の公式ドキュメントを参考に、ドメインを登録する。

[さくらのサポート情報 ドメインを利用(他社で取得・管理のドメイン)]
(https://help.sakura.ad.jp/app/answers/detail/a_id/2205)

※ 独自ドメインを設定するの部分を参照。
※ STEP4 のネームサーバの変更は不要。さくらのネームサーバを利用していないので。

---

以上。
OpenGL ESで使えるデータ型

OpenGL ESで使えるデータ型

| 型名称 | Javaでの型 |扱える値の範囲 |容量|
|:-----------|------------:|:------------:|:--------------:|
| CL_UNSIGNED_BYTE      |     byte |    0~255  | 1byte|
| GL_UNSIGNED_SHORT |      short |    0~65535   | 2byte|
| GL_SHORT      |        short |    -32768~32737     | 2byte|
| GL_FIXED       |        int |     -2147483648~-2147483647   | 4byte|
| GL_FLOAT       |       float |   ±1.4e-45~±3.4028234e38  | 4byte
ubunutu14.04 + Windows8.1 でSynergyを問題なく動かす

別PCにインストールされたWindowsとLinuxを一つのキーボードやマウスで自由に行き来できるソフトの定番として、Synergyというものがあります。

昔のバージョンでは無料だったのですが、ここ１年の間に有料化してしまっており、無料で公開されていた最終バージョン（1.4.18）を使うと次のような辛みに直面します。

* Windowsでウィンドウをアクティブにしようとしても前面に出てこない時がある
* Windowsをサーバにしているとき、UbuntuにShiftキーが送られていないのでShift+な操作ができない(大文字が打てなかったりかなり不便)

幸いにして、ソースは公開されていますし、Own riskで自分でコンパイルして使う分には無料なので、これをなんとかしようという話です。
（もともと有料化したのは、サポートが割に合わないとか、開発者が募金募っても全然こなくてがっかりしたとかそういう理由みたいですし。。。）

ちなみに、私の場合はこんな感じです。
Synergyサーバ：Windows 8.1
クライアント： Ubuntu 14.04


##ソースの場所とか

ソースはgithubにあります。
https://github.com/synergy/synergy/

実はコンパイルしなくても公式にNightly Builds版があったりします。
ブランチ単位などで各環境のものがアップされていますね。
https://synergy-project.org/nightly


どのソースを使うか、、、ですが、取り合えず自分が遭遇したバグを回避できればよいので
Changelogを調べました。で、やはり記述がありました。

```bash:
Bug #4349 - Mouse click does not always bring window to front
Bug #4055 - Shift keys are not sent to clients (Win 8.1 server)
```

ここから、修正済みなバージョンは1.6.3以降ならよさそうです。

で、masterのCommitlogから「Merge branch 1.6.3-stable」の文字があり、このツリーを使えばよい感じになりそうなので、NightyBuild版から「synergy-master-be06c19-Source.tar.gz」を使うことにします。
(バージョンは1.7相当になります)


##Windows 8.1へ導入

最初はビルドしようかなと思いましたが、だいぶめんどくさい感じがしたのでここはありがたくNighty build版をインストールしました。

なお、インストールしたのはこれです。
synergy-master-be06c19-Windows-x64.msi

あとはいつものように設定すればOKでした。


##Ubuntu 14.04LTSへ導入

これもNighty build版にdebパッケージがあったのですが、ビルドしなおしたほうがよさそうな感じだったので、これはソースから自力ビルドします。

といっても難しくなく、公式のWiki http://synergy-project.org/wiki/Compiling をそのままやればOKでした。

```bash:
sudo apt-get install cmake make g++ xorg-dev libqt4-dev libcurl4-openssl-dev libavahi-compat-libdnssd-dev
```

で必要パッケージをインストールしてから

```bash:
./hm.sh conf -g1
./hm.sh build
```

で、ビルドしたディレクトリのbin/以下にsynergyが入ります。

あとはusr/binにコピーするなり好きにするなり、、ですが、

```bash:
./hm.sh package
```

で、debパッケージが作れるので、作ってしまってからdpkgで新しくインストールすると、後々面倒がなくなりますね。
MySQLの諸々の設定


# インストール
```
$ brew install mysql
```

# rootでログインする時にパスワードをセットする．(初期)
まずrootでログインする．
その後rootに対してパスワードを設定する．
設定後に権限の反映を行う処理をすると終わり．

```
$ mysql -u root


$ SET PASSWORD for root@localhost = PASSWORD('自分の好きなパスワード');
$ SET PASSWORD for root@'127.0.0.1' = PASSWORD('自分の好きなパスワード');
$ SET PASSWORD for root@'::1'  = PASSWORD('自分の好きなパスワード');


$ FLUSH PRIVILEGES;
```

パスワード設定後にログインする時は

```
$ mysql -u root -p
```

# ユーザの作成

```
CREATE USER ユーザ名
```

# 権限の付与

```
GRANT ALL PRIVILEGES ON 'DB名'.'テーブル' TO 'ユーザ名@'ホスト名';
```

権限の一覧は[こちらのサイトへ](http://www.dbonline.jp/mysql/user/index5.html "権限の一覧参考サイト")

### GRANT OPTION
このオプションを設定すると他のユーザに対して，自分が与えられている権限まで与える事ができるというオプション．

```
GRANT ALL PRIVILEGES ON 'DB名'.'テーブル' TO 'ユーザ名'@'ホスト名' WITH GRANT OPTION;
```
rbenv-gemsetでgemsetの作成と選択


# 作成

例) Ruby2.1.0の中にSampleProjectというgemsetを作成する．

```
$ rbenv gemset create 2.1.0 SampleProject
```

# 選択
gemsetの選択には，どのgemsetを使うかを指定したファイルをプロジェクトのルートに配置する．

```
$ echo > .rbenv-gemsets SampleProject
```

# 作ったGemsetを確認する．

```
$ rbenv gemset list
```

# 現在有効なGemsetを確認する．

```
$ rbenv gemset active
```
appcompat 21+でPreferenceActivityを実現する方法

appcompat-22ならもっと簡単に実現できます。
⇒ [appcompat 22でPreferenceActivityを実現する方法](http://qiita.com/takke/items/cbea9de0162d8657a6d2)

----

appcompat-21以降ではActionBarActivityを継承したActivityがMaterialテーマになりますが、いわゆる設定画面を実現するPreferenceActivityはActionBarActivityを継承していないために実にかっこ悪い設定画面になります。

|PreferenceActivity|ActionBarActivity+PreferenceFragment|
|----|----|
|![appcompat-v21対応(対応前).png](https://qiita-image-store.s3.amazonaws.com/0/39221/286f9804-bc17-c34f-c2f6-fce9ef6185cb.png)|![appcompat-v21対応(対応後).png](https://qiita-image-store.s3.amazonaws.com/0/39221/daa8c9c0-53b1-b2f8-2d06-234a6ef4073b.png)|

そこで PreferenceActivity の代わりに ActionBarActivity+PreferenceFragment を使うのが定石です。Jake神もそう言ってます。

[AppCompat v21 — Lollipop 搭載前のデバイスにマテリアル デザインを！ - Google Developer Japan Blog](http://googledevjp.blogspot.jp/2014/11/appcompat-v21-lollipop.html)
>''Preferences で AppCompat を使用するにはどうしたらいいですか？ ''
API v11 以上のデバイスでは、引き続き ActionBarActivity で PreferenceFragment を使用できます。それより古いデバイスではマテリアル スタイル化されていない、通常の PreferenceActivity を提供する必要があります。

# Android2.x対応のためには？

PreferenceFragment は Android 2.x 非対応なので PreferenceFragment-Compat を利用するといいです。

- [Machinarius/PreferenceFragment-Compat](https://github.com/Machinarius/PreferenceFragment-Compat)

RingtonePreference は動作しない場合があるので [Not work with RingtonePreference · Issue #1 · kolavar/android-support-v4-preferencefragment](https://github.com/kolavar/android-support-v4-preferencefragment/issues/1) を参考に修正してください。
RSSの最新情報だけを取得(修正&加筆版) 

[RSS2.0の最新情報を取得](http://qiita.com/ao_love/items/39600dc45debe031696d)
に頂いたコメントを受けて修正＆`RSS1.0`と`Atom`版も追加

```php:RSS.php
    $RSS = simplexml_load_file($url);
    
    if( $RSS->channel->item[0] ){//RSS2.0
        
        $site_name = (string)$RSS->channel->title;
        $item  = $RSS->channel->item[0];
        $title = (string)$item->title;
        $link  = (string)$item->link;
        $date  = (string)$item->pubDate;

    }elseif( $RSS->item[0] ){//RSS1.0
        
        $site_name = (string)$RSS->channel->title;
        $item  = $RSS->item[0];
        $title = (string)$item->title;
        $link  = (string)$item->link;
        //dc:dateのデータはそのままでは取得できないのでchildrenメソッドを呼ぶ
        $date  = (string)$item->children('http://purl.org/dc/elements/1.1/')->date;

    }elseif( $RSS->entry[0] ){//Atom
        
        $site_name = (string)$RSS->title;
        $item  = $RSS->entry[0];
        $title = (string)$item->title;
        $link  = (string)$item->link->attributes()->href;
        $date  = (string)$item->published;

    }
```

複数サイトから取得するため、サイト名も取得するようにしました。
日付のところは実際の表示の際は

```php
$date = date("Y.m.d",strtotime($date));
```

として表示させています。
bundle execとかdb:createとかが何をしているのか


Railsで``bundle exec ~~~~~``とか``rake db:create``とかが一体何をしているのかよく知らなかったので調べてみた．

# bundle execとは?
例えばコマンドラインで

```
$ bundle exec rails s
```
と入力して実行するとRailsサーバーが立ち上がる．
しかし，

```
$ rails s
```
と入力して実行してもRailsサーバーは立ち上がる．

じゃあ，前に付いている``bundle exec``って何をしているのかという話なんです．
``bundle exec``とつけて実行すると，そのRailsプロジェクトのGemfileで指定された環境で実行する事ができるようになります．

# bundle install --without production
--without productionオプションを追加すると，本番用のgemはローカル環境にインストールはされない．

# rake db:createって?
このコマンドを実行すると，Railsプロジェクトのconfigディレクトリの中にあるdatabase.ymlを読み込み，そのファイルに基づいてデータベースを作成します．

# rake db:migrateって?
このコマンドを実行すると，Railsプロジェクトのdb/migrateディレクトリの中にあるスクリプトファイルに基づいてデータベースにテーブルを作成します．

# rake db:seedって?
このコマンドを実行すると，Railsプロジェクトのdbディレクトリの中にあるseed.rbファイルを実行してデータベースにデータを格納します．

# rake master:importって?
このコマンドを実行すると，Railsプロジェクトのlib/tasks内にある該当するスクリプトファイルを実行します．
gulp-uglifyで特定のコメントを残したままJavaScriptをminifyする

## やりたいこと
* hoge-source.jsをminifyしてhoge.jsにする
* hoge-source.jsのファイル先頭にあるライセンス表記はminifyしても残したい

意外と同一ディレクトリ内にminifyして出す例が少なかったのでメモ。

## やったこと
### Gulpとgulp-uglifyを追加

```bash
% npm install --save-dev gulp
% npm install --save-dev gulp-uglify
% npm install --save-dev gulp-rename
```

gulp-renameなしで出力ファイル名指定するやり方が分からず…。


### gulpfile.jsを作成

ポイントは、uglifyに `{preserveComments: 'some'}` を渡すと、

```js

/*! 
  License
*/
```

のように「 **!** 」を追加したブロックコメントを残してくれること。

```js
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');

var source = 'hoge-source.js';
var exportSource = 'hogejs';

gulp.task('minify', function() {
	gulp.src(source)
		.pipe(uglify({preserveComments: 'some'}))
		.pipe(rename(exportSource))
		.pipe(gulp.dest('.'));
});
```

### 実行

```bash
% gulp minify
```

これで、minifyされたhoge.jsが完成。
ターミナルで作業ディレクトリのローテーションが便利

ターミナルで複数のディレクトリで作業するときに使ってる便利なコマンドです。昔から使ってるのですが、Qiitaに無さそうなので追加。

シェルの```pushd```を使うとディレクトリをメモしてくれます。```popd```で戻れるのですが、何度も行き来すると面倒です。

```shell-session
~ $ pushd .
~ $ cd /
/ $ popd
~ $
~ $ cd /
```

そこで、```pushd +1```を使うと、ディレクトリを行き来できます。

```shell-session
~ $ pushd .
~ $ cd /
/ $ pushd +1
~ $ pushd +1
/ $ pushd +1
```

便利そうですね。

しかし、何度も「pushd +1」と書くのは面倒。そこで、aliasしてます。

```shell-session
alias rd='pushd +1'
```

すると、

```shell-session
~ $ pushd .
~ $ cd /
/ $ rd
~ $ rd
/ $ rd
~ $ rd
/ $ rd
~ $ rd
```

これだと、簡単に行き来できます。３つ以上のディレクトリでも、ぐるぐるできます。

> rd: rotate-directory

です。
yum memo


入れといた方がいいパッケージ

`yum-utils`

## インストール

```
# yum install <package name>
```

## アンインストール

```
# yum remove <package name>
```

## アップデート

```
# yum update 
```

## インストールしてるパッケージ一覧

```
# yum list installed
```

## インストールしてるパッケージから抽出

```
# yum list installed | grep <name>
```

## パッケージを検索

```
# yum search <name>
 
 もしくは
 
# repoquery '*<name>*'
```

## パッケージの製作者情報を表示

```
# repoquery --info <name>
```


## パッケージの中身にあるファイル一覧

```
# repoquery --list <package name>
```
arm > ELFファイルからplain binaryへの変換 > arm-none-eabi-objcopy -O binary foo.elf foo.bin

動作環境
    
    arm用ツールが入った状態

ELFファイルを plain binary　形式へ変換する場合は以下のようにする

     $arm-none-eabi-objcopy -O binary foo.elf foo.bin

[参考](http://stackoverflow.com/questions/18999168/how-to-convert-elf-to-dma-format-in-arm)

objcopyはGNU toolsらしい。

他にもformelf(ARM tools)があるようだが、今のところ使わないので説明は割愛する。
Arrays#binarySearchを使うときに注意したいこと

Java Collections Frameworkにある[Arrays#binarySearch](https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html) はこんな感じに使います。

```
int result = Arrays.binarySearch(検索対象配列, 検索キー);
```

resultに見つかった要素のインデックスが入ります。

このメソッドを使う際に注意しておきたいことです。

# (1) 検索対象配列をソートしておく

二分探索なので、ソートしておかないと結果がどうなるかはわかりません。
たまたま期待した結果になるかもしれませんし、ならないかもしれません。

# (2) 見つかったかどうかだけ知りたいときは``>=0``で比較する

``Arrays#binarySearch`` は、検索キーが見つかった配列内要素のインデックスが返ります。

検索キーが見つからないときは、-(配列のサイズ+1)～-1の範囲の値が返ります。

# (3) 検索対象配列に重複する値があると結果は不定

先頭要素のインデックスが返ってきて欲しい気もしますが、二分探索なのでどうなるかはわかりません。
Macbook iPhone iPadのデバイス間でinstant hotspot全滅w


![22.png](https://qiita-image-store.s3.amazonaws.com/0/5222/5996fa20-9e4a-7b94-f49f-81a6aba231c4.png "22.png")

- Macbookのbluetooth環境設定でそれっぽいデバイスのペアリングを削除
- <b><font color=red>Macbookから</font></b>iPad iPhoneをペアリングし直す

※Type2Phone使ってるのでiPad iPhoneからMacbookへはペアリングしてた

![11.png](https://qiita-image-store.s3.amazonaws.com/0/5222/4376c2a9-0a35-7a56-60b7-a5cd197308c9.png "11.png")

<h1>復活！</h1>

<font color=gray>iCloud再ログインせい</font>とか<font color=gray>機内モードにしてみい</font>とか見かけましたが、ぼくの場合だめでした。
vagrantでubuntuにplenv設定

# 0. 説明

vagrantでubunu 14.04にplenv環境を設定したときのメモ


# 1. 環境
ホストOS: windows7 64bit
ゲストOS: Ubuntu 14.04 64bit

＃　内容

Vagrantfileに以下追記

```Vagrantfile

 # yum install関連のシェルスクリプト
 config.vm.provision :shell, :path => "bootstrap.sh"
 # ユーザーを追加するスクリプト
 config.vm.provision :shell, :path => "useradd.sh"

```

```bootstrap.sh

#!/usr/bin/env bash

# build-essential
apt-get install -y build-essential
apt-get install -y git

# expect ユーザー追加用
apt-get install -y expect

```

```useradd.sh

#!/usr/bin/env bash

# -m: ホームディレクトリ作成
# -s: ログインシェル指定
useradd -m yasu -s /bin/bash;

# expectでユーザー追加
# user: yasu, pass: hogehoge
expect -c "
spawn passwd yasu
expect \"New password:\"
send -- \"hogehoge\n\"
expect \"Retype new password:\"
send -- \"hogehoge\n\"
#expect \"passwd: all authentication tokens updated successfully.\"
expect \"passwd: password updated successfully\"
send -- \"exit\n\"
";

# plenv 設定用のスクリプトを実行
sudo -u yasu -i env sh /vagrant/plenv_setup.sh;

```


```plenv_setup.sh

#!/bin/bash

cd;
git clone git://github.com/tokuhirom/plenv.git ~/.plenv;
echo 'export PATH="$HOME/.plenv/bin:$PATH"' >> ~/.bash_profile;
echo 'eval "$(plenv init -)"' >> ~/.bash_profile;

# bash_profileの内容を反映
# source ~/.bash_profile; # for zsh?
. ~/.bash_profile

#download files
git clone git://github.com/tokuhirom/Perl-Build.git ~/.plenv/plugins/perl-build/;
plenv rehash;

plenv install 5.18.1;

plenv global 5.18.1;

plenv install-cpanm;

exit
```
Webアプリが利用するパスワードどこに保存しよう？

## 要約

いまどきのWebアプリでは、twitter/facebookを始め様々な外部WebAPIと連携して利用する事がよくあります。外部APIにはAPI呼び出し用のキーやトークンを必要とするものも多く、それらの扱いに毎回なんとなく引っかかるものを感じていたので、`Keystorage`というコマンドを書きました。

## 背景

Railsのシークレットキー(secret_key_base)や外部APIのトークンを
そのままハードコーディングして、プライベートとはいえgitリモートリポジトリにpushするのは抵抗ありますよね？

よくあるのは、コードの中では環境変数を参照するようにしていて、
その環境変数を起動時に設定してやることで秘密鍵のハードコーディングを避ける方法です。

私は長年この方法を使ってきましたが問題点がありました。

この環境変数に秘密鍵を何処かで設定する必要があり、往々にしてWebサーバの起動スクリプトにハードコーディングすることになります。この設定ファイルのバックアップやサーバ間同期が確実にできるか？という問題です。[AnsibleのVault](https://docs.ansible.com/playbooks_vault.html)はこの問題を解決できますが、デプロイ手段毎に保管方法を変えるのは面倒です。(CIツールも使いますよね？)

「キーをすこしでもマシな方法でリポジトリに入れたい。そのキーから秘密鍵を一つの環境変数で取り出したい。」という要求から`keystorage`というコマンドを作りました。

## インストール

`Keystorage`は`Ruby`のスクリプトで`rubygems`で配布されていますので、そこからインストールするのが簡単です。コマンドが実装されているので、Rubyアプリ以外にも利用できます。

```bash
gem install keystorage
```

## 使い方

`keystorage`というコマンドがインストールされるのでこれを使います。まず、キーを設定します。そのまえにキーファイルの保管場所(PATH)とパスワードを決めておいて下さい。以下では、`/app/.keystorage`に`P@ssw0rd`とパスワードを掛けてけて保管します。

```bash
$ keystorage -f /app/.keystorage -s P@ssw0rd set TWITTER API 1a024ce7f0fa1f2bffd7
```

上の例でTWITTERはグループ名、APIはキー、`1a024ce7f0fa1f2bffd7`の部分は保管するAPIキーです。

このコマンドで以下のようなキーファイルが`/app/.keystorage`に生成されます。

```
---
'@':
  token: POUpeMM6eKCO48Wdk6-JFg
  sig: afdf2f9c9c63fcf0d65eaf0c9c86f7e04c970d06056f641e0ffe1f1ff3c981f20b4e3da719fee7159c770dfa5a7a99c8f3eb688bb760a4d24103c83b62e25528
TWITTER:
  API: 736901b66dc3981edccf23c672f852f416b15a54d9ab92d9912288e47faf39cb
```

このファイルと、パスワードがあればキーの内容を読むことができるようになります。

キーの内容を取り出すには以下のようにします。

```bash
$ keystorage -f /app/.keystorage -s P@ssw0rd get TWITTER API
1a024ce7f0fa1f2bffd7
```

この調子で必要なグループ名、キーを設定してきます。

```bash
$ keystorage -f /app/.keystorage -s P@ssw0rd set TWITTER SECRET fa1f2bffd71a024ce7f0
$ keystorage -f /app/.keystorage -s P@ssw0rd set FACEBOOK KEY a024ce7f0fa1f2bffd71
$ keystorage -f /app/.keystorage -s P@ssw0rd set FACEBOOK SECRET a024ce7f0fa1f2bffd71
```

キーファイルは以下のようになりました。（通常はいちいち中見ることはありません）

```
---
'@':
  token: POUpeMM6eKCO48Wdk6-JFg
  sig: afdf2f9c9c63fcf0d65eaf0c9c86f7e04c970d06056f641e0ffe1f1ff3c981f20b4e3da719fee7159c770dfa5a7a99c8f3eb688bb760a4d24103c83b62e25528
TWITTER:
  API: 736901b66dc3981edccf23c672f852f416b15a54d9ab92d9912288e47faf39cb
  SECRET: f814eac8d80e41d8e56efd0ad17a462d74e10cc16fdc53717cfe7ab37eb780df
FACEBOOK:
  KEY: 6f8c3fee96c321c5f4c128fa9f38ddd36e5a91a00fbda9624aa8f8bdc72de00f
  SECRET: 6f8c3fee96c321c5f4c128fa9f38ddd36e5a91a00fbda9624aa8f8bdc72de00f
```

このファイルの内容を環境変数に指定して子プロセスを立ちあげることが出来ます。`printenv`すると以下のように設定されています。

```
-> % keystorage -f /app/.keystorage -s P@ssw0rd exec printenv                           
FACEBOOK_KEY=a024ce7f0fa1f2bffd71
TWITTER_SECRET=fa1f2bffd71a024ce7f0
TWITTER_API=1a024ce7f0fa1f2bffd7
FACEBOOK_SECRET=a024ce7f0fa1f2bffd71
...
```

実際にはhttpdとか指定してあげて以下のように使うのかなっと

```
$ keystorage -f /app/.keystorage -s P@ssw0rd exec httpd
```

これで、httpdの中身で環境変数が参照できます。その他の使い方は、githubの[tumf/keystorage](https://github.com/tumf/keystorage) README.mdあたりを御覧ください。:grinning:
【Linux】端末(terminal)から画像を表示する。【CentOS?・Bash?】

###1.`$eog test.jpg`('eog'は[eye of gnome](https://wiki.gnome.org/Apps/EyeOfGnome)の略です。)
![eoj1.png](https://qiita-image-store.s3.amazonaws.com/0/69767/258e7d05-1d20-3a1a-b85c-5e816ae8443a.png)

###2.そして、Enter
![eoj2.png](https://qiita-image-store.s3.amazonaws.com/0/69767/332df80e-d899-2897-9e5d-81d88bcebd43.png)
CircleCIのBundle Installを高速化した

Bundle Installをキャッシュ化、並列化して高速化した

```circleci.yml
dependencies:
  cache_directories:
    - "vendor/bundle"
  override:
    - bundle -j4 --path=vendor/bundle
```

## Before
![saicologic_phoenix__112_-_CircleCI.png](https://qiita-image-store.s3.amazonaws.com/562/2432/f98972c6-9b52-a46d-69d9-69926055dc58.png)

## After
![saicologic_phoenix__114_-_CircleCI.png](https://qiita-image-store.s3.amazonaws.com/562/2432/9de92b56-bcda-782a-313c-27b3d6fd194a.png)

12倍高速！（2分24秒から、12秒に短縮）
SQL Developer 「ファイル・タイプ・アソシエーションの設定」ダイアログが起動のたびに必ず表示される。

#事象

Oracle に付属している便利ツール SQL Developer を起動するたびに「ファイル・タイプ・アソシエーションの設定」ダイアログが毎回必ず表示される。

Windows 限定。

## 原因
以下の設定ファイルの変更に管理者権限が必要であり、SQL Developer に管理者権限がないことが原因。

```
<sqldeveloper root>\bin\sqldeveloper.conf
```

## 対策
上記の設定ファイルに以下の一文を書き加えることで訊かれなくなる。

```
AddVMOption -Dno.shell.integration=true
```

SQL Developer を管理者権限で一度実行しておくと（おそらく上記の一文が書き加えられて）それ以降訊かれなくなるという話も見かけたが、自分の場合はうまくいかなかった。
インストール方法しだいでこの状況が発生すると思われるが、そのあたりまで検証はしていない。

## 参考
参考リンク先がありましたがリンク先サイト消失につき、リンクを削除しました。


## その他
数年悩んだ。
ページ内のリンクにスムーズに移動するjquery

jquery読み込んで

```
<!-- スムーズスクロール部分の記述 -->
<script>
$(function(){
   // #で始まるアンカーをクリックした場合に処理
   $('a[href^=#]').click(function() {
      // スクロールの速度
      var speed = 400; // ミリ秒
      // アンカーの値取得
      var href= $(this).attr("href");
      // 移動先を取得
      var target = $(href == "#" || href == "" ? 'html' : href);
      // 移動先を数値で取得
      var position = target.offset().top;
      // スムーススクロール
      $('body,html').animate({scrollTop:position}, speed, 'swing');
      return false;
   });
});
</script>
```
これだけ。
safari で見ると汚くなる mask


単純に svg で mask をつかった表現をすると拡大したり、通常時でも歪んでみえることもある。
円盤系で回転のアニメーションつけたりすると酷い。

chrome では大丈夫。ファックス。

## あきらめよう

時には諦めも肝心。png の方がシャキッとする時もあるんで、png にしよう。

## 嘘こいてんじゃねーよと思う人！

まじで解決方法あるならコメントください。
ESLintでReactを扱う


めまぐるしく変更が適用されてるESLintですが
2015/4/1(v0.17)時点でReact/JSXをLintingするにはeslint-plugin-reactが便利です。

https://github.com/yannickcr/eslint-plugin-react

## 導入

### ESLintとeslint-plugin-reactをインストール

```
npm install eslint eslint-plugin-react -g
```

### .eslintrcの設定

最低限度ですが。

```
{
  "env": {
    "node": true,
    "es6: true
  },
  "ecmaFeatures": {
    "jsx": true 
  },
  "plugins": [
    "react"
  ],
  "rules": {
    "react/jsx-uses-vars": 1
  }
}
```

ESLintは標準パッケージでjsxをサポートしてるのですが、React独自表記の部分はサポート外となっていて、そこはpluginでカバーする感じになっています。

例えば`react/jsx-uses-vars`を無しでReact/ESLintを使うと`Hoge is defined but never used (no-unused-vars)`とエラーが出てしまいます。
Hogeが定義されているけど使われないですよというエラーなのですが、この設定により`<Hoge />`と使うのを許可します。

```
var React = require('react' );
var Hoge = React.createElement({
  render(){
    return <span>hoge</span>;
  }
});
React.render(<Hoge />, document.querySelector("#hoge"));
```

その他pluginで設定できるルールについては[こちら](https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules)をみてください。


## 単独実行

```
eslint hoge.jsx
```

自分は`vim`の`syntastic`設定に`let g:syntastic_javascript_checkers = ['eslint']`としています。

---

ESLint自体がまだ若いツールで、またすぐに仕様が変わるかもしれないので、おかしいな？と思ったら公式ブログのリリースノートをチェックするなどしてみてください。
この形式になったのもつい最近の話です。
http://eslint.org/blog/2015/03/eslint-0.17.0-released/
Jestを簡単に動かしてみた

JestはFacebookがReact.jsを使ったアプリケーション開発に使っているフロントエンドのテストフレームワーク。

とりあえず動かしてみたときの手順メモ。

```bash
$ mkdir jest_test; cd jest_test; git init
$ npm init # test => jest
$ git add .; git cm -m "Initialize package.json"
$ npm install --save-dev jest-cli
$ git add .; git cm -m "Add jest-cli to node_modules"
```

ここまでで準備完了。次に実行ファイルを書く。FacebookのJest公式トップにある例そのまま。

```sum.js

function sum(value1, value2) {
  return value1 + value2;
}

module.exports = sum;

```

次にテストスクリプト。

```javascript:__tests__/sum-test.js

jest.dontMock('../sum');

describe('sum', function() {
  it('adds 1 + 2 to equal 3', function() {
    var sum = require('../sum');
    expect(sum(1, 2)).toBe(3);
  });
});
```

テストを実行してみる。

```bash
$ npm test

> jest_test@1.0.0 test /Users/yusukenozoe/Desktop/jest_test
> jest

Using Jest CLI v0.4.0
 PASS  __tests__/sum-test.js (0.01s)
1 test passed (1 total)
Run time: 0.217s
```

かなり簡単に導入できるということがわかった。
AndroidStudioでプロジェクトインポートしたときのsyncエラー

またAndroidStudioでハマった。
以前古いバージョンで作成したプロジェクトをcheckoutしてimportしたところ、原因不明のエラーに遭遇。gradleのバージョンが問題だったが、たどり着くのに苦労したのでメモ。

### 環境
Win7 pro
AndroidStudio:1.1.0
GradlePlugin:1.1.0
Gradle(Gradle wrapper) 1.12 => 2.2.1 ★結局コレ

### 現象
以前古いバージョンのAndroidStudioで作成したプロジェクトをcheckoutしてimportしたところ
gradle syncエラー。

<pre>
Error:Unable to load class 'org.codehaus.groovy.runtime.typehandling.ShortTypeHandling'.
Possible causes for this unexpected error include:

 - You are using JDK version 'java version "1.7.0_75"'. Some versions of JDK 1.7 (e.g. 1.7.0_10) may cause class loading errors in Gradle.
Please update to a newer version (e.g. 1.7.0_67).
 - Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
 - The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.

In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.
</pre>

### 調査

上記、原因の可能性として挙げられている3つは試したが、現象変わらず。

* JDKは「1.7.0_67などの新しいバージョンにしろ」と言っている。当初1.7.0_3Xくらいだったので、より新しい1.7.0_75にした結果が↑。変わっていない。
* 設定を色々変更してはこの方法で何度も消してみた。が、変わらず。
* Gradle daemonを止めてみたら直るかも、と言われているので、言うとおりクリックしてみたが変わらず。

ググっても同じ症状が出てこず。

一度同じ構成のProjectを作り直して、各build.gradleファイルなど見比べども、なかなか違いが見出せずにいたところ、ディレクトリごと比較しやっと気付いたのがここ。

[プロジェクトルート]/.gradle/1.12

作り直したプロジェクトではここが2.2.1になっていた。つまり、gradleのバージョンが怪しいことに気がつく。

### 対処（gradleのバージョン変更）
結局、

http://qiita.com/AbeHaruhiko/items/fd9a01ad6fc84309e857
の、2.gradle-wrapper.propertiesの編集　にあるように

[プロジェクトルート]/gradle/wrapper/の

```properties:gradle-wrapper.properties
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
```
を

```properties:gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
```
に変更。

この修正により、やっと解決。
結局gradleかよ。
ここに気がつくまで長かった。当初、各build.gradleばかり見ていて、かつ、graldeプラグインとgradleを混同していたため、gradleのバージョンの問題ではないと思っていたことが災いした。
AndroidStudio、プロジェクトの構成が難解すぎる。
cakephpのDebugKitは3.0対応済み

cakephp2系で追加時はブランチを指定
$ git submodule add -b 2.2 https://github.com/cakephp/debug_kit.git Plugin/DebugKit

.gitmodulesにブランチ名がつきます
$ cat .gitmodules
[submodule "Plugin/DebugKit"]
path = Plugin/DebugKit
url = https://github.com/cakephp/debug_kit.git
branch = 2.2
起動中のvCenter Server Appliance 6.0にアクセスすると503 Service Unavailable

単なるメモ。

起動完了していないvCenter Sever Appliance 6.0にブラウザアクセスした場合、`503 Service Unavailable`になる。HTTPレスポンスコード含め普通の動作だけど、時々エラーメッセージの確認の要などが出てくるので、メモしておく。

![vcsa60-error503.png](https://qiita-image-store.s3.amazonaws.com/0/55718/082fe79f-85fe-7efa-8f5e-b25182bb8738.png)

メッセージ全文は以下。

    503 Service Unavailable (Failed to onnect to endpoint: [N7Vmacore4Http20NamedPipeServiceSpecE:0x7fe31405_serverNamespace= / _isRedirect = false _pipeName=/var/rum/vmware/vpdx-webserver-pipe

起動完了が確認できてからアクセスすれば、問題ない。
セッション管理に対する攻撃と対策

# セッションとは何か?

セッションとは、ログインしてからログアウトするまでのような一連の手続きのこと。
セッション管理を行うことで、通常ステートレスなHTTPにおいて、ログイン情報やオンラインショッピングシステムのカートなどの情報を保存して、必要な時に取り出すことができる。


セッションが必要なページにアクセスすると、サーバーから「セッションID」と呼ばれるセッション管理番号が発行されて、HTTPレスポンスに含まれる。
その際にはHTTPレスポンスに

```
Set-cookie: PHPSESSID=32geasfal3lf234e2332534; path=/
```
のような文字列が含まれている。（ここではPHPのsession_start();を用いた場合を示す）
上記のようにセッションIDはCookieとしてブラウザが記憶する。

以降、Cookieの期限が切れるまでか、ブラウザが閉じられるまで、このCookieのドメインとして指定されたサイトへのHTTPリクエストヘッダには

```
Cookie: PHPSESSID=32geasfal3lf234e2332534
```

が含まれる。

サーバーはこのセッションIDを受け取ることで、セッションを特定することができる。



# セッションを用いた攻撃

## セッションハイジャック

### 内容

他人のセッションIDを盗聴などで盗み、そのセッションIDを使って、その人になりすまして操作を行うこと。

例えばAさんが、セッションを開始する時に

```
Set-cookie: PHPSESSID=hoge;
```

とセッションIDを発行されたとする。このセッションID=hogeを何らかの方法でBさんが知り、HTTPリクエストにこのセッションIDを含ませる事で

```
Cookie: PHPSESSID=hoge;
```

BさんはAさんのセッションを乗っ取ることができる。


### 対策

セッションIDの漏洩を防ぐ（URLにセッションIDを含めない、SSLによる暗号化でネットワーク盗聴を防ぐ）


## セッションIDの固定化(Session Fixation)攻撃

### 内容

セッションIDの固定化攻撃は、正規のサイトから悪意を持ったユーザが正規のセッションIDを取得し、そのセッションIDを他のユーザに強制する。

強制されたセッションIDでユーザがログインを行った場合、そのセッションIDを元々知っている悪意を持ったユーザはログインしたユーザに成り代わって操作を行うことができる。

### 対策

ログイン後にセッションを新規に作る（セッションIDの再発行）。
or
ログイン後にセッションIDとは別に認可されたことを証明する情報を付加する。
長期欠席

「計画することがすべてだ。立てた計画はどうでもいい。」
これは計画について話し合うことが重要であり、その結果としてアウトプットされるものはそこまで重要ではない、ということを指す

必ず計画で想定しなかったことが、現実には起こり得る。
このとき、計画作りに参加しコンクテクストを共有した人間にはこれも対応できる。
我々は何がしたいか、制約は何か、手持ちはなにか、を理解しているから


中途でジョインしたり、あるいは計画作りに参加しなかった人間にアウトプットだけ渡せばいままでいた人間と同様の働きができるかといえば必ずそれはNoになる
かれらは、アウトプットに含まれないコンテクストがわからないので、アウトプットに記載された内容を、コンテクストが理解できている人間ほど理解できない

長期の欠席の後学校に出てきた人間にとって入院中に休んでいたせいで「当然みんな理解している前提」のもとで進む授業、というのが近いかもしれない

彼らは計画作りの会議に出ても、半分も理解することはできない、あるいは流れる言葉の内容をコンテクストを理解している人間とは別の理解の仕方をするかもしれない。
コンテクストを持たないからだ。
しかし会議はそのまま進んでしまうため、結果的に会議に存在してはいるが、理解はできない状態になる

重要なことは、コンテクストを理解できている人間にとってコンテクストを理解できていない人間にとってなにが理解できないかを検知できないことである。

# これを防止するために
ある開発ロット単位で、中途のジョインを防ぐ
ある開発ロットは最初から最後までアサインできる人間のみで進める。
中途参加した人間はロットによらないタスクを振るか、あるいは後発の開発ロットにアサインするか、または限定的なタスクしかこなせない前提で見る
お互いの期待値をそう設定することでお互いのすれ違いを防ぐことはできる
Python Conda Tips

Pythonの実行環境である[Miniconda](http://conda.pydata.org/miniconda.html)のコマンドTips。ドキュメントがあまり充実していない・・・というか、かゆいところに手が届かない感じなのでまとめておく。

[公式ドキュメント](http://conda.pydata.org/docs/)

## Command Flow

```
# 仮想環境を作成(virtualenv的なもの)
conda create -n my_env numpy scipy

# 仮想環境の一覧を表示
conda info -e

# 仮想環境を有効化
activate my_env # Windows
source activate my_env # Max/Linux

# 仮想環境に追加でインストール(バージョンを指定する場合conda install scipy=0.12.0など)
conda install scikit-learn

# condaで取得できないものについて、pipでインストール(仮想環境にpipを入れて対応)
conda install pip
pip install Flask

# condaでインストールしたライブラリを書き出し
conda list --export > conda_requirements.txt

# インストールしたパッケージのアップデート(conda自身はconda update conda)
conda update numpy

# 仮想環境無効化
deactivate # Windows
source deactivate # Max/Linux

# ファイルから仮想環境を作成
conda create -n my_new_env --file conda_requirements.txt

# 最近はconda env exportを使い方が良いよう
conda env export > environment.yml
conda env create -f environment.yml

```

pyenvを利用している場合、source activateでシェルが落ちる場合がある。これはpyenvのactivateとcondaのactivateがバッティングするために起こる現象のようで、解決策は[こちら](http://qiita.com/icoxfog417/items/950b8af9100b64c0d8f9)参照。condaのactivateをフルパスで指定する。

## References

[Using the Anaconda Python Distribution](http://davebehnke.com/using-python-anaconda-distribution.html)
[Advanced Features of Conda Part 1](http://continuum.io/blog/advanced-conda-part-1)
[Conda FAQ](http://conda.pydata.org/docs/faq.html)
MySQLでカラム内の区切り文字(列)より後方部分を取得して、別の列にコピー

#やりたいこと
ある列内の文字列中にある区切り文字(列)より後方部分を取得して、別の列にコピー。

#概要
LOCATE("区切り文字", `検索列`)
で区切り文字の位置を取得し、

SUBSTRING(`検索列`, 切出し開始位置)
で取得
(より後方なので、区切り文字の文字数を加える)

全行に区切り文字がある場合は、WHERE部分は不要かも。

#コード
```MySQL
UPDATE
	`対象DB`.`対象TBL`
SET
	`更新列`=SUBSTRING(`検索列`, LOCATE("区切り文字", `検索列`) + 1)
WHERE
	`検索列` like "%区切り文字%"
;
```
SQL メモ書き

# 概要
　SQL(Oracle)のメモ書きです。
　少しずつ更新していきます。

```lang:最新の１０件取得
select * 
from (select * from tablename order by lastupdatetime desc)
where rownum <=10
```

```lang:シーケンスの値を、yyyyMMddに変換する
select TO_DATE('00000','HH24MISS') + (10 / 86400) from dual
```

```lang:対象カラムに同じ値が2件以上あるものを探す
select count(*) from tablename group by columnname having count(*) > 1
```
```lang:対象カラムへの文字列置き換え
UPDATE `dbname`.`tblname` SET 対象カラム名=REPLACE(対象カラム名, "置換え前", "置換え後")
```
MySQLでカラム内の文字列を置き換えて保存（update）

#やりたいこと
・SQLでカラム内の文字列置き換え
#概要
特定のカラムで文字列置き換えを行う
#コード
```mysql
UPDATE `dbname`.`tblname` SET 対象カラム名=REPLACE(対象カラム名, "置換え前", "置換え後");
```
MySQLで別テーブルの情報を用いてカラムを更新する

#やりたいこと
・別テーブルの情報でカラムを更新する
・Excelでいうところのvlookup的な処理
本当はViewでも作ればよいのだけど、速度とか既にこのテーブル依存でコードを作ってしまっているなどの事情でできない場合など。Join？やらないやらない。
#概要
tbl_aのurl列に、idで検索したtbl_bのurlを入れる。
#コード
```mysql
UPDATE
    `db1`.`tbl_a` a,
    `db2`.`tbl_b` b
SET
    a.`url` = b.`url`
WHERE
    a.`id` = b.`id`
```
2015.4.1 以降も Choregraphe を利用する

最近話題のロボット Pepper の SDK 「Choregraphe」。
インストールして使ってみたものの、4/1で試用期限が切れてしまった、という人も多いかもしれない。

そこで「Choregraphe」を末永く利用するための方法を考えてみたのだが、どうも何をやっても3/31で試用期限が切れてしまうようだ。
OSを再インストールして、改めて「Choregraphe」をインストールしてもダメだった。

なので、4/1 以降も「Choregraphe」を利用するのは以下の方法しかないかもしれない。

**【インストール済みの場合　日付を戻す】**

・PCの日付を過去に戻せば、そのままChoregrapheが使える。
　この場合、自動的に時計が戻ってしまわないよう設定を修正する。
　（ネットワーク経由で時刻情報を取得して自動修正する機能が
　　さいきんのOSではだいたい標準で有効になっている。）
UIButtonの上にUIPanGestureRecognizerを置いたとき、UIButtonにはどういうイベントが発生するのか

# 概要
UIPanGestureRecognizer（ドラッグ・スワイプ）を使った挙動を実装する必要があった。
しかしその領域にはUIButtonがあったのだった。

UIButtonの上で、UIPanGestureRecognizerに拾われる操作をしたとき、
一体UIButtonにはどんなイベント（UIControlEvents）が走るのか？

# 結論
```
[self.button addTarget:self action:@selector(cancelButton) forControlEvents:UIControlEventTouchCancel];
```
UIPanGestureRecognizerに操作が拾われた場合、UIButtonには上記のイベントが走る。

UIControlEventTouchCancel は キャンセルイベントが発生したときのイベント名だけど
こういうときに動くらしい。

```
UIControlEventTouchDown // これはUIPanGestureRecognizerで拾われるドラッグ操作するとき、最初のタップ時にイベント発生。
UIControlEventTouchUpOutside // これは発生しない
UIControlEventTouchDragExit // これも発生しない
```
こういうイベントとは別になるので要注意だった。
power of reflect.DeepEqual

Greetings,

`reflect.DeepEqual` helped a lot this days, and somebody here asked how do you compare strings by `strings.Join`. so I thought I might share it here.

```go
package main

import (
	"fmt"
	"reflect"
)

func main() {

	// map	
	m1 := map[string]string{"a": "b", "c": "d"}
	m2 := map[string]string{"a": "b", "c": "d"}	

	// slice
	a1 := []int{1, 2, 3}
	a2 := []int{1, 2, 3,}

	// map equality
	mapsAreEq := reflect.DeepEqual(m1, m2)
	fmt.Println(mapsAreEq)
	
	// slices equality
	slicesAreEq := reflect.DeepEqual(a1, a2)
	fmt.Println(slicesAreEq)	
}
```

`reflect.DeepEqual` takes an `interface{}` type parameter, so basically, you can pass anything on it(so be careful with it). 

```go
func DeepEqual(a1, a2 interface{}) bool
```

thats it!, hope it may do good for you too :D
CentOS7でDocker1.5が正式提供されたようです。


```
yum install docker
```

でDocker 1.5がインストールできるようになりました！！
これはうれしい！！

http://mirror.centos.org/centos/7/extras/x86_64/Packages/

# device-mapperも更新しておく

device-mapperが古いままだと、相性問題でエラーが出る可能性があるので更新しておくとよいでしょう。

```
yum update device-mapper
```
スリープから復帰後にマウント中だったサーバに接続できない現象の解決方法


通常だとFinderのサイドバーにマウントしたサーバが以下のように表示されています。

![スクリーンショット 2015-04-02 10.19.56.png](https://qiita-image-store.s3.amazonaws.com/0/44554/8a6728c3-acdc-e587-421a-ea161bd946b4.png "スクリーンショット 2015-04-02 10.19.56.png")

それがスリープ復帰後、消えている場合があります。原因は不明です。
しかたないので再度Finderの「サーバへ接続」から接続を試みると、
何もアラートが無く、表示ができない現象が起こりました。

## ログを確認する
アプリケーションの「コンソール」からログを確認します。
起動後、サイドバーにある「system.log」を選択します。

`smb_mount: mount failed to [接続先アドレス], syserr = File exists`

上記のようなログがあるとき、マウントは継続されているが、接続されていなかったのが原因なのかFinderから表示が消えてしまったようです。
この場合、次のような操作で解決できます。

## ディスクの使用量を確認する

アプリケーションの「ターミナル」から以下のコマンドを実行します。

```
$ df
```

するとディスク使用量の一覧が表示されます。

```
Filesystem                512-blocks      Used Available Capacity  iused      ifree %iused  Mounted on
****                         4879001   3574748   1299133    74%   447483   16239163   73%   /
****                             377       377         0   100%      654          0  100%   /***
//[接続先アドレス]/[ディレクトリ]  10321  2380  79405    24%     0   1844670  737095516    0%   /Volumes/[ディレクトリ]
```
一番下に、マウントしている接続できないサーバが表示されています。
こいつを一度アンマウントします。

## アンマウントする

続けて「ターミナル」からコマンドを実行します。

```
$ diskutil unmount /Volumes/[ディレクトリ]
```

再度Finderの「サーバへ接続」からサーバへ接続するとマウントできます。

## 対策
しばらく使用しないサーバはFinder上からアンマウントしておく
REST APIのステータスコード 日本語チートシート

すぐ忘れてしまうので、備忘録代わりに。

# 成功

| | |内容|
|---|---|---|
|200|OK|成功。|
|201|Created|新しいリソースを作成した。POST、PUTなど。|
|202|Accepted|リクエストを受け付けた。同期的に処理できない時に。|
|204|No Content|内容なし。DELETEなどでレスポンスボディが不要な時に。|

# 失敗

| | |内容|
|---|---|---|
|400|Bad Request|汎用エラー。リクエストデータに不正値がある等。|
|401|Unauthorized|認証エラー。|
|403|Forbidden|アクセス禁止。権限がない場合等。|
|404|Not Found|リソースが存在しない。|
|405|Method Not Allowed|メソッドが間違っている。GETしか受け付けないURIに対してPOSTされた時など。|
|409|Conflict|リソースが競合している。ユニークなキーが既存のリソースと衝突した場合等。|
|415|Unsupported Media Type|指定されたメディアタイプがサポートされていない。|
|429|Too Many Requests|リクエストの回数制限に引っかかる場合など。|
|500|Internal Server Error|サーバ側の問題によるエラー。|
|503|Service Unavailable|一時的にサービス出来ない場合。|
Jenkinsで「No space left on device @ io_write」と言われた時の対処法

忘れないために残しておきます！

## 現象
* 要は空き容量不足
* なので、「Jenkinsの管理」-> 「ノードの管理」を見ていただくときっと容量がカツカツになっているのが確認できるはずです！

## 対処方法
1. ビルドの度に容量が増えるようなものであれば、ビルド終了時にログの消去または別な場所で保管などといった処理を入れるべき
2. 一度のビルドで容量がカツカツになるようであれば、実行しているスレーブ(なりマスター)の空き容量を十分に確保したマシン(インスタンス)を用意すべき
3. 応急処置として、そのノードで実行されたらこのエラーが出続けるので一旦実行対象のノードからはずす

# ～ただの宣伝～
* [全国のSeleniumer必読](http://qiita.com/oh_rusty_nail/items/b8ba525d31ea7c522856)
* Seleniumerといっていますが、Selenium, SauceLabs, Travis, Jenkinsに関するノウハウ書いているのでよかったら参考にしてみてください
Framinで、Fx0のアプリを作ってみる（２）

# Framinで、Fx0のアプリを作ってみる （２）

## はじめに

今回は、前回に引き続き、FraminでFx0のアプリを作成したいと思います。
Framinは、決まった「トリガ」と「アクション」を組み合わせることにより、アプリを作成します。その為、複雑なことは出来ないのですが、メニューから選択するだけで、プログラミングの知識がなくても簡単にアプリが作成できます。アイデア次第で、色々なアプリが作成できると思います。

今回は、初めてのFraminでのアプリ作成として、端末を振ると画像が切り替わる「簡易ビューワ」を作成してみました。

## アプリの作成

### ■ アプリの概要

アプリの概要は以下の通りです。

|項目|内容|
|---|---|
|アプリ名|shake|
|動作仕様|端末を振ると画像が切り替わります|

### ■ リソースの準備

アプリの作成に必要なリソースを準備します。
必要なリソースは「アイコン」と「画像」です。

#### ◆ アイコン

今回は、以下のアイコンを作成しました。

![icon.png](https://qiita-image-store.s3.amazonaws.com/0/72852/b5810904-8074-a82e-3d41-975dbd30e1bb.png)

#### ◆ 画像

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/9bb5e008-25d1-8b5b-11f4-0ca051737b58.jpeg" width="50%">

## アプリの作成

### ■ アプリ新規作成(アプリ名およびアイコンの設定)

アプリ名とアプリアイコンを設定します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/5fc91f0e-ad2d-2b45-81e5-4996fac52707.jpeg" width="40%">


### ■ ビューの管理

ビューに、用意したリソースを設定します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/ea634907-4252-373b-a4a2-ae4eeb412546.jpeg" width="40%">

### ■ レシピ作成

レシピに、「レシピ1」および「レシピ2」を設定します。

トリガとして設定可能な一覧です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/fe1efb3e-0b48-9d57-a12e-b9da5c965c91.jpeg" width="40%">

アクションとして設定可能な一覧です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/8a9bc84b-c740-02d8-1307-81eed4664f28.jpeg" width="40%">

### ■ レシピ 1の作成

設定するトリガとアクションは以下の通りです。

|項目|内容|
|---|---|
|トリガ|端末を振る(速さ)|
|アクション|ビューの画像切替　※スライド左|

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/7356b708-b11d-11ca-efd4-0714466ce858.jpeg" width="40%">

Fx0を振るとその時の値が自動的に設定されます。
トリガの設定感度を実際に端末を振ってみて試せることが良いと思いました。
他のセンサーも同様に試しながらしきい値を設定することができます。

以下は、レシピ1を設定した画面です。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/eaacdf70-4961-dd53-65fa-3443ba4731d9.jpeg" width="40%">

### ■ レシピ 2の作成

設定するトリガとアクションは以下の通りです。

|項目|内容|
|---|---|
|トリガ|端末を振る(速さ)|
|アクション|ビューの画像切替　※スライド左|

レシピ2をレシピ1と同様の手順で作成します。

以下は、レシピ2を設定した画面です。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/626e2605-f696-7fa8-5c10-260ed3a69a4d.jpeg" width="40%">

以上の通り、「レシピ1」および「レシピ2」を設定しました。

### ■ アプリのインストール

必要な設定が完了したら「インストール」ボタンでアプリをインストールします。
設定値を修正したい場合は、「編集」ボタンにより、修正することができます。
尚、修正はアプリをインストールした後でも以下の手順で行うことができます。

1. Framinを起動する。
2. 修正対象のアプリを選択する。
3. 「アプリ詳細画面」の「編集する」を選択する。
4. 編集する。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/d99449e9-b553-bd3c-bcb0-7cb30e8d4acf.jpeg" width="70%">

インストールが完了すると、ホーム画面にアイコンが追加されます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/19f8fedd-e5e5-a513-12b2-8d63a2079e44.jpeg" width="40%">

## アプリの実行

アプリ起動直後の画面です。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/eaeceef5-e977-d35d-28a4-b957829b600a.jpeg" width="40%">

Fx0を振ってみます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/72852/785d747c-4c17-91d9-725c-a6828593d071.jpeg" width="40%">

画像が切り替わりました!

## おわりに

作成に要した時間は、10分程度です。非常に簡単にアプリを作成できました。
今回は、お試し感が強かったですが、アイデア次第で実用的なアプリが作成できるのではないでしょうか。