动态嵌套Ruby循环

时间:2016-02-23 21:49:41

标签: ruby api loops dynamic reporting

因此,我尝试做的是调用Reporting API来过滤所有可能的细分(按网站,广告客户,广告类型,广告系列等细分报告......)。但是,有一个问题是,每次登录时,故障都是唯一的。

示例:

  • user1: alice123 的报告细分为["site","advertiser","ad_type","campaign","line_items"]
  • user2: bob789 的报告细分为["campaign","position","line_items"]

当我第一次为此报告API构建代码时,我只有一个登录名要进行测试,因此我对维度(["site","advertiser","ad_type","campaign","line_items"])进行了硬编码。所以我所做的就是为sites的报告创建了API。然后,对于每个site,为advertisers和每个advertiser进行ping操作,我会为下一个维度进行操作,依此类推......让我留下~6层的嵌套循环。< / p>

基本上我正在做的事情:

sites = mechanize.get "#{base_ur}/report?dim=sites"
sites = Yajl::Parser.parse(sites.body) # json parser

sites.each do |site|
  advertisers = mechanize.get "#{base_ur}/report?site=#{site.fetch("id")}&dim=advertiser"
  advertisers = Yajl::Parser.parse(advertisers.body) # json parser

  advertisers.each do |advertiser|
    ad_types = mechanize.get "#{base_ur}/report?site=#{site.fetch("id")}&advertiser=#{advertiser.fetch("id")}&dim=ad_type"
    ad_types = Yajl::Parser.parse(ad_types.body) # json parser

    ad_types.each do |ad_type|
      ...and so on...
    end
  end
end

GET <api_url>/?dim=<dimension to breakdown>&site=<filter by site id>&advertiser=<filter by advertiser id>...etc...

在嵌套循环结束时,我留下了一份尽可能细化的报告。

现在这很有用,因为我只想到有一条崩溃路径,但显然每个帐户都有不同的维度细分。

所以我要问的是,如果给出一系列细分,我如何设置一个嵌套循环来动态地遍历粒度奇点?

感谢。

2 个答案:

答案 0 :(得分:1)

我不确定你的JSON / GET究竟返回什么,但对于像这样的问题,你需要递归。

也许这样的事情?它不是很优雅,绝对可以进一步优化,但希望能给你一个想法。

some_hash = {:id=>"site-id", :body=>{:id=>"advertiser-id", :body=>{:id=>"ad_type-id", :body=>{:id=>"something-id"}}}}
@breakdowns = ["site", "advertiser", "ad_type", "something"]

def recursive(some_hash, str = nil, i = 0)
  if @breakdowns[i+1].nil?
    str += "#{@breakdowns[i]}=#{some_hash[:id]}"
  else
    str += "#{@breakdowns[i]}=#{some_hash[:id]}&dim=#{@breakdowns[i + 1]}"
  end

  p str

  some_hash[:body].is_a?(Hash) ? recursive(some_hash[:body], str.gsub(/dim.*/, ''), i + 1) : return
end

recursive(some_hash, 'base-url/report?')

=> "base-url/report?site=site-id&dim=advertiser"
=> "base-url/report?site=site-id&advertiser=advertiser-id&dim=ad_type"
=> "base-url/report?site=site-id&advertiser=advertiser-id&ad_type=ad_type-id&dim=something"
=> "base-url/report?site=site-id&advertiser=advertiser-id&ad_type=ad_type-id&something=something-id"

答案 1 :(得分:0)

如果您只是想要映射数据,可以按另一个用户指出的方式递归映射到散列。如果你实际上是想在循环中对这些数据做一些事情,并且想要动态地重新创建你在问题中列出的循环结构(虽然我建议提出一个不同的解决方案),你可以使用元编程如下:

require 'active_support/inflector'

# Assume we are given an input of breakdowns
# I put 'testarr' in place of the operations you perform on each local variable
# for brevity and so you can see that the code works.
# You will have to modify to suit your needs

result = []
testarr = [1,2,3]
b = binding
breakdowns.each do |breakdown|
  snippet = <<-END
    eval("#{breakdown.pluralize} = testarr", b)
    eval("#{breakdown.pluralize}", b).each do |#{breakdown}|    
  END

  result << snippet 
end

result << "end\n"*breakdowns.length


eval(result.join)

注意:这种方法可能不受欢迎,正如我所说,我确定还有其他方法可以完成你想要做的事情。