module Swift # Adapter. # # @abstract # @see Swift::DB See Swift::DB for concrete adapters. class Adapter attr_reader :options # Select by id(s). # # @example Single key. # Swift.db.get(User, id: 12) # @example Complex primary key. # Swift.db.get(UserAddress, user_id: 12, address_id: 15) # # @param [Swift::Scheme] scheme Concrete scheme subclass to load. # @param [Hash] keys Hash of id(s) {id_name: value}. # @return [Swift::Scheme, nil] # @see Swift::Scheme.get #-- # NOTE: Not significantly shorter than Scheme.db.first(User, 'id = ?', 12) def get scheme, keys resource = scheme.new(keys) prepare_get(scheme).execute(*resource.tuple.values_at(*scheme.header.keys)).first end # Create one or more. # # @example Scheme. # user = User.new(name: 'Apply Arthurton', age: 32) # Swift.db.create(User, user) # #=> Swift::Scheme # @example Coerce hash to scheme. # Swif.db.create(User, name: 'Apple Arthurton', age: 32) # #=> Swift::Scheme # @example Multiple resources. # apple = User.new(name: 'Apple Arthurton', age: 32) # benny = User.new(name: 'Benny Arthurton', age: 30) # Swift.db.create(User, [apple, benny]) # #=> Array # @example Coerce multiple resources. # Swift.db.create(User, [{name: 'Apple Arthurton', age: 32}, {name: 'Benny Arthurton', age: 30}]) # #=> Array # # @param [Swift::Scheme] scheme Concrete scheme subclass to load. # @param [Swift::Scheme, Hash, Array] resources The resources to be saved. # @return [Swift::Scheme, Array] # @note Hashes will be coerced into a Swift::Scheme resource via Swift::Scheme#new # @note Passing a scalar will result in a scalar. # @see Swift::Scheme.create def create scheme, resources statement = prepare_create(scheme) result = [resources].flatten.map do |resource| resource = scheme.new(resource) unless resource.kind_of?(scheme) result = statement.execute(*resource.tuple.values_at(*scheme.header.insertable)) resource.tuple[scheme.header.serial] = result.insert_id if scheme.header.serial resource end resources.kind_of?(Array) ? result : result.first end # Update one or more. # # @example Scheme. # user = Swift.db.create(User, name: 'Apply Arthurton', age: 32) # user.name = 'Arthur Appleton' # Swift.db.update(User, user) # #=> Swift::Scheme # @example Coerce hash to scheme. # user = Swift.db.create(User, name: 'Apply Arthurton', age: 32) # user.name = 'Arthur Appleton' # Swif.db.update(User, user.tuple) # #=> Swift::Scheme # @example Multiple resources. # apple = Swift.db.create(User, name: 'Apple Arthurton', age: 32) # benny = Swift.db.create(User, name: 'Benny Arthurton', age: 30) # Swift.db.update(User, [apple, benny]) # #=> Array # @example Coerce multiple resources. # apple = Swift.db.create(User, name: 'Apple Arthurton', age: 32) # benny = Swift.db.create(User, name: 'Benny Arthurton', age: 30) # Swift.db.update(User, [apple.tuple, benny.tuple]) # #=> Array # # @param [Swift::Scheme] scheme Concrete scheme subclass to load. # @param [Swift::Scheme, Hash, Array] resources The resources to be updated. # @return [Swift::Scheme, Swift::Result] # @note Hashes will be coerced into a Swift::Scheme resource via Swift::Scheme#new # @note Passing a scalar will result in a scalar. # @see Swift::Scheme#update def update scheme, resources statement = prepare_update(scheme) result = [resources].flatten.map do |resource| resource = scheme.new(resource) unless resource.kind_of?(scheme) keys = resource.tuple.values_at(*scheme.header.keys) # TODO: Name the key field(s) missing. raise ArgumentError, "#{scheme} resource has incomplete key: #{resource.inspect}" \ unless keys.select(&:nil?).empty? statement.execute(*resource.tuple.values_at(*scheme.header.updatable), *keys) resource end resources.kind_of?(Array) ? result : result.first end # Delete one or more. # # @example Scheme. # user = Swift.db.create(User, name: 'Apply Arthurton', age: 32) # user.name = 'Arthur Appleton' # Swift.db.delete(User, user) # @example Coerce hash to scheme. # user = Swift.db.create(User, name: 'Apply Arthurton', age: 32) # user.name = 'Arthur Appleton' # Swif.db.delete(User, user.tuple) # @example Multiple resources. # apple = Swift.db.create(User, name: 'Apple Arthurton', age: 32) # benny = Swift.db.create(User, name: 'Benny Arthurton', age: 30) # Swift.db.delete(User, [apple, benny]) # @example Coerce multiple resources. # apple = Swift.db.create(User, name: 'Apple Arthurton', age: 32) # benny = Swift.db.create(User, name: 'Benny Arthurton', age: 30) # Swift.db.delete(User, [apple.tuple, benny.tuple]) # # @param [Swift::Scheme] scheme Concrete scheme subclass to load. # @param [Swift::Scheme, Hash, Array] resources The resources to be deleteed. # @return [Swift::Scheme, Array] # @note Hashes will be coerced into a Swift::Scheme resource via Swift::Scheme#new # @note Passing a scalar will result in a scalar. # @see Swift::Scheme#delete def delete scheme, resources statement = prepare_delete(scheme) result = [resources].flatten.map do |resource| resource = scheme.new(resource) unless resource.kind_of?(scheme) keys = resource.tuple.values_at(*scheme.header.keys) # TODO: Name the key field(s) missing. raise ArgumentError, "#{scheme} resource has incomplete key: #{resource.inspect}" \ unless keys.select(&:nil?).empty? if result = statement.execute(*keys) resource.freeze end result end resources.kind_of?(Array) ? result : result.first end protected def prepare_get scheme raise NotImplementedError end def prepare_create scheme raise NotImplementedError end def prepare_update scheme raise NotImplementedError end def prepare_delete scheme raise NotImplementedError end end # Adapter end # Swift