ホーム ブログ ページ 64

case文の落とし穴

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

初めまして、エンジニア一年目のサンドリバー砂川です。

今回は開発中につまずいたcase文の挙動について解説をします。

こんな感じのcase文を考えてみます。

class Obj
  class Foo
  end

  class Bar
  end
end

obj = Obj::Foo

case obj
  when Obj::Foo
    puts "obj is Foo."
  when Obj::Bar
    puts "obj is Bar"
  else
    puts "obj is unknown...."
end

スクリプトを実行してみると

obj is unknown....

何故か比較がうまいこと出来てません。

実はcase文ではこんな風に比較が行われます。

case obj
  when Obj::Foo
end
↓
if Obj::Foo === obj

問題は演算子===で、こいつは呼び出したオブジェクトの型によって挙動が変わります。

例えばString#===なら==と同じ挙動ですが、Class#===の場合はkind_of?と同じ挙動になります。

kind_of?メソッドは、引数が呼び出したオブジェクトのインスタンスの場合にtrueを返します。

今回のコードではobj = Obj::Fooとクラスオブジェクト自体を代入していたのでfalseになってしまったんですね。

なので解決策として、objにインスタンスを代入する。

obj = Obj::Foo.new

あるいはto_sメソッドを利用して比較する。

case obj.to_s
  when Obj::Foo.to_s
    puts "obj is Foo."
  when Obj::Bar.to_s
    puts "obj is Bar"
  else
    puts "obj is unknown...."
end

obj is Foo.

で解決です。

Rails と MeCab で Twitter の発言内容を解析する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。

KBMJの佐藤です。

今回は Rails と MeCab を使って Twitter の発言内容を解析してみます。

MeCab について

MeCab はオープンソースの形態素解析エンジンです。

Mechanize のインストール

% sudo gem install mechanize

Hpricot のインストール

% sudo gem install hpricot

Mecab のインストール

% sudo port install mecab
% sudo port install mecab-ipadic-utf8
% sudo port install rb-mecab

マイグレーションファイルを書く

class CreateStatuses < ActiveRecord::Migration
  def self.up
    create_table :statuses do |t|
      t.column :text, :string
      t.column :screen_name, :string
      t.timestamps
    end
  end

  def self.down
    drop_table :statuses
  end
end

コードを書く

require "rexml/document"
require "open-uri"
require 'MeCab'

module MeCab
  class Node
    def category
      return self.feature.split(/,/)[0]
    end

    def each(&b)
      b[self]
      self.next.each(&b) if self.next
    end
  end
end

class Status < ActiveRecord::Base
  def self.get_xml_page(user, page)
    xml = open("http://twitter.com/statuses/user_timeline/#{user}.xml?page=#{page}").read # XMLを取ってくる
    doc = REXML::Document.new xml
    doc.elements.each('/statuses/status') do |s|
      text = s.elements["text"].text # 発言内容を取得
      screen_name = s.elements['user/screen_name'].text
      p "#{screen_name} #{text}"
      status = Status.new(:text => text, :screen_name => screen_name)
      if status.save # DBに挿入
        p "SUCCESS"
      else
        p "FAILED"
      end
    end
  end

  def self.parse
    m = MeCab::Tagger.new
    h={}
    Status.find(:all).each do |s|
      nodes = m.parseToNode(s.text)
      nodes.each do |node|
        next unless node.category == '名詞' # 名詞のみ解析対象とする
        if h[node.surface]
          h[node.surface] += 1 # 出現回数をカウント
        else
          h[node.surface] = 1
        end
      end
    end
    # 結果出力
    h.to_a.sort{ |a,b|
      (b[1] <=> a[1]) * 2 + (a[0] <=> b[0])
    }.each{ |e| puts "#{e[0]} #{e[1]}"}
  end

  def self.get_xml
    Status.delete_all
    1.upto(10) do |page|
      get_xml_page('akio0911', page)
    end
    parse
  end
end

処理を実行する

ruby script/runner 'Status.get_xml'

実行結果

Twitterにおいて最近よく使っているキーワードを見ることができます。

インストール 12
:// 11
http 11
com 10
ー 10
こと 9
1 7
emacs 7
メガネ 7
人 7
会 7
会社 7
勉強 7
忘年会 7
時 7
5 6
Twitter 6
tinyurl 6
さ 6
よう 6
電源 6
0911 5
2 5
akio 5
インターネット 5
ブログ 5

さいごに

Rails と MeCab を組み合わせると、ネットから取得してきた各種情報を DB に格納したり、それに対して解析を行ったりすることが手軽にできます。

次回以降、Rails と MeCab を連携することによる応用例を書いていきたいと思います。

お楽しみに!

個人ブログ 拡張現実ライフ

Mechanize, Hpricot, MeCab でブログの頻出単語を調べる

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。

KBMJの佐藤です。

今回は Mechanize, Hpricot, MeCab でブログの頻出単語を調べてみます。

http://farm4.static.flickr.com/3212/3101925914_6580eb0fc8.jpg

Mechanize について

Mechanize を使うと、ウェブサイトへのアクセスを自動化(リンクをたどる、フォームを submit する、リダイレクトをたどる、など)することができます。

Hpricot について

Hpricot は Ruby 用の HTML パーサです。HTML の解析や書き換えに威力を発揮するライブラリです。

MeCab について

MeCab はオープンソースの形態素解析エンジンです。

Mechanize のインストール

% sudo gem install mechanize

Hpricot のインストール

% sudo gem install hpricot

Mecab のインストール

% sudo port install mecab
% sudo port install mecab-ipadic-utf8
% sudo port install rb-mecab

コードを書く

require 'MeCab'
require 'rss'
require 'mechanize'
require 'kconv'
require 'hpricot'
require 'open-uri'

module MeCab
  class Node
    def category
      return self.feature.split(/,/)[0]
    end

    def each(&b)
      b[self]
      self.next.each(&b) if self.next
    end
  end
end

agent = WWW::Mechanize.new
page = agent.get('http://d.hatena.ne.jp/akio0911/archive') # ページを開く
m = MeCab::Tagger.new
h={}

# エントリへのリンクを抽出
page.links_with(:href => /\/\d{8}\/p\d/).each{ |l| 
  puts l.href
  doc = Hpricot(open(l.href))
  text = doc.search("div.section").text.toutf8.gsub(/\t/, "").gsub(/\n/,"") # 文章部分を取得

  nodes = m.parseToNode(text)
  nodes.each do |node|
    next unless node.category == '名詞' # 名詞以外はカウント対象としない
    next if node.surface =~ /^\d+$/ # 数字も対象としない
    if h[node.surface]
      h[node.surface] += 1
    else
      h[node.surface] = 1
    end
  end
}

