7. Rubyツアー 1/8: クラス定義
public class Circle extends Shape { class Circle < Shape
private final int radius; def initialize(radius)
public Circle(int radius) { @radius = radius
this.radius = radius; end
} attr_reader :radius
public int getRadius() { def area
return radius; Math::PI * (@radius ** 2)
} end
public double getArea() { end
return Math.PI * Math.pow(radius, 2); puts Circle.new(2).area
}
public static void main(String[] args) {
double area = new Circle(2).getArea(); extends → <
継承は単一継承
System.out.println(area);
}
}
メソッド定義 → def
コンストラクタ → initialize
8. Rubyツアー 2/8: インスタンス変数
public class Circle extends Shape { class Circle < Shape
private final int radius; def initialize(radius)
public Circle(int radius) { @radius = radius
this.radius = radius; end
} attr_reader :radius
public int getRadius() { def area
return radius; Math::PI * (@radius ** 2)
} end
public double getArea() { end
return Math.PI * Math.pow(radius, 2); puts Circle.new(2).area
}
public static void main(String[] args) {
double area = new Circle(2).getArea(); this → @
System.out.println(area);
}
}
attr_readerはアクセサメソッド定義用メソッド
9. Rubyツアー 3/8: 動的型付け
public class Circle extends Shape { class Circle < Shape
private final int radius; def initialize(radius)
public Circle(int radius) { @radius = radius
this.radius = radius; end
} attr_reader :radius
public int getRadius() { def area
return radius; Math::PI * (@radius ** 2)
} end
public double getArea() { end
return Math.PI * Math.pow(radius, 2); puts Circle.new(2).area
}
public static void main(String[] args) {
double area = new Circle(2).getArea(); 変数に型なし
System.out.println(area);
} duck-typing
}
引数の型・数の違いによるメソッドoverloadなし
10. Rubyツアー 4/8: 全てが値を持つ
public class Circle extends Shape { class Circle < Shape
private final int radius; def initialize(radius)
public Circle(int radius) { @radius = radius
this.radius = radius; end
} attr_reader :radius
public int getRadius() { def area
return radius; Math::PI * (@radius ** 2)
} end
public double getArea() { end
return Math.PI * Math.pow(radius, 2); puts Circle.new(2).area
}
public static void main(String[] args) {
double area = new Circle(2).getArea(); return不要
}
System.out.println(area);
文の値は最後の式
}
11. Rubyツアー 5/8:
全てがオブジェクト、全てがメソッド
public class Circle extends Shape { class Circle < Shape
private final int radius; def initialize(radius)
public Circle(int radius) { @radius = radius
this.radius = radius; end
} attr_reader :radius
public int getRadius() { def area
return radius; Math::PI * (@radius ** 2)
} end
public double getArea() { end
return Math.PI * Math.pow(radius, 2); puts Circle.new(2).area
}
public static void main(String[] args) {
double area = new Circle(2).getArea(); Circle: 定数
System.out.println(area);
} a*2 == a.*(2)
}
Circle.new:
クラスオブジェクトのnewメソッドを呼び出す
12. Rubyツアー 6/8: ブロック(クロージャ)
def aaa(name, &block)
File.open(name) do |file| (1) File.open用ブロック
file.each_line do |line|
yield line
ブロック実行後に自動close
(2) end (1)
end
end
(2) each_line用ブロック
1行読み込む毎に呼ばれる
aaa('a.txt') do |line|
p line (3)
end
(3) aaa用ブロック
people.group_by { |e| e.lang } aaa内部のyieldに呼ばれる
button1 = ...
label1 = ...
button1.on_action do |event|
label1.text = 'sending...'
end
← その他利用例
13. Rubyツアー 7/8:
Mix-in、オープンクラス
module Utils
def name Mix-in: 実装の継承
self.class.name 実装 Utilsモジュールの実装を
end
end
class Book
BookクラスにMix-in
include Utils 継承
def say
"Hello from #{name}"
end
end
obj = Book.new
p obj.say #=> "Hello from Book"
class Book
オープンクラス:
def say Bookクラスのsayメソッド
"I'm #{name}"
end を再定義
end
p obj.say #=> "I'm Book"
14. Rubyツアー 8/8: フックメソッド
class Base
@@all = [] inherited: クラスが継承
def self.inherited(klass)
@@all << klass
された場合に、継承したクラ
end スを引数に呼ばれる
end
class Sub < Base
p @@all
その他: included、
end method_added、
class SubSub < Sub method_removed、
p @@all
end method_missing、
※@@はクラス変数の接頭辞 const_missing等
※クラスオブジェクトのキャッシュは
リークの元なので普通やらない
20. Java連携 (Java -> Ruby)
JavaからRubyライブラリを利用
import org.jruby.embed.ScriptingContainer;
public class HelloWorld {
public static void main(String[] args) {
ScriptingContainer ruby = new ScriptingContainer();
ruby.runScriptlet("puts "hello,world!"");
}
source 'http://localhost/'
}
group :development do
host 'localhost'
port 12345
reloadable true
例: 独自定義ファイル解析の debug true
end
DSL処理系として group :production do
host 'www.example.com'
end
29. Javaテスト (RSpec)
RubyとJRubyの利点を活かしてJavaをテスト
describe 'ScriptingContainer#put' do
before :each do
RSpec: @x = org.jruby.embed. ScriptingContainer.new
end
振る舞いをテスト it "sets an object to local variable" do
obj = Object.new
http://rspec.info @x.put("var", obj)
@x.run_scriptlet("var").should == obj
% jruby -S rspec jruby_spec.rb end
.. it "overrides the previous object" do
obj = Object.new
Finished in 0.044 seconds @x.put("var", obj)
2 examples, 0 failures @x.put("var", nil)
% @x.run_scriptlet("var").should be_nil
end
end
30. Javaテスト (JtestR)
JtestR: 各種Ruby用テストライブラリ同梱
http://jtestr.codehaus.org/
describe "X509Name" do
it "should use given converter for ASN1 encode" do
converter = mock(X509NameEntryConverter)
name = X509Name.new('CN=localhost', converter)
converter.stubs('getConvertedValue').
with(DERObjectIdentifier.new(CN), 'localhost').
returns(DERPrintableString.new('converted')).
times(1)
name.toASN1Object.to_string.should == '...'
end
end
38. ウェブ開発 (JRuby on Rails)
Ruby on Rails - http://rubyonrails.org
ウェブアプリケーションフレームワーク
フルスタック
CoC: (XML)設定より規約(に従って開発)
DRY: 同じことを繰り返さない
39. Railsツアー 1/7:
アプリケーションの生成
MVC、テスト、サードパーティライブラリ等
常に同じディレクトリ構成
% jruby -S rails new myapp
create
create README
create Rakefile
...
create vendor/plugins
create vendor/plugins/.gitkeep
run bundle install
Fetching source index for http://rubygems.org/
Using rake (0.9.2.2)
Installing multi_json (1.0.3)
...
Installing sass-rails (3.1.5)
Installing uglifier (1.1.0)
Your bundle is complete! Use `bundle show [gemname]` to
see where a bundled gem is installed.
41. Railsツアー 3/7: DBマイグレーション
スクリプトによるDBスキーマ履歴管理
class CreateTodos < ActiveRecord::Migration
def change
create_table :todos do |t|
t.boolean :done
t.string :description
t.timestamps
end
end
end
% jruby -S rake db:migrate
== CreateTodos: migrating
====================================================
-- create_table(:todos)
-> 0.0040s
-> 0 rows
42. Railsツアー 4/7: サーバ起動
% jruby -S rails server
scaffoldだけ => Booting WEBrick
=> Rails 3.1.3 application starting in development
でも動く on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2011-11-28 15:58:15] INFO WEBrick 1.3.1
[2011-11-28 15:58:15] INFO ruby 1.8.7 (2011-11-27)
[java]
43. Railsツアー 5/7: 生成されたコード
モデル class Todo < ActiveRecord::Base
end
<%= form_for(@todo) do |f| %>
<div class="field">
<%= f.label :done %><br />
ビュー <%= f.check_box :done %>
</div>
コントローラ <div class="field">
<%= f.label :description %><br />
<%= f.text_field :description %>
</div>
class TodosController < ApplicationController<div class="actions">
def index <%= f.submit %>
@todos = Todo.all </div>
respond_to do |format| <% end %>
format.html # index.html.erb
format.json { render :json => @todos }
end
end
def create
...
end
44. Railsツアー 6/7:
ActiveRelation (Arel)
遅延SQL生成用のDSL
Todo.where(:done => false)
SELECT "todos".* FROM "todos" WHERE "todos"."done" = 'f'
Todo.where(:done => false).where('created_at < "2011-11-29"')
SELECT "todos".* FROM "todos" WHERE "todos"."done" = 'f' AND
(created_at < "2011-11-29")
Todo.where(:done => false).order("created_at DESC").limit(1)
SELECT "todos".* FROM "todos" WHERE "todos"."done" = 'f'
ORDER BY created_at DESC LIMIT 1
スコープ class Todo < ActiveRecord::Base
scope :finished, where(:done => true)
end
Todo.finished.size
SELECT COUNT(*) FROM "todos" WHERE "todos"."done" = 't'
49. Java SE 7: InvokeDynamic
新たなメソッド呼び出しバイトコード
bootstrapメソッド
dynamic language support (java.lang.invoke.*)
MethodHandle
MethodType
SwitchPoint
CallSite