google_api 1.0.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
 - data/.rspec +2 -0
 - data/Gemfile +4 -0
 - data/LICENSE +22 -0
 - data/README.md +453 -0
 - data/Rakefile +9 -0
 - data/google_api.gemspec +22 -0
 - data/lib/google_api.rb +37 -0
 - data/lib/google_api/cache.rb +49 -0
 - data/lib/google_api/configuration.rb +37 -0
 - data/lib/google_api/core_ext/hash.rb +11 -0
 - data/lib/google_api/core_ext/string.rb +13 -0
 - data/lib/google_api/date.rb +59 -0
 - data/lib/google_api/ga.rb +52 -0
 - data/lib/google_api/ga/data.rb +335 -0
 - data/lib/google_api/ga/data/data_dsl.rb +66 -0
 - data/lib/google_api/ga/data/filters_dsl.rb +11 -0
 - data/lib/google_api/ga/data/segment_dsl.rb +11 -0
 - data/lib/google_api/ga/helper.rb +41 -0
 - data/lib/google_api/ga/management/account.rb +37 -0
 - data/lib/google_api/ga/management/goal.rb +58 -0
 - data/lib/google_api/ga/management/management.rb +36 -0
 - data/lib/google_api/ga/management/profile.rb +64 -0
 - data/lib/google_api/ga/management/segment.rb +41 -0
 - data/lib/google_api/ga/management/webproperty.rb +52 -0
 - data/lib/google_api/ga/session.rb +165 -0
 - data/lib/google_api/version.rb +3 -0
 - data/spec/lib/google_api_spec.rb +63 -0
 - data/spec/spec_helper.rb +8 -0
 - metadata +125 -0
 
| 
         @@ -0,0 +1,66 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module GoogleApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Ga
         
     | 
| 
      
 3 
     | 
    
         
            +
                class DataDsl
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  OPERATORS = ['==', '!=', '>', '<', '>=', '<=', '=~', '!~']
         
     | 
| 
      
 6 
     | 
    
         
            +
                  OPERATORS_METHOD =  {'%' => '=@', '**' => '!@'}
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @result = []
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  # Make operators 
         
     | 
| 
      
 13 
     | 
    
         
            +
                  OPERATORS.each do |operator|
         
     | 
| 
      
 14 
     | 
    
         
            +
                    eval <<-METHOD
         
     | 
| 
      
 15 
     | 
    
         
            +
                      def #{operator} (value)
         
     | 
| 
      
 16 
     | 
    
         
            +
                        @result << @attribute + "#{operator}" + value.to_s
         
     | 
| 
      
 17 
     | 
    
         
            +
                        self
         
     | 
| 
      
 18 
     | 
    
         
            +
                      end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    METHOD
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  OPERATORS_METHOD.each do |key, value|
         
     | 
| 
      
 22 
     | 
    
         
            +
                    eval <<-METHOD
         
     | 
| 
      
 23 
     | 
    
         
            +
                      def #{key} (value)
         
     | 
| 
      
 24 
     | 
    
         
            +
                        @result << @attribute + "#{value}" + value.to_s
         
     | 
| 
      
 25 
     | 
    
         
            +
                        self
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                    METHOD
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def method_missing(name)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if name.to_s =~ /\A[a-zA-Z0-9]+\Z/
         
     | 
| 
      
 32 
     | 
    
         
            +
                      @attribute = "ga:#{name}"
         
     | 
| 
      
 33 
     | 
    
         
            +
                      self
         
     | 
| 
      
 34 
     | 
    
         
            +
                    else
         
     | 
| 
      
 35 
     | 
    
         
            +
                      super
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def &(other)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @result << :and
         
     | 
| 
      
 41 
     | 
    
         
            +
                    self
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  def |(other)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    @result << :or
         
     | 
| 
      
 46 
     | 
    
         
            +
                    self
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def build_parameter
         
     | 
| 
      
 50 
     | 
    
         
            +
                    i = @result.index{ |x| x.is_a?(Symbol) }
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    if !i.nil?
         
     | 
| 
      
 53 
     | 
    
         
            +
                      result = @result[i-2] + (@result[i] == :and ? ";" : ",") + @result[i-1]
         
     | 
| 
      
 54 
     | 
    
         
            +
                      @result.delete_at(i)
         
     | 
