読者です 読者をやめる 読者になる 読者になる

SQL メモ

重複しているカラムを持つレコード抽出

select email from users group by email having count(email) <> 1;

xcode KeyBindingSet カスタマイズ

手順としては

  1. ターミナルを開いて $ open /Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Versions/A/Resources/IDETextKeyBindingSet.plist を打つ
  2. /Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Versions/A/Resources/IDETextKeyBindingSet.plist を読み書き可能に変更
  3. /Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Versions/A/Resources/ を読み書き可能に変更
  4. /Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Versions/A/Resources/IDETextKeyBindingSet.plist を開いて追加したい内容書き込む
  5. xcode を再起動

新しいキーバインドの追加

/Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Versions/A/Resources/IDETextKeyBindingSet.plist を開いて、以下を入力

~省略~

<key>customized</key>
    <dict>
      <key>Delete Current Line</key>
      <string>deleteToBeginningOfLine:, moveToEndOfLine:, deleteToBeginningOfLine:, deleteBackward:, moveDown:, moveToBeginningOfLine:</string>
    </dict>
    <key>Edit</key>
    <dict>
      <key>Duplicate Line</key>
      <string>selectLine:, copy:, moveToEndOfLine:, insertNewline:, paste:, deleteBackward:</string>
    </dict>
</dict>
</plist>

として保存。

追加した内容を反映

xcodeを再起動して、preferences を開いて KeyBindings を開いて、検索フォームに、上でで指定した単語を調べる。 そしたら、項目が出てくるので、好きなキーバインドを入力して終わり。

Ruby で Python の virtualenv 的なことをする

PythonのvirtualenvをRubyでやる。

rbenv-gemset というツールで実現できます。

環境は Mac を想定。

rbenv, rbenv-gemset インストール

rbenv は Ruby のバージョン管理ツールです。

$ brew install rbenv ruby-build rbenv-gemset
$ rbenv -v
rbenv 1.0.0
$ rbenv gemset version
rbenv-gemset 0.5.9
by Jamis Buck <jamis@jamisbuck.org>
Currently maintained by Jeffrey 'jf' Lim <jfs.world@gmail.com>

http://github.com/jf/rbenv-gemset

Ruby インストール

rbenvを使ってRubyをインストールします。

$ rbenv install 2.2.5
$ rbenv versions
* system (set by /Users/hoge/.rbenv/version)
  2.2.5

マシン全体のRubyを2.2.5に変えます

$ rbenv global 2.2.5
$ rbenv versions
   system (set by /Users/hoge/.rbenv/version)
* 2.2.5

gem は初期状態で以下のものが入ってます。

$ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.6)
io-console (0.4.3)
json (1.8.1)
minitest (5.4.3)
power_assert (0.2.2)
psych (2.0.8)
rake (10.4.2)
rdoc (4.2.0)
test-unit (3.0.8)

rbenv-gemsetを使って仮想環境の作成

何もせずに gem install するとマシン全体の Ruby 2.2.5 にどんどんインストールされてだんだん汚くなるので、プロジェクトごとに入れるものを分けたい。

まずはプロジェクトで使いたいRubyバージョンを決める。

rbenv local バージョン

でできる。

$ mkdir project
$ cd project
$ rbenv local 2.2.5
$ ruby -v
ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-darwin16]

次に、仮想環境の作成を行う。仮想環境の名前を sample とする。

$ rbenv gemset create 2.2.5 sample
$ rbenv gemset init sample
$ ls -a
./              ../             .rbenv-gemsets  .ruby-version

これで完了。

汚れるかどうかの確認

まずはプロジェクト内の gem

$ pwd
/Users/hoge/project
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.6)
io-console (0.4.3)
json (1.8.1)
minitest (5.4.3)
power_assert (0.2.2)
psych (2.0.8)
rake (10.4.2)
rdoc (4.2.0)
test-unit (3.0.8)

そして全体の gem

$ pwd
/Users/hoge
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.6)
io-console (0.4.3)
json (1.8.1)
minitest (5.4.3)
power_assert (0.2.2)
psych (2.0.8)
rake (10.4.2)
rdoc (4.2.0)
test-unit (3.0.8)

どちらも同じ状態。

プロジェクト内で serverspec をインストールして後に gem を見てみます

$ pwd
/Users/hoge/project
$ gem install serverspec
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.6)
diff-lcs (1.3)
io-console (0.4.3)
json (1.8.1)
minitest (5.4.3)
multi_json (1.12.1)
net-scp (1.2.1)
net-ssh (4.1.0)
net-telnet (0.1.1)
power_assert (0.2.2)
psych (2.0.8)
rake (10.4.2)
rdoc (4.2.0)
rspec (3.5.0)
rspec-core (3.5.4)
rspec-expectations (3.5.0)
rspec-its (1.2.0)
rspec-mocks (3.5.0)
rspec-support (3.5.0)
serverspec (2.38.0)
sfl (2.3)
specinfra (2.67.2)
test-unit (3.0.8)

いろいろ入りました。

そして、マシン全体の gem を見てみます。

