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

my coredump

自分用の公開メモです。主にプログラムのこととか書くはず。

elixir, phoenix導入メモ

elixirを試したいので入れた。 大まかな流れは Installation · Phoenix の通り。

ただしMacだとbrewで簡単に入るけど、今後のためにexenvで入れてみた。 Rubyでいうところのrbenv

erlang

まずはerlangが必要だった。brewで入る。

brew install erlang

erlangにもerlenvというのがあるらしいけど、ビルドをしてくれるコマンドがまだないとのことだったので使わなかった。 あとで本格的に使うときに考えよう。

exenv -> elixir

mururu/exenv · GitHub

exenv自体はbrewで入れた。 exenv installをするにはelixir-buildも必要。rbenvっぽい。

brew install exenv
brew install elixir-build

# PATHの設定とかまでは自動でやってくれなかった。
echo 'export PATH="$HOME/.exenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(exenv init -)"' >> ~/.bash_profile
exec $SHELL

elixirを入れる。

# インストールできるバージョンを確認。
exenv install -l
# インストール
exenv install 1.0.5
# バージョン確認
elixir -v
Elixir 1.0.5
mix -v
Mix 1.0.5

node, npm

phoenixではアセットのコンパイルにnpm(とbrunch.io)を使うらしいのでnodeも入れておく。 最近v4.0.0が出たらしいのでついでに改めて入れてみる。 phoenixがちゃんと対応しているかは知らず。

nodebrew install v4.0.0
nodebrew alias default v4.0.0
nodebrew use v4.0.0

しかしアセットをnodeで管理するのは時代を感じるし理にかなってる。 Railsも本家でこういう対応してくれないだろうか。。。

phoenix

phoenixのインストールはちょっと見慣れない感じで以下のようにやるらしい。

mix archive.install https://github.com/phoenixframework/phoenix/releases/download/v1.0.2/phoenix_new-1.0.2.ez

mixというのはelixirに付いてくるビルドツールでnpmのようなもの?? Web上のアーカイブ(中身はZIPらしい)を持ってきて$HOME/.mix/archives/に配置してくれるらしい。

以上で準備できた。簡単。

Hello, Phoenix

とりあえず動作確認まで。

mix phoenix.new hello_phoenix
* creating hello_phoenix/config/config.exs
* creating hello_phoenix/config/dev.exs
* creating hello_phoenix/config/prod.exs
* creating hello_phoenix/config/prod.secret.exs
* creating hello_phoenix/config/test.exs
* creating hello_phoenix/lib/hello_phoenix.ex
* creating hello_phoenix/lib/hello_phoenix/endpoint.ex
* creating hello_phoenix/test/controllers/page_controller_test.exs
* creating hello_phoenix/test/views/error_view_test.exs
* creating hello_phoenix/test/views/page_view_test.exs
* creating hello_phoenix/test/views/layout_view_test.exs
* creating hello_phoenix/test/support/conn_case.ex
* creating hello_phoenix/test/support/channel_case.ex
* creating hello_phoenix/test/test_helper.exs
* creating hello_phoenix/web/channels/user_socket.ex
* creating hello_phoenix/web/controllers/page_controller.ex
* creating hello_phoenix/web/templates/layout/app.html.eex
* creating hello_phoenix/web/templates/page/index.html.eex
* creating hello_phoenix/web/views/error_view.ex
* creating hello_phoenix/web/views/layout_view.ex
* creating hello_phoenix/web/views/page_view.ex
* creating hello_phoenix/web/router.ex
* creating hello_phoenix/web/web.ex
* creating hello_phoenix/mix.exs
* creating hello_phoenix/README.md
* creating hello_phoenix/lib/hello_phoenix/repo.ex
* creating hello_phoenix/test/support/model_case.ex
* creating hello_phoenix/priv/repo/seeds.exs
* creating hello_phoenix/.gitignore
* creating hello_phoenix/brunch-config.js
* creating hello_phoenix/package.json
* creating hello_phoenix/web/static/css/app.css
* creating hello_phoenix/web/static/js/app.js
* creating hello_phoenix/web/static/js/socket.js
* creating hello_phoenix/web/static/assets/robots.txt
* creating hello_phoenix/web/static/assets/images/phoenix.png
* creating hello_phoenix/web/static/assets/favicon.ico

