Blame platform-demos/gl/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="gl">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
  <title type="text">Record collection (JavaScript)</title>
Packit 1470ea
    <link type="guide" xref="js#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>Cree un pequeno aplicativo con unha base de datos para ordenar a súa 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>Proxecto 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>Fran Dieguez</mal:name>
Packit 1470ea
      <mal:email>frandieguez@gnome.org</mal:email>
Packit 1470ea
      <mal:years>2012-2013.</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>Record collection</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

Neste titorial aprenderá:

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

Como conectar con unha base de datos usando libgda

</item>
Packit 1470ea
    <item>

Como insertar e examinar rexistros nunha táboa dunha base de datos

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

Esta demostración usa o linguaxe JavaScript. Vaise demostrar como conectar e usar unha base de datos desde un programa GTK, usando a biblioteca GDA («GNOME Data Access», Acceso a datos de GNOME). Polo tanto, é preciso ter instalada tamén esta biblioteca.

Packit 1470ea
  

GNOME Data Access (GDA) é unha biblioteca cuxo propósito é fornecer acceso universal a diferentes tipos de orixes de datos. Isto vai desde os sistemas de bases de datos relacionais tradicionais a calquera tipo imaxinábel de orixe de datos como un servidor de correo, un directorio LDAP, ect. Para máis información e para obter a API completa e a documentación visite o <link href="http://library.gnome.org/devel/libgda/stable/">sitio web de GDA</link>.

Packit 1470ea
  

Aínda que a maioría do código está relacionado con interfaces de usuario (GUI), imos enforcar este titorial nas partes relacionadas coa base de datos (aínda que podemos mencionar outras partes que son relevantes). Para saber máis sobre os programas JavaScript en GNOME vexa o titorial <link xref="image-viewer.js">programa Visor de Imaxes</link>.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="anjuta">
Packit 1470ea
  <title>Cree un proxecto de Anjuta</title>
Packit 1470ea
  

Antes de comezar a programar, deberá configurar un proxecto novo en Anjuta. Isto creará todos os ficheiros que precise para construír e executar o código máis adiante. Tamén é útil para manter todo ordenado.

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

Inicie Anjuta e prema <guiseq><gui>Ficheiro</gui><gui>Novo</gui><gui>Proxecto</gui></guiseq> para abrir o asistente de proxectos.

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

Seleccione <gui>JavaScript xenérico</gui> desde a lapela <gui>JS</gui>, prema <gui>Adiante</gui> e complete os seus detalles nas seguintes páxinas. Use <file>record-collection</file> como nome do proxecto e cartafol.

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

Prema <gui>Rematar</gui> e o proxecto será creado. Abra <file>src/main.js</file> desde a lapela <gui>Proxecto</gui> ou <gui>Ficheiros</gui>. Contén código de exemplo moi básico.

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

Esta demostración é un aplicativo GTK (cunha única xanela) capaz de inserir rexistros nunha táboa de base de datos así como navegar por tódolos rexistros da toa. A táboa ten dous campos: id, un enteiro e name, un varchar. A primeira sección (na parte superior) do aplicativo permítelle inserir un rexistro na táboa. A última sección (abaixo) permítelle ver tódolos rexistros dunha táboa. Os contidos actualízanse cada vez que se insire un novo rexistro e ao iniciar o aplicativo.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="start">
Packit 1470ea
  <title>Comezar a diversión</title>
Packit 1470ea
  

Comezar examinando o esqueleto do 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>

Liñas 1-4: importacións iniciais. Preste especial atención á liña 3, que indica que JavaScript importe a a biblioteca GDA, noso obxectivo neste titorial.

</item>
Packit 1470ea
    <item>

Liñas 6-17: Define a clase Demo. Poña especial atención ás liñas 13-15, onde chamamos a 3 métodos que farán o traballo. Falaremos deles máis adiante.

</item>
Packit 1470ea
    <item>

