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

モンモンブログ

Ruby, Python, PHP, JavaScript/jQuery などなど気分に応じて

Rails + Grape 構成で Grape API ファイルを自動再読み込みさせるには

RESTful な API が楽ちんに書ける graperails との組み合わせで使う場合も README に従うだけで簡単に出来ますが、なぜか自動再読み込み (auto reloading) されないって問題にぶち当たります。

development 環境だと model や controller への修正はブラウザをリロードするだけで即反映されますよね。でも grape の api ファイルはなぜか再読み込みされない。いちいち rails サーバを再起動しないといけなくて、非常に困っちゃんです。

(よく理解してませんが rails 上で別の rack フレームワーク(この場合 grape)を動かそうとするとrails の自動再読み込みの仕組みがうまく動かないみたいです)

で、解決方法ですが、grape api ファイルの更新を検知して、無理やり再読み込みさせてやります。

環境

古くてごめんなさい

MacOSX Mavericks
ruby 1.9.3p547 (2014-05-14 revision 45962) [x86_64-darwin13.3.0]
rails-3.2.11
grape-0.9.0

セットアップ

今回は既存の rails アプリに grape を追加しました。手順をざくっと書いておきます。

Gemfile に追記して、

gem 'grape'

インストール

bundle install

grape api ファイルを置くディレクトリを作って

mkdir app/api

Hello World なやつを書いた。(app/api/skimatalk_api.rb)

require 'grape' # この行は grape 単体で動かす場合に必要。rails との組み合わせでは不要
class SkimatalkApi < Grape::API
  format :json

  resource :ehehe do
    desc 'this is a test'
    get :hoe do
      {a: 1, b: 2}
    end
  end
end

rails と組み合わせて実験する前に grape 単体で動かしてみたかったので、同じディレクトリにテスト用の config.ru を作成 (app/api/config.ru)

# coding: utf-8
require './skimatalk_api.rb'
run SkimatalkApi

起動

$ cd app/api
$ rackup
Thin web server (v1.6.2 codename Doc Brown)
Maximum connections set to 1024
Listening on 0.0.0.0:9292, CTRL+C to stop
127.0.0.1 - - [22/Nov/2014 19:54:05] "GET /ehehe/hoe HTTP/1.1" 200 13 0.0971

http://localhost:9292/ehehe/hoe にアクセスすると JSON が表示された。わーい。

f:id:ymdsmn:20141122201157p:plain

(さっき作った config.ru はもう不要なので削除してよいです)

