18 de julio de 2006

Abrir tablas

Artículo original: Opening tables
http://weblogs.foxite.com/andykramek/2006/06/10/opening-tables
Autor: Andy Kramek
Traducido por: Ana María Bisbé York


Uno de los códigos, que se escribe con más frecuencia, en la mayoría de las aplicaciones, tiene el siguiente aspecto:
*** Guardar el área de trabajo actual
lnSelect = SELECT()
*** Seleccionar el área requerida
IF ! USED( <Alias> )
  USE <table_name> IN 0 AGAIN ALIAS <Alias>
ENDIF
SELECT <New Work Area>
*** Hacer algo aquí
...
<commands>
...
*** Devolver el control al área original
SELECT (lnSelect)
Bien, admitamos que no es tan difícil; pero de esta forma o con alguna variación se repite muchas veces en una aplicación. Debemos ser capaces de hacerlo mejor, y de hecho podemos, ya que tenemos detrás nuestro el poder de la Orientación a objetos. La clase SelAlias define un objeto que acepta el nombre del alias de una tabla como un parámetro y establece el área de la tabla. Si la tabla no está abierta, abrirá la tabla por nosotros y si no puede encontrar la tabla, nos preguntará su localización para poder encontrarla. Más importante aun, la clase "recordará" que fue abierta la tabla y cuando el objeto sea liberado cerrará la tabla y se restaurará el área de trabajo que estaba activa cuando fue instanciado el objeto. La clase, brinda además la posibilidad para un parámetro adicional que puede ser utilizado para especificar un nombre físico de tabla cuando es necesario abrir la tabla con un alias diferente del nombre de la tabla.

Vea que esta clase no expone propiedades o métodos y hace todo su trabajo en los métodos Init y Destroy. Al crear un objeto basado en esta clase, y definirla como LOCAL, nosotros nunca más necesitaremos escribir el código que aparece antes. Se pretende que la clase pueda ser utilizada en cualquier momento que se necesite abrir una tabla al vuelo, por tanto típicamente la utilizo al crear una variable local para utilizarla como referencia al objeto. La consecuencia es que tan pronto como el método que crea la referencia termine, el objeto es liberado y la tabla se cierra (si no estaba abierta antes) y el alias original se vuelve a activar.

La clase está basada en la clase base relation - es pequeña y ligera, es rápida de instanciar; pero a diferencia de la clase base empty tiene los métodos nativos Init() y Destroy().

He utilizado este código de forma extensa "tal cual"; pero puede extenderse fácilmente para controlar otras condiciones y escenarios - por ejemplo, no va a funcionar con vistas, debido a que asume que existe un archivo físico - pero es fácilmente reparable si necesita que controle también este escenario. En cualquier caso, he aquí el código, es usted libre de modificarlo y mejorarlo
********************************************************************
*** Nombre.....: SELALIAS.PRG
*** Autor...: Andy Kramek & Marcia Akins
*** Fecha.....: 06/10/2006
*** Nota...: Copyright (c) 2006 Tightline Computers, Inc
*** Compilador.: Visual FoxPro 09.00.0000.3504 for Windows
*** Función.: Clase para seleccionar un área de trabajo específica y restablecerla
*** .........: Utilice como un objeto local para cambiar el área de trabajo.
*** .........: Al liberarlo va a restablecer el área de trabajo anterior
*** .........: Acepta dos parámetros, el primero es el Alias y es obligatorio
*** .........: El segundo es el nombre de la tabla. Si no se pasa, asume que será
*** .........: el mismo alias que está utilizando.
*** .........: loSel = CREATEOBJECT( 'xSelAlias', <Alias> [, |<File Name> ] )
********************************************************************
********************************************************************
DEFINE CLASS xSelAlias AS RELATION
******************************************************************
  PROTECTED nOldArea
  nOldArea = 0
  PROTECTED lWasOpen
  lWasOpen = .T.
  PROTECTED cAlias
  cAlias = ''
  ****************************************************************
  *** Init: Método nativo de inicialización
  ****************************************************************
  PROCEDURE INIT( tcAlias, tcTable )
    LOCAL llRetVal
    *** No se pasa ningún Alias - Nos vamos
    IF ! VARTYPE( tcAlias ) = "C" OR EMPTY( tcAlias )
      ASSERT .F. MESSAGE "Debe pasar un nombre de ALIAS PARA seleccionar el área
      de trabajo"
        RETURN .F.
    ENDIF
    tcAlias = UPPER( ALLTRIM( tcAlias ) )
    IF VARTYPE( tcTable ) # "C" OR EMPTY( tcTable )
      tcTable = tcAlias
    ELSE
      tcTable = UPPER( ALLTRIM( tcTable ) )
    ENDIF
    *** Si ya está en esa área de trabajo, no hace nada
    IF UPPER( ALLTRIM( ALIAS() ) ) == tcAlias
      RETURN .F.
    ELSE
      *** ¿Existe la tabla?
      tcTable = FORCEEXT( tcTable, 'dbf' )
      IF NOT FILE( tcTable )
        *** Intenta encontrarla....
        tcTable = LOCFILE( JUSTFNAME( tcTable ), 'dbf', "Cannot FIND" )
        IF EMPTY( tcTable )
          *** No podemos hacer nada más
          RETURN .F.
        ELSE
          *** Quizás sea que recibimos mal el nombre - establece el alias de la tabla
          tcAlias = JUSTSTEM( tcTable )
        ENDIF
      ENDIF
    ENDIF
    *** Si el alias especificada no está abierta - la abre
    IF ! USED( tcAlias )
      USE ( tcTable ) AGAIN IN 0 ALIAS ( tcAlias ) SHARED
      *** ¡ Y verifica !
      llRetVal = USED( tcAlias )
      *** If Forced Open, Note the fact
      IF llRetVal
        THIS.lWasOpen = .F.
      ENDIF
    ELSE
      llRetVal = .T.
    ENDIF
    *** Si todo OK, guardamos el área de trabajo actual
    *** Ahora se mueve al área de trabajo especificada
    IF llRetVal
      THIS.nOldArea = SELECT()
      SELECT ( tcAlias )
      THIS.cAlias = tcAlias
    ENDIF
    *** Devuelve el estado
    RETURN llRetVal
  ENDPROC
  ****************************************************************
  *** Destroy: Método nativo de destrucción de objetos
  ****************************************************************
  PROCEDURE DESTROY
    WITH THIS
      *** Si la tabla fue abierta por el objeto, se cierra
      IF NOT .lWasOpen
        USE IN ( THIS.cAlias )
      ENDIF
      *** Restablece el área de trabajo anterior
      IF NOT EMPTY( .nOldArea )
        SELECT ( .nOldArea )
      ENDIF
    ENDWITH
  ENDPROC
ENDDEFINE

No hay comentarios. :

Publicar un comentario