| 
      
 55 
     | 
    
         
            +
                      @result.delete_at(i-1)
         
     | 
| 
      
 56 
     | 
    
         
            +
                      @result[i-2] = result
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                      build_parameter
         
     | 
| 
      
 59 
     | 
    
         
            +
                    else
         
     | 
| 
      
 60 
     | 
    
         
            +
                      @result.join
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                  
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module GoogleApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Ga
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Helper
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  # Same as get but automaticly add day, month and year to dimension
         
     | 
| 
      
 6 
     | 
    
         
            +
                  #
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # Also check cache
         
     | 
| 
      
 8 
     | 
    
         
            +
                  #
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def get_by_day(parameters, start_date = prev_month, end_date = now, expire = nil)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    
         
     | 
| 
      
 11 
     | 
    
         
            +
                    [:dimensions, :sort].each do |param|
         
     | 
| 
      
 12 
     | 
    
         
            +
                      parameters[param] = [] unless parameters[param]
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                      if parameters[param].is_a?(String) || parameters[param].is_a?(Symbol)
         
     | 
| 
      
 15 
     | 
    
         
            +
                        parameters[param] = [parameters[param]]
         
     | 
| 
      
 16 
     | 
    
         
            +
                      end
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    parameters[:dimensions] << :day
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    if more_years?(start_date, end_date)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      parameters[:dimensions] << :month
         
     | 
| 
      
 23 
     | 
    
         
            +
                      parameters[:dimensions] << :year
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                      parameters[:sort] << :year
         
     | 
| 
      
 26 
     | 
    
         
            +
                      parameters[:sort] << :month
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    elsif more_months?(start_date, end_date)
         
     | 
| 
      
 29 
     | 
    
         
            +
                      parameters[:dimensions] << :month
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                      parameters[:sort] << :month
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    parameters[:sort] << :day
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    get(parameters, start_date, end_date, expire)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module GoogleApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Ga
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Account < Management
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(account)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    set(account)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def self.all(account_id = '~all')
         
     | 
| 
      
 10 
     | 
    
         
            +
                    get({ accountId: account_id }).map { |account| Account.new(account) }
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def self.find(account_id)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    all(account_id).first
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def refresh
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @webproperties = nil
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    set( Account.get({ accountId: @id }).first )
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def webproperties
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @webproperties ||= Webproperty.all(@id)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  private
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    def self.get(parameters = nil)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      super(@@session.api.management.accounts.list, parameters)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                  
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,58 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module GoogleApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Ga
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Goal < Management
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :accountId
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :webPropertyId
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :profileId
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :value
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :active
         
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :type
         
     | 
| 
      
 11 
     | 
    
         
            +
                  attr_reader :goal
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(goal)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    set(goal)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def self.all(account_id = '~all', webproperty_id = '~all', profile_id = '~all', goal_id = '~all')
         
     | 
| 
      
 18 
     | 
    
         
            +
                    get({ accountId: account_id, webPropertyId: webproperty_id, profileId: profile_id, goalId: goal_id }).map { |goal| Goal.new(goal) }
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def self.find(goal_id)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    all('~all', '~all', '~all', goal_id).first
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def refresh
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @profile  = nil
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    set( Goal.get({ accountId: @accountId, webPropertyId: @id, profileId: @profileId, goalId: @id }).first )
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def profile
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @profile ||= Profile.find(@profileId)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  private
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    def self.get(parameters = nil)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      super(@@session.api.management.goals.list, parameters)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    def set(goal)
         
     | 
| 
      
 44 
     | 
    
         
            +
                      @accountId     = goal['accountId']
         
     | 
| 
      
 45 
     | 
    
         
            +
                      @webPropertyId = goal['webPropertyId']
         
     | 
| 
      
 46 
     | 
    
         
            +
                      @profileId     = goal['profileId']
         
     | 
| 
      
 47 
     | 
    
         
            +
                      @value         = goal['value']
         
     | 
| 
      
 48 
     | 
    
         
            +
                      @active        = goal['active']
         
     | 