# カウント結果を出力
h.to_a.sort{ |a,b|
  (b[1] <=> a[1]) * 2 + (a[0] <=> b[0])
}.each{ |e| puts "#{e[0]} #{e[1]}"}

さいごに

Mechanize, Hpricot, MeCab を使うと、ページ内容を解析するプログラムを簡単に書くことが出来ます。みなさんも是非試してみてはいかがでしょうか。

個人ブログ 拡張現実ライフ

CappuccinoとObjective-JでHello Worldを書いてみる

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。

KBMJの佐藤です。

今回はCappuccinoとObjective-JでHello Worldを書いてみます

Cappuccino と Objective-J を使うと iPhone や Mac 向けのアプリ開発と同じ感覚で Web アプリケーションを開発することができます。

http://farm4.static.flickr.com/3151/3064248883_ffdfecd321.jpg

CappuccinoとObjective-Jについて

Cappuccino は、デスクトップソフトウェアのユーザーがうちとけやすい見た目のアプリケーションを開発するためのオープンソースフレームワークです。

Cappuccino は JavaScript などの標準的なWeb技術の上に構築されています。そしてアップルのCocoaフレームワークに非常に近い実装がなされています。

Cappuccino でプログラムしたとき、HTML, CSS, DOM などの伝統的なWeb技術を意識する必要がありません。

複雑なクロスブラウザアプリケーションを構築する際の不愉快さはありません。

Cappuccino は Objective-C をモデルとした新しいプログラミング言語である Objective-J で実装されています。Objective-J は JavaScript の上に構築されています。Objective-J で書かれたプログラムはクライアント上で翻訳されるので、プラグインなどは必要ありません。Objective-J のライセンスは LGPL となっています。

ソースコード

Hello World のソースコードを以下に示します。

import <foundation /cpobject.j>

// アプリケーションコントローラークラスである AppController を宣言します
@implementation AppController : CPObject
{
  // ラベルオブジェクトをメンバ変数として持たせます
  CPTextField label;
}

// アプリケーションの起動時に呼ばれる関数です。ここに各種初期化処理などを記述します
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
    // ウィンドウオブジェクトを生成し、そのビューを管理する contentView を取り出します
    var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
        contentView = [theWindow contentView];

    // ラベルオブジェクトを生成します
    label = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
    // ボタンオブジェクトを生成します
    var button = [[CPButton alloc] initWithFrame: CGRectMake(
			     CGRectGetWidth([contentView bounds]) / 2.0 - 40,
			     CGRectGetMaxY([label frame]) + 100,
		    80, 18
		 )];
    // ボタンオブジェクトの自動リサイズに関する設定を行います
    [button setAutoresizingMask:CPViewMinXMargin |
	                        CPViewMaxXMargin |
	                        CPViewMinYMargin |
                        	CPViewMaxYMargin];

    // ボタンのタイトルを設定します
    [button setTitle:"swap"];

    // ボタンが押された際に呼ばれる処理を登録します
    [button setTarget:self];
    [button setAction:@selector(swap:)];

    // ビューにボタンを追加します。
    [contentView addSubview:button];

    // ラベルのキャプションとフォントを設定します
    [label setStringValue:@"Hello World!"];
    [label setFont:[CPFont boldSystemFontOfSize:24.0]];
    
    [label sizeToFit];
    
    // ラベルの自動リサイズ設定を行います
    [label setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin | CPViewMinYMargin | CPViewMaxYMargin];
    // ラベルの位置を設定します
    [label setFrameOrigin:CGPointMake[1]CGRectGetWidth([contentView bounds]) - CGRectGetWidth([label frame] / 2.0, (CGRectGetHeight([contentView bounds]) - CGRectGetHeight([label frame])) / 2.0)];
    
    // ビューにラベルを追加します
    [contentView addSubview:label];
    
    [theWindow orderFront:self];

    // ラベルのキャプションを中央に設定します
    [label setAlignment:CPCenterTextAlignment];
    
    // メニューバーを表示します
    [CPMenu setMenuBarVisible:YES];
}

// ボタンが押された際に呼ばれる処理
-(void)swap:(id)sender
{
  // ラベルのキャプションを変更します
  if([label stringValue] == "Hello World!")
    [label setStringValue:"Goodbye!"];
  else
    [label setStringValue:"Hello World!"];
}

@end

さいごに

Cappuccino を使うと Mac や iPhone のソフト開発と同じ感覚で Web アプリケーションを開発することが可能です。

次回以降、Objective-J, Objective-C, Cocoa, Cocoa Touch などに関する記事を掲載していきたいと思います。

お楽しみに!

個人ブログ 拡張現実ライフ

References

