MacRuby / Ruby 1.9.0 のObjective-C実装

去年の12/25にリリースされたRuby 1.9.0ですが、Mac上で動作するRuby 1.9.0 の実装が公開されていました。
Objective-Cで実装されているので、それなりに実行速度は速そうです。
気になるのは、本家との互換性、MacPortsでインストールしている1.8.6と同居可能かというところです。
早くMacPortsで配布してほしいところです。

ようやく、主要なプラットホームで動作するようになってきたので、Mac 上で 1.9.x系を検証する場合に合わせて使ってみますか。

Ext Scaffold Generator Pluginを使う

管理機能などのCRUD画面で使用できるscaffoldジェネレータを探していたところ、extjsを使用したscaffoldジェネレータを見つけました。
http://inside.glnetworks.de/2008/01/18/announcing-ext-scaffold-generator-plugin-for-rails/
以下は、検証した記録です。

インストール

Ext Scaffold Generator Pluginは、Rails Version 2.0 以上が必要です。
1.2.x以前のバージョンの場合、予め、gem update railsを実行します。

  1. ext-2の配布ファイル(2008/02/27時点最新版:ext-2.0.1.zip)をダウンロード:http://extjs.com/deploy/ext-2.0.1.zip
  2. $rails_app/public/配下にextディレクトリ作成。
  3. ダウンロードしたext-2.0.1.zipを作成したextディレクトリに展開。
  4. $rails_appディレクトリでscript/pluginを実行します。
$ script/plugin install http://rug-b.rubyforge.org/svn/ext_scaffold

以上でインストール完了です。

ext_scaffoldジェネレータを使う

空のMVCを作成する

"script/generate ext_scaffold ModelName"を実行すると、モデルのMVC作成されます。

$ script/generate ext_scaffold Hoge
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/hoges
      exists  app/views/layouts/
      exists  test/functional/
      exists  test/unit/
      exists  public/images/ext_scaffold
      create  app/views/hoges/index.html.erb
      create  app/views/hoges/show.html.erb
      create  app/views/hoges/new.html.erb
      create  app/views/hoges/edit.html.erb
      create  app/views/hoges/_form_items.html.erb
      create  app/views/layouts/hoges.html.erb
  dependency  model
      exists    app/models/
      exists    test/unit/
      exists    test/fixtures/
      create    app/models/hoge.rb
      create    test/unit/hoge_test.rb
      create    test/fixtures/hoges.yml
      exists    db/migrate
      create    db/migrate/001_create_hoges.rb
      create  app/controllers/hoges_controller.rb
      create  test/functional/hoges_controller_test.rb
      create  app/helpers/hoges_helper.rb
       route  map.resources :hoges

通常のscaffoldジェネレータと違い、modelも作成されます。
CRUD用viewファイルは作成されますが、モデルのフィールド定義がないため、Newアクションを実行しても新規作成画面は何も表示できません。
Viewの一覧もID列しか表示されないようです。

このため、一覧の列定義、入力フィールド等は、"app/views/hoges/index.html.erb"、"app/views/hoges/_form_items.html.erb"に記述します。

一覧の列項目/入力項目を指定してext_scaffoldを実行する

「空のMVCを作成する」で実行した場合、一覧の列項目や入力項目が追加されないため、そのまま管理画面で使用できません。
管理画面で使える様にするためにext_scaffoldジェネレータ実行時に表示/編集する項目を設定します。
+ 書式: script/generate ext_scaffold User field_name:データ型[, field_name:データ型, ...]


"script/generate ext_scaffold DataModel name:string"様にに実行すると、一覧にID列とName列が表示され、新規作成画面では、Nameを入力できる様になります。以下は、Fugaモデルに、nameカラムを追加してext_scaffoldを実行しています。

$ script/generate ext_scaffold Fuga name:string
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/fugas
      exists  app/views/layouts/
      exists  test/functional/
      exists  test/unit/
      exists  public/images/ext_scaffold
      create  app/views/fugas/index.html.erb
      create  app/views/fugas/show.html.erb
      create  app/views/fugas/new.html.erb
      create  app/views/fugas/edit.html.erb
      create  app/views/fugas/_form_items.html.erb
      create  app/views/layouts/fugas.html.erb
  dependency  model
      exists    app/models/
      exists    test/unit/
      exists    test/fixtures/
      create    app/models/fuga.rb
      create    test/unit/fuga_test.rb
      create    test/fixtures/fugas.yml
      exists    db/migrate
      create    db/migrate/002_create_fugas.rb
      create  app/controllers/fugas_controller.rb
      create  test/functional/fugas_controller_test.rb
      create  app/helpers/fugas_helper.rb
       route  map.resources :fugas

