#editor #sublime #textmate #textmate

最近#textmateのTwitterタグでたまたまsublimetextを目にするんですが、Textmate2の代わりになれるかで議論されているようです。

一応入れてみたのですが、最初の印象というえば

  • 速い。163MBのcsvファイルをたった数秒で開きました。Textmateはもう何分間固まったんです。
  • モダンなインターフェイス。アニメーションとか、縦二画面ができるなどTextmateよりは確実に進化しています。
  • command + Tでファイルを開くのが速いしスムーズ
  • コードの比較機能が便利
  • ShiftJISなどの日本語文字コードは依然サポートされない

このへんにいいTipsを紹介してくれる記事があります。 http://net.tutsplus.com/tutorials/tools-and-tips/sublime-text-2-tips-and-tricks/

#ruby #metaprogramming

下記ソースコードに英語コメントで書いてますが、日本語で解釈してみます。

定義

まずinstance_evalはObjectのインスタンスメソッドです。なので全てのオブジェクトがこのinstance_evalを呼び出すことができます。instance_evalはブロックを受け取ります。

機能

  • 呼び出すオブジェクト(receiver)のスコープ内でブロックを評価(実行)する、つまりreceiverのプライベートメソッドやインスタンス変数にアクセスできること
  • 現在スコープの変数などBindingにアクセスできる

サンプルコードではPersonというclassに@nameのインスタンス変数、credit_cardというプライベートメソッドを定義しました。

someoneはPersonのインスタンスで、someoneからinstance_evalをコールすると、そのブロック内ではselfがsomeoneとなり、@nameやcredit_cardにアクセスできます。

さらにinstance_evalの外で定義した変数outter_valにもアクセスできます。

Real-life example

さて、原理は分かったとして、実際はどのように使われているのか、Railsのソースコードでgrepしてこんなコードが見つかりました。

in ActiveRecord

まずマイグレーションでまあよく使うchange_columnメソッドのソースコードです。

definition[column_name]がinstance_evalを呼び出したのですが、definition[column_name]はActiveRecord::ConnectionAdapters::ColumnDefinitionクラスのオブジェクトで、ColumnDefinitionの実態はStructを継承し、カラムの名前、種類、limit、precision、デフォルト値などの情報が格納されているオブジェクトです。

definition[column_name].instance_evalを使うことで、そのオブジェクト(テーブルカラム)の種類、limit、default値とnull可否を変更することが分かりましたね。 optionsはinstance_evalブロックの外の変数ですが、普通にアクセスできます。

in ActiveSupport

上記ActiveRecordのコードが分かればここは分かりやすいと思います。 実際の意味はさておき、instance_evalを利用して@marshal_with_utc_coercionというインスタンス変数が定義されていれば、それを削除する使い方ですね。

まとめ

instance_evalを使ってオブジェクトの構造(インスタンス変数の値の変更、インスタンス変数の追加削除など)を実行時に変更するのが使い道、というのが個人的な感想です。

最後に注記:この記事はRails3.1.0のソースコードを使ってます。

現象

SQL# Plusで出力したcsvファイルなどをExcelで開いたら日本語の部分が全部文字化けになっちゃいました。

原因

出力ファイルはUTF8ですが、ExcelではShiftJisじゃないと文字化けするらしいです。

解決策

秀丸などのエディターで出力ファイルを開き、エンコードUTF8で名前をつけて保存。 そうすればExcelで開くときに文字化けは治る。

#ruby #metaprogramming

Rubyのクラスにメソッドを追加する方法です。ここではStringを例にしました。

solution_1.rbはOpen Classというテクニックです。classキーワードで既存クラスを定義するときは上書きするのではなく、拡張した感じで、他のStringメソッドに影響がないです。

solution_2.rbはただclass_evalの理論を試したかっただけです。class_evalはスコープ内のselfcurrent classをreceiverのStringクラスに変更するんです。だからclass_evalのブロック内に定義したメソッドはStringのinstance methodになります。

solution_mistake.rbはStringのクラスメソッド(Singleton methods)を定義したもので、instance methodではないです。

最近「Metaprogramming Ruby」という本を読んでます。よくわからなかったこととか、曖昧だっだことがすっきりした感じです。お勧めです!

#linux

コメントでいろいろ書いてますが、root権限付与のところは多分個人の場合はそのままvisudoにユーザ名を追記して、会社の場合はグループを変更したほうが良さそうです。

# HOW TO CREATE USER AND GROUP, GRANT ROOT PRIVILEGE

## PART1 CREATE USER
# assume user1,user2,user3 is already created
# and they are in wheel group, which can execute as root
# and here we're creating a new user named:new_user

# create new user
useradd new_user
# set password for it, in the prompt
passwd new_user


# you can now login as new_user
# but when you run sudo you may get this error
new_user is not in the sudoers file.  This incident will be reported.
# so you need to set the privilege to new_user

## PART2 GRANT SUDO PRIVILEGE
## 1. BY CHANGE USER GROUP
$ visudo
############ in visudo ############
## Allows people in group wheel to run all commands
# %wheel        ALL=(ALL)       ALL
## Same thing without a password
%wheel  ALL=(ALL)       NOPASSWD: ALL
############ in visudo ############
# It means people in wheel group can run all commands, without password
# Below we're adding the new user called new_user to the wheel group.

# list users and user id, group id, home directory, login shell, etc.
$ cat /etc/passwd
...
wheel:x:10:root,user1,user2,user3
...

$ id -a [user name]
uid=503(user3) gid=503(init_group) 所属グループ=503(init_group),10(wheel)
$ usermod -g init_group -G init_group,wheel new_user
$ id -a new_user
uid=506(new_user) gid=503(init_group) 所属グループ=503(init_group),10(wheel)

## 2. BY ADD USER TO sudoers FILE.
$ visudo
############ in visudo ############
new_user          ALL=(ALL) NOPASSWD: ALL
############ in visudo ############

## some handy commands
# show user list
$ cut -d: -f1 /etc/passwd
root
bin
daemon
adm
...

# TODO
# what is the difference between -g(initial_group) and -G(group)

# Reference
# (ENG) http://superuser.com/questions/120340/user-not-in-the-sudoers-file-this-incident-will-be-reported
# (JPN) http://kazmax.zpp.jp/linux_beginner/usermod.html