References
1 CGRectGetWidth([contentView bounds]) - CGRectGetWidth([label frame]

[Rails]特定ビューだけで特定のヘルパーの関数を使いたい

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

 こんにちは。

 KBMJでRuby on Rails を使ったweb開発に携わっているyoppiといいます。

 基本的にビューで使いたい関数を持っているヘルパーはコントローラー側で読み込んであげる必要があります。ただ、あるヘルパーの関数をあるビューで使いたいというニッチな要求に対しては不便な場合があります。今回は、そのニッチな要求を簡単に満たしちゃう方法を紹介したいと思います。

 方法はとても簡単で、呼び出したい関数を持っているヘルパー(今回はHogeHelper)を読み込むコードをビューに埋め込んであげればいいだけです。

 実際は以下のようになります。

<% self.class.send(:include, HogeHelper) -%>

 こうすれば、これを記述した以降の部分で読み込んだヘルパーの関数が呼び出せるようになります。

 簡単ですね。 ヘルパー内の関数は多くなりすぎですが、このテクニックを使えば、スッキリとできるかもしれません。どこまでニーズがあるかはわかりませんが、参考にしていただくと幸いです。

Let’s  find your niche!

button_to ボタンでリンク rails

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちはカツオです。

今日は、初心に戻ってハイパーリンクではなく、ボタンでリンクする方法を紹介します。 

 link_toやurl_forを使えば、リンクを作成することはできると思いますが

ハイパーリンクではなくボタン形式でリンクを作成する方法です。

ボタンでリンクを作成する場合には

○button_to

を使用します。

 使い方は、link_toと同じです。

button_to(“更新”, :action =>’update’)

#=><form method “post” action=”/top/update” class=”button-to”>

       <div><input type=”submit” value”更新” /></div></form>

このbutton_toポイントとしては、

・formタグで作成されるので、既にformタグの中にいる場合は使えない

・当然ボタンによるリンクになる

・postメソッドが用いられるので、データの更新がある場合などのリンクに適している。

ということがあげられます。

今日は初歩的な内容でしたね。

でわでわまた。

Objective-C + Cocoaにおけるメモリ管理について

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。

KBMJの佐藤です。

今回はObjective-CでCocoaアプリケーションを作る際における

メモリ管理について解説します。

http://farm4.static.flickr.com/3280/2987292642_b6d5e38a07.jpg

MyObject.h

#import <cocoa /cocoa.h>

// (1)
@interface MyObject : NSObject {
}

// (2)
-(void)dealloc;

@end

MyObject.m

#import "MyObject.h"

@implementation MyObject

// (3)
-(void)dealloc
{
	NSLog(@"MyObject dealloc");
	[super dealloc];
}

@end

Memory.m

#import <foundation /foundation.h>
#import "MyObject.h"

int main (int argc, const char * argv[]) {
    // (4)
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // (5)	
    MyObject* object1;
    object1 = [[MyObject alloc] init];
    [object1 release];

    // (6)
    MyObject* object2;
    object2 = [[[MyObject alloc] init] autorelease];

    // (7)	
    NSString* string0;
    string0 = [NSString stringWithCString:"new string" encoding:NSASCIIStringEncoding];

    // (8)	
    NSString* string1;
    string1 = [[[NSString alloc] initWithCString:"new string" encoding:NSASCIIStringEncoding] autorelease];

    // (9)	
    NSLog(@"before pool release");
    [pool release];
    NSLog(@"after pool release");

    return 0;
}

コード解説(1)

@interface MyObject : NSObject {
}

MyObjectクラスを宣言します。

NSObjectを親クラスとします。

コード解説(2)

-(void)dealloc;

deallocメソッドを宣言します。

このメソッドはインスタンス解放時に呼び出されます。

コード解説(3)

-(void)dealloc
{
	NSLog(@"MyObject dealloc");
	[super dealloc];
}

deallocメソッドを実装します。

NSLog関数にてメッセージを出力し、

親クラスであるNSObjectのdeallocを呼び出します。

コード解説(4)

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSAutoreleasePoolのオブジェクトを作成する。

この後に自動開放指定されたオブジェクトについては、

[pool drain] の時点で解放されます。

コード解説(5)

    MyObject* object1;
    object1 = [[MyObject alloc] init];
    [object1 release];

MyObjectオブジェクトのためのメモリを確保、

オブジェクトを初期化し、

解放します。

コード解説(6)

    MyObject* object2;
    object2 = [[[MyObject alloc] init] autorelease];

MyObjectオブジェクトのためのメモリを確保、

オブジェクトを初期化し、

自動開放指定します。

このオブジェクトは [pool drain] された時点で解放されます。

コード解説(7)

    NSString* string0;
    string0 = [NSString stringWithCString:"new string" encoding:NSASCIIStringEncoding];

NSStringオブジェクトのためのメモリを確保、

オブジェクトを初期化し、

自動開放指定します。

コード解説(8)

    NSString* string1;
    string1 = [[[NSString alloc] initWithCString:"new string" encoding:NSASCIIStringEncoding] autorelease];

NSStringオブジェクトのためのメモリを確保、

オブジェクトを初期化し、

自動開放指定します。

stringWithCString を用いる場合に比べてコードが冗長になりますので、

こういった場合は stringWithCString を呼び出した方が良いでしょう。

コード解説(9)

    NSLog(@"before pool release");
    [pool release];
    NSLog(@"after pool release");

NSAutoreleasePoolオブジェクトを解放する。

自動開放指定されたオブジェクトはこのタイミングでまとめて解放されます。

実行ログ

2008-10-30 12:15:01.597 Memory[6684:10b] MyObject dealloc
2008-10-30 12:15:01.598 Memory[6684:10b] before pool release
2008-10-30 12:15:01.599 Memory[6684:10b] MyObject dealloc
2008-10-30 12:15:01.600 Memory[6684:10b] after pool release

自動開放指定したオブジェクトが

[pool release] したタイミングで、

まとめて解放されていることが分かります。

さいごに

Objective-C + Cocoa のような参照カウント方式のメモリ管理では

オブジェクトの生存期間を意識しながらコードを書いていく必要があるかと思います。

次回以降、Objective-C や Cocoa に関する記事を掲載していきたいと思います。

お楽しみに!

個人ブログ 拡張現実ライフ

FireFoxでWebページの色を抜き出すアドオン

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Web制作ではよくお世話になるブラウザFireFox。

その中で、お手軽にWebページに使われる色を抜き出すアドオンを

ご紹介します。 

アドオン名はcolorzilla。

このアドオンを入れることによって簡単にWebページで気になる色を

取得することができます。

使い方は、まずはアドオンを入手しインストール。

インストールが済めば、ブラウザ上の左下にスポイトマークが表示されるはずです。

このスポイトマークをクリックすることで、即機能が使えます。

マウスカーソルが十字になったら、後は抜き出したい色に重ねてクリックしてください。

RGBでの数値や座標、HTMLタグがステータスバーに表示されるはずです。 

この状態で、スポイトを右クリックするとカラーコードをコピーしてくれる機能も

うれしいところ。

右クリックでさらに細かい機能も使うことができます。

Firebugでもソースコードからカラーコードを調べることはできますが、

colorzillaだと画像からも直接カラーコードを抜き出せるところが違います。

画像と同じ色で背景色を指定したい、などといった場合に重宝しますね。

Webカメラからの入力動画に対してActionScriptで2値化を行う

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。

KBMJの佐藤です。

今回はActionScript3.0を使って、

Webカメラからの入力動画に対して2値化を行ってみます。

http://farm3.static.flickr.com/2284/2983782725_3acc71f952.jpg

ソースコード

package{
    import flash.display.*;
    import flash.events.*;
    import flash.media.*;
    import flash.system.*;
    import flash.text.*;
    import flash.geom.*;
    import flash.filters.*;

    [SWF(width="640", height="480")]

    public class Threshold2 extends Sprite {
	private var video:Video;
	private var camera:Camera;
	private var msg:String;
	public var txtArea:TextField = new TextField();
	public var bdTmp:BitmapData;
	public var bmp:Bitmap;

	public function Threshold2()
	{
	    stage.scaleMode = StageScaleMode.NO_SCALE;
	    stage.align = StageAlign.TOP_LEFT;

	    // (1)
	    camera = Camera.getCamera();
	    if(camera != null){
		camera.addEventListener(StatusEvent.STATUS, statusHandler);
		camera.setMode(640, 480, 15);
		camera.setMotionLevel(10);
		camera.setQuality(0, 50);

		// (2)
		video = new Video(camera.width, camera.height);
		video.attachCamera(camera);

		addEventListener(Event.ENTER_FRAME, tick);
	    }else{
		msg = "使用可能なカメラがありません。";
		txtArea.text = msg;
	    }

	    txtArea.autoSize = TextFieldAutoSize.LEFT;
	    txtArea.text = "Threshold";
	    txtArea.textColor = 0xffffff;
	    txtArea.x = 2;
	    txtArea.y = this.height - txtArea.textHeight - 10;
	    this.addChild(txtArea);

	    // (3)
	    bdTmp = new BitmapData(video.width, video.height, false, 0xffffff);
	    bmp = new Bitmap(bdTmp);
	    this.addChild(bmp);
	}

	private function statusHandler(evt:StatusEvent):void{
	    if(camera.muted){
		msg = "カメラへのアクセスが拒否されました。";
		msg += "カメラの映像を表示するにはアクセスを許可してください。";
		txtArea.text = msg;
		Security.showSettings(SecurityPanel.PRIVACY);
	    }else{
		msg = "使用中のカメラ : " + camera.name + "\n";
		msg += "幅x高さ : " + camera.width + "x" + camera.width;
		txtArea.text = msg;
	    }
	}

	private function tick(event:Event):void{
	    if(video == null || camera == null){
		return;
	    }
	    if(camera.muted == true){
		return;
	    }
	    // (4)
	    var s:BitmapData = new BitmapData(video.width, video.height);
	    s.draw(video);

	    // (5)
	    var r:Rectangle = new Rectangle(0, 0, video.width, video.height);
	    bdTmp.fillRect(r, 0xffffffff);

	    // (6)
	    var threshold:uint = 0x00800000;
	    var color:uint = 0x00000000;
	    var maskColor:uint = 0x00ff0000;
	    bdTmp.threshold(s, r, new Point(0, 0), "<=", threshold, color, maskColor, false);
	}
    }
}

コード解説(1)

camera = Camera.getCamera();

Webカメラに対して各種操作の行えるCameraオブジェクトを取得します。

コード解説(2)

video = new Video(camera.width, camera.height);
video.attachCamera(camera);

Webカメラからの入力映像をVideoオブジェクトに流し込みます。

コード解説(3)

bdTmp = new BitmapData(video.width, video.height, false, 0xffffff);
bmp = new Bitmap(bdTmp);
this.addChild(bmp);

画像操作用のバッファとしてBitmapDataオブジェクトを作成し、

Bitmapオブジェクトに関連づけて、画面に表示します。

コード解説(4)

var s:BitmapData = new BitmapData(video.width, video.height);
s.draw(video);

Webカメラからの入力をBitmapDataオブジェクトにコピーします。

コード解説(5)

var r:Rectangle = new Rectangle(0, 0, video.width, video.height);
bdTmp.fillRect(r, 0xffffffff);

処理対象の矩形をRectangleオブジェクトとして作成し、

BitmapDataオブジェクトの内容を白でクリアします。

コード解説(6)

var threshold:uint = 0x00800000;
var color:uint = 0x00000000;
var maskColor:uint = 0x00ff0000;
bdTmp.threshold(s, r, new Point(0, 0), "<=", threshold, color, maskColor, false);

thresholdメソッドを用いて2値化を行います。

対象のカラー要素をmaskColor(0x0ff0000)によって抽出し、

閾値threshold(0x00800000)より大きい場合は

ピクセル値color(0x00000000)に設定します。

さいごに

2値化には様々な方法があるのですが、

この記事では非常に簡単な方法を用いました。

ヒストグラムなどを作成した上でそれを元に2値化を行えば

より良い処理結果を得ることができます。

次回以降もActionScriptで様々な画像処理を紹介していきたいと思います。

お楽しみに!

個人ブログ 拡張現実ライフ

クローラー対策 ロボットテキスト (robots txt)

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちはカツオです。

今日はrobots.txtの書き方について説明します。

というのも

webサーバーでmongrelを使ったrailsアプリで、mongrelがよく落ちるのですが、

クローラーのアクセス数が多いので、

googleのクローラーをIPで制限してみたら、

mongrelの落ちる回数が、極端に減りました。

対策の一つとして、robots.txtを書く機会があったので、ご紹介です。  

■robots.txtとは?

クローラーや、スパイダー、検索ロボットといわれる
検索エンジンのインデックスを取得するために、web上を巡回しているソフトがあります。

もちろんそれらにアクセスされると、
検索エンジンのインデックスに登録される可能性があります。

しかし、サイトを運営していれば
インデックスされたくないページ等もあるでしょう。

そういったページ等をアクセスさせないよう命令するのが
robots.txtです。

■robots.txtの書き方
基本的にはrobotsテキストでは2つの命令がかけます。

1.アクセス制限
2.アクセス間隔の調整

上記2つです。

まずアクセス制限から説明します。

クローラーのアクセスを制限する場合
2種類の記述が必要です。

User-Agent:    命令の対象となるロボット
Disallow:    制限するページまたはディレクトリ

例)全てのロボットに、全てのページをインデックスさせない場合
User-Agent: *
Disallow: /