この処理で"db/migrate/002_create_fugas.rb"に:nameカラムが追加されます。
ただし、現在のバージョンでは、データ型定義以外の制約は設定できなため、必要な制約は、migrateファイルに記述します。
ext_scaffoldジェネレータを実行後、"rake db:migrate"を実行します。。

$ rake db:migrate
(in /Users/maxy/repos/rails_sandbox)
== 3 CreateFugas: migrating ===================================================
-- create_table(:fugas)
   -> 0.0027s
== 3 CreateFugas: migrated (0.0030s) ==
========================================

rake実行後、サーバを起動します。http://localhost:3000/fugas/へアセスすると、ID/Nameカラムが表示されます。

Newボタンクリックすると新規作成画面が表示されます。Nameの入力が行えます。

日本語による入力も問題ないようです。

Editボタンをクリックすると、編集画面が表示されます。
また、Deleteボタンによる選択行の削除、Search欄からの検索なども実行できます。

気がついた点

Ext Scaffold Generator Pluginは、まだ公開された直後らしく安定した動作をしていない点がみられました。

  1. モデルが存在する状態でgenerateを実行すると、Controllerが作成できない。
  2. script/generate ext_scaffold 実行時にmodelのカラムを指定した場合に、指定したデータ型で作成されない場合がある。

今回は時間が無かったため、各問題の解決方法まで調査できませんでした。
時間があるときに調査してみたいです。

ps. Dojoベースのscaffoldジェネレータとかあると便利そう。作ってみるか...

はてなダイアリーを試す。

はてな記法ソースコードの表示ができるようなので、試してみました。

Rubyのコードを貼り付け

出展:http://jp.rubyist.net/magazine/?0005-RubyOnRails
まずは、ActionControllerのクラスから

 require File.dirname(__FILE__) + '/../test_helper'
 require 'debate_controller'
 
 # Re-raise errors caught by the controller.
 class DebateController; def rescue_action(e) raise e end; end
 
 class DebateControllerTest < Test::Unit::TestCase
   def setup
     @controller = DebateController.new
     @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
   end
 
   # Replace this with your real tests.
   def test_truth
     assert true
   end
 end

次は、YAML

 development:
   adapter: mysql
   database: rails_development
   host: localhost
   username: root
   password: 
 
 test:
   adapter: mysql
   database: rails_test
   host: localhost
   username: root
   password:
 
 production:
   adapter: mysql
   database: rails_production
   host: localhost
   username: root
   password: 

Javascript

出展:http://extjs.com/deploy/dev/examples/grid/array-grid.js

/*
 * Ext JS Library 2.0.1
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 * 
 * http://extjs.com/license
 */

