APIフレームワークGrapeをRuby on Railsの中で動かすと遅いぞ
ある仕事でスマフォ用のAPIサーバーを作る事になり、REST-like APIが簡単に作れるフレームワーク grape を調査してみました。grapeの良さは、DSLで簡単にAPIサーバーが書ける点とRackで動く軽いフレームワークなのでRuby on Railsに比べ高いパフォーマンスが期待できる点です。
システム構成
Grapeは Mounting に書かれているようにいくつかの構成で動かせます
- Rack: Rack上で動かす
- ActiveRecord without Rails: Rackの上で動かすけど ActiveRecord を使う
- Rails: Ruby on Railsの中で動かす
- ...
今回のシステムでは管理者用のWebアプリは Ruby on Railsで作るので、モデルを共有できるRuby on Railsに組み込み使うのが魅力的です。
評価用コードを作ってみた
準備
- まずはRailsのプロジェクトを作り、scaffoldでいつものアプリを作成
$ rails new api_test
$ cd apt_test
$ rails g scaffold todo due:date task:string
- テストデータ作成 db/seed.rb も作成
Todo.delete_all 100.times { |i| Todo.create!(due: Time.now + i.day, task: sprintf("task%02d", i)) }
json.array!(@todos) do |todo| json.extract! todo, :id, :due, :task, :created_at, :updated_at end
Grape
- Gemfile
source 'https://rubygems.org' .... gem 'grape'
- API のコード
class SimpleApi < Grape::API version 'v1' format :json resource :todos do desc "Return all todos." get do Todo.all end end end
- config/routes.rb に APIをマウント
Rails.application.routes.draw do resources :todos mount SimpleApi => '/api' end
- config/application.rb にAPIのコードを読み込むように設定
module ApiTest class Application < Rails::Application .... config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb') config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')] end end
これで http://localhost:3000/api/v1/todos をアクセスするとtodosテーブルの全内容がJSONで取得できます
性能が気になる
Ruby on Railsのコードも http://localhost:3000/todos.json で JSONを返せるます。grapeがどれくらい性能が良いのかを比較してみました。
比較する環境は実際の環境に近くなるように
- RAILS_ENV は production
- サーバーは unicorn、worker_processes は 4
- アプリは EC2 t2.micro で実行
- ただし、RDBはsqlite3のまま、Nginx等のフロントエンドは無し
ab -c 8 -n 1000 URL で性能を計測
Framework | Requests per second |
---|---|
Grape within Rails | 33.66 |
Ruby on Rails | 34.49 |
Grape の性能は Ruby on Rails と同じくらい!? もちろん、テストデータ、abのパラメータにより多少状況は変わりますが・・・
ActiveRecord without Railsを試した
Rackの上で直接動くシンプルな grape の性能がこんなに低いのは納得出来なかったので、ActiveRecord without Rails で試してみました
- Rackの上で動かす grape.ru を作成
require 'grape' require 'active_record' require 'sqlite3' require_relative 'app/api/simple_api' require_relative 'app/models/todo' use ActiveRecord::ConnectionAdapters::ConnectionManagement ActiveRecord::Base.configurations = YAML.load_file('config/database.yml') ActiveRecord::Base.establish_connection(:production) run SimpleApi
この grape.ru を指定し unicorn 起動
Framework | Requests per second |
---|---|
Grape | 56.65 |
Ruby on Rails に比べ 1.6倍の性能が出ました!
結論
テスト中のサーバーのメモリー使用量も調べてみました。実メモリ使用量(RES)は Ruby on Railsに比べると半分以下です。
Framework | Requests per second | VIRT(memory) | RES(memory) |
---|---|---|---|
Grape within Rails | 33.66 | 345308 | 91828 |
Ruby on Rails | 34.49 | 345308 | 91828 |
Grape | 56.65 | 253472 | 38852 |
結論としては、grape を使って API サーバーを作るなら Rackベースで起動し、 Ruby on Railsとは別に動かした方が良い。
ただし、開発時は Ruby on Railsの中で動かした方が開発しやすいかも知れませんね。
開けましておめでとうございます。本年もEY-Officeをよろしくお願いいたします。
2015年、開けましておめでとうございます。
本年も吉田裕美ならびに、EY-Officeをよろしくお願いいたします。お正月休みに考えた事を少し書いてみました。
すし処佐治のおせち料理
EY-Officeの歴史を振り返った
2000年に長年勤めたCADのベンチャー企業から独立し EY-Office という会社を作り1人で仕事を始めました。開発や教育の仕事自体は私一人で行っていますが、お金の面を中心に大塚絵理さんに助けてもらっている2人の会社です。
もう独立してから、15年に成ろうとしています。そこで簡便的に5年に区切りまとめてみます。
2000〜2004年
独立し開発を始めたとはいえ、実はお仕事の殆どは一つの会社から受託していました。以前行っていたCADの開発とはまったく違うWeb系の仕事で色々な事を学ばせて頂きました。そして、その会社の売り上げの中心になるサービースのWeb Application Framework を作りました。CADの会社でもCADのベースになる図形データを扱う基本部分を作ってきた経験が生かせ、その会社の社長の経験や発想を混ぜたユニークなフレームワークが出来たと思っています。
また、Perl言語を使って開発していたので Perlのコミュニティーである Shibuya.pm に参加し、色々な方と知り合えたり、他の技術系のコミュニティー(例えば Seasarプロジェクト) などにも参加するようになっていきました。
2005〜2010年
一つの会社から受託していると その会社の経営状況に依存します、またコミニュティーなどを通じて得た新しい技術を試すことも出来なくなります。
そして一つの会社の仕事を行っていると、サラリーマンとそれほど変わらない立場、メンタルになってしまします。そこで、コミニュティーなどを通じて知り合った方などに紹介して頂いた新しい会社とのお付き合いが始まりました。
この時期にEY-Officeにとって大きな事がおきました。一つは、開発でお付き合いのあった会社から「教育」を行ってくれないかという依頼があり、コミニュティーの学んだスタイルを元におそるおそる教育を行ってみました。 長年開発しかしてこなかったので、講師としての能力の低さを痛感しながらも教えるのは面白いなと感じました。
さらに、空前のRuby on Railsブームが起こり、キャッチアップするために Rails勉強会@東京 に参加するようになりました、超出来るプログラマー達が集まる勉強会はとても刺激的でした。そして何回か参加する頃から初心者向けのセッションを行うようになっていきました。これが現在の EY-OfficeのRuby on Rails教育へと繋がって行きました。
2010〜2014年
Ruby on Rails教育 はEY-Officeという会社としての初めてのビジネスだったのかも知れません。しかし営業力もなく、Ruby on Railsブームも開発者だけでの盛り上がりで教育ビジネスでだけで食べて行くことはできず、受託開発も行いながらたまに教育を行うというスタイルが続きました。ただし、2012年頃から経営層にもRuby on Railsが届いたようで、大企業からも教育の注文が来るようになってきました。
しかし教育の仕事を絶えず取るのは難しいです、しばらく仕事絶えてしまう事もありました、そんなあるとき iPhoneもMacも持っているのだからiPhone開発でもやってみるか! という感じで勉強でアプリを作ったり、受託でアプリを作ったりしました。 iPhoneの開発情報は当初NDAで保護されていた事もあり開発コミニュティー等が少なかったのですが、ある時期から勉強会が始まり参加するようになりました。 自分が勉強して来た事は教育コンテンツとして教えられると判っていたので、iPhone開発の教育も始めました。ある時期はかなり需要がありましたが、現在はあまり需要がないようです。
仕事が絶えてしまった時にコミニュティーで知り合った方から仕事を頂いたり、たくさんの方のおかげで何とかやっている状況でした。
さて今年はどうしようか
昨年は、このブログ、会社のホームページ 開発の仕事を募集したのですが、ほぼありませんでした。教育の仕事はある程度あるのですが、夏は暇で(Docker, Node.js,Swift,Go..など)たくさんのお勉強をする時間に恵まれてしまいました ^^;
昨年末に、以前お世話になった方から小規模の開発の仕事を頂きました。その方と話をしていた時に、受託はどうしてもお客様に依存してしまうので、やはり自社で何かビジネスをしないとダメなのではと言われました。
また最近はベンチャーがたくさん立ち上がって来ていますが、最初から開発者を抱えて自分たちのビジネスを育てています。以前に比べると技術者の流動化は高まっていて、魅力的なビジネス・経営者であれば優秀なエンジニアをリクルートしやすくなり、フリーの技術者に頼る必要性が下がってきたのかも知れません。 開発会社としてのEY-Officeや開発者としての吉田裕美というのは知名度が低すぎマーケットに届いていないと思います。
そこで、今年はどうするかですが、
- 教育ビジネスも力を入れて行っていきます。
- 受託の開発案件も引き続き探します、よろしくお願いいたします。
- 今のところ、自社サービスやアプリの目処はないですが、今年はあいている時間で思いついた、小さなアプリやサービスをリリースしていきたいと思います。少しずつアイデアを貯めています・・・・
- 頂いた仕事は、開発も教育も自分の力を出し切りがんばって行きます。
さらに個人的には
- 英語力の無さを痛感しています。挨拶程度の会話は出来ますが、現在は issueを書いたり質問をしたり出来る能力が不足しています。中学校2年くらいですでに英語を捨てていたの単語力や基本的な文法力がありません。先ずはこの辺をクリア出来るようにしたと思います。
- 歳をとり体力が落ちています、近くの公園でのジョギングを毎週おこなうように心がけます、昨年も時々行っていたのですが、ついつい行かない時期がありました。
結論
お仕事募集中です !
本気のiOS開発者は読むべき一冊「UIKit徹底解説 iOSユーザーインターフェイスの開発」
入門書や入門講座などを終わり、これから本気でiOSアプリを作るぞ! と思っているいる人は買うべき一冊です。またiOSアプリを一つ二つ作った人も「なるほど!」と思うUIKitの知識が詰まっています。
内容はiOS7用に書かれているので iOS8で導入された機能やSwift言語には対応していませんが、ここに書かれている内容は iOS8でもほとんどが使えます。また SwiftでiOSアプリを書く場合もUIKitは同じですから、ほんの少しの脳内コード変換で使えます。
電子書籍も買えるのが嬉しいですね (Kindle以外に PDFも 達人出版会から買えます)
- 作者: 西方夏子
- 出版社/メーカー: インプレス
- 発売日: 2014/06/18
- メディア: Kindle版
- この商品を含むブログ (1件) を見る
この本の読み方
問題解決
最初から読む必要はありません。テーマー毎にチャプターになっていますので、興味のあるところ、今作っているアプリが思うように動かない時に関連しそうなチャプターを読むと良いと思います。
内容は、かなり細部まで書かれています。 特に自分の作っているアプリのUIが思っているように動作しない時や、他のアプリで実現されている機能がどうやったら実現できるのか判らない時には StackOverflow や Qiita のような回答そのものではなく、iOSの原理や設計思想などの基本部分に付いても学べます。
スキルアップ
ネット上の情報には偏りがあります。また、UIに付いての解説はたくさんの概念図やスクリーン画像、適切なサンプルコードが必要になるので日本語での良質な情報はネット上には少ないと思います。
本書のような本を読むことは、自分の中で欠けている知識の補足になりますし、あらためてiOSの原理や設計思想などの基本部分を学ぶ事で開発力を高める事ができます。
また、分かりにくい Text Kit や UITableView、UICollectionView の高度な使い方も解説されています。
SwiftからEvernote APIを使うのが予想外に面倒だったのでまとめました
SwiftでEvernote APIを使うiOSアプリを作ろうとして、なかなか上手く行かなかったので、今回行った手順をまとめておきました。
基本的には Using the Evernote API from Swift に書かれた手順ですが、上手く行かなかったので少し追加しました。
手順
1. Evernote Cloud SDK for iOS の追加
GitHubのEvernote Cloud SDK for iOS を submodule としてプロジェクトに追加します
% git submodule add https://github.com/evernote/evernote-cloud-sdk-ios.git Cloning into 'evernote-cloud-sdk-ios'... ... % git submodule 804c0ff4221a430fa5e9619ca717503abdad92c8 evernote-cloud-sdk-ios (heads/master)
2. プロジェクトへ追加
の2つをプロジェクトに追加します
3. 依存ライブラリーの追加
Getting Started with the Evernote Cloud SDK for iOS に書かれているように、以下の2つのフレームワーク・ライブラリーを追加します。
- MobileCoreServices.framework
- libxml2.dylib
4. ブリッジヘッダーファイルを書く
SwiftからObjective-Cで書かれたライブラリーを呼び出すには、ブリッジヘッダーファイルを作る必要があります。ブリッジヘッダーファイルは半自動で出来るように書かれた ドキュメント もありますが、出来なかったので手動でつくりました。
- EvernoteSample-Bridging-Header.h の内容
#import <ENSDK/ENSDK.h>
- Build Settings
EvernoteSample/EvernoteSample-Bridging-Header.h
5. Header Search Path
ここでコンパイルしてもエラーが出ます。Evernote Cloud SDK for iOS や libxml2 のヘッダーファイルが見つからないからです。設定しましょう
${PROJECT_DIR}/evernote-cloud-sdk-ios/evernote-sdk-ios
/usr/include/libxml2
6. Prefix Header の設定
ここまでで Using the Evernote API from Swift に書かれた設定は全て出来たはずですが、以下のような意味不明なエラーが出て悩みました・・・
そしてGoogle先生にたずねながら理解しました。Evernote Cloud SDK for iOS内には独自のPrefix Header evernote-sdk-ios-Prefix.pch が在るのですが、これが参照されてないようです
そこで Prefix Header を設定。 これでコンパイルエラーが無くなりました ^^)/
${PROJECT_DIR}/evernote-cloud-sdk-ios/evernote-sdk-ios/evernote-sdk-ios-Prefix.pch
サンプルコード
この記事を書くために Evernote Cloud SDK for iOSを使いノートを作成する簡単なテストコードを作りました、コードは GitHub にあります。
import UIKit class ViewController: UIViewController { let CONSUMER_KEY = "YOUR CONSUMER_KEY" let CONSUMER_SECRET = "YOUR CONSUMER_SECRET" override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) postTestNote() } private func postTestNote() { ENSession.setSharedSessionConsumerKey(CONSUMER_KEY, consumerSecret: CONSUMER_SECRET, optionalHost: ENSessionHostSandbox) var session = ENSession.sharedSession() if session.isAuthenticated { var note = ENNote() note.title = "Test" note.content = ENNoteContent(string: "test test test ...") session.uploadNote(note, notebook: nil, completion: { noteRef, error in if error == nil { println("OK") } else { println("Upload note error: \(error)") } }) } else { session.authenticateWithViewController(self, preferRegistration: false, completion: { error in if error == nil { self.postTestNote() } else { println("Authentication error: \(error)") } }) } } override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
- CONSUMER_KEY/CONSUMER_SECRET は https://dev.evernote.com/intl/jp/doc/ から取得して下さい
- 作成されるのは sandbox.evernote.com の方です、ノートブックはデフォルトが使われます
- 画面が表示された瞬間(viewDidAppear)にノートをEvernoteに作ります
- 最初に起動した際に認証画面が表示されます
UIVewのanimateWithDuration〜メソッドを他のUI更新と一緒に実行してはいけない!
昨晩から、約4時間をこの問題の解決に費やしてしまいまいました 。。。。他の人が同じ間違いしないように記録しておきました。
あるアプリに下のような動きをする、簡単なアニメーションを付けました(この画像、コードは説明用サンプルです)。
失敗のはじまり
コードは以下のように書きました。
@interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *scrollLabel; @property (weak, nonatomic) IBOutlet UILabel *statusLabel; - (IBAction)touchStartButton:(id)sender; @end @implementation ViewController - (IBAction)touchStartButton:(id)sender { _statusLabel.text = @"scrolling..."; [UIView animateWithDuration:2.0 animations:^{ _scrollLabel.center = CGPointMake(_scrollLabel.frame.size.width * -0.5, _scrollLabel.center.y); }]; }
このコードは、 statusLabel に scrolling... と表示してから、scrollLabel(黄色いバックグラウンドのラベル)を 2秒かけて、左端に追い出します。
しかし、動かすと下のように動作します ^^; scrollLabelのY座標は、画面の中央にあるはずなのに、なぜかアニメーション開始時右端からはじまります (>_<)
実際のアプリは、こんなにシンプルではないので、いろいろと調べてみましたが・・・・・。 また AutoLayoutだとアニメーションが思ったように動作しないなど記事を見つけ、また、あーだーこーだー・・・。 ちなみに上のサンプルは AutoLayoutは使っていません。
解決編
そこで、シンプルなサンプルを作り実験してみました。すると正しく動作するコードが判りました!! なんと、 statusLabel に @"scrolling..." を代入するのを止めれば良いのです。
あああ! やっと判りました。それをタイトル「UIVewのanimateWithDuration〜メソッドを他のUI更新と一緒に実行してはいけない!」にしました。 iOSでのほとんどの画面操作API等は、呼び出した(statusLabelへの代入も同じく)瞬間に実行されるのではなく、イベント待ちに戻った時に実行されます。上のコードではアニメーションとstatusLabelの表示変更が同事(?)に行われアニメーションが正しくない動作になってしまうのです。
そこで、以下のコードのようにstatusLabelへ代入を行った後でアニメーションを始めれば正しい動作になるのです。(^○^)
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *scrollLabel; @property (weak, nonatomic) IBOutlet UILabel *statusLabel; - (IBAction)touchStartButton:(id)sender; @end @implementation ViewController - (IBAction)touchStartButton:(id)sender { _statusLabel.text = @"scrolling..."; [self performSelector:@selector(scrolling) withObject:nil afterDelay:0.1]; } - (void)scrolling { [UIView animateWithDuration:2.0 animations:^{ _scrollLabel.center = CGPointMake(_scrollLabel.frame.size.width * -0.5, _scrollLabel.center.y); }]; } @end
LoopBack (Open SourceのBaaS)を使ってみよう! その1. PostgreSQL接続とTwitter認証
あるiOSアプリを作ろうとしています、このアプリはバックエンドのサーバーと情報をやり取りします。バックエンドのサーバーはRuby on Railsで作ってもよいのですが、なるべく早くプロトタイプを動かしたいので、今回は既存のBaaS(Backend as a Service)を使ってみる事にしました。
!
1. なぜ LoopBack を使う事にしたのか
現在BaaSのサービス、Open Sourceのソフトはたくさんあります。ネット上でいろいろと調べてみると BaaS にもサービスよりのものとプラットフォームよりのものがあります(この分類は、私がそう思っているだけかもしれません)。
サービスより のもとしては、実際に良く使われている Parse があげられます。Parseはプッシュ通知やアプリのデータ同期・共有などを複数のプラットフォーム(iOS,Android,PC...)に提供するサービスです。
プラットフォームより のものとしては、Loopbackや以前は話題になったdeploydなどがあります。これらはスマフォとやり取りするAPIサーバーを構築するためのフレームワークやクラウドです。 LoopbackはOpen Sourceのソフトですが、それをクラウドで提供するStrongLoopのような会社もあります。
BaaSは現在も進化・競争している世界で、どのサービス・ソフトが良いのかは 簡単には決められない世界のようです。詳しくはBaaSはまだ戦国時代だったのか、まとめ。(執筆中)が参考になります。
今回、Loopbackを使う事にした理由は
- プラットフォームよりで、今回作るアプリに適切
- Open Sourceなので、突然のサービス停止にも泣かない
- ドキュメントもそれなりにある
- いろいろとサンプルコードがある
- Node.jsベース。Node.jsはまだまだ初心者ですが Ruby/Railsの世界感にも近い
- サーバーを自前で準備する必要があるが、このへんは慣れいてる
2. LoopBack入門
a. 前提条件
LoopBackを使うには、Node.js を使って簡単なWebアプリを作れる知識・経験が必要だと思います。
- JavaScript
- Node.js
- npm コマンド
- 英語ドキュメントが読める (LoopBackの日本語の情報はほぼありません)
b. 入門
- node.jsのインストール (v0.10.xを使って下さい。v0.11.xでは動きません)
- LoopBackのGetting startedページを試す
- Ruby on Railsの scaffold のようなものです
- Modelを定義すると、そのモデルのCRUD操作が出来るREST APIサーバーが出来ます
- プロジェクトの構成、設定ファイルの役割等を知って下さい
- ドキュメントを読みましょう(先にExamplesを試しても良いですが、たぶん読まないと詰まります)
- LoopBackのExamplesの興味があるものを試す
- Examplesのリンク先はGitHubです
- 詳しい手順が書かれています。たいてい git clone して設定ファイル等を変更し実行する流れです
- 手順通りにやっても動かない事もままあります。がんばって対応しましょう、とても勉強になります ^^;
- コードはJavaScriptで書かれています、問題になっているコードを読んでみましょう
3. LoopBackをPostgreSQLにつなぐ
概要
LoopBackはいろいろなDBと接続出来るようになっていますが、大きく2つのタイプがあります
- MongoDBのようなダイナミックDB
- RDB
- このタイプのDBを使う場合はModelにはプロパティー(カラム)の定義が必要です
- MySQL, PostgreSQL, Oracle, SQL Serverなど主要なRDB用のコネクターが準備されています
- 先ずはGitHubのloopback-example-databaseをcloneして動かしてみるのが良いと思います
- ドキュメントはData sources and connectorsとPostgreSQLをつかうならPostgreSQL connector
設定ファイル
LoopBackではDBと接続するための設定ファイルがいくつかあります
- server/datasources.json : 接続するDBの定義ファイル。
- 複数のDBを使う事が出来ます
- Memory DBは最初から定義されています
- PostgreSQLの定義ファイルにはDatabase名、login、passwordやサーバーなどの情報を書きます、他のソフトでもよくあるものだと思います。
{ "db": { "name": "db", "connector": "memory" }, "pgDB": { "name": "pgDB", "connector": "postgresql", "port": 5432, "debug": true, "database": "node_test", "username": "node_test", "password": "node_test" } }
- server/model-config.json: Modelの一覧と、Modelが使うDBなどの定義。
- 最初の _meta の sources は Modelファイルのある場所のリスト
{ "_meta": { "sources": [ "../common/models", "./models", "./node_modules/loopback-component-passport/lib/models" ] }, "user": { "dataSource": "pgDB", "public": true }, .... "Role": { "dataSource": "db", "public": false } }
- common/models/Model名.json : Modelの定義
- 対応するRDBのテーブル名、カラム名、型や関連などを定義します
- optionsを指定する事で、細かいテーブル・カラムの設定が書けます
- 定義の意味はData sources and connectorsと下位のページに書かれていますが、全てが網羅された情報は無いようです(?)
- デフォルトでは、Model名、プロパティー名がテーブル名、カラム名にそのまま使われます。対応を変えたい場合はoptionsで指定する必要があります
- テーブルにはプライマリーキーが必要です、idInjectionをtrueにすればRailsのように整数型のidカラムが自動生成されます
- 関連情報relationsにはRails同様に hasMany, belongsTo が定義出来ます
{ "plural": "users", "base": "User", "options": { "postgresql": { "table": "users" } }, "idInjection": true, "properties": { "username": { "type": "String", "required": true }, "password": { "type": "String", "required": true } }, "relations": { "accessTokens": { "type": "hasMany", "model": "accessToken", "foreignKey": "userId" } }, "validations": [], "acls": [], "methods": [] }
- 他の例
- 特定のカラムをプライマリーキーにしたい場合は、idInjectionをfalseにし、プロパティーにid属性を指定をします。
{ "name": "accessToken", "plural": "accessTokens", "base": "AccessToken", "options": { "postgresql": { "table": "access_tokens" } }, "idInjection": false, "properties": { "id": { "type": "String", "id": 1, "required": false }, "ttl": { "type": "Number", "required": false }, "userId": { "type": "Number", "postgresql": { "columnName": "user_id" }, "required": false }, "created": { "type": "Date", "required": false } }, "validations": [], "relations": {}, "acls": [], "methods": [] }
- server/create-test-data.js : テーブルの作成とテストデータの作成
- このファイルは自動生成されないので、Exampleからコピーして作る必要があります。
var server = require('./server'); var dataSource = server.dataSources.accountDB; var Account = server.models.account; var accounts = [ { email: 'foo@bar.com', created: new Date(), modified: new Date() }, { email: 'bar@bar.com', created: new Date(), modified: new Date() } ]; var count = accounts.length; dataSource.automigrate('account', function(er) { if (er) throw er; accounts.forEach(function(account) { Account.create(account, function(er, result) { if (er) return; console.log('Record created:', result); count--; if(count === 0) { console.log('done'); dataSource.disconnect(); } }); }); });
4. LoopBackでTwitter/Facebookの認証を使う
概要
LoopBackにはThird-party loginとい機能があり、これを使うと簡単にTwitter/Facebookの認証を使う事ができます。
- この機能はloopback-component-passport コンポーネントをインストールする事で実現できます
- GitHubのloopback-example-passportをcloneして動かしてみるのが良いと思います
- ドキュメントはThird-party login
- Twitterの consumerKey, consumerSecret は予め入手しておいて下さい
設定ファイル
設定ファイルは providers.json で loopback-example-passportには providers.json.template が用意されているのでコピーして使ってください。
- Twitterは http://localhost で確認できますが、Facebookは動作しないようです
{ "local": { "provider": "local", "module": "passport-local", "usernameField": "username", ... "twitter-login": { "provider": "twitter", "authScheme": "oauth", "module": "passport-twitter", "callbackURL": "http://localhost:3000/auth/twitter/callback", "authPath": "/auth/twitter", "callbackPath": "/auth/twitter/callback", "successRedirect": "/auth/account", "consumerKey": "ここにconsumerKeyを指定", "consumerSecret": "ここにconsumerSecretを指定" }, .... }
5. LoopBackでPostgreSQL接続とTwitter認証
PostgreSQLに接続し、Twitter認証が行えるようにしてみました。 GitHubに loopback-example-passportをPostgreSQL対応した例 を置きました、これを参考にして下さい。
- PostgreSQLのテーブル定義は、後々の事を考えRuby on Railsのルールに合わせました
- providers.jsonはTwitterの consumerKey, consumerSecretを入手し作って下さい
- server/create-test-data.js を実行するとテーブルが作成されます
- loopback-example-passportは Memoryを使っているので、user モデルにカラム定義がありませんが server/datasources.json に file属性を指定するとDBをファイルにJSONで保存してくれるのでそれを見てカラム定義は作りました
- user モデル以外の認証に必要なモデルの定義はThird-party+loginに書かれています
ドキュメントには書かれてない部分があったり、callbackの中で起こるエラーはtracebackが在っても役に立たず苦労しました ^^);
Jekyllを1.5.1から2.3.0にアップデートした
私は会社のホームページや教育で使うテキストはJekyllを使って作っています。
最近ずっとアップデートしてなかったので、久しぶりにアップデートしてみました。使っていたのは 1.5.1 で現在の最新は 2.3.0 とメジャー・バージョンアップになるので少し不安でしたが、とくに問題なくアップデートできました。
アップデート手順
通常のRubyプログラムのアップデートと同じです。アップデートでJekillの生成するHTMLがおかしくなってないか確認するために現在の変換結果 _site/以下を保存しておき、アップデート後diffを見られるようにしたくらいです。
% mv _site _site.0 # 現バージョンの変換結果を保存 % mkdir _site % bundle update # Jekyllと関連するgemはbundleで管理しています (中身は jekyllとRedCloth) Fetching gem metadata from https://rubygems.org/........ Resolving dependencies... Using RedCloth 4.2.9 Using blankslate 2.1.2.4 ... Installing redcarpet 3.1.2 (was 2.3.0) Using safe_yaml 1.0.3 (was 1.0.1) Using parslet 1.5.0 Using toml 0.1.1 Installing jekyll 2.3.0 (was 1.5.1) Using bundler 1.6.2 Your bundle is updated! % rbenv rehash % jekyll -v jekyll 2.3.0 % jekyll server --watch --port 4000 # Jekyllを起動すると幾つかのワーニングが Configuration file: /Users/yy/Documents/jekyll-ey-office/_config.yml Deprecation: The 'pygments' configuration option has been renamed to 'highlighter'. Please update your config file accordingly. The allowed values are 'rouge', 'pygments' or null. Source: /Users/yy/Documents/jekyll-ey-office Destination: /Users/yy/Documents/jekyll-ey-office/_site Generating... Build Warning: Layout 'nil' requested in atom.xml does not exist. done. Auto-regeneration: enabled for '/Users/yy/Documents/jekyll-ey-office' Configuration file: /Users/yy/Documents/jekyll-ey-office/_config.yml Deprecation: The 'pygments' configuration option has been renamed to 'highlighter'. Please update your config file accordingly. The allowed values are 'rouge', 'pygments' or null. Server address: http://0.0.0.0:4000/ Server running... press ctrl-c to stop. %
ワーニングに対応
- _config.yml これはワーニングメッセージにある通り修正
-pygments: false +highlighter: :pygments
- atom.xml こちらは修正方法が GitHub issueにありました
-layout: nil +layout: null
レイアウト無しがの指定が nil から null に変更されたのですね (ナゼ^^;)
確認
RSSの作成日付が変わったのみで、生成されるHTMLはまったく同じでした!
% jekyll server --watch --port 4000 ... ^c % diff -r _site.0 _site diff -r _site.0/atom.xml _site/atom.xml 7c7 < <updated>2014-09-08T16:19:29+09:00</updated> --- > <updated>2014-09-08T17:32:18+09:00</updated>
独自の_plugin(マクロ)も使っていますが、問題ありませんでした。