例)googleのクローラーから、testというディレクトリを制限する場合
User-Agent: Googlebot
Disallow: /test

例)yahooのクローラーから、「/test/index.html」というページを制限する場合
User-Agent: Slurp
Disallow: /test/(もしくは/test/index.html)

このような形で表記します。

例)複数のクローラーを制御する場合
1行あけて次のUser-Agentを書いてください。

User-Agent: Googlebot
Disallow: /test

User-Agent: Slurp
Disallow: /test/

例)複数の制限したいディレクトリがある場合
Disallowを行をあけずに書いてください。

User-Agent: *
Disallow: /test
Disallow: /demo

また、クローラーのアクセス間隔を指定する場合ですが
一度アクセスがあったら、次のアクセスまでに30秒間隔をあける場合は

○百度のクローラ
User-Agent:baiduspider
Crawl-Delay: 30

○yahooのクローラー
User-Agent:Slurp
Crawl-Delay:0.5
※yahooに関しては、単位が”分”らしいです。

○googleのクローラー
Crawl-Delayのコマンドにgoogleは対応していないので、
googleウェブマスターツールで
アカウント登録して、クローラーのアクセス頻度を下げるしかないようです。

■robots.txtの設置箇所

robots.txtの設置箇所はルートディレクトリと決められています。

