Development

Railsで request.body を触るのは避けたほうがいいかも

API等を実装していて create アクションなどで以下のように json payload をパースするケースがありました。

def create
  payload = JSON.parse(request.body.string)
  ...
end

開発中だとこれでも問題ないのですが、本番環境などで unicorn を使っていると request.body の返すオブジェクトが変わってくるのでエラーしてしまいました。

ググったところこちらの方法が良さそうです。
http://stackoverflow.com/questions/24566423/checking-request-body-in-grape-api

def create
  payload = JSON.parse(env["rack.input"])
  ...
end

ただこれでもテスト環境だと env[“rack.input”] は nil を返すので、テストが落ちてしまいました。

で最終的に落ち着いたのがこれ

def create
  payload = JSON.parse(env["rack.input"].try(:read) || request.body.string)
  ...
end

これでなんとかどの環境でも動くようになりました。

ちなみに JSON.parse が空文字や nil を受け取ると例外を投げるので実際には以下のようにするといいと思います。

def create
  payload = parse_json_payload
  ...
end

private
  def parse_json_payload
    JSON.parse(env["rack.input"].try(:read) || request.body.string)
  rescue => _
    nil
  end
標準
Development

rubyで 3 / 2 は 1.5 じゃありません

rubyで小数点のつくデータ型はFloatですが、整数同士の計算をしていても解に小数点は勝手につかないので注意しましょう。
(久々に初歩的なところでハマった…)

3 / 2 # => 1

こうしなければいけない

3.to_f / 2 # => 1.5

どちらかがFloatならok

ちなみにjavascriptだと 3 / 2 は 1.5 を返します。
number型しかないからですかね。

標準
Development

ES2015でenumを作ってみる

javascriptにはenumという型はありませんので、今まで(ES5)は以下のように擬似的にenum的なものを作っていました

var Sample = {
  One: "one",
  Two: "two"
};

ついでに const 宣言も無かったので後から書き換え可能になっているのも残念なところです。

ES2015になってつい嬉しくて const 宣言を使って以下のようにしていました。

const Sample = {
  One: "one",
  Two: "two"
};

しかしこれも実は残念なところがあって、値が文字列である以上他の由来の文字列でも比較がtrueになってしまうのです。

const Sample = {
  One: "one",
  Two: "two"
};
const Other = {
  One: "one",
  Two: "two"
};

console.log(Sample.One === Other.One); // => true

これはいただけませんね。enumの役割をちゃんと果たしていません。

ES2015ではSymbolが使えるようになったので以下のようにするととってもいい感じだとおもいます。

const Sample = {
  One: Symbol("one"),
  Two: Symbol("two")
};
const Other = {
  One: Symbol("one"),
  Two: Symbol("two")
};

console.log(Sample.One === Other.One); // => false

Symbol() はグローバルにユニークな値を返すので、同じ引数で実行しても結果が異なるためにこのような使い方ができるわけです。

ちなみにグローバルに同一なSymbolを参照したい場合は Symbol.for() を使うといいみたいです。

let one = Symbol.for("one");
console.log(one === Symbol.for("one")); // => true

Symbolのブラウザでの実装状況はこちら http://kangax.github.io/compat-table/es6/#test-Symbol

標準
Development

Chromeを48.0.2564.97にアップデートしたらレンダリングが非常に遅くなってしまった

結論から言うと CSSプロパティ `font-feature-settings` を設定すると特定のChromeバージョンにおいてレンダリング(layout, painting)が非常に遅くなる(レポート報告済)。

font-feature-settingsとは?

OpenType Fontの先進的なタイポグラフィーの機能を使用するためのプロパティ。下記のような機能がある。

  • font-kerning (カーニング)
  • legature (合字)
  • pnum (Proportional figures)

Demoを見つけたので共有: http://clagnut.com/sandbox/css3/

なぜ使っていたのか?

プロジェクト開始時は `normalize.css` と bourbonファミリーを下地にすることが多いのですが、bourbonファミリーの一つであるbittersで生成したbase cssにそれが入っていたようです。

対策

今回この現象が発生したプロジェクトでは `font-feature-settings` を使う意図が無かったので該当コードをCSSより削除しました。

標準
Development

Github Flow的な作業の始めかた

ハレノヒではプロジェクト管理はtrelloかgithubを使っています。これは決まりではありませんがどちらもチームが使い慣れていますので今では当たり前のようにこれらを使っています。
他にもいいプロジェクト管理ツールがあれば使ってみたいですね。

