Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raise exception when accessing attributes that doesn't exist in OpenStruct

I'm trying to figure out how to make it so that a subclass of OpenStruct (or any class for that matter), or hash, will raise a custom exception if I try to access an attribute that hasn't been set. I couldn't get define_method and method_missing to do this so I'm clueless how it should be done in Ruby.

Here's an example:

class Request < OpenStruct...

request = Request.new

begin
  request.non_existent_attr
rescue CustomError...

I could imagine it would have to be something like this:

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

Edit: Attributes that exist shouldn't raise an exception. The functionality I'm looking for is so that I can just access attributes freely and if it happens not to exist my custom exception will be raised.

like image 597
Seralize Avatar asked Jun 03 '13 20:06

Seralize


People also ask

What is OpenStruct in Ruby?

An OpenStruct is a data structure, similar to a Hash, that allows the definition of arbitrary attributes with their accompanying values. This is accomplished by using Ruby's metaprogramming to define methods on the class itself.

Why OpenStruct?

OpenStruct objects are useful when you need something to fit a certain method call interface (i.e. send in a duck-typed object responding to #name and #value ), or when you want to encapsulate the implementation details, but also want to avoid over-engineering the solution.

What is Ostruct in Ruby?

What is a Struct in Ruby? A struct is a built-in Ruby class, it's used to create new classes which produce value objects. A value object is used to store related attributes together.


2 Answers

I use something like

hash = { a: 2, b: 3 }

Struct.new(*hash.keys).new(*hash.values).freeze

to get an immutable object which will raise NoMethodError in case unexpected method is invoked

like image 103
vbyno Avatar answered Oct 28 '22 18:10

vbyno


If you need a strict hash, simply:

class StrictHash < Hash
  alias [] fetch
end

It works as expected:

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>'
like image 34
djanowski Avatar answered Oct 28 '22 16:10

djanowski