class Empire
Attributes
Public Class Methods
app_key is your Empire
application key, and is necessary for using the API opts can include any of:
* :api_server => the server to connect to (default: api.empiredata.com) * :enduser => a string identifying the end user, required for any operations on views (default: nil) * :secrets_yaml => the path to a YAML file generated by https://login.empiredata.co (default: nil)
# File lib/empire.rb, line 19 def initialize(app_key = nil, opts = {}) api_server = opts[:api_server] || 'api.empiredata.co' @app_key = app_key @enduser = opts[:enduser] @session_key = nil @http_client = HTTPClient.new protocol = api_server.start_with?('localhost') ? 'http' : 'https' @base_url = "#{protocol}://#{api_server}/empire/" @service_secrets = nil if opts[:secrets_yaml] @service_secrets = YAML.load_file opts[:secrets_yaml] end end
Public Instance Methods
Connect to specific service service: service name secrets: hash with service secrets (optional if the Empire
instance was initialized with a secrets_yaml)
# File lib/empire.rb, line 40 def connect(service, secrets = nil) path = "services/#{service}/connect" unless secrets unless @service_secrets raise Empire::MissingSecretsError.new end secrets = {} @service_secrets[service]['option'].each{|k, v| secrets[k] = v['value'] } end request path, :post, {}, secrets end
Describe all services, all tables within a given service, or a given table
# File lib/empire.rb, line 58 def describe(service = nil, table = nil) path = 'services' if service and table path += "/#{service}/#{table}" elsif service and !table path += "/#{service}" elsif !service and table raise Empire::MissingServiceError.new("Service must be specified if table is specified") end request path end
Delete a materialized view of SQL query
# File lib/empire.rb, line 106 def drop_view(name) unless @enduser raise Empire::MissingEnduserError.new end path = "view/#{name}" request path, :delete end
Insert a new row into this service table. The row should be a hash of {column: value}
# File lib/empire.rb, line 90 def insert(service, table, row) path = "services/#{service}/#{table}" request path, :post, {}, row end
emulate default Object#inspect method but only display the object_id, not the properties to make things cleaner and more similar to Python client
# File lib/empire.rb, line 136 def inspect "#<Empire:#{(object_id << 1).to_s(16)}>" end
Materialize a SQL query as a view. This creates or updates a view.
# File lib/empire.rb, line 96 def materialize_view(name, sql) unless @enduser raise Empire::MissingEnduserError.new end path = "view/#{name}" data = {'query' => sql} request path, :put, {}, data end
Paginated printing of an SQL query
# File lib/empire.rb, line 72 def print_query(sql) IRB::Pager.pager { query(sql) do |l| puts l end } end
Issue a SQL query, yielding each row
# File lib/empire.rb, line 81 def query(sql) path = 'query' io = request path, :post, {}, {query: sql}, stream: true io.each do |l| yield l end end
Datetime that this view was materialized at. nil if the materialization is currently pending.
# File lib/empire.rb, line 129 def view_materialized_at(name) status = view_status(name) Date.parse(status['materializedAt']) rescue nil end
Boolean check if a materialized view is ready for querying. @note The user is expected to check view_ready? before querying a view with query()
# File lib/empire.rb, line 116 def view_ready?(name) status = view_status(name) case status['viewStatus'] when 'ready' then true when 'pending' then false else raise APIError.new("Unknown view status: #{response['viewStatus']}") end end
Run automatic test of all services from YAML
# File lib/walkthrough.rb, line 5 def walkthrough @last_service = nil @last_table = nil unless @service_secrets puts "Please connect some services in https://login.empiredata.co, and download the new yaml file" return end @service_secrets.each do |secret| service = secret[0] walkthrough_service(service) end walkthrough_materialized_view(@last_service, @last_table) nil end
Private Instance Methods
# File lib/empire.rb, line 156 def create_session headers = {'Authorization' => "Empire appkey=\"#{@app_key}\""} session_url = "session/create" if @enduser session_url = session_url + "?enduser=#{@enduser}" end data = do_request session_url, :post, headers @sessionkey = data['sessionkey'] end
# File lib/empire.rb, line 166 def do_request(path, method = :get, headers = {}, data = {}, opts = {}) url = @base_url + path headers.merge!({'Content-Type' => 'application/json', 'Accept' => '*/*'}) if opts[:stream] # return an IO object representing the streamed content conn = @http_client.request_async method, url, nil, data.to_json, headers conn.pop.content else # return the response body, parsed as JSON response = @http_client.request method, url, body: data.to_json, header: headers begin json = JSON.parse(response.body) rescue => e raise Empire::APIError.new("#{e} #{response.body}") end if json["status"] != "OK" raise Empire::APIError.new(json["error"]) end json end end
# File lib/walkthrough.rb, line 94 def print_row(row, max_length = 70) fragment = row.slice(0, max_length) if fragment.length == max_length fragment = fragment + "..." end puts " #{fragment}" end
# File lib/empire.rb, line 150 def request(path, method = :get, headers = {}, data = {}, opts = {}) create_session unless @sessionkey headers_with_session = headers.merge({'Authorization' => "Empire sessionkey=\"#{@sessionkey}\""}) do_request path, method, headers_with_session, data, opts end
# File lib/empire.rb, line 142 def view_status(name) unless @enduser raise Empire::MissingEnduserError.new end path = "view/#{name}/status" request path, :get end
# File lib/walkthrough.rb, line 71 def walkthrough_materialized_view(service, table) unless @enduser puts "Please specify an enduser parameter when instantiating the client, so that you can try materialized views" return end puts "empire.materialize_view('view_name', 'SELECT * FROM #{service}.#{table} LIMIT 5')" materialize_view('view_name', "SELECT * FROM #{service}.#{table} LIMIT 5") puts "until empire.view_ready? 'view_name'\n sleep 0.01\nend" until view_ready? 'view_name' sleep 0.01 end puts "empire.query 'SELECT * FROM view_name'" query('SELECT * FROM view_name') do |row| print_row(row) end puts "empire.drop_view 'view_name'" drop_view 'view_name' end
# File lib/walkthrough.rb, line 26 def walkthrough_service(service) puts "empire.connect '#{service}'" begin connect service rescue puts "Problem connecting to #{service}" return end tables = describe service unless tables and tables['service'] and tables['service']['tables'] puts "Can't find tables belonging to #{service}" return end tables['service']['tables'].each do |table_data| table = table_data['table'] walkthrough_table(service, table) end @last_service = service end
# File lib/walkthrough.rb, line 50 def walkthrough_table(service, table) if service == "mailchimp" # These mailchimp tables can only be queried when filtering by a particular list. if ["list_member", "campaign", "campaign_sent_to", "campaign_opened"].include? table return end end begin sql = "SELECT * FROM #{service}.#{table} LIMIT 5" puts "empire.query '#{sql}'" query(sql) do |row| print_row(row) end rescue Exception => e puts "Problem with #{service}.#{table}" end @last_table = table end