2009-06-13 21 views
0

私は著者のクラスを持っている:to_sの定義Rubyがto_sを自動的に実行しないのはなぜですか?

class Author < ActiveRecord::Base 
    def to_s 
    name 
    end 
end 

は私がputs Author.firstを行うことができますが、ないputs Author.first.rjust(10):Rubyが自動的に文字列メソッドの前にto_sをしようとした場合

NoMethodError: undefined method `rjust' for #<Author:0x21eb5d4> 

は、それは良いことではないだろうこのようなケース?この現象を起こす方法はありますか?

答えて

18

まずは、いいえ、そうではありません。私はルビーがちょうど "ちょっと、たぶん、これは文字列のメソッドです、私は実行した後にそれを実行することができるかどうかは、to_s"任意のオブジェクト上で見てみましょうしたくないです。あなたがしたいことには2つの解決策があります:

Authorインスタンスでは、誰かが持っていないメソッドを呼び出しても、Stringの場合は文字列ではないものにrjustは "最初to_sを呼び出すことを意味する必要があり、その後、:魔法「あなたが言いたい場合は

class Author < ActiveRecord::Base 
    def to_s 
    name 
    end 

    def method_missing(s, *a) 
    x = to_s 
    if x.respond_to? s then 
     return x.send(s, *a) 
    else 
     super 
    end 
    end 
end 

これを行うには、":to_sを呼び出す

class Object 
    def rjust(*a) 
    to_s.rjust(*a) 
    end 
end 

(REPE所望の他の方法で、これにより、86.rjust(10)のようなことができることに注意してください。

+3

'それsuper.method_missing(sが、* A)'間違っています。同じ引数を持つメソッドのスーパークラスのバージョンを呼び出す 'super'だけでなければなりません。 Rubyでは、スーパーは受信者ではなくメソッドのように動作します。 – Chuck

+0

@チャック:ありがとう、固定。私は投稿する前に自分のコードをテストしましたが、 "super"のアクションが例外をスローすることになっているので、だまされました - これは、この特定のケースでは、誤った構文が期待通りに機能したことを意味します。 (rubyはsuperの戻り値で "method_missing"を呼び出そうとしないので) –

2

Rubyがこのような場合に文字列メソッドの前に自動的に_しようとしたほうが良いのではないでしょうか?いいえ、いいのかどうかは味わえませんか?

「ほとんどの場合、私が意味することをする」という言葉を求めて、滑りやすい斜面を向いています。多くの場合、それは意味をなさないかもしれませんが、それはエッジの周りのものを汚すことに拘束されます。あなたの場合、rjustと言う人は、Author(またはそのスーパークラスの1つ)で定義されたメソッドではありません。

1

実は...これまで漠然と似ただろう方法があります:to_str

しかし、それはまだ、この特定のケースのために暗黙的に呼び出されることはないが。 Rubyでto_strメソッドが存在することは、「通常Stringをパラメータとしてとるメソッドは、to_strメソッドを呼び出すことで、このオブジェクトを暗黙的にこのオブジェクトをStringに変換することができます。標準ライブラリのほとんどのメソッドは、このテクニックを使用してStringを強制しようとします。多くのサードパーティライブラリも同様です。

しかし、あなたが与えた例では、Rubyが未処理のメッセージがStringのようなものであり、変換していることを検出することは絶対に不適切です。これは、多くの非文字列関連コード、特にそこにあるコードのうち、あらゆる種類のエラー、バグ、および一般的な誤動作を招くでしょう。通常の欠落メソッド動作に依存しています。

関連する問題