Forcing attr_writer to a type?

  • Thread starter Robert William Vesterman
  • Start date
R

Robert William Vesterman

Is there a way to force an attr_writer to store its input as a certain
type?

For example, I'm reading records out of a text file, splitting them
into fields, and setting various members of a class from those fields.
Some of the fields are intended to be floating point numbers. But
since they are read as strings, if I do something like:

attr_writer :blah

I'm stuck with them as strings. Obviously I can get around this by
changing it to a float before calling the attr_writer:

bling.blah = input.to_f

But rather than put a bunch of "to_f" calls all over the place, it
seems that it would be easier, cleaner, and safer to let me do
something along the lines of:

attr_writer :blah { |input| input.to_f }

I understand that's not valid syntax - what I mean by it is "when
something tries to write to blah to a value, set blah to the results
of calling to_f on the value".

I also understand that I can manually write a "def blah=", but
attr_writer is much more succinct.

Is there a nice way to do that?

Thanks in advance for any help.

Bob Vesterman.
 
T

Timothy Hunter

Robert said:
I also understand that I can manually write a "def blah=", but
attr_writer is much more succinct.

Is there a nice way to do that?

I think "def blah-" _is_ the nice way.

def blah=(foo)
@blah = foo.to_i
end

Or even

def blah=(foo)
begin
@blah = Integer(foo)
rescue ArgumentError
raise "Can't convert #{foo} to integer"
end
end
 
T

Trans

I used to have attr caster methods:

attr_writer :a => :to_f

Worked pretty well from time to time. But did not seem generally useful
enough in the long run. In fact I prefer specifying default values usng
the hash variation instead. So I moved casting to a seperate method and
it takes either a symbol/string or a proc too:

cast_writer :w => :to_f
cast_writer :w => proc { |x| x.to_f }

Yet lately George Moschovitis' code and the new YAML shcema Kwalify,
along with my pet shorthand for #attr, has me thinking of eleborating
on something more like this:

attr :r, :w!, :a= # my shorthand

attr :r => { :default=>10, :cast=>:to_f },
:w! => { :cast=>:to_f }

Will have all this panned out soon. Nitro is already doing some of
this, albeit in a slightly different format.

Oh, If you didn't already know, the trick to creating these is defining
them in class Module. ie.

class Module
def attr(*args)
...
class_eval { def ...

Now you make your own :)

HTH,
T.
 
D

Daniel Schierbeck

Is it even possible to write a method that acts like

attr_writer :blah { |input| input.to_f }

I've tried a bit, but I've come up short so far.


Cheers,
Daniel
 
M

Malte Milatz

Daniel said:
Is it even possible to write a method that acts like

attr_writer :blah { |input| input.to_f }

Here is my try, which seems to work:

class Class
def attr_accessor(attr)
attr = attr.to_str if attr.respond_to? :to_str
attr = attr.id2name if attr.respond_to? :id2name
attr_reader(attr)
if not block_given?
attr_writer(attr)
else
define_method(attr + '=') do |value|
instance_variable_set('@' + attr, yield(value))
end
end
end
end

class Test
attr_accessor :blah do |x| x.to_f end
attr_accessor :bla
end

t = Test.new
t.bla = 10
p t.bla
t.blah = 10
p t.blah

# Malte
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top