Fetch and install dependencies? [Yn] 
* running npm install && node node_modules/brunch/bin/brunch build

We are all set! Run your Phoenix application:

    $ cd hello_phoenix
    $ mix deps.get
    $ mix ecto.create
    $ mix phoenix.server

You can also run your app inside IEx (Interactive Elixir) as:

    $ iex -S mix phoenix.server

途中で「依存関係をインストールする?」と聞かれてyesと答えるとこうなる。 noにしてもプロンプトに表示されるように、あとでnpm install && node node_modules/brunch/bin/brunch buildすれば良いらしい。

で続きもプロンプトに出ているように以下のコマンドを打つ。

mix deps.get
Could not find hex, which is needed to build dependency :phoenix
Shall I install hex? [Yn] 
2015-09-14 23:18:39 URL:https://s3.amazonaws.com/s3.hex.pm/installs/1.0.0/hex.ez [269416/269416] -> "/Users/xxx/.mix/archives/hex.ez" [1]
* creating /Users/xxx/.mix/archives/hex.ez
Running dependency resolution
Dependency resolution completed successfully
  cowboy: v1.0.3
  cowlib: v1.0.1
  decimal: v1.1.0
  ecto: v1.0.2
  fs: v0.9.2
  phoenix: v1.0.2
  phoenix_ecto: v1.2.0
  phoenix_html: v2.2.0
  phoenix_live_reload: v1.0.0
  plug: v1.0.0
  poison: v1.5.0
  poolboy: v1.5.1
  postgrex: v0.9.1
  ranch: v1.1.0
・・・以下略・・・

出だしにShall I install hex?と聞かれるのでyesと答える。 hexとはelixirのパッケージマネージャだそうだ。 あれ?ってことはmixmakeてきな位置付けなのかな? このへんまだよくわからない。

次にmix ecto.createectoRailsでいうActiveRecord的なもの?

mix ecto.create
Could not find rebar, which is needed to build dependency :fs
I can install a local copy which is just used by mix
Shall I install rebar? [Yn] 
* creating /Users/akiyoshi/.mix/rebar
==> fs (compile)
Compiled src/sys/inotifywait.erl
Compiled src/sys/fsevents.erl

・・・中略・・・

** (Mix) The database for HelloPhoenix.Repo couldn't be created, reason given: "psql: FATAL:  role \"postgres\" does not exist\n".

大量のファイルが生成されたが最後にエラー。 DBの設定ができてなかったみたい。 postgresユーザーをパスワードpostgresで作成する。

# postgresqlサーバー起動
pg_ctl -l /usr/local/var/postgres/server.log start
# postgresユーザー作成
createuser -P -d postgres
# 確認
psql -q -c'select * from pg_user' postgres

もういちどmix ecto.createするとできた。

mix ecto.create
The database for HelloPhoenix.Repo has been created.

ようやくサーバー起動

mix phoenix.server
[info] Running HelloPhoenix.Endpoint with Cowboy on http://localhost:4000
14 Sep 23:37:53 - info: compiled 5 files into 2 files, copied 3 in 2398ms

http://localhost:4000/ にアクセスすると無事見れた。

f:id:akiyoshi83:20150914233909p:plain

参考

公式と以下の記事がとても参考になりました。感謝。

etc9.hatenablog.com

RSpecでデフォルトであるクラスのインスタンスメソッドをスタブにしたい

外部APIとかテスト中は常にスタブにしたいときに、個々のspecで設定するのが面倒だし忘れそうなケース。

こんな :spec/support/xxx_helper.rb を作っておいて

