2013-09-10 3 views
0

J'ai une application simple qui est destiné à tirer des statistiques de compte Adwords (via le adwordsapi) et le présenter à l'utilisateur dans une table dans une vue Rails. Il fonctionne correctement en tirant toutes les infos pour plusieurs campagnes à l'exception d'un numéro.Sum Touches identiques dans un hachage Ruby

Je ne parviens pas à obtenir les totaux de chaque champ (coût total, nombre total d'impressions, etc.). Je suis en mesure de diffuser des impressions pour chaque campagne du compte, mais je ne parviens pas à obtenir les totaux pour le compte.

Je présente mes excuses à l'avance pour le code noob à suivre :)

Voici le adwordscampaign_controller.rb

class AdwordscampaignController < ApplicationController 

PAGE_SIZE = 50 

def index() 
@selected_account = selected_account 

if @selected_account 
    response = request_campaigns_list() 
    if response 
    @campaigns = Adwordscampaign.get_campaigns_list(response) 
    @campaign_count = response[:total_num_entries] 
    @start = params[:start] 
    @end = params[:end] 

    @myhash = Adwordscampaign.get_campaigns_list(response) 

    end 
end 
end 

private 

def request_campaigns_list() 

# Prepare start and end date for the last week. 

if params[:start].nil? 
start_date = DateTime.parse((Date.today - 7).to_s).strftime("%Y%m%d") 
end_date = DateTime.parse((Date.today - 1).to_s).strftime("%Y%m%d") 
else 
start_date = params[:start] 
end_date = params[:end] 
end 

api = get_adwords_api() 
service = api.service(:CampaignService, get_api_version()) 
selector = { 
    :fields => ['Id', 'Name', 'Status', 'Cost', 'Impressions', 'Clicks', 'Ctr', 'Conversions', 'Amount'], 
    :ordering => [{:field => 'Id', :sort_order => 'ASCENDING'}], 
    :date_range => {:min => start_date, :max => end_date}, 
    :paging => {:start_index => 0, :number_results => PAGE_SIZE} 
} 
result = nil 


begin 
    result = service.get(selector) 
rescue AdwordsApi::Errors::ApiException => e 
    logger.fatal("Exception occurred: %s\n%s" % [e.to_s, e.message]) 
    flash.now[:alert] = 
     'API request failed with an error, see logs for details' 
end 
return result 
end 
end 

le modèle pertinent: adwordscampaign.rb

class Adwordscampaign 
    attr_reader :id 
    attr_reader :name 
    attr_reader :status 
    attr_reader :cost 
    attr_reader :impressions 
    attr_reader :clicks 
    attr_reader :ctr 
    attr_reader :costdecimal 
    attr_reader :costperconversiondecimal 


def initialize(api_campaign) 
    @id = api_campaign[:id] 
    @name = api_campaign[:name] 
    @status = api_campaign[:status] 

    budget = api_campaign[:budget] 

    stats = api_campaign[:campaign_stats] 

    @cost = (stats[:cost][:micro_amount]/10000) 
    @costdecimal = (@cost * 10000).round.to_f/1000000 
    @impressions = stats[:impressions] 
    @clicks = stats[:clicks] 
    @ctr = (stats[:ctr] * 100) 

end 


def self.get_campaigns_list(response) 
    result = {} 
    if response[:entries] 
    response[:entries].each do |api_campaign| 
     campaign = Adwordscampaign.new(api_campaign) 
     result[campaign.id] = campaign 
    end 
    end 
    return result 
end 
end 

Le tableau à partir des vues \ adwordscampaign \ index.html.erb

<table class="table table-striped table-bordered"> 
    <tr> 
    <th>ID 
    <th>Name 
    <th>Status 
    <th>Impressions 
    <th>Clicks 
    <th>CTR 
    <th>Cost 

<% @campaigns.each do |id, campaign| %> 
    <tr> 
    <td><%= campaign.id %></td> 
    <td><%= campaign.name %></td> 
    <td><%= campaign.status %></td> 
    <td><%= number_with_delimiter(campaign.impressions) %></td> 
    <td><%= number_with_delimiter(campaign.clicks) %></td> 
    <td><%= number_with_precision(campaign.ctr, precision: 2) %>%</td> 
    <td>$<%= number_with_delimiter(campaign.costdecimal) %></td> 



<% end %>  

<td><%= @campaigns %></td> 

</table> 

J'ai lancé @campaigns dans la vue (en bas) pour que je puisse voir ce que la sortie était. La syntaxe est un peu familier pour moi, mais il semble être hash imbriqués dans un hachage (correct?)

sortie @campaigns dans la vue

{109886905=>#<Adwordscampaign:0x4528ba0 @id=109879905, @name="Upholstery Cleaning",  @status="ACTIVE", @cost=2702, @costdecimal=27.02, @impressions=824, @clicks=7, @ctr=0.8495145631067961>, 103480025=>#<Adwordscampaign:0x7028b28 @id=109880025, @name="Carpet Cleaning", @status="ACTIVE", @cost=16739, @costdecimal=167.39, @impressions=4457, @clicks=29, @ctr=0.6506618801884676>, 104560145=>#<Adwordscampaign:0x3e9ibac8 @id=109880145, @name="Competitors", @status="ACTIVE", @cost=1596, @costdecimal=15.96, @impressions=515, @clicks=5, @ctr=0.9708737864077669> 

Enfin à la question - Comment puis-je obtenir le total @clicks (ou @impressions, @cost, etc.) pour chacune des 3 campagnes trouvées ici?

J'ai cherché des choses comme «comment faire la somme des clés/valeurs de hachage identiques» ou «comment fusionner les hachages imbriqués» en vain.

Merci d'avance! Ressemble à un simple hachage de {id -> Adwordscampaign}

+2

Nous n'avons pas besoin de l'ERB et du code modèle. Nous avons besoin d'un échantillon des données que vous recevez, réduites à l'essentiel. –

Répondre

0

@campaigns La notation #<ObjectName:data> est Ruby faisant de son mieux pour vous donner quelque chose de lisible pour cet objet.

En somme clics, par exemple, est une carte simple-Reduce:

total_clicks = @campaigns.map { |id, campaign| campaign.clicks } .reduce(&:+) 

Cela crée un tableau de toutes les valeurs campaign.clicks, puis les combine tous en utilisant l'opérateur +. Cela suppose qu'un #clicks est présent sur ces objets. Si non, modifier en conséquence.

Si tout ce que vous faites est la somme des attributs différents, vous pouvez simplifier l'utiliser plusieurs fois comme ceci:

camp_list = @campaigns.map { |id, campaign| campaign } 
total_clicks  = camp_list.map(&:clicks).reduce(&:+) 
total_cost  = camp_list.map(&:cost).reduce(&:+) 
total_impressions = camp_list.map(&:impressions).reduce(&:+) 

Réduire davantage est un exercice au lecteur. :)

+0

Parfait! Merci pour les informations supplémentaires dans votre réponse! – macoughl

Questions connexes