[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

newbie Q: conditional object creation

Paul Van Delst

7/5/2006 7:14:00 PM

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... :o)

cheers,

paulv

--
Paul van Delst Ride lots.
CIMSS @ NOAA/NCEP/EMC Eddy Merckx
5 Answers

Marcin Mielzynski

7/5/2006 8:35:00 PM

0

Paul Van Delst wrote:
> 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

Paul Van Delst

7/5/2006 8:52:00 PM

0

Marcin MielżyÅ?ski wrote:
> Paul Van Delst wrote:
>
>> 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

--
Paul van Delst Ride lots.
CIMSS @ NOAA/NCEP/EMC Eddy Merckx

Daniel Schierbeck

7/5/2006 11:22:00 PM

0

Paul Van Delst wrote:
> 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/seeingMetaclassesCl...

Robert Klemme

7/6/2006 9:26:00 AM

0

Daniel Schierbeck wrote:
> Paul Van Delst wrote:
>> 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/seeingMetaclassesCl...

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

Paul Van Delst

7/6/2006 2:06:00 PM

0

Robert Klemme wrote:
> Daniel Schierbeck wrote:
>

[excellent code examples elided]

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

cheers,

paulv

--
Paul van Delst Ride lots.
CIMSS @ NOAA/NCEP/EMC Eddy Merckx