今度はこれを rails 上で動かします。 config/routes.rb に以下を追加して /api/* へのリクエストを grape へ渡すようにします

  mount SkimatalkApi => '/api'

サーバ再起動してから、

rails s

http://localhost:3000/api/ehehe/hoe にアクセス。JSON が表示された。やったね。

f:id:ymdsmn:20141122201201p:plain

でも(さっきも言ったとおり)app/api/skimatalk_api.rb を修正してリロードしても変更が反映されません。困ったね。

解決方法

ここからが本題。 config/initializers/reload_api.rb を作って以下のように書きます

if Rails.env.development?
  api_reloader = ActiveSupport::FileUpdateChecker.new(Dir['app/api/*']) do # app/api/* は環境にあわせて変更すること
    Rails.application.reload_routes! # or do something better here
  end

  ActionDispatch::Callbacks.to_prepare do
    api_reloader.execute_if_updated
  end
end

これだけで、 app/api/* への修正を検知して自動再読み込みしてくれるようになりました。

仕組みは読めばなんとなく分かるよね。分かんなくてもいいよね。

参考

正直このエントリは stackoverflow のこれ↓を解説しただけです。ググって見つけるのに苦労したので書きました…
Ruby on Rails 3 - Reload lib directory for each request - Stack Overflow

vimeoの埋め込み動画が表示されなくて困ったけどプロトコルをhttpsにしたら解決した

動画を埋め込む時は動画URLのプロトコルhttps にしておきましょうというお話。

このvimeoの動画は下のようなHTMLで埋め込んでます。

<iframe
  src="http://player.vimeo.com/video/69996517"
      ↑動画URLのプロトコルはhttp
  width="480"
  height="360"
  ></iframe>

動画URLのプロトコルhttp です。これで何の問題もなく再生できますよね。

ですが、動画を埋め込んでるページ(このブログ)自体のURLのプロトコルhttps だった場合、ブラウザによっては(具体的には FirefoxGoogle Chrome などでは)動画が表示されません。からっぽの長方形が表示されるだけです。

MacOSXFirefox 29.0.1, Google Chrome 34.0.1847.137 で確認。Safari 7.0.3, Opera 10.9.2 ではプロトコルに関わらず動画が表示されました)

<iframe
  src="https://player.vimeo.com/video/69996517"
       ↑プロトコルをhttpsに変更
  width="480"
  height="360"
  ></iframe>

こうやって動画URLのプロトコルhttps にしておけば、ページのURLのプロトコルが http だろーと https だろーとちゃんと表示されます。これで安心。

以上です(:3[___]

実験

でもまあ「ほんまかいな?」て人は実験してみましょう。

以下を video.html ってファイル名でどこでもいいので保存して、

<!DOCTYPE html>
<html lang="ja">
    <head>
       <meta charset="utf-8">
       <title>vimeo sample</title>
   </head>
    <body>
        <div style="float:left">
            <div>動画URLのプロトコルがhttp</div>
            <iframe
                 src="http://player.vimeo.com/video/69996517"
                 width="480"
                 height="360"
                 ></iframe>
        </div>
        <div style="float:left">
            <div>動画URLのプロトコルがhttps</div>
            <iframe
                 src="https://player.vimeo.com/video/69996517"
                 width="480"
                 height="360"
                 ></iframe>
        </div>
    </body>
</html>

同じディレクトリに、以下を https-server.rb ってファイル名で保存して、
httpsなWebサーバを立ち上げるスクリプトです。cf. WEBrickでSSLを有効にする

#!/usr/bin/env ruby
require 'webrick'
require 'webrick/https'

server = WEBrick::HTTPServer.new(
    :BindAddress => '127.0.0.1',
    :Port => 9999,
    :DocumentRoot => '.',
    :SSLEnable  => true,
    :SSLCertName  => [ [ 'CN', 'localhost' ] ]
)
Signal.trap('INT') { server.shutdown }
server.start

実行してWebサーバを立ち上げまして、

$ ruby https-server.rb

さっき作った vimeo.htmlhttps で開いてみます。不正なSSL証明書だよって怒られるけど適当にパスして下さい。

https://localhost:9999/vimeo.html

Firefox, Google Chrome では https の方の動画だけ表示されるかと思います。こんな風に。

f:id:ymdsmn:20140520101842p:plain

以上でござる(:3[___]

jQuery プラグインを bower のレジストリに登録してみた

表題の通り、jQuery プラグイン jquery.narrowsbowerレジストリに登録してみた時の記録です。

bower とは?

こちらが非常に分かりやすかったです。

基礎編の冒頭から(勝手に)引用させて頂きますと、bower とは

Twitter社が作ったフロントエンド用のパッケージマネージャです。 Java で言う MavenRuby で言う gem、 Perl で言う cpan のようなものです。 Node.jsには npm と呼ばれるパッケージマネージャがありますが、それに強く影響を受けています。

ということです。

bower のパッケージは bower レジストリってところで管理されています。 登録済みパッケージの一覧は Bower components ってページで見られます。検索もできます。

この bower レジストリにおいらの jQuery プラグインをいっちょ登録したるぜ!と思い立ちました。

bower レジストリに登録すると何が嬉しいの?

ここに登録しておけば、

bower search で検索したり("sinon" は javascript のテスト用ライブラリです)

$ bower search sinon
Search results:

    sinon git://github.com/cjohansen/Sinon.JS.git
    sinon-chai git://github.com/domenic/sinon-chai.git
    sinonjs git://github.com/blittle/sinon.js.git
(以下略)

bower info でインストール可能なバージョンを調べたり

$ bower info sinon
bower sinon#*               not-cached git://github.com/cjohansen/Sinon.JS.git#*
bower sinon#*                  resolve git://github.com/cjohansen/Sinon.JS.git#*
bower sinon#*                 download https://github.com/cjohansen/Sinon.JS/archive/v1.7.3.tar.gz
bower sinon#*                  extract archive.tar.gz
bower sinon#*                 resolved git://github.com/cjohansen/Sinon.JS.git#1.7.3

{
  name: 'sinon',
  homepage: 'https://github.com/cjohansen/Sinon.JS',
  version: '1.7.3'
}

Available versions:
  - 1.7.3
  - 1.7.1
  - 1.7.0
(中略)
  - 0.6.0
  - 0.5.0
  - 0.2.3

You can request info for a specific version with 'bower info sinon#<version>'

bower install で指定したバージョンをダウンロードしたり出来ます。

$ bower install sinon#1.7.3
bower sinon#1.7.3               cached git://github.com/cjohansen/Sinon.JS.git#1.7.3
bower sinon#1.7.3             validate 1.7.3 against git://github.com/cjohansen/Sinon.JS.git#1.7.3
bower sinon#1.7.3              install sinon#1.7.3

sinon#1.7.3 bower_components/sinon

デフォルトで bower_components ディレクトリ以下にダウンロードされます。

$ ls bower_components/sinon
AUTHORS        LICENSE        build*         lib/           release.sh*
Changelog.txt  README.md      jsl.conf       package.json   test/

JavaScript ライブラリがコマンドラインだけでダウンロード出来ちゃうのがステキです。 いちいちググって、ダウンロードやら git clone やらして、って手間が不要です。

(あと npm の package.jsondependency や devDependency と同様の機能も備えますがここでは触れません)

bower レジストリ登録への道のり

  1. bower.json を作ってリポジトリにコミットして、
  2. リリースバージョン番号をタグ付けして、
  3. bower register コマンドを叩く

という感じ。簡単。順に説明します。

0. bower をインストール

npm でインストール。

$ npm install -g bower
$ bower -v
1.2.8

1. bower.json を作成

bower init コマンドを叩いて質問に答えていくと bower.json の雛形が生成できます。

$ bower init
[?] name: jquery.narrows
[?] version: 0.3.1
[?] description: jQuery Hierselect Plugin
[?] main file: jquery.narrows.js
[?] keywords: jQuery,select,hierselect
[?] authors: simon <xxxxx@gmail.com>
[?] license: MIT
[?] homepage: https://github.com/monmonmon/jquery.narrows
[?] set currently installed components as dependencies? Yes
[?] add commonly ignored files to ignore list? Yes
[?] would you like to mark this package as private which prevents it from being accidentally published to the registry?
[?] would you like to mark this package as private which prevents it from being accidentally published to the registry?
No

{
  name: 'jquery.narrows',
  main: 'jquery.narrows.js',
  version: '0.3.1',
  homepage: 'https://github.com/monmonmon/jquery.narrows',
  authors: [
    'simon <xxxxx@gmail.com>'
  ],
  description: 'jQuery Hierselect Plugin',
  keywords: [
    'jQuery',
    'select',
    'hierselect'
  ],
  license: 'MIT',
  ignore: [
    '**/.*',
    'node_modules',
    'bower_components',
    'test',
    'tests'
  ]
}