module XxxHelper

  # テスト全体で共通の前処理
  shared_context 'common_before', common_before: true do
    before :all do
      # 全体の前処理(あれば)
    end

    before :each do
      # Userがtweetというメソッドを持っている場合
      allow_any_instance_of(User).to receive(:tweet).and_return(true)
    end
  end
end

以下のように spec/request/xxx_spec.rbinclude_context するか

require 'rails_helper'

describe Xxx do
  include_context 'common_before'
end

もしくは以下のように describe で宣言的に指定する。

require 'rails_helper'

describe Xxx, common_before: true do
end

spec/rails_helper.rbspec/support 以下を読み込む設定をコメントインするのを忘れずに。

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

また個々のspecで expect_any_instance_of で上書きすればスタブ化したメソッドが呼ばれたか調べたいときも対応できる。

describe 'some_spec' do
  before :each do
   expect_any_instance_of(User).to receive(:tweet).and_return(true)
  end
  it 'xxxxx' do
    # xxxxx
  end
end

簡単だけど以上。

MacでJavaがまたわからなくなった

新しいMacBook Pro (2015)を買って便利に使っていたんだけど、やっぱり仕事でまたJava(AndroidStudio)が必要になった。

まだ入れてなかったので今使ってるYosemite10.10.3では何が入ってるんだろうと確認したところ、、、

$ java --version
No Java runtime present, requesting install.

とでて下記のようなダイアログが出る。

f:id:akiyoshi83:20150426140416p:plain

そうかもはやデフォルトでは入ってないのか、、、
しかしこの java コマンドは何もの??
これを伝えるためだけに存在するの??

$ which java
/usr/bin/java
$ ls -l /usr/bin/java
lrwxr-xr-x  1 root  wheel  74  2 22 18:00 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java

うーん、どうやらMacでのいつもの場所にあってその辺の構成は変わってないみたいだけどよくわからない。

まあとりあえずJava6,7,8が使い分けられる状態にできればいいや。

こちらを参考にさせていただきました。

Mac に brew で Oracle Java のバージョンを指定してインストールする方法 - Qiita

抜粋

- hosts: localhost
  connection: local
  gather_facts: no
  sudo: no
  vars:
    homebrew_taps:
      - homebrew/binary
      - homebrew/dupes
      - caskroom/cask
      - caskroom/versions
    homebrew_packages:
      - { name: readline }
      - { name: openssl }
      - { name: openssl, state: linked, install_options: force }
      - { name: python }
      - { name: ansible }

    homebrew_cask_packages:
      - { name: java6 }
      - { name: java7 }
      - { name: java }
      - { name: android-studio }

全体

github.com

.bashrcには以下のように書いた。

# Java (未インストールの場合はあるバージョンのが入る)
export JAVA_HOME6=$(/usr/libexec/java_home -v 1.6 2>/dev/null)
export JAVA_HOME7=$(/usr/libexec/java_home -v 1.7 2>/dev/null)
export JAVA_HOME8=$(/usr/libexec/java_home -v 1.8 2>/dev/null)
export JAVA_HOME=$JAVA_HOME7
export PATH=$JAVA_HOME/bin:$PATH

