# encoding: utf-8 # require 'mode/sdk/warehouse_util' module Mode module Sdk # Represents a table stored in the Mode public data warehouse # # @example # table = Mode::Sdk::Table.new('sf_film_locations') # table.columns = [ # { name: 'movie_title', type: 'string' }, # { name: 'release_year', type: 'integer' }, # { name: 'location', type: 'string' } # ] # table.create # # @attr_reader [Array] columns an array of hashes defining column # names and types # # @attr [String] description a brief table description # @attr [String] upload_token the token of the Mode::Sdk::Upload # containing the CSV with which to populate the table # class Table extend Mode::Sdk::WarehouseUtil # Pattern to determine whether a String is a valid table name # NAME_PATTERN = /\A[a-z][a-z0-9_]{2,62}[a-z0-9]\z/ attr_reader :columns attr_accessor :description, :upload_token # Construct a new Table instance # # @param name [String] valid table name # @param options [optional, Hash] hash of options # # @option options [String] :owner the username or alias of the Mode # account associated with the table (defaults to currently # authenticated account) # # @return [Mode::Sdk::Table] the instance # def initialize(name, options = {}) @name = name @options = options end # Determine whether a table with this name already exists for the given # Mode account # # @return [true, false] whether the table exists # def exists? Mode::Sdk::Client.head(resource_path, expect: [200, 404]).code == 200 end # Create the table in Mode # # @return [Mode::Sdk::Client::Response] the response # def create upsert(:create) end # Replace an existing table in Mode # # @return [Mode::Sdk::Client::Response] the response # def replace upsert(:replace) end # Assign columns to the table and unmemoize column set, if any # # @param columns [Array] an array of hashes defining column names # and types # # @return [Array] the array of columns # def columns=(columns) if instance_variable_defined?(:@column_set) remove_instance_variable(:@column_set) end @columns = columns end # The full name of the table, including owner schema # # @return [String] the full name # def full_name [owner, name].join('.') end private attr_reader :name, :options def owner options.fetch(:owner, nil) || Mode::Sdk.username end def collection_path "/api/#{owner}/tables" end def resource_path [collection_path, name].join('/') end def column_set @column_set ||= Mode::Sdk::ColumnSet.new(columns) end def validate! unless upload_token fail InvalidError, 'Missing required attribute: upload_token' end unless name =~ NAME_PATTERN fail InvalidError, "Invalid name: #{name.inspect}" end column_set.validate! true end def upsert(action) validate! path = action == :replace ? resource_path : collection_path verb = action == :replace ? :put : :post response = Mode::Sdk::Client.send( verb, path, upsert_json, expect: [202, 400]) if response.code == 400 fail InvalidError, "Could not #{action} table: #{response.body}" end response end def upsert_json upsert_data.to_json end def upsert_data { upload_token: upload_token, table: { name: name, description: description, columns: column_set.to_array } } end class InvalidError < StandardError; end end end end