获取一个关键的红宝石

时间:2017-11-10 20:41:28

标签: ruby

我有这个json:

{"user"=>
      {"name"=>"Lebron James",
       "email"=>"lebron.james@gmial.com",
       "time_zone"=>"America/Chicago",
       "contact"=>
        [{"id"=>"PO0JGV7",
          "type"=>"email_contact_method_reference",
          "summary"=>"Default",
          "self"=>
           "https://pagerduty.com/users/000000/contact/000000",
          "html_url"=>nil},
         {"id"=>"000000",
          "type"=>"phone_contact_method_reference",
          "summary"=>"Mobile",
          "self"=>
           "https://pagerduty.com/users/000000/contact/000000",
          "html_url"=>nil},
         {"id"=>"000000",
          "type"=>"push_notification_contact_method_reference",
          "summary"=>"XT1096",
          "self"=>
           "https://api.pagerduty.com/users/000000/contact/000000",
          "html_url"=>nil},
         {"id"=>"000000",
          "type"=>"sms_contact_method_reference",
          "summary"=>"Mobile",
          "self"=>
           "https://pagerduty.com/users/000000/methods/000000",
          "html_url"=>nil}],

我希望能够检索自键的值,但只能检索具有"type" => "email_contact_method_reference""summary"=>"Mobile"的值。这是我认为会起作用的。

    phone = File.open("employee_phone_api.txt", "w+") 
    jdoc.fetch("user").fetch("contact_methods").each do |contact|
            if contact["type"] == "email_contact_method_reference" and contact["summary"] == "Mobile" 
                phone.puts contact["self"]
            else
            end
    end

思考?和/或建议?

1 个答案:

答案 0 :(得分:0)

无需使用#each,因为有更多表达方式来处理此问题。与许多Ruby问题一样,您希望获得一个Array然后对其进行转换。在这种情况下,您要选择某些联系人,然后提取特定值。

您的示例哈希有一个“联系”键,但没有“contact_methods”键。我正在使用“联系”作为我的例子。此外,您的示例不包含符合条件的对象,因此我将其修改为包含一个。

首先我们得到一个包含所有联系人的数组:

contacts = jdoc.fetch("user").fetch("contact")

然后我们使用Enumerable#select将它们过滤到所需的类型,这会产生一个单个Hash对象的数组:

email_contacts = contacts.select { |contact| contact['type'] == 'email_contact_method_reference' && contact['summary'] == 'Mobile' }
#=> [{"id"=>"PO0JGV7", "type"=>"email_contact_method_reference", "summary"=>"Mobile", "self"=>"https://pagerduty.com/users/000000/contact/000000", "html_url"=>nil}]

接下来,我们只绘制出我们想要的信息:

urls = email_contacts.map { |contact| contact['self'] }

这会导致为urls分配一个单个字符串的数组:

#=> ["https://pagerduty.com/users/000000/contact/000000"]

在现实世界中,您将需要一个接受参数的方法,使逻辑变得灵活。你可能会这样做:

def fetch_urls(doc, type, summary)
  doc.fetch("user").fetch("contact")
      .select { |contact| contact['type'] == type && contact['summary'] == summary }
      .map { |contact| contact['self'] }
end

>> fetch_urls(jdoc, 'email_contact_method_reference', 'Mobile')
#=> ["https://pagerduty.com/users/000000/contact/000000"]

现在您有了一个工作方法,您可以在文件编写器中使用它:

>> phone = File.open("employee_phone_api.txt", "w+") 
>> phone.puts fetch_urls(jdoc, 'email_contact_method_reference', 'Mobile').join("\n")
>> phone.close
>> File.read(phone)
#=> "https://pagerduty.com/users/000000/contact/000000\n"