Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Depending on where you ask for a property, the library now returns th…

…e most expected value according to property status.

If you try to access a property from the answer object, Whois::Answer always returns the value if the property is defined, nil otherwise no matter if the property is not supported or undefined.

    a = Whois.query "google.ac"
    a.nameservers
    # => nil even if not supported

If you want a more granular level of response, you can access the underling parser implementation.

    a = Whois.query "google.ac"
    a.parser.nameservers
    # => PropertyNotSupported
  • Loading branch information...
commit d0ed5877d05cd9ccd288fbac52fd80ba65b943db 1 parent b191fcc
@weppos authored
View
14 CHANGELOG.rdoc
@@ -107,6 +107,20 @@
* CHANGED: All not supported properties now raise a PropertyNotSupported error instead of returning nil.
+* CHANGED: Depending on where you ask for a property, the library now returns the most expected value according to property status.
+ If you try to access a property from the answer object, Whois::Answer always returns the value if the property is defined,
+ nil otherwise no matter if the property is not supported or undefined.
+
+ a = Whois.query "google.ac"
+ a.nameservers
+ # => nil even if not supported
+
+ If you want a more granular level of response, you can access the underling parser implementation.
+
+ a = Whois.query "google.ac"
+ a.parser.nameservers
+ # => PropertyNotSupported
+
* CHANGED: Increased DEFAULT_TIMEOUT to 10 seconds
* REMOVED: Deprecated #supported? method
View
21 lib/whois/answer.rb
@@ -113,20 +113,17 @@ def parser
# Returns a Hash containing all supported properties for this Answer
# along with corresponding values.
def properties
- list = Parser.properties.inject([]) do |l,a|
- l.concat([a, send(a)]) if property_available?(a)
- l
- end
- Hash[*list]
+ hash = {}
+ Parser.properties.each { |property| hash[property] = send(property) }
+ hash
end
# Returns <tt>true</tt> if the <tt>property</tt> passed as symbol
# is supported by any available parser for this answer.
# See also <tt>Whois::Answer::Parser.supported?</tt>.
- def property_available?(property)
- parser.property_available?(property)
+ def property_supported?(property)
+ parser.property_supported?(property)
end
- alias :property_supported? :property_available?
protected
@@ -134,12 +131,16 @@ def property_available?(property)
# Delegates all method calls to the internal parser.
def method_missing(method, *args, &block)
if Parser.properties.include?(method)
- parser.send(method, *args, &block)
+ if property_supported?(method)
+ parser.send(method, *args, &block)
+ else
+ nil
+ end
else
super
end
end
-
+
end
end
View
7 lib/whois/answer/parser.rb
@@ -56,10 +56,9 @@ def parsers
# Returns <tt>true</tt> if the <tt>property</tt> passed as symbol
# is supported by any available parser.
# See also <tt>Whois::Answer::Parser::Base.supported?</tt>.
- def property_available?(property)
- parsers.any? { |parser| parser.property_available?(property) }
+ def property_supported?(property)
+ parsers.any? { |parser| parser.property_supported?(property) }
end
- alias :property_supported? :property_available?
private
@@ -88,7 +87,7 @@ def delegate_to_parsers(method, *args, &block)
elsif parser = select_parser(method)
parser.send(method, *args, &block)
- # The property is not supported not defined.
+ # The property is not supported nor defined.
else
raise PropertyNotAvailable, "Unable to find a parser for `#{method}'"
end
View
122 lib/whois/answer/parser/base.rb
@@ -37,44 +37,6 @@ class Parser
#
class Base
- attr_reader :part
-
-
- def initialize(part)
- @part = part
- end
-
- ::Whois::Answer::Parser.properties.each do |method|
- define_method(method) do
- raise PropertyNotImplemented, "You should overwrite this method."
- end
- end
-
- # This is an internal method primaly used as a common access point
- # to get the content to be parsed as a string.
- #
- # The main reason behind this method is because I changed the internal
- # representation of the data to be parsed more than once
- # and I always had to rewrite all single parsers in order to reflect these changes.
- # Now, as far as the parser access the data via the content method,
- # there's no need to change each single implementation in case the content source changes.
- #
- # That said, the only constraints about this method is to return the data to be parsed as string.
- #
- def content
- part.response
- end
-
-
- # Returns <tt>true</tt> if the <tt>property</tt> passed as symbol
- # is available for the current parser.
- def property_available?(property)
- self.class.property_registered?(property, :supported)
- end
- alias :property_supported? :property_available?
-
-
-
@@property_registry = {}
#
@@ -168,39 +130,93 @@ def self.register_property(property, status, &block)
end
- # Registers a <tt>property</tt> as <tt>:supported</tt>
- # and defines a method with the content of the block.
- #
- # # Defines a supported property called :disclaimer.
- # property_supported(:disclaimer) do
+ # Registers a <tt>property</tt> as <tt>:not_implemented</tt>
+ # and defines a method which will raise a <tt>PropertyNotImplemented</tt> error.
+ #
+ # # Defines a not implemented property called :disclaimer.
+ # property_not_implemented(:disclaimer) do
# ...
# end
- #
+ #
# # def disclaimer
- # # ...
+ # # raise PropertyNotImplemented, "You should overwrite this method."
# # end
- #
- def self.property_supported(property, &block)
- register_property(property, :supported, &block)
+ #
+ def self.property_not_implemented(property)
+ register_property(property, :not_implemented) do
+ raise PropertyNotSupported
+ end
end
- # Registers a <tt>property</tt> as <tt>:supported</tt>
+ # Registers a <tt>property</tt> as <tt>:not_supported</tt>
# and defines a method which will raise a <tt>PropertyNotSupported</tt> error.
- #
+ #
# # Defines an unsupported property called :disclaimer.
# property_not_supported(:disclaimer) do
# ...
# end
- #
+ #
# # def disclaimer
# # raise PropertyNotSupported
# # end
- #
+ #
def self.property_not_supported(property)
- register_property(property, :implemented) do
+ register_property(property, :not_supported) do
raise PropertyNotSupported
end
end
+
+ # Registers a <tt>property</tt> as <tt>:supported</tt>
+ # and defines a method with the content of the block.
+ #
+ # # Defines a supported property called :disclaimer.
+ # property_supported(:disclaimer) do
+ # ...
+ # end
+ #
+ # # def disclaimer
+ # # ...
+ # # end
+ #
+ def self.property_supported(property, &block)
+ register_property(property, :supported, &block)
+ end
+
+
+
+ def initialize(part)
+ @part = part
+ end
+
+ ::Whois::Answer::Parser.properties.each do |property|
+ property_not_implemented(property)
+ end
+
+ def part
+ @part
+ end
+
+ # This is an internal method primaly used as a common access point
+ # to get the content to be parsed as a string.
+ #
+ # The main reason behind this method is because I changed the internal
+ # representation of the data to be parsed more than once
+ # and I always had to rewrite all single parsers in order to reflect these changes.
+ # Now, as far as the parser access the data via the content method,
+ # there's no need to change each single implementation in case the content source changes.
+ #
+ # That said, the only constraints about this method is to return the data to be parsed as string.
+ #
+ def content
+ part.response
+ end
+
+
+ # Returns <tt>true</tt> if the <tt>property</tt> passed as symbol
+ # is supported by the current parser.
+ def property_supported?(property)
+ self.class.property_registered?(property, :supported)
+ end
end
View
14 test/answer/parser/base_test.rb
@@ -25,25 +25,19 @@ def test_content
end
- def test_property_available?
+ def test_property_supported?
klass = Class.new(@klass) do
- register_property(:disclaimer, :supported) {}
end
- assert klass.new(@part).property_available?(:disclaimer)
+ assert !klass.new(@part).property_supported?(:disclaimer)
assert klass.new(@part).respond_to?(:disclaimer)
klass = Class.new(@klass) do
+ register_property(:disclaimer, :supported) {}
end
- assert !klass.new(@part).property_available?(:disclaimer)
+ assert klass.new(@part).property_supported?(:disclaimer)
assert klass.new(@part).respond_to?(:disclaimer)
end
- def test_property_available_should_return_false_unless_registrable_method
- parser = @klass.new(@part)
- assert !parser.property_available?(:content)
- assert parser.respond_to?(:content)
- end
-
def test_self_property_registry
assert_instance_of Hash, @klass.property_registry
View
8 test/answer/parser_test.rb
@@ -53,25 +53,25 @@ def test_parsers_with_two_parts
def test_property_supported_with_zero_parts
answer = Whois::Answer.new(nil, [])
parser = @klass.new(answer)
- assert !parser.property_available?(:disclaimer)
+ assert !parser.property_supported?(:disclaimer)
end
def test_property_supported_with_one_part_supported
answer = Whois::Answer.new(nil, [Whois::Answer::Part.new(nil, "whois.nic.it")])
parser = @klass.new(answer)
- assert parser.property_available?(:disclaimer)
+ assert parser.property_supported?(:disclaimer)
end
def test_property_supported_with_one_part_unsupported
answer = Whois::Answer.new(nil, [Whois::Answer::Part.new(nil, "invalid.nic.it")])
parser = @klass.new(answer)
- assert !parser.property_available?(:disclaimer)
+ assert !parser.property_supported?(:disclaimer)
end
def test_property_supported_with_two_parts
answer = Whois::Answer.new(nil, [Whois::Answer::Part.new(nil, "whois.crsnic.net"), Whois::Answer::Part.new(nil, "whois.nic.it")])
parser = @klass.new(answer)
- assert parser.property_available?(:disclaimer)
+ assert parser.property_supported?(:disclaimer)
end
View
53 test/answer_test.rb
@@ -85,34 +85,45 @@ def test_parser
assert_instance_of Whois::Answer::Parser, answer.parser
end
+
+ class Whois::Answer::Parser::WhoisParserFake < Whois::Answer::Parser::Base
+ property_supported :created_on do
+ Date.parse("2010-10-20")
+ end
+ property_not_supported :updated_on
+ # property_not_defined :expires_on
+ end
+
+ def test_property_supported?
+ answer = @klass.new(nil, [Whois::Answer::Part.new("", "whois.parser.fake")])
+ assert answer.property_supported?(:created_on)
+ assert !answer.property_supported?(:updated_on)
+ assert !answer.property_supported?(:expires_on)
+ end
+
def test_properties
- answer = @klass.new(nil, [])
- answer.parser.expects(:property_available?).with(:domain).returns(true)
- answer.parser.expects(:property_available?).with(:domain_id).returns(true)
- answer.parser.expects(:property_available?).with(Not(any_of(:domain, :domain_id))).at_least(1).returns(false)
- answer.parser.expects(:domain).returns("foo.com")
- answer.parser.expects(:domain_id).returns(27)
-
+ answer = @klass.new(nil, [Whois::Answer::Part.new("", "whois.parser.fake")])
properties = answer.properties
- assert_equal 2, properties.keys.length
- assert_equal "foo.com", properties[:domain]
- assert_equal 27, properties[:domain_id]
+
+ assert_equal Whois::Answer::Parser.properties.size, properties.keys.size
+ assert_equal Date.parse("2010-10-20"), properties[:created_on]
+ assert_equal nil, properties[:updated_on]
+ assert_equal nil, properties[:expires_on]
end
- def test_property_available?
- answer = @klass.new(nil, [])
- answer.parser.expects(:property_available?).with(:disclaimer).returns(:value)
- assert_equal :value, answer.property_available?(:disclaimer)
+ def test_should_delegate_supported_property_to_parser
+ answer = @klass.new(nil, [Whois::Answer::Part.new("", "whois.parser.fake")])
+ assert_equal Date.parse("2010-10-20"), answer.created_on
end
+ def test_should_return_nil_with_not_supported_property
+ answer = @klass.new(nil, [Whois::Answer::Part.new("", "whois.parser.fake")])
+ assert_equal nil, answer.updated_on
+ end
- Whois::Answer::Parser.properties.each do |method|
- define_method "test_should_delegate_#{method}_to_parser" do
- answer = @klass.new(nil, [Whois::Answer::Part.new("", "whois.nic.it")])
- parser = answer.parser
- parser.expects(method).returns(:value)
- assert_equal :value, answer.send(method)
- end
+ def test_should_return_nil_with_not_implemented_property
+ answer = @klass.new(nil, [Whois::Answer::Part.new("", "whois.parser.fake")])
+ assert_equal nil, answer.expires_on
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.