| 
      
 49 
     | 
    
         
            +
                      @type          = goal['type']
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                      @goal = goal[camelize(@type) + 'Details']
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                      super(goal)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module GoogleApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Ga
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Management
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  @@session = Session
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :id
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :name
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :created
         
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :updated
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def camelize(string)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    string = string.downcase.split('_').map!(&:capitalize).join
         
     | 
| 
      
 14 
     | 
    
         
            +
                    string[0] = string[0].downcase
         
     | 
| 
      
 15 
     | 
    
         
            +
                    string
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 19 
     | 
    
         
            +
                  
         
     | 
| 
      
 20 
     | 
    
         
            +
                    def self.get(api_method, parameters = nil)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      JSON.parse( 
         
     | 
| 
      
 22 
     | 
    
         
            +
                        @@session.client.execute(api_method: api_method,
         
     | 
| 
      
 23 
     | 
    
         
            +
                                                 parameters: parameters).body
         
     | 
| 
      
 24 
     | 
    
         
            +
                      )["items"]
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    def set(values)
         
     | 
| 
      
 28 
     | 
    
         
            +
                      @id      = values['id']
         
     | 
| 
      
 29 
     | 
    
         
            +
                      @name    = values['name']
         
     | 
| 
      
 30 
     | 
    
         
            +
                      @created = values['created']
         
     | 
| 
      
 31 
     | 
    
         
            +
                      @updated = values['updated']
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,64 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module GoogleApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Ga
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Profile < Management
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :accountId
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :webPropertyId
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :currency
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :timezone
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(profile)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    set(profile)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def self.all(account_id = '~all', webproperty_id = '~all', profile_id = '~all')
         
     | 
| 
      
 15 
     | 
    
         
            +
                    get({ accountId: account_id, webPropertyId: webproperty_id, profileId: '~all' }).map { |profile| Profile.new(profile) }
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def self.find(profile_id)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    all('~all', '~all', profile_id).first
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def refresh
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @webproperty = nil
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @goals       = nil
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    set( Profile.get({ accountId: @accountId, webPropertyId: @webPropertyId, profileId: @id }).first )
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def webproperty
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @webproperty ||= Webproperty.find(@webpropertyId)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def goals
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @goals ||= Goal.all(@accountId, @webPropertyId, @id)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  # def get(parameters, start_date = prev_month, end_date = now, expire = nil)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #   Data.get(@id, parameters, start_date, end_date, expire)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  # end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  # def get!(parameters, start_date = prev_month, end_date = now)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  #   Data.get!(@id, parameters, start_date, end_date)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  # end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  private
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    def self.get(parameters = nil)
         
     | 
| 
      
 50 
     | 
    
         
            +
                      super(@@session.api.management.profiles.list, parameters)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    def set(profile)
         
     | 
| 
      
 54 
     | 
    
         
            +
                      @accountId     = profile['accountId']
         
     | 
| 
      
 55 
     | 
    
         
            +
                      @webPropertyId = profile['webPropertyId']
         
     | 
| 
      
 56 
     | 
    
         
            +
                      @currency      = profile['currency']
         
     | 
| 
      
 57 
     | 
    
         
            +
                      @timezone      = profile['timezone']
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                      super(profile)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
                  
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module GoogleApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Ga
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Segment < Management
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_accessor :segmentId
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_accessor :definition
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(segment)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    set(segment)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def self.all(segment_id = '~all')
         
     | 
| 
      
 13 
     | 
    
         
            +
                    get({ segmentId: segment_id }).map { |segment| Segment.new(segment) }
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def self.find(segment_id)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    all(segment_id).first
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def refresh
         
     | 
| 
      
 21 
     | 
    
         
            +
                    set( Segment.get({ segmentId: @id }).first )
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  private
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    def self.get(parameters = nil)
         
     | 
| 
      
 29 
     | 
    
         
            +
                      super(@@session.api.management.segments.list, parameters)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                    
         
     | 
| 
      
 32 
     | 
    
         
            +
                    def set(segment)
         
     | 
| 
      
 33 
     | 
    
         
            +
                      @segmentId  = segment['segmentId']
         
     | 
| 
      
 34 
     | 
    
         
            +
                      @definition = segment['definition']
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                      super(segment)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
                  
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,52 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module GoogleApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Ga
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Webproperty < Management
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :accountId
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :websiteUrl
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(webproperty)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    set(webproperty)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def self.all(account_id = '~all', webproperty_id = '~all')
         
     | 