$ pwd
/Users/hoge
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.6)
io-console (0.4.3)
json (1.8.1)
minitest (5.4.3)
power_assert (0.2.2)
psych (2.0.8)
rake (10.4.2)
rdoc (4.2.0)
test-unit (3.0.8)

マシン全体のほうに serverspec がインストールされていない!!

これでちゃんとプロジェクト内が独立な環境になるようにできました。

よく使うインフラ系のコマンド

dstat

$ dstat -tcmdlnsg

ln

$ ln -s src dst

netstat

$ netstat -antup

随時更新する。

Pythonでのネストされた配列の展開 (Rubyでのflatten)

Rubyでのネストされた配列を展開して、1つの配列に詰め込むflattenメソッドをPythonでやる。

Rubyでの結果は以下

[1] pry(main)> a = [[1,2,],[3,4]]
=> [[1, 2], [3, 4]]
[2] pry(main)> a
=> [[1, 2], [3, 4]]
[3] pry(main)> a.flatten
=> [1, 2, 3, 4]

こんな感じに展開される。

これをPythonでやるには、itertools を使う。

In [1]: a = [[1,2],[3,4]]

In [2]: a
Out[2]: [[1, 2], [3, 4]]

In [3]: from itertools import chain

In [4]: chain.from_iterable(a)
Out[4]: <itertools.chain at 0x107ec5d30>

In [5]: list(chain.from_iterable(a))
Out[5]: [1, 2, 3, 4]

こんな感じ。

GROUP BY のイメージ

ただ並べ替えるだけの「GROUP BY」じゃなくて、指定されたカラムで分けて、分けられたそれぞれで考える というイメージ。

mysql> select * from users;                                                                          +----+------+------+------+
| id | name | age  | sex  |
+----+------+------+------+
|  1 | hoge |   12 |    1 |
|  2 | foo  |   76 |    0 |
|  3 | bar  |   45 |    0 |
|  4 | hoge |   34 |    0 |
|  5 | foo  |   44 |    1 |
|  6 | bar  |   24 |    1 |
+----+------+------+------+

これを以下のような name, man_age, woman_age カラムのような男女別の年齢を出すことを考える。

+------+---------+-----------+
| name | man_age | woman_age |
+------+---------+-----------+
| bar  |      24 |        45 |
| foo  |      44 |        76 |
| hoge |      12 |        34 |
+------+---------+-----------+

出してみる

まずは、hoge, foo, bar それぞれでまとめたいので、GROUP BY name として分ける。

mysql> select name from users;
+------+
| name |
+------+
| hoge |
| foo  |
| bar  |
| hoge |
| foo  |
| bar  |
+------+
6 rows in set (0.00 sec)

mysql> select name from users group by name;
+------+
| name |
+------+
| bar  |
| foo  |
| hoge |
+------+
3 rows in set (0.00 sec)

また、CASE を使うことで if else のような操作ができる。

mysql> select name,case when sex = 1 then age else 0 end as man_age, case when sex = 0 then age else 0 end as woman_age from users;
+------+---------+-----------+
| name | man_age | woman_age |
+------+---------+-----------+
| hoge |      12 |         0 |
| foo  |       0 |        76 |
| bar  |       0 |        45 |
| hoge |       0 |        34 |
| foo  |      44 |         0 |
| bar  |      24 |         0 |
+------+---------+-----------+
6 rows in set (0.00 sec)

上記の表を name ごとにそれぞれ合計すれば出したい表ができる。

mysql> select name,sum(case when sex = 1 then age else 0 end) as man_age, sum(case when sex = 0 then age else 0 end) as woman_age from users group by name;
+------+---------+-----------+
| name | man_age | woman_age |
+------+---------+-----------+
| bar  |      24 |        45 |
| foo  |      44 |        76 |
| hoge |      12 |        34 |
+------+---------+-----------+
3 rows in set (0.00 sec)

まとめ

GROUP BY name ときたら、「name で分けてそれぞれで考える」 かつ並べ替えるというイメージ

AndroidからSlack WebHookを利用

Android から Slack WebHookにPOSTしてみます。

使用ライブラリ

  • Gson
  • ButterKnife
  • OkHttp

build.gradle の dependencies に追加

    compile 'com.jakewharton:butterknife:8.5.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
    compile 'com.google.code.gson:gson:2.8.0'
    compile 'com.squareup.okhttp:okhttp:2.0.0'

コード

送るメッセージを入れるクラス

public class Slack {
    public String text;
    public Slack(String text) {
        this.text = text;
    }
}

ボタンを押したらPOSTする

@OnClick(R.id.button)
    public void getRequest(final Button button) {
        button.setEnabled(false);

        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                String result = null;

                Gson gson = new Gson();
                RequestBody requestBody = RequestBody.create(
                    MediaType.parse("text/plain"), gson.toJson(new Slack("Hello"))
                );

                Request request = new Request.Builder()
                    .url("WebHook URL")
                    .post(requestBody)
                    .build();

                OkHttpClient client = new OkHttpClient();
                try {
                    Response response = client.newCall(request).execute();
                    result = response.body().string();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                // 返す
                return result;
            }

            @Override
            protected void onPostExecute(String result) {
                Log.d("result", result);
                button.setEnabled(true);
            }
        }.execute();
    }