Как мне json закодировать всю информацию, доступную в объекте парсера?

Я очень новичок в рубине и рельсах. Я пытаюсь вывести всю проанализированную информацию whois в вывод json. У меня есть следующее:

class WhoisController < ApplicationController
  def index
    c = Whois::Client.new
    record = c.lookup("google.com")
    parser = record.parser
    created = parser.created_on
    msg = {:created => created}
    render :json => msg
  end
end

Выход:

{"created":"1997-09-15T00:00:00.000-07:00"}

Тем не менее, синтаксический анализатор имеет НАМНОГО больше доступной информации .... не зная всех доступных полей, как мне сбросить все ключи/значения в json?

Я пытался:

class WhoisController < ApplicationController
  def index
    c = Whois::Client.new
    record = c.lookup("google.com")
    parser = record.parser
    msg = {:whois => parser}
    render :json => msg
  end
end

Но в итоге получаю:

SystemStackError in WhoisController#index

РЕДАКТИРОВАТЬ:

Я также пробовал:

parser.attributes.each do |attr_name, attr_value|
  puts attr_name
end

Но в итоге получаю другую ошибку:

undefined method `attributes' for #<Whois::Parser:0x00007fc030d74018>

И Python, и Go (путем отражения) могут это сделать. Каков способ Ruby для достижения этого?

РЕДАКТИРОВАТЬ:

class WhoisController < ApplicationController
    def index
        c = Whois::Client.new
        record = c.lookup("google.com")
        parser = record.parser
        msg = {}
        for x_prop in Whois::Parser::PROPERTIES
            msg[x_prop] = parser.send(x_prop)
        end
        render :json => msg
    end
end

Это работает ТОЛЬКО если все свойства существуют в парсере. Однако некоторые доменные имена не обладают всеми свойствами, что приведет к следующему:

Unable to find a parser for property `registrant_contacts'

Затем я пытаюсь установить его, только если это свойство существует:

msg = {}
for x_prop in Whois::Parser::PROPERTIES
  parser.has_attribute?(:x_prop) 
    msg[x_prop] = parser.send(x_prop) 
end
render :json => msg

Я получаю другую ошибку:

undefined method `has_attribute?'

РЕДАКТИРОВАТЬ № 3:

Я также пробовал:

msg = {}
for prop in Whois::Parser::PROPERTIES
  msg[prop] = parser.send(prop) if parser.respond_to?(prop)
end
render :json => msg

Это по-прежнему не работает, если свойство отсутствует в синтаксическом анализаторе. ;(


person user_78361084    schedule 02.02.2019    source источник


Ответы (3)


class WhoisController < ApplicationController
    def index
        c = Whois::Client.new
        record = c.lookup("google.com")
        parser = record.parser
        msg = {}
        for x_prop in Whois::Parser::PROPERTIES
            msg[x_prop] = parser.send(x_prop)
        end
        render :json => msg
    end
end

в некоторых случаях некоторые свойства могут быть пустыми и вызывать ошибку, чтобы избежать этого:

begin
    msg[x_prop] = parser.send(x_prop)
rescue
    # do nothing
end
person thiaguerd    schedule 03.02.2019
comment
На паре из них я получаю Невозможно найти парсер для свойства `registrant_contacts' - person user_78361084; 04.02.2019
comment
parser.has_attribute?(:prop) msg[prop] = parser.send(prop) Я получаю неопределенный метод `has_attribute?' - person user_78361084; 04.02.2019
comment
@MarissaLevy просто используйте попытку поймать, как мое редактирование в ответе - person thiaguerd; 04.02.2019
comment
спасибо за помощь новичку .... еще одна награда придет, когда мне будет позволено вознаградить ее. - person user_78361084; 05.02.2019
comment
Возникает вопрос: зачем использовать цикл for, если можно использовать #each? Или #each_with_object в этом отношении. - person 3limin4t0r; 05.02.2019
comment
for...in очень однозначен для Ruby. Это правильно, но использование итераторов, таких как предложение @JohanWentholt, обычно приводит к более лаконичному и понятному коду. Кроме того, проверка способности выполнить задачу (if..else..end), как правило, более эффективна, чем спасение. Rescue лучше использовать для обнаружения exceptions неожиданностей, а не для обработки ожидаемых сбоев. - person Tom; 07.02.2019
comment
Другая проблема с for...in заключается в том, что он не создает новую область. Все переменные, установленные в области (включая x_prop), по-прежнему доступны после итерации. Иногда это может привести к неожиданному поведению. Принимая во внимание, что использование итератора добавит новую область поверх текущей области, что позволит вам затенить внешние переменные или установить переменные, которые доступны только во время итерации. В некоторых случаях вы можете захотеть использовать for...in, но в целом, если у вас нет веской причины, вы используете #each. - person 3limin4t0r; 07.02.2019

Для SystemStackError in WhoisController#index:

Я думаю, это потому, что вы снова звоните whois через Whois в record = Whois.whois("google.com"). Попробуйте record = whois("google.com").

Для undefined method `attributes' for #<Whois::Parser:0x00007fc030d74018>: метод атрибутов не работает для парсера whois. См. https://whoisrb.org/docs/v3/parser-properties/. .

person Aaditya Maheshwari    schedule 02.02.2019
comment
Whois.whois действителен... также действителен whois.lookup. Я смешивал и сочетал. Я отредактировал образцы. - person user_78361084; 02.02.2019
comment
то есть нет возможности перебрать все поля? В python и go есть способы сделать это. - person user_78361084; 03.02.2019
comment
@MarissaLevy Я бы не сказал, что нет никакого способа. Но вам придется написать цикл самостоятельно, чтобы перебирать свойства парсера. Иногда некоторые библиотеки имеют незначительные различия в функциях/методах, которые они предоставляют для разных языков. - person Aaditya Maheshwari; 03.02.2019

Вы можете использовать methods или inspect.

    c = Whois::Client.new
    record = c.lookup("google.com")
    parser = record.parser
    render json: parser.methods.to_json
    render json: parser.inspect.to_json
person mogbee    schedule 03.02.2019