[?] Looks good? Yes

それを手直しして、コミット。

$ vim bower.json
$ git add bower.json
$ git commit
$ git push

ちなみに手直しした結果はこんな感じ。

{
  "name": "jquery.narrows.js",
  "version": "0.3.1", // <-gitでのバージョン番号を記述
  "description": "jQuery Hierselect Plugin",
  "license": "MIT",
  "main": "jquery.narrows.js", // <-パッケージのメインとなるファイル
  "ignore": [ // <-bower install した時にダウンロードさせたくないファイルのリスト
    "**/.*",
    "**/*.html",
    "Gruntfile.coffee",
    "node_modules",
    "README.md",
    "package.json",
    "lib",
    "spec"
  ]
}

さっきのBower入門(応用編)にも書かれていますが、 "main" と "ignore" をキチンと書かないと bower install した時に余計なものまでダウンロードしちゃって鬱陶しいので、気をつけて記述します。 (例えば Gruntfile.coffee はライブラリ利用者には不要なので "ignore" に含めてます。)

あと "version" にも要注意。ここに書いたバージョン番号を、次で git tag でタグ付けします。

2. リリースバージョン番号をタグ付け

bower.json に書いたバージョン番号をタグ付けしてやります。 bower はこのバージョン番号に基いてパッケージを管理します。