# Android Studio
export STUDIO_JDK=${JAVA_HOME7%/*/*}

Java、せっかく便利(?)なんだからこの辺もうちょい小慣れてほしい。。

Sass/ScssフレームワークBourbon使ってみた

要約

BourbonたちはしっかりHTML/CSS書きたいとき向け。
CSSの習熟度によって感想変わりそうではある)

きっかけ

以下の記事をみてSass/ScssのフレームワークであるBourbonとその仲間たちを知った。

CSSフレームワークBourbon/Neat/Bitters/Refillsは美しい

CSSフレームワークといえばBootstrap便利でよく使ってるんだけど、記事でも言われているようにクソマークアップ問題は感じている。
そこで代替としてBourbonファミリーはどんなもんか自分でも触ってみた。

色々試した結果
akiyoshi83/ex_bourbon · GitHub

Bourbonとその仲間たちの現時点での認識は以下の様な感じ。

お試しプロジェクト用意

Railsで試してみる。

$ rails new -B -T ex_bourbon
$ cd ex_bourbon

Gemfileに追加してインストール。

$ ehoc ‘gem “neat”’ >> Gemfile
$ ehoc ‘gem “bitters”’ >> Gemfile
$ ehoc ‘gem “refills”’ >> Gemfile
$ bin/bundle install —path vendor/bundle

Bourbon自体はNeat, Bitters, Refillsがそれぞれ依存しているので勝手に入ってくる。

$ echo ‘/vendor/bundle’ >> .gitignore
$ git init
$ git add .
$ git ci -m “First commit"

お試し用のページを用意。

$ bin/rails g controller home index
$ git add .
$ git ci -m "Add home/index and set root path"

Bourbonをセットアップ

参考 http://bourbon.io/

とはいっても app/assets/stylesheets/application.cssapp/assets/stylesheets/application.scssにリネームして 既存の内容を全て消してからその中に@importを記述するだけ。

@import ‘bourbon’;

Railsでない場合は以下のコマンドを打つとカレントディレクトリにbourbonディレクトリが出来る。

$ bundle exec bourbon install

—pathオプションで配置場所を変更できる。

Neatをセットアップ

参考 https://github.com/thoughtbot/neat#requirements
これもBourbonと同じ要領。

ただし@importはBourbonのよりあとに書く。
Rails以外ではコマンドでセットアップする必要があるのも同じ。

Bittersをセットアップ

参考 https://github.com/thoughtbot/bitters#installation

これはRailsでもコマンドでセットアップが必要。

$ (cd app/assets/stylesheets/; ../../../bin/bundle exec bitters install)

以下のようになる。

$ tree app/assets/stylesheets/
app/assets/stylesheets/
├── application.css
└── base
    ├── _base.scss
    ├── _buttons.scss
    ├── _forms.scss
    ├── _grid-settings.scss
    ├── _lists.scss
    ├── _tables.scss
    ├── _typography.scss
    └── _variables.scss

そしてBourbonのあとに@importする。
Neatも併用する場合はNeatをBittersのあとに@importする。

@import 'bourbon';
@import 'bitters';
@import 'neat';

それとbase/_base.scss@import “grid-settings”;をコメントインする必要があるらしい。 手元では簡単なグリッドはコメントインしなくても動いたけど必要なのかな?

他にもやりたいことによって@importのパスを変えたり色々変える必要があるらしけどとりあえずこの設定で試す。

あとはこれで普通にHTML書いていくとある程度のスタイルがBittersによってあたっているし(最小限っぽいけど)、グリッドもSCSS側で書けば簡単に実装できる。

またBittersが生成するSCSSは8つあるけどどれも100行未満で簡単に読めてカスタマイズも容易そう、かつSass/Scssビギナーには参考になる気がする。

Refillsをセットアップ

参考 https://github.com/thoughtbot/refills#installation

以下のコマンドで試用できるスニペット一覧が表示される。

$ bin/rails g refills:list
Available Refills
=================
- accordion-tabs-minimal
- accordion-tabs
- accordion
- animate-info
- animate
- badges
- breadcrumbs
- button-group
- cards
- centered-navigation
- comment
- device
- dropdown
- expander
- fade-in
- flashes
- flex-boxes
- footer-2
- footer
- grid-items-lines
- grid-items
- hero
- hover-tile-animation
- icon-bullet-points
- image-gradient-dynamic
- maps
- modal
- navigation
- pagination
- parallax
- progress-bar-indication
- progress-bar
- ribbon
- scroll-on-page
- search-bar
- search-tools
- side-image
- sliding-menu
- stats
- switch
- tables-minimal
- tables
- texture-legend
- textures
- tooltip
- type-system-geometric
- type-system-rounded
- type-system-sans
- type-system-serif
- type-system-slab
- type-system-traditional
- vertical-tabs
- video

スニペットのインストールは

$ bin/rails generate refills:import SNIPPET

スクリプトCoffeeScriptで欲しい時は以下。

$ bin/rails generate refills:import SNIPPET --coffee

スニペットは1つずつ指定してインストールするらしい。 単純そうなfooterをインストールしてみる。

$ bin/rails g refills:import footer --coffee
      create  app/views/refills/_footer.html.erb
      create  app/assets/stylesheets/refills/_footer.scss

うーん、ほんとサンプルコードが生成されます、ッて感じで、あんまり使い勝手良くないかも。 あくまで参考にする程度か。

感想

Bootstrapみたいにclassを書くだけで劇的にスタイリングが楽になるようなものではない。あくまでスタイルはガシガシ書く必要がある。

ただもちろんブラウザごとの書き方の違いは吸収してくれるし、HTMLに謎のclassが散りばめられることはなくなる。 Bootstrapもちゃんと使うとスタイルの上書きやなんやらで結構ガシガシ書くし、余計なことを気にせずマークアップを正しく書いて見た目はCSSでっていう成功法で実装するには都合が良さそう。

使い捨ての社内ツールやプロトタイプでプログラマが手っ取り早く見た目を整えたいって場合は相変わらずBootstrapは有力な選択肢。

あとCompassもそうだけどBourbonが用意してくれるmixinは結構マニアックなプロパティに関するものもあるので、そもそもCSSにちゃんと詳しくないと使い方が分からないであろうものも結構ある。 そういう場合もBootstrapで充分かも。

BourbonらはあくまでHTML/CSSをちゃんと書きたい人向けのツールだと思った。

とはいえ今後自分が作るツールとかにBourbon使わずBootstrap使うかといえば微妙で、できれば簡単なものでもBourbon使っていきたい。 自分の場合、そもそも簡単なものならBootstrapすら使わず最低限のCSSとJSで済ませてしまうことも多いので。 どうせBootstrap使わないならブラウザ間の違いも吸収してくれるしSCSSもっと使いこなせるようになりたいしBourbon使ったほうが良い気がする。

でどうせならNeatのグリッドシステムあれば便利だしBittersでタイポグラフィとかあたってくれるとまあこれでいいかってなるのでそれも使いそう。 ただテーブルとか変更したいものもあるけどカスタマイズも容易そうなので。Refillsは参考程度かな…

まあ自分の選択のレベルだと好みで良いかなってレベルだけど。 長期的にHTML/CSSをメンテしていく時にはもっと明確にメリットが出るかもしれない。その辺はもっと使い込んでみないとハッキリ言えないけど。

昔入れてたMySQLを入れなおしたメモ

ローカルのMac上にMySQLが欲しくなって入ってたっけな?と調べたときのメモ。

あと最終的にMacPortsで入れてたMySQLをHomebrewで入れなおしたんだけど、なんかMac特有っぽい事があったのでそれも。

調べたら簡単にインストールし直せたんだけど、こういった環境周りで忘れてしまったことの調査って、分からない人には結構時間かかることかもしれないので誰かの参考になれば。

まず過去にインストールしてたらMySQLへの接続コマンドが入ってそうなので打ってみる。

$ mysql

と打ってタブで補完すると以下のように出てきた。

mysql5                       mysql_install_db5            mysqladmin5                  mysqlhotcopy5
mysql_client_test5           mysql_secure_installation5   mysqlbinlog5                 mysqlimport5
mysql_client_test_embedded5  mysql_setpermission5         mysqlbug5                    mysqlshow5
mysql_config5                mysql_tzinfo_to_sql5         mysqlcheck5                  mysqlslap5
mysql_convert_table_format5  mysql_upgrade5               mysqld_multi5                mysqltest5
mysql_find_rows5             mysql_waitpid5               mysqld_safe5                 mysqltest_embedded5
mysql_fix_extensions5        mysql_zap5                   mysqldump5                  
mysql_fix_privilege_tables5  mysqlaccess5                 mysqldumpslow5  

うーん、一体いつ入れたんだっけ?
昔過ぎて思い出せない。
このまま新しくインストールするのは気持ち悪いので消そう。

Linuxでもそうだけどwhichコマンドで指定したコマンドのパスを調べられる。

$ which mysql5
/opt/local/bin/mysql5

場所はわかったけど、どうやってインストールしたんだっけ?
パス的に自分でビルドしたものではなさそう(自前ビルドはいつも別の場所でやっているので)なのでパッケージ管理システムっぽい気がする。

このMacではHomebrewとMacPortsで入れたものが微妙に混在している…
Homebrewから調べる

$ brew list | grep mysql

違った…じゃあMacPortsか?

$ port installed | grep mysql
  mysql5-devel @5.5.2-m2_1 (active)

これだ!
なんでdevelだけインストールしてたんだろう…?
何かが依存してるかもだけど全く覚えてないので、壊れてるの発見したらその時考えよう…

$ port uninstall mysql5-devel

これで綺麗になったので改めてbrewでインストールする。

$ brew update
$ brew install mysql
==> Installing mysql dependency: openssl
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/openssl-1.0.2.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring openssl-1.0.2.yosemite.bottle.tar.gz
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl/certs

and run
  /usr/local/opt/openssl/bin/c_rehash

This formula is keg-only, which means it was not symlinked into /usr/local.

Mac OS X already provides this software and installing another version in
parallel can cause all kinds of trouble.

Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/openssl/lib
    CPPFLAGS: -I/usr/local/opt/openssl/include

==> Summary
🍺  /usr/local/Cellar/openssl/1.0.2: 459 files, 18M
==> Installing mysql
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/mysql-5.6.22.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring mysql-5.6.22.yosemite.bottle.tar.gz
==> Caveats
A "/etc/my.cnf" from another install may interfere with a Homebrew-built
server starting up correctly.

To connect:
    mysql -uroot

To have launchd start mysql at login:
    ln -sfv /usr/local/opt/mysql/*.plist ~/Library/LaunchAgents
Then to load mysql now:
    launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
Or, if you don't want/need launchctl, you can just run:
    mysql.server start
==> /usr/local/Cellar/mysql/5.6.22/bin/mysql_install_db --verbose --user=akiyoshi --basedir=/usr/local/Cellar/mysql/5.6.22 --dat
==> Summary
🍺  /usr/local/Cellar/mysql/5.6.22: 9666 files, 339M

依存関係でOpenSSLも入った。
今までなかったんだっけ???

またインストールの出力にMac特有っぽいことが書いてあったのでメモ。

  • 他でインストールしたmysql/etc/my.confがあると正常に起動できないかもよ(これはMacだけじゃないか…でも親切ね)
  • ログイン時に自動起動するには~/Library/LaunchAgents/usr/local/opt/mysql/*.plistシンボリックリンクを貼ってよ
  • launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql.plistで今すぐ起動もできるよ(?)
  • mysql.server startでも可だよ

あとインストールの出力の最後のように書かれている通り勝手に初期設定もしてくれたっぽい。

試しに起動してみる。

$ mysql.server start
Starting MySQL
.. SUCCESS!

psコマンドで確認すると確かにプロセスが起動していた。
接続してみる。

$ mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.22 Homebrew

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)

イケた!
どんな初期設定になったかは調べてないけどとりあえずMySQL使えれば良いレベルなので困ったらで良いか。

Promiseのスニペット

JavaScriptのPromiseが便利そうなので使い始めてたのだけど、メソッドチェインしたり入れ子にしていたら混乱してきたのでまとめる。

この数日でよく使った(そして度々間違えた)パターンのメモ。

逐次実行

こんな感じのPromiseオブエジェクトを返す関数があったとする。

function promise1() {
  console.log('promise1 args', arguments);
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      // resolveしたものがthenの引数になる
      resolve('resolve promise1');
    }, 500);
  });
}

function promise2() {
  console.log('promise2 args', arguments);
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('resolve promise2');
    }, 400);
  });
}

function promise3() {
  console.log('promise3 args', arguments);
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('resolve promise3');
    }, 300);
  });
}

単純にthenで連結すると逐次実行になる。
これは単純。

// それぞれのpromise関数には前の関数でresolveした値が引数にくる
promise1()
.then(promise2)
.then(promise3)
.then(function() {
  // promise3でresolveに与えたものが引数で渡ってくる
  console.log(arguments);
  // returnした値を次のthenのコールバックで受け取れる
  return "returm then callback";
}).then(function() {
  console.log(arguments);
});

出力。

promise1 args []
promise2 args ["resolve promise1"]
promise3 args ["resolve promise2"]
["resolve promise3"]
["returm then callback"]

別のパターン。
事前にいくつthenが必要になるか分からないときなどはこういった手間がいるかも。(以下はJavaScript Promiseの本の例そのままです)

// 以下の様なヘルパー関数を使って
// Promiseオブジェクトを返す関数の配列を
// 逐次処理することもできる
function sequenceTasks(tasks) {
  function recordValue(results, value) {
    results.push(value);
    return results;
  }
  var pushValue = recordValue.bind(null, []);
  // reduceの第2引数のpromiseオブジェクトを初期値に折りたたむ
  return tasks.reduce(function (promise, task) {
    return promise.then(task).then(pushValue);
  }, Promise.resolve());
}

// 逐次実行
sequenceTasks([promise1, promise2, promise3]);

出力。

promise1 args [undefined]
promise2 args ["resolve promise1", "resolve promise2", "resolve promise3"]
promise3 args ["resolve promise1", "resolve promise2", "resolve promise3"]

入れ子

API全体をPromise使おうとしていたんだけど、「あれ?この関数でreturnしているpromiseオブジェクトをそのまま返せば良いんだっけ?新しくnewしないといけないんだっけ?」と迷った。

結論をいうとそのまま返して良いし、返す前にthenやcatchで処理を追加してもよい。thenやcatchが返すオブジェクトも新しいpromiseオブジェクトであるため。

thenやcatchは処理を追加していくイメージっぽい。

function promiseInner() {
  console.log('promiseInner args', arguments);
  return new Promise(function(resolve, reject) {
    resolve('promiseInner');
  });
}

function promiseOuter() {
  console.log('promiseOuter args', arguments);
  // promiseのなかでもpromiseが使える
  // promise関数自体もthenも
  // 新しいPromiseオブジェクトが返るので
  // それをそのまま返せばメソッドチェインできる
  return promiseInner().then(function() {
    console.log('promiseOuter after4', arguments);
    return "return promiseInner in promiseOuter";
  });
}

promiseOuter()
.then(function() {
 console.log('afterInner', arguments);
});

出力。

promiseOuter args []
promiseInner args []
promiseOuter after4 ["promiseInner"]
afterInner ["return promiseInner in promiseOuter"]

もっと慣れたら便利っぽいので小さいところから使って慣れていこう。

MacでのJDK管理

MacJavaLinuxより更にややこしい。
ググったのが通算3回位になったのでそろそろ自分でもメモ。

Linuxでのは昔書いた記事参照。
UbuntuでのJDK管理 - my coredump

MacでのJava事情とかどこにインストールされるのかとかの詳しいことは、 他の方が書いているのでここでは手っ取り早く結論だけ書きます。

OSXでJavaのバージョンを切り替える
(お世話になっております)

結論

ダウンロードするところ

2014.01.10時点

インストール

普通にdmgを実行する。 インストールする順番とかは気にしないでも大丈夫だった(1.7の後に1.6入れたり)。

バージョン切り替え

.bash_profileとかお好みのドットファイルにに以下を記述。

export JAVA_HOME=$(/usr/libexec/java_home -v 1.6)
export PATH=$JAVA_HOME/bin:$PATH

-v 1.6の部分を切り替えればバージョンが切り替えられる。 変更した後は.bash_profileなどを再読込するかログアウト・ログインする。