さて、Githubを使っているということは当然gitを使ってバージョンを管理をしているのですが、ブランチを作り作業を始める際の定番手順を紹介したいとおもいます。

Github Flowについてはこちらに日本語翻訳記事がありますので御覧ください
https://gist.github.com/Gab-km/3705015

はじめに

例としてSuper Awesomeなポートフォリオサイトを構築していたとします。
ポートフォリオサイトなので作品紹介ページは作ったのですが、お問い合わせページがまだ無いのでそれを追加する作業を進めていきます。

またGithub社が提供する hub コマンドを使うと便利なのでこれも合わせて紹介します。

1. masterブランチからfeatureブランチを作成する

まずは作業するためのブランチを作成します。この場合新機能の開発なので feature(機能)という名前空間の下に作業内容がわかりやすい名前で作成します。

git checkout -b feature/contact_form

git checkout -bを使うとブランチの作成とチェックアウトを同時に行えるので便利です。

2. 空のコミットをしておく

新しいブランチではcommitが一つもないのでこのままではPull Requestが作成できません。
なので以下のように空のコミットでブランチを作成したという内容だけを記録しておきます。

git commit --allow-empty -m "Create a branch"

3. originにpushする

git push origin feature/contact_form

4. Pull Requestを作成する

ここでhubコマンドの登場です。
https://github.com/github/hub

Mac OS XならHomebrewでインストールできます。

brew install hub

hub コマンドでPull Requestを作成する方法はこちらです

hub pull-request -m "[WIP] お問い合わせフォームを実装"

-m でPull Requestのタイトルを付けられますが、先頭に[WIP]をつけました。
これは Work In Progress の略称です。
つまりまだ作業中ですよという意味ですね。

5. チェックリストを作成する

hubコマンドでPull Requestを作成すると標準出力にWebページのURLが表示されますのでそこにアクセスしましょう。

 hub pull-request -m "[WIP] お問い合わせフォームを実装"
https://github.com/yourname/yourrepo/pull/1

チェックリストは作業を意味のある単位で分割して書くようにしています。
たとえば `GET /conatct_us` と `POST /contact_us` という2つのRouteを追加するのであれば
「contact_usのroutesを追加」という項目にまとめてしまいます。

より詳細に記述したい場合はチェックリストに階層をつけるといいとおもいます。

今回は以下のようにしました

Githubのコメント欄にはMarkdownが書けますが、- [ ]というリストを使うとチェックリストを作成できます

このように

6. 作業をすすめる

ここまでできたら後はガンガンコードを書いて開発をすすめます。
途中で一段落ついたらこまめにoriginへpushすることをオススメします。
そうすると何か間違っていたり、別のブランチで同じ作業をしてしまっていたりしたらお互いにコメントしあえるからです。

紆余曲折があってレビューの際に質問されそうだなと思う部分があるなら自分から先にコメントしてしまうのも手です。

例えば以下のように

7. レビューしてもらう

チェックリストが全部Doneしてマージする準備ができたらチームメンバーにレビューしてもらいます。
先にPull Requestのタイトルから [WIP] を削除しておきましょう。

ほんの小さな変更であればこの手順を省略してもいいとおもいますが、できるだけレビューしてもらうことで自分でも気づかなかった部分が見えてくることがあります。

この時、粗探しだけをするのではなく感心したり勉強になるようなことがあれば伝えてあげるといいとおもいます。

8. マージする

マージは基本Pull Requestを作った本人が行います。
GithubのWebページからマージボタンを使うと、忘れがちなDeleteもすぐに行えてマージ済みブランチがたくさんある状態を防げます。

リモートでマージをしたら忘れずにローカルにも反映しておきます。

git checkout master
git pull origin master
git branch -d feature/contact_form

ローカルの feature/contact_form ブランチも削除しておきましょう。

まとめ

以上がgithubを使った作業の進め方です。
そんなに難しいことはありませんが、気をつけるとことがあるとすれば自分の書いたコードは誰かに読んでもらうということを前提に作業をしていると、レビューしてもらう相手はもちろん未来の自分にも優しくなれるように気がします。

標準
Development

Elasticsearch 1.5.2をインストールする

Amazon Elasticsearch Service が 1.5.2 を使っているということで(2016-01-29)

ローカルMacに1.5.2をインストールしようかと思って、brew search elasticsearch を叩くと 2.1系しかヒットしません。
homebrew/versions も見てみましたが一番古くて1.7でした。

ということで本家のダウンロードページからzipをダウンロードすることに
https://www.elastic.co/downloads/past-releases/elasticsearch-1-5-2

