1. Getting started

RubyMotion は静的にビルドする Ruby 言語ですが、RubyMotion では既存の Ruby 用に作られた gems は動作しません。RubyMotion の gems は、RubyMotion 向けに特別に構成する必要があります。

RubyMotion では、gems はプロジェクトの Rakefile で require され、プロジェクトの設定を拡張します。たとえば、プロジェクトにファイルの追加や、新しい設定や、rake タスクを導入します。

この記事では、foo という仮の gem を題材にします。その gem は以下のようなファイル構造です。

foo.gemspec
lib
  foo.rb

foo gem は RubyMotion プロジェクトの Rakefile で単に require することで使用できます。

$:.unshift("/Library/RubyMotion/lib")
require 'motion/project'

require 'rubygems'
require 'foo'

# ...
Note Ruby 1.9 を使用している場合には require "rubygems" は必要ありません。

foo.rb は gem の最初に呼び出されるファイルです。次のようなコードをこのファイルに追加し、RubyMotion 以外の Ruby から require されることを防止しておくと良いでしょう。

unless defined?(Motion::Project::Config)
  raise "This file must be required within a RubyMotion project Rakefile."
end

2. Adding source files

gem は、Motion::Project::App ブロックを用い app.files 変数へパスを追加することで、RubyMotion プロジェクトにファイルを追加することができます。

例として、lib/foo 内にいくつかファイルを保有する foo gem を仮定しましょう。lib/foo 内のファイルは RubyMotion プロジェクトへ追加されることを意図しています。

foo.gemspec
lib
  foo.rb
  foo
    foo-model.rb
    foo-view.rb
    foo-controller.rb

lib/foo.rb ファイルは、次のように変更することができます。

unless defined?(Motion::Project::Config)
  raise "This file must be required within a RubyMotion project Rakefile."
end

Motion::Project::App.setup do |app|
  Dir.glob(File.join(File.dirname(__FILE__), 'foo/*.rb')).each do |file|
    app.files.unshift(file)
  end
end

foo-model.rb, foo-view.rbfoo-controller.rb はプロジェクトのほかのファイルよりも前にビルドシステムによってコンパイルされます。

3. Adding dependencies

foo gem はソースファイル追加に制限がされていません。そのため、Motion::Project::Config や、RubyMotion プロジェクトで行う同じ設定にアクセスできます。

たとえば、foo gem が Objective-C のソースコードを持っているとしましょう。

foo.gemspec
lib
  foo.rb
  ...
vendor
  native-foo
    native-foo-model.{m,h}
    native-foo-view.{m,h}
    native-foo-controller.{m,h}

このコードは CoreData framework をアプリにリンクされることを必要とします。

vendor のネイティブコードに応じて foo.rb を変更することができ、framework の依存関係を設定できます。

unless defined?(Motion::Project::Config)
  raise "This file must be required within a RubyMotion project Rakefile."
end

Motion::Project::App.setup do |app|
  Dir.glob(File.join(File.dirname(__FILE__), 'foo/*.rb')).each do |file|
    app.files.unshift(file)
  end
  app.vendor_project(File.expand_path(File.join(File.dirname(__FILE__), '../vendor/native-foo')), :static)
  app.frameworks += ['CoreData']
end

4. Adding rake tasks

RubyMotion の gem は、ビルドシステムを拡張し新しい rake タスクを追加することも非常に簡単にできます。

foo.rb は RubyMotion プロジェクトの Rakefile ファイル内で require されるので、タスクをそこで定義するだけです。

例として、架空のサービスに接続する foo タスクを定義しましょう。

unless defined?(Motion::Project::Config)
  raise "This file must be required within a RubyMotion project Rakefile."
end

Motion::Project::App.setup do |app|
  ...
end

desc "Submit your code to the foo service"
task :foo do
  ...
end