$ git tag 0.3.1
$ git push --tags
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:monmonmon/jquery.narrows.git
 * [new tag]         0.3.1 -> 0.3.1

バージョン 0.3.1 がリリースされました。

3. bower register

さていよいよ、ライブラリをレジストリへ登録します。コマンドの書式は

bower register <my-package-name> <git-endpoint>

です。

$ bower register jquery.narrows git@github.com:monmonmon/jquery.narrows.git
bower                          convert Converted git@github.com:monmonmon/jquery.narrows.git to git://github.com/monmonmon/jquery.narrows.git
bower jquery.narrows#*         resolve git://github.com/monmonmon/jquery.narrows.git#*
bower jquery.narrows#*        download https://github.com/monmonmon/jquery.narrows/archive/0.3.1.tar.gz
bower jquery.narrows#*         extract archive.tar.gz
bower jquery.narrows#*        resolved git://github.com/monmonmon/jquery.narrows.git#0.3.1
[?] Registering a package will make it installable via the registry (https://bower.herokuapp.com), continue? (Y/n)
bower jquery.narrows          register git://github.com/monmonmon/jquery.narrows.git

Package jquery.narrows registered successfully!
All valid semver tags on git://github.com/monmonmon/jquery.narrows.git will be available as versions.
To publish a new version, just release a valid semver tag.

Run bower info jquery.narrows to list the available versions.

ほんとに登録されたのか確認してみましょう。

$ bower info jquery.narrows
bower jquery.narrows#*          cached git://github.com/monmonmon/jquery.narrows.git#0.3.1
bower jquery.narrows#*        validate 0.3.1 against git://github.com/monmonmon/jquery.narrows.git#*

{
  name: 'jquery.narrows.js',
  version: '0.3.1',
  main: 'jquery.narrows.js',
  description: 'jQuery Hierselect Plugin',
  license: 'MIT',
  ignore: [
    '**/.*',
    '**/*.html',
    'Gruntfile.coffee',
    'node_modules',
    'README.md',
    'package.json',
    'lib',
    'spec'
  ],
  homepage: 'https://github.com/monmonmon/jquery.narrows'
}

Available versions:
  - 0.3.1

You can request info for a specific version with 'bower info jquery.narrows#<version>'

出た出た!

Bower components でも、検索フィールドに "jquery.narrows" って入力するとちゃんと表示されました。

試しに bower install してみる

今登録したライブラリがちゃんと bower install 出来るかも実験してみましょう。

$ bower install jquery.narrows#0.3.1
bower jquery.narrows#0.3.1      cached git://github.com/monmonmon/jquery.narrows.git#0.3.1
bower jquery.narrows#0.3.1    validate 0.3.1 against git://github.com/monmonmon/jquery.narrows.git#0.3.1
bower jquery.narrows#0.3.1     install jquery.narrows#0.3.1

jquery.narrows#0.3.1 bower_components/jquery.narrows

そしたらホラホラ!

$ ls -l bower_components/jquery.narrows
bower.json             jquery.narrows.js      jquery.narrows.min.js

ひゃっほい。

bowser.json の "ignore" をちゃんと書いたおかげで、余計なファイルを(ほぼ)含まずに js ファイルだけダウンロードすることが出来ました。(bower.json 自身だけ "ignore" に入れるのを忘れてたけど…笑)

というわけで

快適な bower ライフをお楽しみ下さい(とってつけた)