Liñas 19-23: Iniciar o aplicativo.

</item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="design">
Packit 1470ea
  <title>Deseñar o aplicativo</title>
Packit 1470ea
  

Botémoslle unha ollada ao método setupWindow. É o responsábel de crear a Interface de Usuario (UI). Xa que a UI non é o noso enfoque explicaremos só as partes máis 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: "Insert a record", 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: "Browse the table", 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>

Liñas 22 e 27: crear as dúas entradas (para os dous campos) nas que o usuario escribirá algo para inserilo na base de datos.

</item>
Packit 1470ea
    <item>

Liñas 31-34: crear o botón «Insertar». Conéctase o seu sinal clicked co método privado _insertClicked de clase. Este método detállase a continuación

</item>
Packit 1470ea
    <item>

Liña 39: Crear o widget (TextView) onde se mostrarán os contidos da táboa.

</item>
Packit 1470ea
    <item>

Liña 44: crea a etiqueta onde se mostrará o número de rexistros existentes na táboa. Inicialmente está baleiro, actualizarase máis tarde.

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

O código que fai a conexión coa base de datos está no método setupDatabase de embaixo:

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
      

Liña 2-3: crear o obxecto de GDA Conection. Debe fornecerlle ao seu construtor algunhas propiedades:

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

provider: un dos fornecedores con asistencia en GDA. GDA é compatíbel con SQLite, MySQL, PostgreSQL, Oracle e moitos outros. Para os propósitos desta demostración usaremos unha base de datos SQLite, xa que ven instalada por omisión na maioría das distribucións e é moi sinxela de usar (usa un só ficheiro por base de datos).

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

cnc_string: A cadea de conexión. Pode cambiar dun fornecedor a outro. A sintaxe para SQLite é: DB_DIR=PATH;DB_NAME=FILENAME. Nesta demostración accederemos a unha base de datos chamada gnome_demo no cartafol persoal do usuario (olle a chamada á función de GLib get_home_dir).

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

Se o fornecedor non é compatíbel con GDA, ou falta algún elemento na cadea de conexión, dispararase a excepción da liña 2. Polo que na vida real deberíamos xestionar as declaracións JavaScript entre bloques try...catch.

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

Liña 4: Abrir a conexión. No fornecedor de SQLite, se a conexión non existe crearase neste paso.

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

Liñas 6-10: Tenta facer unha selección sinxela para comprobar que a táboa existe (liña 7). Se non existe (porque a base de datos foi recén creada), esta orde disparará unha excepción, que está xestionada polo bloque try...catch. Se este é o caso executarase a declaración de creación de táboa (liña 9).

Packit 1470ea
      

In order to run the SQL commands above we are using the GDA connection methods execute_select_command and execute_non_select_command. They are simple to use, and just require two arguments: The Connection object and the SQL command to be parsed.

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

Neste punto temos a base de datos configurada e lista para usala.

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

Despois de conectarse á base de datos, o construtor da nosa demostración chama ao método selectData. É responsábel de obter tódolos rexistros na táboa e para mostrarllas no widget TextView. Votémoslle unha ollada:

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 = "" + dm.get_n_rows () + " record(s)";
Packit 1470ea
  },]]>
Packit 1470ea
  <list>
Packit 1470ea
    <item>

Line 2: The SELECT command. We are using the GDA connection's execute_select_command method for that. It returns a DataModel object, which is later used to retrieve the rows.

</item>
Packit 1470ea
    <item>

Liña 3: Crea un obxecto Iter, que se usa para iterar sobre os rexistros de DataModel.

</item>
Packit 1470ea
    <item>

Liña 7: Iterar por tódolos rexistros e obtelos coa axuda do obxecto Iter. Neste punto a variábel iter contén os datos actualizados obtidos. O seu método move_next devolve false cando se chegue ao último rexistro.

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

Liñas 8-9: fanse dúas cousas en cada liña:

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

