require_relative 'parser' module Whois class SafeRecord < BasicObject # @api private def self.define_property_method(method) class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{method}(*args, &block) if property_any_supported?(:#{method}) parser.#{method}(*args, &block) end end RUBY end # @api private def self.define_method_method(method) class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{method}(*args, &block) if parser.respond_to?(:#{method}) parser.#{method}(*args, &block) end end RUBY end # @api private def self.define_question_method(method) return if method.to_s.end_with?("?") class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{method}? !#{method}.nil? end RUBY end Parser::PROPERTIES.each do |method| define_property_method(method) end Parser::METHODS.each do |method| define_method_method(method) end (Parser::PROPERTIES + Parser::METHODS).each do |method| define_question_method(method) end attr_reader :record def initialize(record) @record = record end alias target record # Checks if this class respond to given method. # # Overrides the default implementation to add support # for {Whois::Parser::PROPERTIES} and {Whois::Parser::METHODS}. # # @return [Boolean] # def respond_to?(*args) respond_to_parser_method?(args.first) || target.respond_to?(*args) end # Lazy-loads and returns the parser proxy for current record. # # @return [Whois::Parser] def parser @parser ||= Parser.new(record) end # Returns a Hash containing all supported properties for this record # along with corresponding values. # # @return [{ Symbol => Object }] def properties hash = {} Parser::PROPERTIES.each do |property| hash[property] = __send__(property) end hash end # Shortcut for <tt>#registrant_contacts.first</tt>. # # @see Whois::Parser#registrant_contacts # # @return [Whois::Parser::Contact] # If the property is supported and a contact exists. # @return [nil] # If the property is not supported or the contact doesn't exist. def registrant_contact if property_any_supported?(:registrant_contacts) registrant_contacts.first end end # Shortcut for <tt>#admin_contacts.first</tt>. # # @see Whois::Parser#admin_contacts # # @return [Whois::Parser::Contact] # If the property is supported and a contact exists. # @return [nil] # If the property is not supported or the contact doesn't exist. def admin_contact if property_any_supported?(:admin_contacts) admin_contacts.first end end # Shortcut for <tt>#technical_contacts.first</tt>. # # @see Whois::Parser#technical_contacts # # @return [Whois::Parser::Contact] # If the property is supported and a contact exists. # @return [nil] # If the property is not supported or the contact doesn't exist. def technical_contact if property_any_supported?(:technical_contacts) technical_contacts.first end end # Collects and returns all the contacts. # # @see Whois::Parser#contacts # # @return [Array<Whois::Parser::Contact>] def contacts parser.contacts end private # @api private def respond_to_parser_method?(symbol) name = symbol.to_s =~ /\?$/ ? symbol.to_s[0..-2] : symbol Parser::PROPERTIES.include?(name.to_sym) || Parser::METHODS.include?(name.to_sym) end # Checks if the property passed as symbol # is supported in any of the parsers. # # @api private # @see Whois::Parser::Parser#property_any_supported? # # @param [Symbol] property The name of the property to check. # @return [Boolean] def property_any_supported?(property) parser.property_any_supported?(property) end # Delegates any missing method to Record. def method_missing(method, *args, &block) target.send(method, *args, &block) end end end