弊社のURLの場合(http://www.kbmj.com/)

http://www.kbmj.com/robots.txt

このような階層に置かなければいけません。

※無料ブログの場合等は設置権限がない場合があります。

■robots.txtのファイル名

robots.txtのファイル名は間違えず、半角小文字で書きましょう

○ robots.txt

↓これは間違いです。

× robot.txt
× robots.text
× robots.txt

■補足
全てのクローラーがrobots.txtを読んでくれるわけではなく、
なかなか読んでくれないクローラーもあるようです。

ただ、もし、クローラーのアクセスでサーバー負荷が増えてしまっていたりする場合は、
一度試してみたら、いかがでしょう。

Railsでの画像の出力方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

どうも。

バッチです。 

今回のテーマは以外に忘れやすかったりする、

Railsで画像を出力する方法です。 
RailsでHTMLのIMGタグを出力するには、

<%= image_tag (“/images/hoge”) %>

と書きます。

ちなみにオプションを付ける場合は、

<%= image_tag (“/images/hoge”, :size=>”100×100″, :alt=>”画像”) %>

と書くことで、それに対応したHTMLが出力されます。

また、画像にリンクを張りたい場合は、

<%= link_to(image_tag(“/images/hoge”, :size=>”100×100″, :alt=>”画像”), {:controller => ‘hoge’, :action => ‘hoge’}) %>

といった感じで記述します。

紛らわしく、意外と忘れやすいので注意ですね。

Webカメラからの入力動画に対してActionScriptで色彩変換を行う

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。

KBMJの佐藤です。

今回はActionScript3.0を使って、

Webカメラからの入力動画に対して色彩変換を行ってみます。

http://farm4.static.flickr.com/3236/2980918123_5fe237e523.jpg

ソースコード

package{
    import flash.display.*;
    import flash.events.*;
    import flash.media.*;
    import flash.system.*;
    import flash.text.*;
    import flash.geom.*;
    import flash.filters.*;

    [SWF(width="640", height="480")]

    public class Threshold extends Sprite {
	private var video:Video;
	private var camera:Camera;
	private var msg:String;
	public var txtArea:TextField = new TextField();
	public var bdTmp:BitmapData;
	public var bmp:Bitmap;

	public function Threshold()
	{
	    stage.scaleMode = StageScaleMode.NO_SCALE;
	    stage.align = StageAlign.TOP_LEFT;

	    // (1)
	    camera = Camera.getCamera();

	    if(camera != null){
		camera.addEventListener(StatusEvent.STATUS, statusHandler);
		camera.setMode(640, 480, 15);
		camera.setMotionLevel(10);
		camera.setQuality(0, 50);

		// (2)
		video = new Video(camera.width, camera.height);
		video.attachCamera(camera);

		addEventListener(Event.ENTER_FRAME, tick);
	    }else{
		msg = "使用可能なカメラがありません。";
		txtArea.text = msg;
	    }

	    txtArea.autoSize = TextFieldAutoSize.LEFT;
	    txtArea.text = "Threshold";
	    txtArea.textColor = 0xffffff;
	    txtArea.x = 2;
	    txtArea.y = this.height - txtArea.textHeight - 10;
	    this.addChild(txtArea);

	    // (3)
	    bdTmp = new BitmapData(video.width, video.height, false, 0xffffff);
	    bmp = new Bitmap(bdTmp);
	    this.addChild(bmp);
	}

	private function statusHandler(evt:StatusEvent):void{
	    if(camera.muted){
		msg = "カメラへのアクセスが拒否されました。";
		msg += "カメラの映像を表示するにはアクセスを許可してください。";
		txtArea.text = msg;
		Security.showSettings(SecurityPanel.PRIVACY);
	    }else{
		msg = "使用中のカメラ : " + camera.name + "\n";
		msg += "幅x高さ : " + camera.width + "x" + camera.width;
		txtArea.text = msg;
	    }
	}

	private function tick(event:Event):void{
	    if(video == null || camera == null){
		return;
	    }
	    if(camera.muted == true){
		return;
	    }

	    // (4)
	    bdTmp.draw(video);

	    // (5)
	    var rect:Rectangle = new Rectangle(bmp.width/2, 0, 
					       bmp.width/2, bmp.height);
	    var target:Point = new Point(bmp.width/2, 0);

	    // (6)
	    var filter:ColorMatrixFilter = new ColorMatrixFilter();
	    filter.matrix = new Array(1, 0, 0, 0);

	    // (7)
	    bdTmp.applyFilter(bdTmp, rect, target, filter);
	}
    }
}

コード解説(1)

camera = Camera.getCamera();

Webカメラに対して各種操作の行えるCameraオブジェクトを取得します。

コード解説(2)

video = new Video(camera.width, camera.height);
video.attachCamera(camera);

Webカメラからの入力映像をVideoオブジェクトに流し込みます。

コード解説(3)

bdTmp = new BitmapData(video.width, video.height, false, 0xffffff);
bmp = new Bitmap(bdTmp);
this.addChild(bmp);

画像操作用のバッファとしてBitmapDataオブジェクトを作成し、

Bitmapオブジェクトにひも付け、画面に表示します。

コード解説(4)

bdTmp.draw(video);

Videoオブジェクトの内容をBitmapDataオブジェクトにコピーします。

コード解説(5)

var rect:Rectangle = new Rectangle(bmp.width/2, 0, 
                                   bmp.width/2, bmp.height);
var target:Point = new Point(bmp.width/2, 0);

フィルタを適用するための矩形と座標を決定します。

コード解説(6)

var filter:ColorMatrixFilter = new ColorMatrixFilter();
filter.matrix = new Array(1, 0, 0, 0);

画素に対して変換を施すためのフィルタを作成し、

そのフィルタで用いる変換用の行列を設定します。

これは各ピクセルのRGBAカラー値に対して適用するための4×5行列であり、

これによって新しいRGBAカラー値を得ることができます。

コード解説(7)

bdTmp.applyFilter(bdTmp, rect, target, filter);

BitmapDataオブジェクトに対してフィルタを適用します。

この際、矩形と座標も同時に指定します。

さいごに

ColorMatrixFilterを使えば、

彩度変更、色相回転、輝度アルファ変換など、各種効果を汎用的に施すことができます。

皆さんも是非試してみて下さい。

個人ブログ 拡張現実ライフ

Webカメラからの入力に対してActionScriptでエッジ検出を行う

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。

KBMJの佐藤です。

今回はActionScriptを使って、

Webカメラからの入力に対してエッジ検出を行ってみます。

http://farm4.static.flickr.com/3022/2977769785_fc19b82eea.jpg

ソースコード

package
{
    import flash.display.*;
    import flash.events.*;
    import flash.media.*;
    import flash.filters.*;

    public class Motion extends Sprite {
	private var bd:BitmapData;
	private var video:Video;
	private var bitmap:Bitmap;

	public function Motion(){
	    // (1)
	    bd = new BitmapData(640, 480, false, 0x00000000);
	    bitmap = new Bitmap(bd);
	    addChild(bitmap);
	    addEventListener(Event.ENTER_FRAME, onEnterFrame);

	    // (2)
	    var camera:Camera = Camera.getCamera();

	    if(camera != null){
		video = new Video(640, 480);
		video.attachCamera(camera);
	    }
	}
        public function onEnterFrame(evt:Event):void {
	    // (3)
	    bd.draw(video);
	    var conv:ConvolutionFilter;
	    var edges:Array = [0, -1, 0,
                               -1, 4, -1,
                               0, -1, 0];
	    convFilter(bitmap, edges, 1);
        }
        private function convFilter(dispObj:DisplayObject, m:Array, d:int):void{
	    // (4)
	    var conv:ConvolutionFilter = new ConvolutionFilter(3, 3, m, d);
	    dispObj.filters = [conv];
	}
    }
}

コード解説(1)

bd = new BitmapData(640, 480, false, 0x00000000);
bitmap = new Bitmap(bd);
addChild(bitmap);

ここではWebカメラからの入力を描画するためのBitmapDataオブジェクトを生成しています。

ActionScriptではBitmapDataオブジェクトを用いることによって、

ビットマップを直接操作することができます。

コード解説(2)

var camera:Camera = Camera.getCamera();

if(camera != null){
    video = new Video(640, 480);
    video.attachCamera(camera);
}

Cameraオブジェクトを取得し、

そこからの入力をVideoオブジェクトに割り当てています。

コード解説(3)

    bd.draw(video);
    var conv:ConvolutionFilter;
    var edges:Array = [0, -1, 0,
                       -1, 4, -1,
                       0, -1, 0];
    convFilter(bitmap, edges, 1);

Videoオブジェクトの内容をBitmapオブジェクトに描画しています。

畳み込みフィルタの内容を配列で作成し、

Bitmapオブジェクトに設定しています。

コード解説(4)

    // (4)
    var conv:ConvolutionFilter = new ConvolutionFilter(3, 3, m, d);
    dispObj.filters = [conv];

ConvolutionFilterオブジェクトを生成して

畳み込みフィルタの配列を適用しています。

filtersとあるように、フィルタは複数設定することができます。

さいごに

ActionScriptはWebブラウザ上で実行でき、

なおかつリッチなプレゼンテーションが得意なので、

グラフィック処理を色々と試してみるには良いプラットフォームだと思います。

皆さんも是非試してみて下さい。

個人ブログ 拡張現実ライフ

ruby-openglで三角形を描画する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ruby-openglのインストール

gem install ruby-opengl

ソースコードを書く

require "opengl"
require "glut"

display = proc {
  GL.Clear(GL::COLOR_BUFFER_BIT)

  GL.Begin(GL::TRIANGLES)
  GL.Color3f(1.0, 0.0, 0.0)  # red
  GL.Vertex3f(0.0, 0.0, 0.0) # center
  GL.Color3f(0.0, 1.0, 0.0)  # green
  GL.Vertex3f(1.0, 0.0, 0.0) # right
  GL.Color3f(0.0, 0.0, 1.0)  # blue
  GL.Vertex3f(0.0, 1.0, 0.0) # up
  GL.End();

  GLUT.SwapBuffers()
}

GLUT.Init()
GLUT.CreateWindow("ruby-opengl test")
GLUT.DisplayFunc(display)
GL.ClearColor(0.5,0.5,0.5,0.0)
GLUT.MainLoop()

実行する

ruby -rubygems SimpleExample.rb

ウィンドウが表示され、グラデーションで塗りつぶされた三角形が描画されます。

さいごに

ループなどを用いて頂点座標を変化させていくことで、

Begin()/End()だけでも様々なグラフィックを描画することができます。

色々と試してみると面白いと思います。

個人ブログ 拡張現実ライフ

hyper estraierのindexの再構築

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

どうもメガネです。11回目です。 今回はHyper estraierのindexの再構築について説明します。

Hyper estraierは便利なのですが、サーバなどの電源が落ちると_nodeの中が消えてします。

なので再構築を方法を紹介します。

今回はコマンドだけで行います。

まずはHyper estraierが起動していることを確認

$ ps -ef | grep estmaster

動いていない場合は起動する。

$estmaster -bg indexを初期化したパス database.ymlを確認する

estraier:

 node: node 

database.ymlを確認したら_nodeの中にdatabase.ymlファイルに記述されているnodeがあるかを確認する

$ ls /indexを初期化したパス/_node/

ない場合は作成する。

$ estcmd create -tr -apn -xl /indexを初期化したパス/_node/作成したいnode

作成が終わったら再構築したいRAILSAPPのtopに行って $ruby scrip/console >>再構築したいMODEL.reindex! あとはひたすら待つのみ

以上

RubyでGoogleカレンダーを操作する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

TrinityTです。

約半年ぶりの投稿になってしまいました・・・

今回はRubyでGoogleカレンダーを操作する方法を説明します。

ここではzorioさんが作成したRuby用のGoogleCalendarAPI操作ライブラリを使用しました。

参考URL:http://gcalapi.rubyforge.org/

 インストール

gemでインストール可能です。

$ gem install gcalapi

 

 使用方法

以下の3クラスを主として使用します。

GoogleCalendar::Event : 予定

GoogleCalendar::Calendar : ユーザのカレンダー

GoogleCalendar::Service : カレンダーサービスへの認証や検索条件を対話的に行う

検索

通常の検索の場合は以下のようにします。

# アカウントメールアドレス
mail = "hoge@gmail.com"
# パスワード
pass = "huga"
# Googleカレンダーの「カレンダー設定」画面から取得した非公開URL
feed = "http://www.google.com/calendar/feeds/hoge%40gmail.com/private-xx.../basic"

srv = GoogleCalendar::Service.new(mail, pass)
cal = GoogleCalendar::Calendar::new(srv, feed)
events = cal.events

events.each do |event|
  p event.title
  p event.desc
end
# 実行結果 >
"飲み会"
"期間: 2008/08/13 19:00~23:00 \nJST........"
"フットサル"
"期間: 2008/08/09 09:30~11:30 \nJST........"
....

 

また、Service.queryメソッドを使うことで取得条件を付加することが可能です。

...
srv = GoogleCalendar::Service.new(mail, pass)
srv.query(feed, :"max-results" => 5)
...

 

主な条件

:max-results : 最大取得数

:orderby : 並び替え

:updated-min : 更新日(最古)

:updated-max : 更新日(最新)

:published-min : 登録日(最古)

:published-max : 登録日(最新)

:author : 登録者

新規作成

次に予定の新規作成を行います。

前項で使用した非公開URLは読み取り専用のため、更新可能なURLに置き換える必要があります。

非公開URL(読み取り専用):
 http://www.google.com/calendar/feeds/hoge%40gmail.com/private-xx.../basic
非公開URL(更新可能):
 http://www.google.com/calendar/feeds/hoge%40gmail.com/private/full
mail = "hoge@gmail.com"
pass = "huga"
feed = "http://www.google.com/calendar/feeds/hoge%40gmail.com/private/full"
srv = GoogleCalendar::Service.new(mail, pass)
cal = GoogleCalendar::Calendar::new(srv, feed)
event = cal.create_event
event.title = "ゆっくり"
event.desc = "ゆっくりしていってね!"
event.where = "ゆっくりした結果がこれだよ!"
event.st =  Time.mktime(2008, 12, 24, 0, 0, 0)
event.en =  Time.mktime(2008, 12, 24, 12, 0, 0)
event.save!

実行結果

更新&削除

更新や削除は取得したEventインスタンスに対してupdate,delete(destroy)を実行することで可能です。

# 更新
events = cal.events
evnet = events[0]
event.title = "Update!"
event.update

 
# 削除
events = cal.events
evnet = events[0]
event.delete

 

 まとめ

本ライブラリを使用することで、他のカレンダーサービスやスケジューラとの連携などのマッシュアップが簡単に可能になると思います。

是非使用してみてはいかがでしょうか!

ruby on railsでグラフを作成する。Open Flash Chart編

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは、KBMJの中平@railsエンジニアです。

今回はruby on railsでグラフを表示させようと思います。

rubyでグラフを作成するのは、Gruff というプラグインがありますが

今回は Gruffではなく Open Flash Chart というグラフ作成プラグインを使用してみます。

このプラグインの特徴は、その名の通りグラフをFlashで表示するプラグインなので、Gruffを使った場合より見た目がいいグラフができるかも? ということで、さっそくruby on rails でグラフを作成してみます。

Open Flash Chartは、こちらのサイトでruby on rails 用のプラグインが公開されています。(ほかの言語のプラグインもあります)

http://pullmonkey.com/projects/open_flash_chart2/

サイトを見ると使い方の手順が書いてあるのでその通りに実行します。

 ※上記のサイトに手順書いてありますので、ここでは要点をざっと説明します。

1.Open Flash Chartプラグインのインストール

ruby script/plugin install git://github.com/pullmonkey/open_flash_chart.git  

2.グラフ表示のためのコントローラーやビューの記述   

サイトに書いてあるサンプルを参考にしてください。棒グラフの作成サンプルです。

(グラフのサンプルコードは数行の簡単なものですので、ここでは省略します)

3.swfobject.jsファイルのコピー   

プラグインに入っている

/vendor/plugins/open_flash_chart/assets/swfobject.js ファイルを  

RAILS_ROOT/public/javascriptsディレクトリにコピーします。

4.open-flash-chart.swfファイルのコピー

プラグインに入っている

/vendor/plugins/open_flash_chart/assets/open-flash-chart.swf ファイルを  

RAILS_ROOT/publicディレクトリにコピーします。

準備はこれで終わりです。

これでrailsを起動しページ表示するとグラフが表示されます。

コントローラー側で、値やグラフの種類を変えることができますので、動的なグラフ表示を簡単に導入できます。

また、このプラグインで、棒グラフ、円グラフ、折れ線グラフなど数種類のグラフが作れるようですし、

日本語でラベルの表示などもできます。

http://pullmonkey.com/projects/open_flash_chart2/

に作成できるグラフの種類と、rails のサンプルコードも一緒にありますので、参考にしてください。

また、http://pullmonkey.com/ を見たところ、ajaxでグラフの種類を切り替えたりするサンプルもあったので、まだ色々な使い方ができそうです。

ruby on railsでグラフ作成するのはOpen Flash Chartの使い方も簡単ですので、参考にしていただければと思います。

※個人的には、GruffよりOpen Flash Chartを使ってのグラフのほうが見た目が好きです。

jpmobileで携帯のGPSから位置情報を取得する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。KBMJの佐藤です。

今回はRuby on Railsにおける携帯電話からの位置情報取得について解説します。

携帯電話からの位置情報取得についてはキャリア毎に仕様が異なります。

しかしjpmobileというRuby on Railsのプラグインを用いることにより、

キャリアを意識せずに統一的なインターフェースで簡単に位置情報を取得することができます。

以下、その方法について解説します。

jpmobileのインストール

railsアプリケーションのディレクトリにて、下記のコマンドを打ち込みます。

ruby script/plugin install svn://rubyforge.org/var/svn/jpmobile/trunk/jpmobile

位置情報取得リンクの作成

位置情報取得リンクを表示したいviewにて、下記のコードを記述します。

<%= get_position_link_to "位置情報取得", :action => :gps %>

位置情報を取得

get_position_link_to にて指定した action にて、下記のコードを記述します。

@position = request.mobile.position

取得した位置情報を表示

view にて下記のように記述することで、取得した位置情報を表示することができます。

緯度:<%h @position.lat %>
軽度:<%h @position.lon %>

さいごに

jpmobile を使えば、位置情報取得に限らず、携帯キャリア毎に仕様の違う各種処理を簡単に記述することができるようになります。

皆さんもぜひお試し下さい。

個人ブログ

拡張現実ライフ

RubyCocoaでウィンドウとボタンを表示する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。

KBMJの佐藤です。

今回はRubyCocoaについて紹介します。

RubyCocoaとは、RubyでCocoaアプリケーションを書いたりできるようになるラ

イブラリおよびフレームワークです。

RubyCocoaのインストール

以下のURLからdmgをダウンロードして、インストールします。

http://sourceforge.net/project/showfiles.php?group_id=44114

LeopardにはOSに標準搭載されているので、インストールの必要はありません。

コードを書く

HelloWorld.rb というファイル名でコードを書きます。

require 'osx/cocoa'
include OSX

class AppDelegate <  NSObject
   def sayHello(sender)
     puts "Hello again, World!"
   end
end


if $0 == __FILE__ then
  app = NSApplication.sharedApplication()

  app.setDelegate(AppDelegate.alloc.init)

  frame = [200.0, 300.0, 250.0, 100.0]
  win = NSWindow.alloc.initWithContentRect_styleMask_backing_defer(frame, 15, 2, 0)
  win.setTitle 'HelloWorld'
  win.setLevel(3)                       # floating window

  hel = NSButton.alloc.initWithFrame [10.0, 10.0, 80.0, 80.0]
  win.contentView.addSubview(hel)
  hel.setBezelStyle(4)
  hel.setTitle( 'Hello!' )
  hel.setTarget( app.delegate )
  hel.setAction( "sayHello:" )

  bye = NSButton.alloc.initWithFrame [100.0, 10.0, 80.0, 80.0]
  win.contentView.addSubview(bye)
  bye.setBezelStyle( 4 )
  bye.setTarget(app)
  bye.setAction('stop:')
  bye.setEnabled( true )
  bye.setTitle( 'Goodbye!' )

  win.display()
  win.orderFrontRegardless()            ## but this one does

  app.run()
end

実行する

ターミナルで

ruby HelloWorld.rb

と打ち込むと、以下のようなウィンドウが表示されます。

http://farm4.static.flickr.com/3185/2928545086_c4406c295c.jpg

Hello! ボタンを押すと、ターミナルにメッセージが表示されます。

http://farm4.static.flickr.com/3263/2927675663_c6011ef314.jpg

Goodbye! ボタンを押すと、ウィンドウが閉じます。

さいごに

RubyCocoaを使えば、CoreAnimationなど、MacOSXのエレガントなフレームワー

クを手軽に試してみることが出来ます。

皆さんもぜひ試してみて下さい。

個人ブログ

拡張現実ライフ

ruby-openglでお手軽3Dプログラミング

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。

KBMJの佐藤です。

今回はruby-openglについて紹介します。

ruby-openglとは、rubyからOpenGLを扱えるようになるgemです。

このgemをインストールすれば、rubyでお手軽に3Dプログラミングを楽しむことができます。

OpenGLについての情報はネット上に豊富に存在しているので、

3Dプログラミングの入門としてはうってつけな気がします。

ruby-openglのインストール

gem install ruby-opengl

ソースコードを書く

require "opengl"
require "glut"

display = proc {
  GL.Clear(GL::COLOR_BUFFER_BIT)
  GL.Color3f(0.0, 0.0, 1.0)
  GLUT.WireTeapot(0.5)
  GLUT.SwapBuffers()
}

timer = proc {
  GL.Rotate(1.0, 0.0, 1.0, 0.0)
  GLUT.PostRedisplay()
  GLUT.TimerFunc(10, timer, 0)
}

GLUT.Init()
GLUT.CreateWindow("ruby-opengl test")
GLUT.DisplayFunc(display)
GL.ClearColor(0.5,0.5,0.5,0.0)
GLUT.TimerFunc(10, timer, 0)
GLUT.MainLoop()

実行する

ruby ruby_gl_test.rb

このようなウィンドウが表示され、ワイヤーフレームのティーポットが回転します。

http://farm4.static.flickr.com/3292/2925352673_f2b44e1eb8.jpg

さいごに

3Dプログラミングは見た目が派手なこともあり、作っていてとても楽しいので、

皆さんも試してみてはいかがでしょうか?

個人ブログ

拡張現実ライフ

MacOSX の sed に気をつけろ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは、たろちゃんです。

先日、MacOSX で sed コマンドを使って置換を行った時にはまってしまったので、それについて書きます。

例えば、以下のようなテキストがCR+LFで保存されていたとします。

egg
spam
ham

これをspamの置換してspamを三行追加しようとします。つまりこういう状態を目指します。

egg
spam
spam
spam
ham

では早速やってみましょう。CR+LFなので改行文字は\r\nとします。

$ sed -e 's/spam/spam\r\nspam\r\nspam/' spam.txt > spam2.txt

すると、こんなテキストファイルができあがってしまいます。

egg
spamrnspamrnspam
ham

改行文字が普通の文字列として認識されてしまいます。これは GNU の sed コマンドではなく FreeBSD 由来の sed コマンドであるからのようです。

ちょっと違う方法でやってみましょう。あまり一般的ではない改行を sed -e に入れる方法です。

sed -e 's/spam/spam\
> spam\
> spam/' spam.txt > spam3.txt

lvなどで確認すると期待通りの結果が得られたように見えますが文字コードを見るとCR+LFとLFが混在してしまっています。

$ od -c spam3.txt 
0000000    e   g   g  \r  \n   s   p   a   m  \n   s   p   a   m  \n   s
0000020    p   a   m  \r  \n   h   a   m  \n 

というわけで、素直に GNU 版 sed を導入する事にしましょう。

筆者はMac Portsを導入しているので、portコマンドから探しました。

$ port search sed
...
gsed                           textproc/gsed  4.1.5        GNU version of the stream editor, sed
ssed                           textproc/ssed  3.62         Super-sed - a heavily enhanced version of sed

gsed というのが GNU 版に該当するようなので、インストールしてみます。

$ sudo port install gsed

インストールが完了したらあとは gsed コマンドで最初の方法を試してみます。

$ gsed -e 's/spam/spam\r\nspam\r\nspam/' spam.txt > spam4.txt

さっそく文字コードを確認してみましょう。

$ od -c spam4.txt 
0000000    e   g   g  \r  \n   s   p   a   m  \r  \n   s   p   a   m  \r
0000020   \n   s   p   a   m  \r  \n   h   a   m 

これで納得した結果が得られました。

Web 上によく掲載されている例は GNU 版の sed コマンドを利用しています。MacOSX を使っている方で shell を良く使う人は GNU 版の sed も入れておくと良いでしょう。

最近人気な記事