Use o método get_value_at de Iter, que só precisa un argumento: o número de columna que recuperar, comezando por 0. Xa que a orde SELECT só devolve dúas columnas, se está recuperando as columnas 0 e 1.

</item>
Packit 1470ea
        <item>

O método get_value_at devolve o campo no formato GValue de GLib. Unha forma sinxela de converter este formato a unha cadea é usando a función global de GDA value_stringify. Que é o facemos aquí, e almacenamos os resultados nas variábeis id_field e name_field.

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

Liña 11: Concaténanse os dous campos para facer unha única liña de texto, separada por "=>", e almacenámolas na variábel text.

</item>
Packit 1470ea
    <item>

Liña 14: Logo de que o bucle remate, temos tódolos rexistros formatados na variábel text. Nesta liña estabelecemos os contidos de TextView con dita variábel.

</item>
Packit 1470ea
    <item>

Liña 15: mostrar o número de rexistros na táboa, usando o 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>Insertando</title>
Packit 1470ea
  

OK, sabemos como conectarse a unha base de datos e como seleccionar filas dunha táboa. Agora é tempo de facer un INSERT na táboa. Lembra arriba no método setupWindow que conectamos o sinal clicked do botón <gui>Insert</gui> ao método _insertClicked? Vexamos a implementación deste 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
  

Packit 1470ea
    We have learned how to use the GDA connection's methods execute_select_command and execute_non_select_command to quickly execute SQL commands on the database. GDA allows one to build a SQL statement indirectly, by using its SqlBuilder object. What are the benefits of this? GDA will generate the SQL statement dynamically, and it will be valid for the connection provider used (it will use the same SQL dialect the provider uses). Let's study the code:
Packit 1470ea
  

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

Liña 2-3: compróbase que o usuario completa tódolos campos. O código do método privato _validateFields é realmente sinxelo e pode lelo no código fonte completo da demostración.

</item>
Packit 1470ea
    <item>

Liña 5: A forma máis rápida é INSERT. Está descomentado xa que queremos ver como usar o obxecto SqlBuilder para construír unha declaración SQL portábel a través das bases de datos.

</item>
Packit 1470ea
    <item>

Liña 7: crea o obxecto SqlBilder. Debemos pasar o tipo de declaración que queremos construír. Pode ser SELECT, UPDATE, INSERT ou DELETE.

</item>
Packit 1470ea
    <item>

Liña 8: estabelecer o nome da base de datos na que operará a sentencia construída (xerará INSERT INTO demo)

</item>
Packit 1470ea
    <item>

Liñas 9-10: estabelecer os campos que formarán parte da sentenza e os seus valores. O primeiro campo é o nome do campo (como aparece na táboa). O segundo é o valor deste campo.

</item>
Packit 1470ea
    <item>

Liña 11: obter o obxecto Statement xerado dinamicamente, que representa unha sentenza SQL.

</item>
Packit 1470ea
    <item>

Liña 12: finalmente, executar a sentenza SQL (INSERT).

</item>
Packit 1470ea
    <item>

Liña 14: limpar os campos id e nome na pantalla. O código do método privado _clearFields é moi sinxelo e pode lelo no código fonte completo da demostración.

</item>
Packit 1470ea
    <item>

Liña 15: actualizar a vista na pantalla facendo outro SELECT.

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

Tamén pode usar parámetros mentres constrúe a sentenza. Usando obxectos e parámetros SqlBuilder será menos susceptíbel a ataques de inxección de SQL. Para obter información adicional sobre os parámetros, consulte a <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>Executar o aplicativo</title>
Packit 1470ea
  

Todo o código que precisa agora está no seu lugar, polo que tente executar o código. Agora ten unha base de datos para a súa colección de rexistros!

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

Se ten problemas co titorial, compare o seu código con este <link href="record-collection/record-collection.js">código de referencia</link>.

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