| 
      
 13 
     | 
    
         
            +
                    get({ accountId: account_id, webPropertyId: webproperty_id }).map { |webproperty| Webproperty.new(webproperty) }
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def self.find(webproperty_id)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    all('~all', webproperty_id).first
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def refresh
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @account  = nil
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @profiles = nil
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    set( Webproperty.get({ accountId: @accountId, webPropertyId: @id }).first )
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def account
         
     | 
| 
      
 30 
     | 
    
         
            +
                    @account ||= Account.find(@accountId)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def profiles
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @profiles ||= Profile.all(@accountId, @id)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  private
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    def self.get(parameters = nil)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      super(@@session.api.management.webproperties.list, parameters)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    def set(webproperty)
         
     | 
| 
      
 44 
     | 
    
         
            +
                      @accountId  = webproperty['accountId']
         
     | 
| 
      
 45 
     | 
    
         
            +
                      @websiteUrl = webproperty['websiteUrl']
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                      super(webproperty)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,165 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "google_api/core_ext/string"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GoogleApi
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Ga
         
     | 
| 
      
 5 
     | 
    
         
            +
                
         
     | 
| 
      
 6 
     | 
    
         
            +
                class Session
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  SCOPE       = "https://www.googleapis.com/auth/analytics.readonly"
         
     | 
| 
      
 9 
     | 
    
         
            +
                  NAME_API    = "analytics"
         
     | 
| 
      
 10 
     | 
    
         
            +
                  VERSION_API = "v3"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  @@api    = nil
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @@client = nil
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  # Config --------------------------------------------------------------------------------
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def self._config
         
     | 
| 
      
 18 
     | 
    
         
            +
                    GoogleApi.config
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def self.client_id
         
     | 
| 
      
 22 
     | 
    
         
            +
                    _config.ga.client_id ? _config.ga.client_id : _config.client_id
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def self.client_secret
         
     | 
| 
      
 26 
     | 
    
         
            +
                    _config.ga.client_secret ? _config.ga.client_secret : _config.client_secret
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def self.redirect_uri
         
     | 
| 
      
 30 
     | 
    
         
            +
                    _config.ga.redirect_uri ? _config.ga.redirect_uri : _config.redirect_uri
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def self.client_cert_file
         
     | 
| 
      
 34 
     | 
    
         
            +
                    _config.ga.client_cert_file ? _config.ga.client_cert_file : _config.client_cert_file
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def self.client_developer_email
         
     | 
| 
      
 38 
     | 
    
         
            +
                    _config.ga.client_developer_email ? _config.ga.client_developer_email : _config.client_developer_email
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def self.key_secret
         
     | 
| 
      
 42 
     | 
    
         
            +
                    _config.ga.key_secret ? _config.ga.key_secret : _config.key_secret
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  # ---------------------------------------------------------------------------------------
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def self.login_by_cert
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @@client = Google::APIClient.new
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    key      = Google::APIClient::PKCS12.load_key(client_cert_file, key_secret)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    asserter = Google::APIClient::JWTAsserter.new(client_developer_email, SCOPE, key)
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 54 
     | 
    
         
            +
                      @@client.authorization = asserter.authorize()
         
     | 
| 
      
 55 
     | 
    
         
            +
                      @@api = @@client.discovered_api(NAME_API, VERSION_API)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    rescue
         
     | 
| 
      
 57 
     | 
    
         
            +
                      return false
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  def self.login_by_cert!
         
     | 
| 
      
 64 
     | 
    
         
            +
                    i = 0
         
     | 
| 
      
 65 
     | 
    
         
            +
                    while !login_by_cert
         
     | 
| 
      
 66 
     | 
    
         
            +
                      print "\r[#{Time.now.strftime("%H:%M:%S")}] ##{i += 1} ... \r".bold
         
     | 
| 
      
 67 
     | 
    
         
            +
                      sleep(1)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  def self.login(code = nil)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    @@client = Google::APIClient.new
         
     | 
| 
      
 75 
     | 
    
         
            +
                    @@client.authorization.client_id     = client_id
         
     | 
| 
      
 76 
     | 
    
         
            +
                    @@client.authorization.client_secret = client_secret
         
     | 
