Blame platform-demos/ca/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="ca">
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>Creació d'una aplicació amb una base de dades per ordenar una col·lecció 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>Projecte de documentació del 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
  </info>
Packit 1470ea
Packit 1470ea
<title>Record collection</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

En aquest programa d'aprenentatge aprendreu a:

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

Connectar-se a una base de dades amb la libgda

</item>
Packit 1470ea
    <item>

Inserir i navegar registres a una taula d'una base de dades

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

Aquesta demostració utilitza el llenguatge JavaScript. Es mostrarà com connectar-se i utilitzar una base de dades des d'un programa escrit amb la GTK+ a través de la biblioteca GDA (Accés a dades del GNOME). Haureu d'instalar-la per poder seguir aquesta demostració.

Packit 1470ea
  

El propòsit de la biblioteca GDA (Accés a dades del GNOME) és proporcionar un accés universal a diferents estils i tipus de fonts de dades. Això compren des dels sistemes tradicionals de bases de dades relacions fins a qualsevol tipus de font de dades imaginable com ara un servidor de correu, un directori d'LDAP, etc. Per més informació i la documentació completa de l'API, aneu al <link href="http://library.gnome.org/devel/libgda/stable/">lloc web de la GDA</link>.

Packit 1470ea
  

Tot i que una gran part del codi està dedicat a la interfície d'usuari (GUI), el programa d'aprenentatge està centrat en les parts relacionades amb la base de dades (es farà menció d'altres parts si es consideren rellevants). Per veure més programes escrits en JavaScript pel GNOME, vegeu el programa d'aprenentatge del <link xref="image-viewer.js">programa de visualització d'imatges</link>.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="anjuta">
Packit 1470ea
  <title>Creació d'un projecte a l'Anjuta</title>
Packit 1470ea
  

Abans de començar a programar, heu de crear un projecte nou a l'Anjuta. L'Anjuta crearà tots els fitxers necessaris per, més endavant, construir i executar el codi. És molt útil per així mantenir-ho tot junt.

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

Inicieu l'Anjuta i feu clic a <guiseq><gui>Fitxer</gui><gui>Nou</gui><gui>Projecte</gui></guiseq> per obrir l'auxiliar de projectes.

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

Trieu <gui>JavaScript genèric</gui> a la pestanya <gui>JS</gui>, feu clic a <gui>Continua</gui> i empleneu les dades de les pàgines següents de l'auxiliar. Utilitzeu <file>record-collection</file> com a nom de projecte i de directori.

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

Feu clic a <gui>Aplica</gui> i es crearà el projecte. Obriu el fitxer <file>src/main.js</file> des de la pestanya de <gui>Projecte</gui> o de <gui>Fitxer</gui>. El fitxer ja conté un exemple de codi molt bàsic.

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
  

Aquesta demostració és una aplicació de GTK+ senzilla (amb una sola finestra) que permet inserir registres a una taula d'una base de dades, així com navegar pels registres d'aquesta. La taula conté dos camps: id, per desar nombres enters i name per desar text de llargada variable. La primera secció (al principi) de l'aplicació permet inserir registres a la taula. La secció de baix (al final) permet veure tots els registres de la taula. S'actualitza el contingut de la taula cada vegada que s'afegeix un registre nou i també quan s'inicia l'aplicació.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="start">
Packit 1470ea
  <title>Ara comença lo bo</title>
Packit 1470ea
  

Primera ullada a l'esquelet 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ínies 1 a 4: importacions inicials. Mireu-vos bé la línia 3 que li diu al JavaScript que importi la biblioteca GDA, la biblioteca central d'aquest programa d'aprenentatge.

</item>
Packit 1470ea
    <item>

Línies 6 a 17: defineixen la classe Demo. Mireu-vos bé les línies 13 a 15, on es criden als 3 mètodes que faran tota la feina i que es descriuran tot seguit.

</item>
Packit 1470ea
    <item>

Línies 19 a 23: inicien l'aplicació.

</item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="design">
Packit 1470ea
  <title>Disseny de l'aplicació</title>
Packit 1470ea
  

Feu una ullada al mètode setupWindow. És el responsable de crear la interfície d'usuari (UI). Com que la interfície no és l'eix principal del programa d'aprenentatge només es comenta per sobre.

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>

Línies 22 i 27: creen dues entrades (per als dos camps) on els usuaris de l'aplicació escriuran alguna cosa per inserir-la a la base de dades.

</item>
Packit 1470ea
    <item>

Línies 31 a 34: creen el botó d'inserció. Es connecta el seu senyal clicked al mètode de classe privat _insertClicked. Aquest mètode es descriu més endavant.

</item>
Packit 1470ea
    <item>

Línia 30: crea el giny (TextView) on es mostrarà el contingut de la taula.

</item>
Packit 1470ea
    <item>

Línia 44: crea l'etiqueta on es mostrarà el nombre de registres de la taula. Inicialment serà buit, s'actualitzarà més endavant.

</item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="connect">
Packit 1470ea
  <title>Connexió i inicialització de la base de dades</title>
Packit 1470ea
  

El codi per connectar a la base de dades és en el mètode setupDatabase que segueix:

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ínies 2 i 3: creen l'objecte Connection de la GDA. S'han de proporcionar unes quantes propietats en el seu constructor:

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

provider: un dels proveïdors amb els que la GDA permet treballar. Són: SQLite, MySQL, PostgreSQL, Oracle i molts d'altres. Per aquesta demostració utilitzarem la base de dades SQLite ja que ve per defecte en la majoria de distribucions i és senzilla de treballar-hi (només fa servir un fitxer com a base de dades).

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

cnc_string: la cadena de connexió. Pot canviar segons el proveïdor. La sintaxi per a l'SQLite és: DB_DIR=CAMÍ;DB_NAME=NOM_DE_FITXER. En aquesta demostració farem servir una base de dades anomenada gnome_demo a la carpeta de l'usuari (adoneu-vos de la crida a la funció get_home_dir de la GLib).

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

Si la GDA no sap treballar amb el proveïdor o si a la cadena de connexió li manca algun element, la línia 2 generarà una excepció, de manera que en codi real hauríem de gestionar-ho amb la sentència de JavaScript try...catch.

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

Línia 4: obre la connexió. Si no existeix la base dades el proveïdor de SQLite la crearà en aquest moment.

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

Línies 6 a 10: es realitza un «SELECT» simple per comprovar si existeix la taula (línia 7). Si no existeix (perquè s'acaba de crear la base de dades), aquesta línia generarà una excepció que es gestionarà en el bloc de codi try...catch. Si és el cas, s'executa la sentència per crear la taula (línia 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
  

En aquest punt d'execució la base de dades ja està configurada i a punt per utilitzar-se.

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

Després de connectar-se a la base de dades, el constructor de la demostració crida el mètode selectData. Aquest mètode és el responsable d'obtenir els registres de la taula i mostrar-los en el giny TextView. Ara es comentarà amb més detall:

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>

Línia 3: crea l'objecte Iter que s'utilitza per iterar sobre els registres de DataModel.

</item>
Packit 1470ea
    <item>

Línia 7: itera sobre tots els registres, els recupera amb l'ajuda de l'objecte Iter. En aquest punt la variable iter conté les dades actuals recuperades de la base de dades. El seu mètode move_next retorna false quan arriba a l'últim registre.

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

Línies 8 i 9: es fan dues coses a cada línia:

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

S'utilitza el mètode get_value_at d'Iter que només necessita un paràmetre: el número de la columna a recuperar, començant a partir de zero. Com que el SELECT que s'ha fet només retorna dues columnes, els índexs de les columnes són el 0 i l'1.

</item>
Packit 1470ea
        <item>

El mètode get_value_at retorna el camp en el format GValue de la GLib. Una manera senzilla de convertir aquest format a una cadena és utilitzant la funció global de la GDA value_stringify. Això és el que es fa aquí i després es desa el resultat a les variables id_field i name_field.

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

Línia 11: es concatenen els dos camps per fer una sola línia de text separada per "=>" i desada a la variable text.

</item>
Packit 1470ea
    <item>

Línia 14: quan s'acaba la iteració, hi ha tots els registres formatats a la variable text. En aquesta línia només s'estableix que el contingut de TextView sigui el d'aquesta variable.

</item>
Packit 1470ea
    <item>

Línia 15: mostra el nombre de registres de la taula amb el mètode get_n_rows de DataModel.

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

Fins ara s'ha connectat a la base de dades i s'ha mostrat com seleccionar les files de la taula. Ara només falta fer un INSERT a la taula. Recordeu que abans en el mètode setupWindow s'ha connectat el senyal clicked del botó <gui>Insert</gui> amb el mètode _insertClicked? Ara se'n mostra la implementació.

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>

Línies 2 i 3: comproven que l'usuari hagi emplenat tots els camps. El codi del mètode privat _validateFields és molt senzill i li podeu fer una ullada en el codi font sencer de la demostració.

</item>
Packit 1470ea
    <item>

Línia 5: la forma ràpida de fer un INSERT. Està comentat perquè es vol mostrar com utilitzar l'objecte SqlBuilder per construir una ordre SQL que sigui vàlida per qualsevol base de dades.

</item>
Packit 1470ea
    <item>

Línia 7: crea l'objecte SqlBuilder. S'ha d'informar del tipus d'ordre que es vol construir. Pot ser un SELECT, un UPDATE, un INSERT o bé un DELETE.

</item>
Packit 1470ea
    <item>

Línia 8: estableix el nom de la taula on s'efectuarà l'ordre (generarà un INSERT INTO demo)

</item>
Packit 1470ea
    <item>

Línies 9 i 10: estableix els camps i els valors que formaran part de l'ordre. El primer argument és el nom del camp (tal i com està definit a la taula). El segon argument és el valor que li volem donar.

</item>
Packit 1470ea
    <item>

Línia 11: s'obté l'objecte generat dinàmicament Statement que representa una ordre SQL.

</item>
Packit 1470ea
    <item>

Línia 12: ara ja sí, s'executa l'ordre SQL (un INSERT).

</item>
Packit 1470ea
    <item>

Línia 14: es netegen els camps id i nom de la pantalla. El codi del mètode privat _clearFields és molt senzill i es pot trobar en el codi font sencer de la demostració.

</item>
Packit 1470ea
    <item>

Línia 15: actualitza la vista de la pantalla fent un altre SELECT.

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

També es poden utilitzar paràmetres mentre construïu l'ordre. Pel fet d'utilitzar objectes SqlBuilder i els seus paràmetres es poden evitar atacs d'injecció d'SQL. Per més informació sobre els paràmetres mireu-vos la <link href="http://library.gnome.org/devel/libgda/stable/">documentació de la GDA</link>.

</note>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="run">
Packit 1470ea
  <title>Execució de l'aplicació</title>
Packit 1470ea
  

Ja s'ha vist tot el codi que fa falta, així que ja es pot executar el codi. S'acaba de crear una aplicació per la gestió d'una col·lecció de música!

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="impl">
Packit 1470ea
 <title>Implementació de referència</title>
Packit 1470ea
 

Si teniu algun problema amb el programa d'aprenentatge, compareu el codi amb el <link href="record-collection/record-collection.js">codi de referència</link>.

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