newbie Q: conditional object creation

P

Paul Van Delst

Hello,

The subject line may be confusing as I don't know the correct terminology, so apologies in
advance.

I'm want to be able to create objects, but I want the object creation to only proceed if
the values passed to the init method are in a valid list. E.g.:

class MyObj
VALID_NAMES=['bananas','dog','water']
attr_reader :name, :value
def initialize(name,value)
i=VALID_NAMES.index(name)
if i then
@name,@value=name,value
else
@name,@value=nil
end
end
end

This sorta does what I want, but looks clunky, ugly and quite un-ruby-ish. Is there a
better way (idiom?) to achieve this sort of thing? I.e. is there a way to make the init
method not create even an "empty" object (as happens above) based on the valid names list?

Thanks for any help. (I have about 4 days of Ruby experience so please be kind... :eek:)

cheers,

paulv
 
M

Marcin Mielżyński

Paul said:
Hello,

The subject line may be confusing as I don't know the correct
terminology, so apologies in advance.

I'm want to be able to create objects, but I want the object creation to
only proceed if the values passed to the init method are in a valid
list. E.g.:

class MyObj
VALID_NAMES=['bananas','dog','water']
attr_reader :name, :value
def initialize(name,value)
i=VALID_NAMES.index(name)
if i then
@name,@value=name,value
else
@name,@value=nil
end
end
end

This sorta does what I want, but looks clunky, ugly and quite
un-ruby-ish. Is there a better way (idiom?) to achieve this sort of

just:

@name,@value=name,value if VALID_NAMES.index(name)
thing? I.e. is there a way to make the init method not create even an
"empty" object (as happens above) based on the valid names list?

any not initialized instance variable will return null, so just don't
bother ;D

lopex
 
P

Paul Van Delst

Marcin said:
Paul said:
Hello,

The subject line may be confusing as I don't know the correct
terminology, so apologies in advance.

I'm want to be able to create objects, but I want the object creation
to only proceed if the values passed to the init method are in a valid
list. E.g.:

class MyObj
VALID_NAMES=['bananas','dog','water']
attr_reader :name, :value
def initialize(name,value)
i=VALID_NAMES.index(name)
if i then
@name,@value=name,value
else
@name,@value=nil
end
end
end

This sorta does what I want, but looks clunky, ugly and quite
un-ruby-ish. Is there a better way (idiom?) to achieve this sort of

just:

@name,@value=name,value if VALID_NAMES.index(name)

Excellent! Thanks very much.

cheers,

paulv
 
D

Daniel Schierbeck

Paul said:
I'm want to be able to create objects, but I want the object creation to
only proceed if the values passed to the init method are in a valid
list. E.g.:

class MyObj
VALID_NAMES=['bananas','dog','water']
attr_reader :name, :value
def initialize(name,value)
i=VALID_NAMES.index(name)
if i then
@name,@value=name,value
else
@name,@value=nil
end
end
end

This sorta does what I want, but looks clunky, ugly and quite
un-ruby-ish. Is there a better way (idiom?) to achieve this sort of
thing? I.e. is there a way to make the init method not create even an
"empty" object (as happens above) based on the valid names list?

class MyObj
VALID_NAMES = %w{bananas dog water} # array of strings

# go into the metaclass
class << self
alias_method :__new__, :new

def new(name, value)
raise unless VALID_NAMES.include? name
__new__(name, value)
end
end

def initialize(name, value)
@name, @value = name, value
end
end

This will raise an exception when MyObj.new is called with an invalid
name. You should read up on metaclasses if you haven't already[1].

If you just want MyObj.new to return nil when supplied with an invalid
argument, this will do the trick:

def new(name, value)
__new__(name, value) if VALID_NAMES.include? name
end


Cheers,
Daniel

[1] http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
 
R

Robert Klemme

Daniel said:
Paul said:
I'm want to be able to create objects, but I want the object creation
to only proceed if the values passed to the init method are in a valid
list. E.g.:

class MyObj
VALID_NAMES=['bananas','dog','water']
attr_reader :name, :value
def initialize(name,value)
i=VALID_NAMES.index(name)
if i then
@name,@value=name,value
else
@name,@value=nil
end
end
end

This sorta does what I want, but looks clunky, ugly and quite
un-ruby-ish. Is there a better way (idiom?) to achieve this sort of
thing? I.e. is there a way to make the init method not create even an
"empty" object (as happens above) based on the valid names list?

class MyObj
VALID_NAMES = %w{bananas dog water} # array of strings

# go into the metaclass
class << self
alias_method :__new__, :new

def new(name, value)
raise unless VALID_NAMES.include? name
__new__(name, value)
end
end

def initialize(name, value)
@name, @value = name, value
end
end

This will raise an exception when MyObj.new is called with an invalid
name. You should read up on metaclasses if you haven't already[1].

If you just want MyObj.new to return nil when supplied with an invalid
argument, this will do the trick:

def new(name, value)
__new__(name, value) if VALID_NAMES.include? name
end


Cheers,
Daniel

[1] http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html

The same effect can be achieved in two other way that do not involve
meta classes:

1. make initialize throw an exception. Although the instance will be
created, nobody ever gets to see it (unless initialize stores self
somewhere).

class MyClass
VALID_NAMES=['bananas','dog','water']

attr_reader :name, :value

def initialize(name, value)
raise ArgumentError, "Invalid name: #{name}" unless
VALID_NAMES.include? name
@name = name
@value = value
end
end


2. add a class method instead of aliasing new.

class MyClass
VALID_NAMES=['bananas','dog','water']

attr_reader :name, :value

def self.create(name, value)
raise ArgumentError, "Invalid name: #{name}" unless
VALID_NAMES.include? name
new name, value
end

def initialize(name, value)
@name = name
@value = value
end
end


I'd probably favor approach 1 as it is more robust (you cannot forget to
call "create" as in the second approach).

Kind regards

robert
 
P

Paul Van Delst

Robert said:
Daniel Schierbeck wrote:

[excellent code examples elided]

Beautiful. Thanks much to both posters. Especially for the exception handling examples.
Much appreicated.

cheers,

paulv
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top