Ext.onReady(function(){

    Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

    var myData = [
        ['3m Co',71.72,0.02,0.03,'9/1 12:00am'],
        ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'],
        ['Altria Group Inc',83.81,0.28,0.34,'9/1 12:00am'],
        ['American Express Company',52.55,0.01,0.02,'9/1 12:00am'],
        ['American International Group, Inc.',64.13,0.31,0.49,'9/1 12:00am'],
        ['AT&T Inc.',31.61,-0.48,-1.54,'9/1 12:00am'],
        ['Boeing Co.',75.43,0.53,0.71,'9/1 12:00am'],
        ['Caterpillar Inc.',67.27,0.92,1.39,'9/1 12:00am'],
        ['Citigroup, Inc.',49.37,0.02,0.04,'9/1 12:00am'],
        ['E.I. du Pont de Nemours and Company',40.48,0.51,1.28,'9/1 12:00am'],
        ['Exxon Mobil Corp',68.1,-0.43,-0.64,'9/1 12:00am'],
        ['General Electric Company',34.14,-0.08,-0.23,'9/1 12:00am'],
        ['General Motors Corporation',30.27,1.09,3.74,'9/1 12:00am'],
        ['Hewlett-Packard Co.',36.53,-0.03,-0.08,'9/1 12:00am'],
        ['Honeywell Intl Inc',38.77,0.05,0.13,'9/1 12:00am'],
        ['Intel Corporation',19.88,0.31,1.58,'9/1 12:00am'],
        ['International Business Machines',81.41,0.44,0.54,'9/1 12:00am'],
        ['Johnson & Johnson',64.72,0.06,0.09,'9/1 12:00am'],
        ['JP Morgan & Chase & Co',45.73,0.07,0.15,'9/1 12:00am'],
        ['McDonald\'s Corporation',36.76,0.86,2.40,'9/1 12:00am'],
        ['Merck & Co., Inc.',40.96,0.41,1.01,'9/1 12:00am'],
        ['Microsoft Corporation',25.84,0.14,0.54,'9/1 12:00am'],
        ['Pfizer Inc',27.96,0.4,1.45,'9/1 12:00am'],
        ['The Coca-Cola Company',45.07,0.26,0.58,'9/1 12:00am'],
        ['The Home Depot, Inc.',34.64,0.35,1.02,'9/1 12:00am'],
        ['The Procter & Gamble Company',61.91,0.01,0.02,'9/1 12:00am'],
        ['United Technologies Corporation',63.26,0.55,0.88,'9/1 12:00am'],
        ['Verizon Communications',35.57,0.39,1.11,'9/1 12:00am'],
        ['Wal-Mart Stores, Inc.',45.45,0.73,1.63,'9/1 12:00am']
    ];

    // example of custom renderer function
    function change(val){
        if(val > 0){
            return '<span style="color:green;">' + val + '</span>';
        }else if(val < 0){
            return '<span style="color:red;">' + val + '</span>';
        }
        return val;
    }

    // example of custom renderer function
    function pctChange(val){
        if(val > 0){
            return '<span style="color:green;">' + val + '%</span>';
        }else if(val < 0){
            return '<span style="color:red;">' + val + '%</span>';
        }
        return val;
    }

    // create the data store
    var store = new Ext.data.SimpleStore({
        fields: [
           {name: 'company'},
           {name: 'price', type: 'float'},
           {name: 'change', type: 'float'},
           {name: 'pctChange', type: 'float'},
           {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
        ]
    });
    store.loadData(myData);

    // create the Grid
    var grid = new Ext.grid.GridPanel({
        store: store,
        columns: [
            {id:'company',header: "Company", width: 160, sortable: true, dataIndex: 'company'},
            {header: "Price", width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'},
            {header: "Change", width: 75, sortable: true, renderer: change, dataIndex: 'change'},
            {header: "% Change", width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'},
            {header: "Last Updated", width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
        ],
        stripeRows: true,
        autoExpandColumn: 'company',
        height:350,
        width:600,
        title:'Array Grid'
    });

    grid.render('grid-example');

    grid.getSelectionModel().selectFirstRow();
});

結論...

結構使えるね。

# Thanks Rubyist Magazine & Extjs.com!

Ubuntu 7.04から7.10へ移行。

もう2、3ヶ月で8.xが出そうな頃ですが、ようやく7.04から7.10へバージョンアップしました。
インストール先メディアがUSBメモリ/4GBと容量が限られているため、通常のアップデート手順では容量不足のために早々に断念。データ移行を行うことにしました.
必要なデータのバックアップを取ってUSBメモリに新規にインストール、その後データパーティションにバックアップを復元して移行完了しました。
参考:Desktop CD をUSBメモリにインストールする方法
今回はUSBメモリパーティションを変更しなかったため、上記ページの手順のうち、「5. fdiskコマンドでパーティションを切る。」手順は省略しました。

バージョンアップ後、アップデートマネージャーでシステムを更新すると、'cupsys: サブプロセス post-installation script はエラー終了ステータス 127 を返しました'のエラーが発生しました。

ググると7.10からAppArmorなるセキュリティ層が導入され、cupsがエラーを起こすとのこと。
参考:Ubuntu 7.10 リリースノート その他の既知の問題 - AppArmorと印刷
以下のコマンドを実行して解決しました。

$ sudo aa-complain cupsd

その後、アップデートマネージャでシステム更新。今度は問題なく更新されました。
apt-get で必要なパッケージをインストールしてアップデート作業終了。

上記手順、アップデートというよりデータ移行なのですが、容量の少ないUSBメモリでバージョンアップする際には有効な方法でしょう。

ということで、Hello Ubuntu 7.10!

ubuntu 7.10にmecab 0.97をインストール

ubuntu 7.10にmecab 0.97とIPA辞書をソースビルドを行いインストールした手順です。
配布元のインストールガイド UNIX項を参考にインストールしました。
参考:MeCab: Yet Another Part-of-Speech and Morphological Analyzer#インストール

1. 必要なパッケージのインストール

ubuntu 7.10をUSBメモリにインストール直後の開発用パッケージをほとんどインストールしていない環境にmecabをインストールしています。
この環境では、makeを実行した時にエラーが発生します。
あらかじめ、gawkとbuild-essentialの2つのパッケージをインストールします。

$ sudo apt-get install gawk
$ sudo apt-get install build-essential

2. mecab 0.97インストール

ubuntuの日本語環境がUTF-8のため、キャラクタセットを'utf-8'でインストールします。

$ wget http://jaist.dl.sourceforge.net/sourceforge/mecab/mecab-0.97.tar.gz
$ tar -xzf mecab-0.97.tar.gz
$ cd mecab-0.97
$ ./configure --with-charset=utf8
$ make
$ make check
$ sudo make install

3. IPA 辞書インストール

mecabに引き続き、IPA辞書をインストールします。

$ wget http://jaist.dl.sourceforge.net/sourceforge/mecab/mecab-ipadic-2.7.0-20070801.tar.gz
$ tar -xzf mecab-ipadic-2.7.0-20070801.tar.gz
$ cd mecab-ipadic-2.7.0-20070801/
$ make
$ sudo make install

4. /etc/ld.so.confファイルの編集

mecabをインストールした状態では、'libmecab.so.1'が見つからない旨のエラーが発生します。

$ mecab
mecab: error while loading shared libraries: libmecab.so.1: cannot open shared object file: No such file or directory

'libmecab.so.1'は、'/usr/local/lib/libmecab.so.1'にインストールされていますが、ubuntu標準の設定では、'/usr/local/lib/'配下のライブラリが読み込まれないようです。
そこで、'/etc/ld.co.conf'ファイルに'/usr/local/lib'を追加し、ライブラリを読み込まれるようにします.

$ sudo vi /etc/ld.so.conf
/usr/local/lib # この一行を追加

追加後、ldconfigを実行して、ライブラリ読み込みパスを更新します。

$ sudo ldconfig

5. mecabの実行

IPA辞書をインストール後、mecabを実行、

$ mecab

と入力待ちになります。ここで適当な文章を入力すると、

$ mecab
はじめまして、mecab
はじめまして 感動詞,*,*,*,*,*,はじめまして,ハジメマシテ,ハジメマシテ
、 記号,読点,*,*,*,*,、,、,、
mecab 名詞,固有名詞,組織,*,*,*,*
EOS

以上の手順で、mecab のインストールは、終了しました。

あとは、この辺のことを試していこうと思います。詳細は後日で。

MacPortsを使ったRuby/Railsのインストール

MacPortsを使ったRubyRuby on Railsのインストール記録です。
Rubyをインストールする場合、Ruby本家からソースコードをダウンロードしてコンパイルする方法が開発者らしいと思ったのですが、自宅Macなので時間をかけたくなかったため、安直な方法を選びました。
MacPortsのインストールとRuby本体、RubyGemsRuby on Railsをインストールすることを目指します。

MacPortsのインストール

MacPortsのインストールははこべにっき#さんの「MacPortsでステキなUNIXツールをインストール」を参考にさせていただきました。

MacPortインストールの準備

MacPortsのインストールにはXcode Toolsが必要です。
Xcode Toolsは、Max OS X付属のインストールディスクを使用してインストールするか、Apple Developper Connectionのサイトからダウンロード(要会員登録)してインストールします。2007/09/02現在、Xcodeの最新版は、2.4.1です。

MacPortsのインストール

MacPortsは、http://www.macports.org/からダウンロードできます。
2007/09/02現在、MacPortsの最新版は、1.5です。
Mac OS X 10.4の場合、MacPorts-1.5.0-10.4.dmgをダウンロードしてインストールします。

環境変数の設定

MacPortsは、/opt/local配下にインストールされます。PATH変数に"/opt/local/bin"と"/opt/local/sbin/"、MANPATH変数に"/opt/local/man/"を追加します。
設定は.bashrcあたりに以下の設定を記述します。

export PATH=/opt/local/bin:/opt/local/sbin/:$PATH
export MANPATH=/opt/local/man:$MANPATH

ここまででMacPortsのインストールは終了です。

Rubyのインストール

MacPortsのインストールが終了したら、本題のRubyRailsのインストールを行います。
まずは、Ruby本体のインストールから。
MacPortsは、通常依存関係があるソフトウェアやライブラリがあわせてインストールされるため、下記コマンドだけでRubyのインストールが実行されます。とっても簡単。

$ sudo port install ruby

MacPortsインストーラはソフトウェアをインストールする際にソースコードのダウンロード、コンパイル、インストールを行っているようなので、Rubyの様な多くのライブラリに依存しているソフトウェアのインストールには時間がかかります。
インストール実行中のログを眺めていると、Rubyが必要としているライブラリが見えてきてちょっとしたお勉強になりますね。

インストール終了後、"ruby -v"を実行すると、バージョン情報が表示されます。

$ ruby -v
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.1]

ruby 1.8.6」と表示されれば、ちゃんとインストールがされています。
Rubyのバージョンが「ruby 1.8.6 (2007-03-13 patchlevel 0) 」ということなので、Ruby本家の最新版(1.8.6-p36)からすると少し古いバージョンがインストールされています。

RubyGemsのインストール

続いて、RubyGemsのインストールです。

$ sudo port install rb-rubygems

Railsのインストール

最後に、Railsのインストールです。

$ sudo port install rb-rails

後は、必要に応じてRubyのライブラリやSQLite/MySQLあたりをインストールすればよいでしょう。
MySQLのインストールやRailsの開発環境構築についてはいずれ書きたいかな。