[Facets] Add a Module#attr_validator method

  • Thread starter Daniel Schierbeck
  • Start date
D

Daniel Schierbeck

I couldn't find a Facets mailing list, and I know the developers use
this list, so therefore I send my proposal here.

I'd like to see the addition of an attribute validator, i.e. a setter
that checks to see if a block returns true when called with the new
value as its only argument. Without further ado, I hereby present
Module#attr_validator:

class Module
def attr_validator(*symbols, &validator)
symbols.each do |symbol|
define_method "#{symbol}=" do |val|
unless validator.call(val)
raise ArgumentError, "Invalid value provided for #{symbol}"
end
instance_variable_set("@#{symbol}", val)
end
end
end
end

Use it, change it, polish it - it's yours.


Cheers,
Daniel Schierbeck
 
D

Daniel Schierbeck

Daniel said:
I couldn't find a Facets mailing list, and I know the developers use
this list, so therefore I send my proposal here.

I'd like to see the addition of an attribute validator, i.e. a setter
that checks to see if a block returns true when called with the new
value as its only argument. Without further ado, I hereby present
Module#attr_validator:

class Module
def attr_validator(*symbols, &validator)
symbols.each do |symbol|
define_method "#{symbol}=" do |val|
unless validator.call(val)
raise ArgumentError, "Invalid value provided for #{symbol}"
end
instance_variable_set("@#{symbol}", val)
end
end
end
end

Use it, change it, polish it - it's yours.


Cheers,
Daniel Schierbeck

Note that this of course only works when you actually *use* the setter
method, i.e. `@attr = val' will not validate `val'. Nor do I think it
should.


Cheers,
Daniel Schierbeck
 
T

Trans

Thanks Daniel, I'll give this some consideration.

A more interesting alternative that could soon come to pass is an
extension to Facets' annotation system. Right now one can easily do:

require 'facet/annotation'

class Foo
attr_accessor :x
ann :x, :validation => proc { |x| ... }
end

But this is nothing more than a note. For it to actually have any
effect one would have to manually utilize the note. With then next
version of annotation.rb I plan to add annotation hooks. By defining a
hook you can automatically have it do what you would like when a
particular annotation is define. For instance:

Annotation.annotation_action( :validation ) { |symbol, validator|
wrap_method( "#{symbol}=") { |target, x|
unless validator.call( x )
raise ArgumentError, "Invalid value provided for #{symbol}"
else
target.call(x)
end
}
}

Now when you make the above annotation it will automatically generate
the validating setter as you describe.

The only downside to this kind of thing at the moment is the lack of an
adequate AOP foundation built into Ruby.

But all that is down the road yet. In the mean time I will likely add
your method. Thanks.

T.

P.S. Using this list is fine, especially if you're interested in wider
input from the Ruby community. You can also email the Nitro list
--Facets is a key component of Nitro/Og. And of course you can always
email me directly.
 
A

ara.t.howard

Thanks Daniel, I'll give this some consideration.

A more interesting alternative that could soon come to pass is an
extension to Facets' annotation system. Right now one can easily do:

require 'facet/annotation'

class Foo
attr_accessor :x
ann :x, :validation => proc { |x| ... }
end

But this is nothing more than a note. For it to actually have any
effect one would have to manually utilize the note. With then next
version of annotation.rb I plan to add annotation hooks. By defining a
hook you can automatically have it do what you would like when a
particular annotation is define. For instance:

Annotation.annotation_action( :validation ) { |symbol, validator|
wrap_method( "#{symbol}=") { |target, x|
unless validator.call( x )
raise ArgumentError, "Invalid value provided for #{symbol}"
else
target.call(x)
end
}
}

Now when you make the above annotation it will automatically generate
the validating setter as you describe.

The only downside to this kind of thing at the moment is the lack of an
adequate AOP foundation built into Ruby.

But all that is down the road yet. In the mean time I will likely add
your method. Thanks.

T.

P.S. Using this list is fine, especially if you're interested in wider
input from the Ruby community. You can also email the Nitro list
--Facets is a key component of Nitro/Og. And of course you can always
email me directly.

fyi.

jib:~/eg/ruby/traits/traits-0.9.0 > irb
irb(main):001:0> require 'traits'
=> true
irb(main):002:0> trait :x, :validate => lambda{|x| Integer === x}
=> [["x", "x="]]
irb(main):003:0> x
=> nil
irb(main):004:0> x 42
=> 42
irb(main):005:0> x
=> 42
irb(main):006:0> x 42.0
ArgumentError: validation of <42.0> failed!
from (eval):98:in `x='
from (eval):91:in `each'
from (eval):91:in `x='
from (eval):3:in `send'
from (eval):3:in `x'
from (irb):6
from :0


steal what you like.

regards.

-a
 
D

Daniel Schierbeck

Trans said:
Thanks Daniel, I'll give this some consideration.

A more interesting alternative that could soon come to pass is an
extension to Facets' annotation system. Right now one can easily do:

require 'facet/annotation'

class Foo
attr_accessor :x
ann :x, :validation => proc { |x| ... }
end

But this is nothing more than a note. For it to actually have any
effect one would have to manually utilize the note. With then next
version of annotation.rb I plan to add annotation hooks. By defining a
hook you can automatically have it do what you would like when a
particular annotation is define. For instance:

Annotation.annotation_action( :validation ) { |symbol, validator|
wrap_method( "#{symbol}=") { |target, x|
unless validator.call( x )
raise ArgumentError, "Invalid value provided for #{symbol}"
else
target.call(x)
end
}
}

Now when you make the above annotation it will automatically generate
the validating setter as you describe.

The only downside to this kind of thing at the moment is the lack of an
adequate AOP foundation built into Ruby.

But all that is down the road yet. In the mean time I will likely add
your method. Thanks.

T.

P.S. Using this list is fine, especially if you're interested in wider
input from the Ruby community. You can also email the Nitro list
--Facets is a key component of Nitro/Og. And of course you can always
email me directly.

Thanks for considering my idea. Personally, I like to think of a
validator as a setter/writer that adds value validation - annotations
just don't fit in my perception of that process, though what you
describe would be useful, too.

Cheers,
Daniel Schierbeck
 

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,997
Messages
2,570,241
Members
46,833
Latest member
BettyeMacf

Latest Threads

Top