Blame platform-demos/es/record-collection.js.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="record-collection.js" xml:lang="es">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
  <title type="text">Colección de música (JavaScript)</title>
Packit 1470ea
    <link type="guide" xref="js#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>Cree una pequeña aplicación con una base de datos para ordenar su colección de música</desc>
Packit 1470ea
Packit 1470ea
    <revision pkgversion="0.1" version="0.1" date="2011-02-22" status="review"/>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>Proyecto de documentación de GNOME</name>
Packit 1470ea
      <email its:translate="no">gnome-doc-list@gnome.org</email>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>Johannes Schmid</name>
Packit 1470ea
      <email its:translate="no">jhs@gnome.org</email>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="editor">
Packit 1470ea
      <name>Marta Maria Casetti</name>
Packit 1470ea
      <email its:translate="no">mmcasettii@gmail.com</email>
Packit 1470ea
      <years>2013</years>
Packit 1470ea
    </credit>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Daniel Mustieles</mal:name>
Packit 1470ea
      <mal:email>daniel.mustieles@gmail.com</mal:email>
Packit 1470ea
      <mal:years>2011 - 2017</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Nicolás Satragno</mal:name>
Packit 1470ea
      <mal:email>nsatragno@gmail.com</mal:email>
Packit 1470ea
      <mal:years>2012 - 2013</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Jorge González</mal:name>
Packit 1470ea
      <mal:email>jorgegonz@svn.gnome.org</mal:email>
Packit 1470ea
      <mal:years>2011</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>Colección de música</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

En este tutorial aprenderá:

Packit 1470ea
  <list>
Packit 1470ea
    <item>

Cómo conectar con una base de datos usando libgda

</item>
Packit 1470ea
    <item>

Cómo insertar y examinar registros en una tabla de una base de datos

</item>
Packit 1470ea
  </list>
Packit 1470ea
</synopsis>
Packit 1470ea
Packit 1470ea
<section id="intro">
Packit 1470ea
  <title>Introducción</title>
Packit 1470ea
  

Esta demostración usa el lenguaje Javascript. Se va a demostrar cómo conectar y usar una base de datos desde un programa GTK, usando la bilbioteca GDA («GNOME Data Access», Acceso a datos de GNOME). Por lo tanto, es necesario tener instalada también esta biblioteca.

Packit 1470ea
  

Acceso a Datos de GNOME (GDA) es una biblioteca cuyo propósito es proporcionar acceso universal a diferentes tipos de fuentes de datos. Esto abarca desde los tradicionales sistemas de bases da datos relacionales hasta cualquier fuente de datos imaginable como un servidor de correo-e, un directorio LDAP, etc. Para obtener más información y una documentación completa de la API, visite la <link href="http://library.gnome.org/devel/libgda/stable/">página web de GDA</link>.

Packit 1470ea
  

Aunque una gran parte del código se refiere a la interfaz de usuario (IU), el tutorial se enfocará a las partes de las bases de datos (aunque se puede hacer mención a otras partes que se consideren relevantes). Para aprender más sobre los programas en Javascript en GNOME, consulte el tutorial del programa<link xref="image-viewer.js">Visor de Imágenes</link>

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="anjuta">
Packit 1470ea
  <title>Crear un proyecto en Anjuta</title>
Packit 1470ea
  

Antes de empezar a programar, deberá configurar un proyecto nuevo en Anjuta. Esto creará todos los archivos que necesite para construir y ejecutar el código más adelante. También es útil para mantener todo ordenado.

Packit 1470ea
  <steps>
Packit 1470ea
    <item>
Packit 1470ea
    

Inicie Anjuta y pulse <guiseq><gui>Archivo</gui><gui>Nuevo</gui><gui>Proyecto</gui></guiseq> para abrir el asistente de proyectos.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

Elija <gui>JavaScript genérico</gui> de la pestaña <gui>JS</gui>, pulse <gui>Adelante</gui> y rellene los detalles en las siguientes páginas. Use <file>coleccion-de-albumes</file> como nombre de proyecto y de carpeta.

Packit 1470ea
   	</item>
Packit 1470ea
    <item>
Packit 1470ea
    

Pulse <gui>Finalizar</gui> y se creará el proyecto. Abra <file>src/main.js</file> desde la pestaña <gui>Proyecto</gui> o <gui>Archivo</gui>. Contiene un ejemplo de código muy básico.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="structure">
Packit 1470ea
  <title>Estructura del programa</title>