ここでzipをダウンロードして、次はインストールか!と意気込んでいたのですが、READMEを読むと

h3. Installation

* "Download":https://www.elastic.co/downloads/elasticsearch and unzip the Elasticsearch official distribution.
* Run @bin/elasticsearch@ on unix, or @bin\elasticsearch.bat@ on windows.
* Run @curl -X GET http://localhost:9200/@.
* Start more servers ...

え、マジ?
指示通り適当な場所に移動させて bin/elasticsearch を叩くとサーバー起動しました!
こんなに簡単なのかー。開発用ならこれで全然問題無いですね。

標準
ruby-on-rails
Development

Railsで複数のasset_hostを動的に切り替える方法

弊社ではRailsアプリのproduction環境ではasset_syncを使ってs3にcssやjsを置くのが定番になっています(世間的に見てもそうかもしれないけど)

asset_syncを使った場合。静的ファイルのホストがRailsアプリと別になるので以下のようにasset_hostを設定します

# config/environments/production.rb
Rails.application.configure do
  config.action_controller.asset_host = '//s3-bucket-name.ap-northeast-1.amazonaws.com'
end

通常はこれで問題ないのですが、s3 bucketの別名を複数用意して静的ファイル読み込みの高速化を図るとか、物理的にデータが別のs3 bucketにあるから変えなきゃいけないなんてときに困ってしまいますよね。

最初はasset_pathをゴニョゴニョするのか…?なんて思ったんですがasset_hostにProcオブジェクトを設定するともとスマートに対応出来ました。

例として、/assets以下のリソースにアクセスする場合と、その他でs3 bucketを分ける場合は

# config/environments/production.rb
Rails.application.configure do
  config.action_controller.asset_host = proc { |source|
    bucket = source.include?('/assets') ? 'assets-bucket' : 'other-bucket'
    "//#{ bucket }.ap-northeast-1.amazonaws.com"
  }
end

引数のsourceはリクエストのパスが渡ってきます。この場合だと ‘/assets/application-87rfhsou4fo4.css’ みたいな感じですね。

標準
ruby-on-rails
Development

複数のRailsアプリで同じDBを使う場合にschema_migrationsを分ける方法

複数のRailsアプリで同じDBに接続する場合DBのマイグレーション履歴が同じschema_migrationsテーブルに格納されるのはちょっとこわい。

でもschema_migrationsって名前はRailsが決めているものだからどうやって変更するの?というのを調べたら接頭辞を使えばいいみたいで

# config/application.rb
module SampleApp
  class Application < Rails::Application
    ...
    config.active_record.table_name_prefix = 'sample_'
  end
end

上記のようにやっておくとアプリ全体のテーブル名にsample_が付くようになって、問題の箇所はsample_schema_migrationsというテーブル名になります。

ちなみにAdminユーザーテーブルを共有して同じアカウントでログイン出来るようにする場合は、sample_接頭辞をつけている側で

# app/models/admin.rb
class Admin < ActiveRecord::Base
  self.table_name_prefix = ''
end

というように個別モデル毎に接頭辞をなくしてあげることも出来るので複数アプリで同じテーブルを参照できますね。

ちなみにDeviseを使っているのでconfig/initializers/devise.rbでconfig.secret_keyを合わせてあげないとログインできませんでした。

多分複数アプリでschema_migrationsを共有しても問題なくて、rake db:migrate:statusすると存在しないmigrationの部分は ********** NO FILE ********** と表示されるだけなんだけどね。

標準
staart-blogtitle
Releases

[Staart]ランキング機能を追加しました!

最近Staartの更新情報ばかりなブログになっておりますハレノヒブログです。
そして今回も新機能追加のお知らせです!

ランキング機能を追加!

アクセスランキングのページを公開しました。
Staartの成長と共にランキングのアクセス数も増えていってくれると思います。

ランキングは今日までの一週間のランキングと、期間を指定して一週間ごとのランキングを見ることが出来ます。まだリリースしたてなのでアーカイブはありませんが、過去のランキングを見たい場合は右側の週間アーカイブからどうぞ。

いまどのライブがアツいのか、トップページのバナーから確認してみてください!

blog-0626

どんどん成長中!

先日追加した検索バーを改良しました。
より見やすく、使いやすくなりましたので沢山検索していただけると嬉しいです。

blog-0626-2

それから、ユーザー機能も開発が進んでいるようです。どうぞお楽しみに!!

アクセスはこちらから!↓
https://www.staart.jp/

標準