| 
      
 77 
     | 
    
         
            +
                    @@client.authorization.scope         = SCOPE
         
     | 
| 
      
 78 
     | 
    
         
            +
                    @@client.authorization.redirect_uri  = redirect_uri
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                    @@api = @@client.discovered_api(NAME_API, VERSION_API)
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    if code
         
     | 
| 
      
 83 
     | 
    
         
            +
                      @@client.authorization.code = code
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 86 
     | 
    
         
            +
                        @@client.authorization.fetch_access_token!
         
     | 
| 
      
 87 
     | 
    
         
            +
                      rescue
         
     | 
| 
      
 88 
     | 
    
         
            +
                        return false
         
     | 
| 
      
 89 
     | 
    
         
            +
                      end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                      return true
         
     | 
| 
      
 92 
     | 
    
         
            +
                    else
         
     | 
| 
      
 93 
     | 
    
         
            +
                      @@client.authorization.authorization_uri.to_s
         
     | 
| 
      
 94 
     | 
    
         
            +
                    end
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  def self.login_by_line(server = 'http://localhost/oauth2callback', port = 0)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    require "launchy" # open browser
         
     | 
| 
      
 99 
     | 
    
         
            +
                    require "socket"  # make tcp server 
         
     | 
| 
      
 100 
     | 
    
         
            +
                    require "uri"     # parse uri
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                    uri = URI(server)
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                    # Start webserver.
         
     | 
| 
      
 105 
     | 
    
         
            +
                    webserver = TCPServer.new(uri.host, port)
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                    # By default port is 0. It means that TCPServer will get first free port.
         
     | 
| 
      
 108 
     | 
    
         
            +
                    # Port is required for redirect_uri.
         
     | 
| 
      
 109 
     | 
    
         
            +
                    uri.port = webserver.addr[1]
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                    # Add redirect_uri for google oauth 2 callback.
         
     | 
| 
      
 112 
     | 
    
         
            +
                    GoogleApi.config.ga.redirect_uri = uri.to_s
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                    # Open browser.
         
     | 
| 
      
 115 
     | 
    
         
            +
                    Launchy.open(login)
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                    # Wait for new session.
         
     | 
| 
      
 118 
     | 
    
         
            +
                    session = webserver.accept
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                    # Parse header for query.
         
     | 
| 
      
 121 
     | 
    
         
            +
                    request = session.gets.gsub(/GET\ \//, '').gsub(/\ HTTP.*/, '')
         
     | 
| 
      
 122 
     | 
    
         
            +
                    request = Hash[URI.decode_www_form(URI(request).query)]
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                    code = request['code']
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                    # Close session and webserver.
         
     | 
| 
      
 127 
     | 
    
         
            +
                    session.close
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                    if login(code)
         
     | 
| 
      
 130 
     | 
    
         
            +
                      session.write("You have been successfully logged. Now you can close the browser.")
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                      return true
         
     | 
| 
      
 133 
     | 
    
         
            +
                    end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                    session.write("You have not been logged. Please try again.")
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                    return false
         
     | 
| 
      
 138 
     | 
    
         
            +
                  end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                  def self.check_session!
         
     | 
| 
      
 141 
     | 
    
         
            +
                    if @@api.nil? || @@client.nil?
         
     | 
| 
      
 142 
     | 
    
         
            +
                      raise GoogleApi::SessionError, "You are not log in."
         
     | 
| 
      
 143 
     | 
    
         
            +
                    end
         
     | 
| 
      
 144 
     | 
    
         
            +
                  end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                  def self.api
         
     | 
| 
      
 147 
     | 
    
         
            +
                    check_session!
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                    @@api
         
     | 
| 
      
 150 
     | 
    
         
            +
                  end
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                  def self.client
         
     | 
| 
      
 153 
     | 
    
         
            +
                    check_session!
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                    if @@client.authorization.refresh_token && @@client.authorization.expired?
         
     | 
| 
      
 156 
     | 
    
         
            +
                      @@client.authorization.fetch_access_token!
         
     | 
| 
      
 157 
     | 
    
         
            +
                    end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                    @@client
         
     | 
| 
      
 160 
     | 
    
         
            +
                  end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                end
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
              end
         
     | 
| 
      
 165 
     | 
    
         
            +
            end
         
     |