Packit 1470ea
  <media type="image" mime="image/png" src="media/record-collection.png"/>
Packit 1470ea
  

Esta demostración es una aplicación GTK sencilla (con una única ventana) capaz de insertar registros en la tabla de una base de datos, así como de examinar todos los registros de la tabla. La tabla tiene dos campos: id, un entero, y name, un «varchar». La primera sección (en la parte superior) de la aplicación le permite insertar un registro en la tabla. La última sección (en la parte inferior) le permite ver todos los registros de la tabla. El contenido se actualiza cada vez que se insertar un registro y al inicio de la aplicación.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="start">
Packit 1470ea
  <title>Empezar la diversión</title>
Packit 1470ea
  

Empezar examinando el esqueleto del programa:

Packit 1470ea
  
Packit 1470ea
const GLib = imports.gi.GLib;
Packit 1470ea
const Gtk = imports.gi.Gtk;
Packit 1470ea
const Gda = imports.gi.Gda;
Packit 1470ea
const Lang = imports.lang;
Packit 1470ea
Packit 1470ea
function Demo () {
Packit 1470ea
  this._init ();
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
Demo.prototype = {
Packit 1470ea
Packit 1470ea
  _init: function () {
Packit 1470ea
    this.setupWindow ();
Packit 1470ea
    this.setupDatabase ();
Packit 1470ea
    this.selectData ();
Packit 1470ea
  }
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
Gtk.init (null, null);
Packit 1470ea
Packit 1470ea
var demo = new Demo ();
Packit 1470ea
Packit 1470ea
Gtk.main ();
Packit 1470ea
  <list>
Packit 1470ea
    <item>

Líneas 1‒4: importaciones iniciales. Preste especial atención a la línea 3, que indica a Javascript que importe la biblioteca GDA, nuestro objetivo en este tutorial.

</item>
Packit 1470ea
    <item>

Líneas 6‒17: definir la clase Demo. Preste especial atención a las líneas 13‒15, donde se llama a 3 métodos que harán todo el trabajo. Se detallarán más adelante.

</item>
Packit 1470ea
    <item>

Líneas 19‒23: iniciar la aplicación.

</item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="design">
Packit 1470ea
  <title>Diseñar la aplicación</title>
Packit 1470ea
  

Eche un vistazo al método setupWindow. Es el responsable de crear la interfaz de usuario (IU). Ya que la IU no es el objetivo, sólo se explicarán las partes relevantes.

Packit 1470ea
  
Packit 1470ea
  setupWindow: function () {
Packit 1470ea
    this.window = new Gtk.Window ({title: "Data Access Demo", height_request: 350});
Packit 1470ea
    this.window.connect ("delete-event", function () {
Packit 1470ea
      Gtk.main_quit();
Packit 1470ea
      return true;
Packit 1470ea
      });
Packit 1470ea
Packit 1470ea
    // main box
Packit 1470ea
    var main_box = new Gtk.Box ({orientation: Gtk.Orientation.VERTICAL, spacing: 5});
Packit 1470ea
    this.window.add (main_box);
Packit 1470ea
Packit 1470ea
    // first label
Packit 1470ea
    var info1 = new Gtk.Label ({label: "<b>Insert a record</b>", xalign: 0, use_markup: true});
Packit 1470ea
    main_box.pack_start (info1, false, false, 5);
Packit 1470ea
Packit 1470ea
    // "insert a record" horizontal box
Packit 1470ea
    var insert_box = new Gtk.Box ({orientation: Gtk.Orientation.HORIZONTAL, spacing: 5});
Packit 1470ea
    main_box.pack_start (insert_box, false, false, 5);
Packit 1470ea
Packit 1470ea
    // ID field
Packit 1470ea
    insert_box.pack_start (new Gtk.Label ({label: "ID:"}), false, false, 5);
Packit 1470ea
    this.id_entry = new Gtk.Entry ();
Packit 1470ea
    insert_box.pack_start (this.id_entry, false, false, 5);
Packit 1470ea
Packit 1470ea
    // Name field
Packit 1470ea
    insert_box.pack_start (new Gtk.Label ({label: "Name:"}), false, false, 5);
Packit 1470ea
    this.name_entry = new Gtk.Entry ({activates_default: true});
Packit 1470ea
    insert_box.pack_start (this.name_entry, true, true, 5);
Packit 1470ea
Packit 1470ea
    // Insert button
Packit 1470ea
    var insert_button = new Gtk.Button ({label: "Insert", can_default: true});
Packit 1470ea
    insert_button.connect ("clicked", Lang.bind (this, this._insertClicked));
Packit 1470ea
    insert_box.pack_start (insert_button, false, false, 5);
Packit 1470ea
    insert_button.grab_default ();
Packit 1470ea
Packit 1470ea
    // Browse textview
Packit 1470ea
    var info2 = new Gtk.Label ({label: "<b>Browse the table</b>", xalign: 0, use_markup: true});
Packit 1470ea
    main_box.pack_start (info2, false, false, 5);
Packit 1470ea
    this.text = new Gtk.TextView ({editable: false});
Packit 1470ea
    var sw = new Gtk.ScrolledWindow ({shadow_type:Gtk.ShadowType.IN});
Packit 1470ea
    sw.add (this.text);
Packit 1470ea
    main_box.pack_start (sw, true, true, 5);
Packit 1470ea
Packit 1470ea
    this.count_label = new Gtk.Label ({label: "", xalign: 0, use_markup: true});
Packit 1470ea
    main_box.pack_start (this.count_label, false, false, 0);
Packit 1470ea
Packit 1470ea
    this.window.show_all ();
Packit 1470ea
  },
Packit 1470ea
  <list>
Packit 1470ea
    <item>

Líneas 22 y 27: crear las dos entradas (para los dos campos) en las que el usuario escribirá algo para insertarlo en la base de datos.

</item>
Packit 1470ea
    <item>

Líneas 31‒34: crear el botón «Insertar». Se conecta su señal clicked con el método privado _insertClicked de la clase. Este método se detalla a continuación.

</item>
Packit 1470ea
    <item>

Línea 39: crear el widget (TextView) donde se mostrarán los contenidos de la tabla.

</item>
Packit 1470ea
    <item>

Línea 44: crear la etiqueta donde se mostrará el número de registros de la tabla. Inicialmente está vacía, se actualizará más tarde.

</item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="connect">
Packit 1470ea
  <title>Conectar e inicializar la base de datos</title>
Packit 1470ea
  

El código que hace la conexión con la base de datos está en método setupDatabase siguiente:

Packit 1470ea
  
Packit 1470ea
  setupDatabase: function () {
Packit 1470ea
    this.connection = new Gda.Connection ({provider: Gda.Config.get_provider("SQLite"),
Packit 1470ea
                                          cnc_string:"DB_DIR=" + GLib.get_home_dir () + ";DB_NAME=gnome_demo"});
Packit 1470ea
    this.connection.open ();
Packit 1470ea
Packit 1470ea
    try {
Packit 1470ea
      var dm = this.connection.execute_select_command ("select * from demo");
Packit 1470ea
    } catch (e) {
Packit 1470ea
      this.connection.execute_non_select_command ("create table demo (id integer, name varchar(100))");
Packit 1470ea
    }
Packit 1470ea
  },
Packit 1470ea
  <list>
Packit 1470ea
    <item>
Packit 1470ea
      

Líneas 2‒3: crear el objeto de GDA Connection. Se deben proporcionar a su constructor algunas propiedades:

Packit 1470ea
      <list>
Packit 1470ea
        <item>
Packit 1470ea
          

provider: uno de los proveedores de GDA soportados. GDA soporta SQLite, MySQL, PostgreSQL, Oracle y muchos otros. Para la demostración se usará una base de datos SQLite, ya que viene instalada de manera predeterminada en la mayoría de las distribuciones y es fácil de usar (sólo usa un archivo como base de datos).

Packit 1470ea
        </item>
Packit 1470ea
        <item>
Packit 1470ea
          

cnc_string: la cadena de conexión. Puede cambiar de un proveedor a otro. La sintaxis de SQLite es: DB_DIR=PATH;DB_NAME=FILENAME. En esta demostración se accederá a una base de datos llamada «gnome_demo» en la carpeta del usaurio (tenga en cuenta la llamada a la función get_home_dir de GLib).

Packit 1470ea
        </item>
Packit 1470ea
      </list>
Packit 1470ea
      <note>
Packit 1470ea
        

Si GDA no soporta el proveedor, o si falta algún elemento en la cadena de conexión, la línea 2 elevará una excepción. Por esto, en la vida real hay que manejarlo con la sentencia try...catch de JavaScript.

Packit 1470ea
      </note>
Packit 1470ea
    </item>
Packit 1470ea
Packit 1470ea
    <item>

Línea 4: abrir la conexión. En el proveedor de SQLite, si la base de datos no existe, se creará en este paso.

</item>
Packit 1470ea
    <item>
Packit 1470ea
      

Líneas 6‒10: intentar hacer una selección simple para comprobar si la tabla existe. Si no existe (porque la base de datos se acaba de crear), este comando elevará una excepción, que se maneja en el bloque try...catch block. Si este es el caso, se ejecuta la sentencia para crear tabla (línea 9).

Packit 1470ea
      

Para ejecutar los comandos SQL anteriores se usan los métodos de conexión de GDA execute_select_command y execute_non_select_command. Son fáciles de usar, y sólo requieren dos argumentos: el objeto Connection y el comando SQL que analizar.

Packit 1470ea
    </item>
Packit 1470ea
  </list>
Packit 1470ea
Packit 1470ea
  

En este punto, ya está configurada la base de datos y lista para usarse.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="select">
Packit 1470ea
  <title>Seleccionar</title>
Packit 1470ea
  

Después de conectar a la base de datos, el constructor de la demostración llama al método selectData. Es el responsable de obtener todos los registros de la tabla y de mostrarlos en el widget TextView. Échele un vistazo:

Packit 1470ea
  
Packit 1470ea
  selectData: function () {
Packit 1470ea
    var dm = this.connection.execute_select_command  ("select * from demo order by 1, 2");
Packit 1470ea
    var iter = dm.create_iter ();
Packit 1470ea
Packit 1470ea
    var text = "";
Packit 1470ea
Packit 1470ea
    while (iter.move_next ()) {
Packit 1470ea
      var id_field = Gda.value_stringify (iter.get_value_at (0));
Packit 1470ea
      var name_field = Gda.value_stringify (iter.get_value_at (1));
Packit 1470ea
Packit 1470ea
      text += id_field + "\t=>\t" + name_field + '\n';
Packit 1470ea
    }
Packit 1470ea
Packit 1470ea
    this.text.buffer.text = text;
Packit 1470ea
    this.count_label.label = "<i>" + dm.get_n_rows () + " record(s)</i>";
Packit 1470ea
  },
Packit 1470ea
  <list>
Packit 1470ea
    <item>

Línea 2: el comando SELECT. Se usa el método de conexión execute_select_command de GDA. Devuelve un objeto DataModel, que se usa más tarde para obtener las filas.

</item>
Packit 1470ea
    <item>

Línea 3: crear un objeto Iter, que se usa para iterar sobre los registros de DataModel.

</item>
Packit 1470ea
    <item>

Línea 7: recorrer todos los registros, recuperándolos con la ayuda del objeto Iter. En este punto, la variable iter contiene los datos obtenidos actualmente. Su método move_next devuelve false cuando se alcanza el último registro.

</item>
Packit 1470ea
    <item>
Packit 1470ea
      

Líneas 8‒9: se hacen dos cosas en cada línea:

Packit 1470ea
      <list>
Packit 1470ea
        <item>

Use el método get_value_at de Iter, que sólo necesita un argumento: el número de columna que recuperar, empezando por 0. Ya que el comando SELECT sólo devuelve dos columnas, se están recuperando las columnas 0 y 1.

</item>
Packit 1470ea
        <item>

El método get_value_at devuelve el campo en el formato GValue de GLib. Una manera sencilla de convertir este valor en una cadena es usar la función global de GDA value_stringify. Es lo que se está haciendo aquí, y el resultado se almacena en las variables id_field y name_field.

</item>
Packit 1470ea
      </list>
Packit 1470ea
    </item>
Packit 1470ea
    <item>

Línea 11: concatenar los dos registros para formar una línea de texto, separados por "=>", y almacenarla en la variable text.

</item>
Packit 1470ea
    <item>

Línea 14: cuando termine el bucle, se tendrán todos los registros formateados en la variable text. En esta línea, simplemente se establece el contenido del TextView con esta variable.

</item>
Packit 1470ea
    <item>

Línea 15: mostrar el número de registros en la tabla, usando el método get_n_rows de DataModel get_n_rows.

</item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="insert">
Packit 1470ea
  <title>Insertar</title>
Packit 1470ea
  

Bien, ahora ya sabe cómo conectarse a la base de datos y cómo seleccionar filas de una tabla. Ahora es el momento de hacer un INSERT en la tabla. ¿Recuerda cuando antes, en el método setupWindow, se conectó la señal clicked del botón <gui>Insertar</gui> al método _insertClicked?. Vea la implementación de este método.

Packit 1470ea
  
Packit 1470ea
  _insertClicked: function () {
Packit 1470ea
    if (!this._validateFields ())
Packit 1470ea
      return;
Packit 1470ea
Packit 1470ea
    // Gda.execute_non_select_command (this.connection,
Packit 1470ea
    //   "insert into demo values ('" + this.id_entry.text + "', '" + this.name_entry.text + "')");
Packit 1470ea
Packit 1470ea
    var b = new Gda.SqlBuilder ({stmt_type:Gda.SqlStatementType.INSERT});
Packit 1470ea
    b.set_table ("demo");
Packit 1470ea
    b.add_field_value_as_gvalue ("id", this.id_entry.text);
Packit 1470ea
    b.add_field_value_as_gvalue ("name", this.name_entry.text);
Packit 1470ea
    var stmt = b.get_statement ();
Packit 1470ea
    this.connection.statement_execute_non_select (stmt, null);
Packit 1470ea
Packit 1470ea
    this._clearFields ();
Packit 1470ea
    this.selectData ();
Packit 1470ea
  },
Packit 1470ea
  

Se ha aprendido a usar los métodos de conexión de GDA execute_select_command y execute_non_select_command para ejecutar comandos SQL rápidamente en la base de datos. GDA le permite construir una sentencia SQL de manera indirecta, usando su objeto SqlBuilder. ¿Cuáles son los beneficios de esto? GDA generará la sentencia SQL dinámicamente, y será válida para el proveedor de la conexión usado (usará el mismo dialecto de SQL que usa el proveedor). Estudie el código:

Packit 1470ea
  <list>
Packit 1470ea
    <item>

Líneas 2‒3: comprobar si el usuario ha rellenado todos los campos. El código del método privado _validateFields es realmente simple y puede leerlo en el código fuente completo de la demostración.

</item>
Packit 1470ea
    <item>

Línea 5: la manera más rápida de hacer el INSERT. Se ha comentado que se quiere mostrar cómo usar el objeto SqlBuilder para construir una sentencia SQL portable entre bases de datos.

</item>
Packit 1470ea
    <item>

Línea 7: crear el objeto SqlBuilder. Se debe pasar el tipo de sentencia que se va a construir. Puede ser SELECT, UPDATE, INSERT o DELETE.

</item>
Packit 1470ea
    <item>

Línea 8: establecer el nombre de la base de datos en la que operará la sentencia construida (generará INSERT INTO demo)

</item>
Packit 1470ea
    <item>

Líneas 9‒10: establecer los campos que formarán parte de la sentencia y sus valores. El primer argumento es el nombre del campo (como aparece en la tabla). El segundo es el valor de este campo.

</item>
Packit 1470ea
    <item>

Línea 11: obtener el objeto Statement generado dinámicamente, que representa una sentencia SQL.

</item>
Packit 1470ea
    <item>

Línea 12: finalmente, ejecutar la sentencia SQL (INSERT).

</item>
Packit 1470ea
    <item>

Línea 14: limpiar los campos «id» y «name» en la pantalla. El código del método privado _clearFields es muy sencillo, y puede leerlo en el código fuente de la demostración completa.

</item>
Packit 1470ea
    <item>

Línea 15: actualizar la vista en la pantalla haciendo otro SELECT.

</item>
Packit 1470ea
  </list>
Packit 1470ea
  <note>

También puede usar parámetros mientras construye la sentencia. Usando objetos y parámetros SqlBuilder será menos susceptible a ataques de inyección de SQL. Para obtener información adicional sobre los parámetros, consulte la <link href="http://library.gnome.org/devel/libgda/stable/">documentación de GDA</link>.

</note>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="run">
Packit 1470ea
  <title>Ejecutar la aplicación</title>
Packit 1470ea
  

Todo el código que necesita debe estar en su lugar, así que trate de ejecutar el código. Ahora tiene una base de datos para su colección de registros.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="impl">
Packit 1470ea
 <title>Implementación de referencia</title>
Packit 1470ea
 

Si tiene problemas con este tutorial, compare su código con este <link href="record-collection/record-collection.js">código de referencia</link>.

Packit 1470ea
</section>
Packit 1470ea
</page>