2013-06-03 4 views
9

私はOpenStructのサブクラス(またはそのことについては、クラス)、またはハッシュは、カスタム例外の場合が発生しますように、それを作る方法を把握しようとしている内に存在しない属性にアクセス私は設定されていない属性にアクセスしようとしています。私はこれを行うにはdefine_methodmethod_missingを得ることができなかったので、私はそれがどのようにRubyで行われるべきであるかわからない。レイズ例外OpenStruct

はここに例を示します

class Hash 
    # if trying to access key: 
    # 1) key exists, return key 
    # 2) key doesn't exist, raise exception 
end 

編集:例外を発生させてはならない存在属性

class Request < OpenStruct... 

request = Request.new 

begin 
    request.non_existent_attr 
rescue CustomError... 

私はそれがこのようなものでなければならないであろうと想像できます。私が探している機能は、属性に自由にアクセスできるだけなので、存在しない場合はカスタム例外が発生します。

答えて

0

私は私が必要とするまさに行い、この溶液を用いて行った:あなたの場合は

class Request < Hash 
    class RequestError < StandardError; end 
    class MissingAttributeError < RequestError; end 

    def initialize(hash) 
    hash.each do |key, value| 
     self[key] = value 
    end 
    end 

    def [](key) 
    unless self.include?(key) 
     raise MissingAttributeError.new("Attribute '#{key}' not found in request") 
    end 

    super 
    end 
end 
+1

ここで '[]'を上書きするのではなく、 'fetch'メソッドを使うことができます。 http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-fetch –

1

ルビーでは、object.horrayと書くときはいつも、メッセージhorrayがオブジェクトobjectに送られます。これは値を返します。すべてのhorrayはメッセージです。オブジェクトがこのメッセージに応答しない場合、この名前の属性を持たないオブジェクトと、この名前のメソッドを持たないオブジェクトを区別できません。

だから、あなたは何のメソッドがタイプミスを持つことはできませんと仮定しますしない限り、あなたがしたいものを行うことはできません。あなたは新しいメンバーを設定するときに、メンバーが有効であるかどうかを確認するためにrespond_to?を使用できるように

+0

を呼び出された場合にはNoMethodErrorが発生します不変オブジェクトを取得するには

hash = { a: 2, b: 3 } Struct.new(*hash.keys).new(*hash.values).freeze 

のようなものを使用初期化時以外は新しいメンバーを作ることができなくなります。 – dbenhur

+0

、。 – fotanus

6

OpenStructは、オブジェクトのシングルトンアクセサメソッドを定義します。実際には、おそらくmethod_missingで定義されていないメソッドをキャプチャし、setterメソッド名でない限りエラーをスローすることができます。その場合はsuperに渡します。

class WhinyOpenStruct < OpenStruct 
    def method_missing(meth, *args) 
    raise NoMemberError, "no #{meth} member set yet" unless meth.to_s.end_with?('=') 
    super 
    end 
end 
0

それは残忍だが、あなたはエラーを発生させるためにnew_ostruct_memberメソッドを上書きすることができます:

require 'ostruct' 

class CustomError < StandardError; end 
os = OpenStruct.new({:a=>1, :b=>1}) 
def os.new_ostruct_member(name) #just wrecking a single instance 
    raise CustomError, "non-existing key #{name} called" 
end 

p os.a=3 
p os.c=4 #=>non-existing key c called (CustomError) 
+0

@Serializeが存在しない属性を読んだ上でエラーを発生させるために望んでいることの例を削除するあなたは、TY正しい@dbenhur –

6

単に、厳格なハッシュを必要とする:

class StrictHash < Hash 
    alias [] fetch 
end 

期待どおりに動作します:

hash = StrictHash[foo: "bar"] 

hash[:foo] 
# => "bar" 

hash[:qux] 
# stricthash.rb:7:in `fetch': key not found: :qux (KeyError) 
#   from stricthash.rb:7:in `<main>' 
+1

私がいた「ドットのアクセス」を探していた何を、アクセスをハッシュません。 +1エレガンスのために、しかし。 – Seralize

1

私はあなたがOpenStructでこれを行う場合は、予期しない方法が

関連する問題