[GO] Grale fangen an

Was ist Gral?

Grails ist ein Full-Stack-Framework, das entwickelt wurde, um viele der Herausforderungen der Webentwicklung durch Kerntechnologie und verwandte Plugins zu lösen.

Während viele Web-Frameworks in der Java-Welt komplex sind und keine DRY-Prinzipien berücksichtigen, baut Grails auf dynamischen Framework-Konzepten auf, die zu modernem Denken über Webanwendungen wie Rails und Django geführt haben. , Basiert auf vorhandenen Java-Technologien wie Spring und Hibernate.

Installieren Sie Grails

Referenz http://docs.grails.org/latest/guide/single.html#requirements

Ich habe die folgende Version im Artikel verwendet.

* So installieren Sie Grails für Benutzer von nix (Mac OS, Linux, BSD OS)

So installieren Sie Grails für Windows-Benutzer

Erstellen Sie eine Grails-Anwendung

Verwenden Sie beim Erstellen einer Grails-Anwendung den Befehl grails create-app, um die erforderlichen Dateien in großen Mengen zu erstellen.

$ cd ${Zielverzeichnis der Anwendung speichern}
$ grails create-app grails-sample-app
# grails-sample-Ändern Sie die App entsprechend in den Anwendungsnamen.
# "grails-sample-app"Ein Verzeichnis wird erstellt
#Der Paketname der Anwendung lautet"grails.sample.app"Wird sein.

Grails Sie können auch einen Modus verwenden, in dem Sie jeden Befehl interaktiv ausführen können. Der interaktive Modus ist verfügbar, wenn Sie den Befehl grails ohne Optionen ausführen und den Befehl im interaktiven Modus mit der Tabulatortaste ausführen können.

Führen Sie die Grails-Anwendung aus

Führen Sie den Befehl run-app aus, um die Anwendung auszuführen.

Führen Sie die Grails-Anwendung aus(Wenn Sie den interaktiven Grails-Modus nicht verwenden)


$ cd ${create-App Zielverzeichnis speichern}
$ grails run-app

Führen Sie die Grails-Anwendung aus(Bei Verwendung des interaktiven Grails-Modus)


$ cd ${create-App Zielverzeichnis speichern}
$ grails #Starten Sie Grails im interaktiven Modus
grails> run-app

Anwendungsbildschirm

Nachdem Sie die Anwendung mit run-app ausgeführt haben, greifen Sie auf http: // localhost: 8080 / zu, und Sie sehen den Grails-Intro-Bildschirm wie unten gezeigt. (Der Bildschirm zeigt den HelloController, der zusätzlich zu der von create-app erstellten Datei erstellt wurde.)

image.png

Verzeichnisaufbau

.gradle/
.idea/              ...Konfigurationsdatei für IntelliJ IDE
build/              ...Datei erstellen(create-Existiert nicht sofort nach dem Ausführen der App)
gradle/
grails-app/         ...Quellcode der Anwendung
  assets/           ...Speicherung von Ressourcen(Von der Asset-Pipeline verarbeitete Dateien)
  conf/             ...Laufzeiteinstellungen
  controllers/      ...Regler(MVC Modell C.)
    ${App Name}/       ...App Name(Wenn Bindestriche enthalten sind, wird das Verzeichnis für jeden Bindestrich getrennt)
      UrlMappings.groovy ...URL-Zuordnung
  domain/           ...Domänenklasse(MVC Modell M.)
  i18n/             ... internationalization(i18n)Konfigurationsunterstützung
  init/             ...Verarbeitung beim Start der Anwendung
  services/         ...Serviceschicht
  taglib/           ...Tag-Bibliothek(Definierte benutzerdefinierte Tags, die in der Ansicht verwendet werden können)
  utils/            ...Grails-spezifischer Nutzen
  views/            ... Groovy Server Page(GSP) or JSON Views (MVC Modell V.)
src/
  integration-test/ ...Integrationstest
  main/             ...Statische Datei, die keine Asset-Pipeline-Verarbeitung durchläuft
    groovy/         ...Domänenklasse, die Sie der DB-Tabelle nicht zuordnen möchten
    webapp/         ...Statische Datei(In WAR enthalten, nicht in JAR)
    resources/public ...Statische Datei(/static/x/y/Zugang mit z)
  test/             ...Gerätetest
    groovy/
      ${App Name}/
        ${***Spec}.groovy
.gitignore          ...Nicht verwaltete VCS-Dateieinstellungen für Git
build.gradle        ...Einstellungen erstellen
gradle.properties   ...Gradle-Einstellungen
gradlew             ...Gradle-Startskript(UN*Für X.)
gradlew.bat         ...Gradle-Startskript(Für Windows)
grails-wrapper.jar
grailsw             ...Grails startet Skript(UN*Für X.)
grailsw.bat         ...Grails startet Skript(Für Windows)
README.md           ... README

Genaue Information

Zeige Hallo Welt

Lassen Sie uns "Hello World!" Als Zeichenkette anzeigen.

Wenn Sie in Grails einen Controller erstellen und eine Aktion in dieser Klasse beschreiben, wird dieser einer eindeutigen URL zugeordnet und kann von einem Browser aufgerufen werden.

Die Zuordnungsregel lautet "/ / / ", und "" ist die Controller-Klasse minus "Klasse".

Gehen Sie wie folgt vor, um einen "HelloController" zu erstellen und die "Index" -Aktion "HelloWorld" anzuzeigen:

Führen Sie die Grails-Anwendung aus


grails> create-controller hello #HelloController-Klasse wird erstellt

Bearbeiten Sie die in grails-app / controller / grails / sample / app / HelloController.groovy erstellte HelloController-Klasse mit den folgenden Inhalten.

grails-app/controllers/grails/sample/app/HelloController.groovy


package grails.sample.app

class HelloController {
  def index() {
    render "Hello World!"
  }
}

Wenn Sie die Anwendung ausführen und auf http: // localhost: 8080 / hello / index oder http: // localhost: 8080 / hello / zugreifen, wird die Zeichenfolge "Hello World!" Angezeigt. (Die Indexaktion kann in der URL weggelassen werden.)

Erstellen Sie eine CRUD-Funktion für Ihre Domain

Die Domäne ist M von MVC in Grails. Sie können einzelne Controller und Ansichten wie im vorherigen HelloWorld-Anzeigebeispiel erstellen, aber Sie können die Option "Alles generieren" verwenden, um Controller und Ansichten mit CRUD-Funktionalität für Ihre Domäne zu erstellen (plus zum Testen). Sie können eine Klasse erstellen).

Erstellen Sie eine Mitarbeiterdomänenklasse, einen Controller für CRUD, eine Ansicht und einen Test


#Erstellen Sie eine Mitarbeiterdomänenklasse
$ grails create-domain-class employee
| Created grails-app/domain/grails/sample/app/Employee.groovy
| Created src/test/groovy/grails/sample/app/EmployeeSpec.groovy
#Erstellen Sie Controller-, Ansichts- und Testklassen für CRUD Employee-Domänenklassen
$ grails generate-all grails.sample.app.Employee
| Rendered template Controller.groovy to destination grails-app\controllers\grails\sample\app\EmployeeController.groovy
| Rendered template Service.groovy to destination grails-app\services\grails\sample\app\EmployeeService.groovy
| Rendered template Spec.groovy to destination src\test\groovy\grails\sample\app\EmployeeControllerSpec.groovy
| Rendered template ServiceSpec.groovy to destination src\integration-test\groovy\grails\sample\app\EmployeeServiceSpec.groovy
| Scaffolding completed for grails-app\domain\grails\sample\app\Employee.groovy
| Rendered template create.gsp to destination grails-app\views\employee\create.gsp
| Rendered template edit.gsp to destination grails-app\views\employee\edit.gsp
| Rendered template index.gsp to destination grails-app\views\employee\index.gsp
| Rendered template show.gsp to destination grails-app\views\employee\show.gsp
| Views generated for grails-app\domain\grails\sample\app\Employee.groovy

Sie haben jetzt die Möglichkeit erstellt, die Domänenklasse "Mitarbeiter" zu CRUDEN.

Die Domänenklasse hat noch keine Attribute. Bearbeiten Sie daher die Datei "grails-app / domain / grails / sample / app / Employee.groovy" und fügen Sie die entsprechenden Attribute hinzu.

grails-app/domain/grails/sample/app/Employee.groovy


package grails.sample.app

class Employee {

  String name

  static constraints = {
  }
}

Wenn ich run-app erneut starte, um den TOP-Bildschirm der Anwendung im Browser anzuzeigen, wird grails.sample.app.EmployeeController zu Available Controllers hinzugefügt :.

Die Zeichenfolge von grails.sample.app.EmployeeController ist ein Link. Wenn Sie darauf klicken, gelangen Sie zum Bildschirm Mitarbeiterliste (http: // localhost: 8080 / employee / index).

Bildschirm mit der Mitarbeiterliste
image.png

Wie Sie bei einigen Vorgängen sehen können, wurden die folgenden Routen hinzugefügt.

Wurzel Funktion
GET /employee/index Bildschirm "Mitarbeiterliste" anzeigen
GET /employee/create Bildschirm "Mitarbeiter neu erstellen" anzeigen
GET /employee/show/:id Bildschirm mit Mitarbeiterdetails(:id ist die ID der Domänenklasse)Show
GET /employee/edit/:id Bildschirm zum Bearbeiten von Mitarbeitern(:id ist die ID der Domänenklasse)Show
POST /employee/save Mitarbeiter neue Kreation
PUT /employee/update/:id Mitarbeiter-Update(:id ist die ID der Domänenklasse)
DELETE /employee/delete/:id Mitarbeiter gelöscht(:id ist die ID der Domänenklasse)

Die von der Anwendung verwendete Datenbank kann für jede Umgebungsvariable wie Entwicklung, Test und Produktion geändert werden. Grails verwendet standardmäßig in allen Umgebungen H2-Datenbank.

Sie werden auch feststellen, dass die Datenbank initialisiert wird, wenn Sie den CRUD-Vorgang beenden, run-app beenden und die Anwendung erneut ausführen. Dies liegt daran, dass H2 eine speicherinterne Datenbank ist und die Datenbank in der Entwicklungsumgebung so eingestellt ist, dass die Datenbank am Ende der Anwendung TROPFEN und beim Start erstellt wird.

Diese Einstellungen werden in grails-app / conf / application.yml festgelegt. (Weitere Informationen zu den Einstellungen finden Sie unter The Grails Framework> The DataSource.)

Dieses Mal werden wir festlegen, dass die in der Entwicklungsumgebung erstellte Datenbank nicht zerstört wird. Schreiben Sie grails-app / conf / application.yml mit dem folgenden Inhalt neu.

grails-app/conf/application.yml


environments:
  development:
    dataSource:
      # create-Wechseln Sie von Drop zu Update
      dbCreate: update
      # mem:von devDb./Wechseln Sie zu devDb
      url: jdbc:h2:./devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE

Folgende Werte können mit dbCreate festgelegt werden.

dbEinstellungen erstellen Erläuterung
create Vorhandenes Schema beim Start(Tabelle,Index,andere)Löschen und neu erstellen
create-drop Entspricht dem Erstellen, löscht jedoch die Tabelle beim Beenden der Anwendung
update Erstellen oder aktualisieren Sie eine nicht vorhandene Tabelle oder einen nicht vorhandenen Index. Löschen Sie keine vorhandenen Tabellen oder Daten.(Beachten Sie, dass alte Spalten und Daten erhalten bleiben, da Änderungen des Spaltennamens nicht ordnungsgemäß behandelt werden können.)
validate Geben Sie eine Warnung aus, indem Sie das vorhandene Schema und die Einstellungen vergleichen, ohne Änderungen an der Datenbank vorzunehmen
any other value nichts tun

Bearbeiten Sie Domänenklassen im Quellcode

Erstellen Sie eine Domain

def p = new Person(name: "Fred", age: 40, lastVisit: new Date())
p.save()

Domain lesen

def p = Person.get(1)
println('name: ' + p.name)

Domain aktualisieren

def p = Person.get(1)
p.name = 'Bob'
p.save()

Domain löschen

def p = Person.get(1)
p.delete()

Erstellen Sie eine Anwendung, die das Mitarbeitermodell verwaltet

Lassen Sie uns die Employee-Domain-Klasse etwas erweitern und praktischer gestalten.

grails-app/domain/grails/sample/app/Employee.groovy


package grails.sample.app

class Employee {

  String name
  String department
  String gender
  Date birth
  Date joinedDate
  Long payment
  String note

  static constraints = {
    name blank: false, unique: true
    department blank: false
    gender blank: false, inList: ['male', 'female', 'other']
    birth blank: false
    joinedDate blank: false
    payment min: new Long(0), blank: false
    note blank: true
  }

  /**
  *Dienstalter
  */
  public int serviceYears() {
    def today = new Date()
    return Math.max(0, today.year - this.joinedDate.year)
  }
}

Bis auf den Hinweis setze ich vorerst "nullable: false" (da dies Standard ist, wird es nicht in Einschränkungen angegeben) und "blank: false". Wenn Sie wie in Anmerkung "leer: wahr" setzen, müssen Sie den Konvertierungsprozess in null deaktivieren, wenn die Daten leer sind.

Die Einstellung kann deaktiviert werden, indem application.groovy wie folgt eingestellt wird. Wenn die Datei nicht existiert, erstellen Sie sie unter "grails-app / conf /".

grails-app/conf/application.groovy


// the default value for this property is true
grails.databinding.convertEmptyStringsToNull = false

Ändern Sie nun den Listenbildschirm und den Bearbeitungsbildschirm, um Mitarbeiter wie folgt anzuzeigen.

Listenbildschirmansicht(grails-app/views/employee/index.gsp)


<!DOCTYPE html>
<html>
  <head>
    <meta name="layout" content="main" />
    <g:set var="entityName" value="${message(code: 'employee.label', default: 'Employee')}" />
    <title><g:message code="default.list.label" args="[entityName]" /></title>
    <script type="text/javascript">
      /*Legen Sie den Status der Bearbeitungsschaltfläche basierend auf dem Optionsfeldstatus fest*/
      function setEditButtonStatusByRadioButton() {
        var edit_button_id = "edit_button";
        var radios = document.getElementsByName('id');
        var checkedNum = 0;
        radios.forEach(e => e.checked && checkedNum++);
        if (checkedNum > 0) {
          document.getElementById(edit_button_id).disabled = false;
        } else {
          document.getElementById(edit_button_id).disabled = true;
        }
      }
    </script>
  </head>
  <body>
    <a href="#list-employee" class="skip" tabindex="-1"><g:message code="default.link.skip.label" default="Skip to content&hellip;"/></a>
    <div class="nav" role="navigation">
      <ul>
        <li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
        <li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
      </ul>
    </div>
    <div id="list-employee" class="content scaffold-list" role="main">
      <h1><g:message code="default.list.label" args="[entityName]" /></h1>
      <g:if test="${flash.message}">
        <div class="message" role="status">${flash.message}</div>
      </g:if>

      <g:form action="edit">
        <table class="table table-striped">
          <thead>
            <tr>
              <th>Edit</th>
              <g:each in="${['id', 'name', 'department', 'gender']}" var="p">
                <g:sortableColumn property="${p}" title="${p}" />
              </g:each>
            </tr>
          </thead>
          <tbody>
          <g:each in="${employeeList}" var="employee">
            <tr>
              <td><input name="id" type="radio" value="${employee.id}" onclick="setEditButtonStatusByRadioButton()" /></td>
              <g:each in="${['id', 'name', 'department', 'gender']}" var="p">
                <g:if test="${p=='id'}">
                  <td><g:link method="GET" resource="${employee}">${employee.properties[p]}</g:link></td>
                </g:if>
                <g:else>
                  <td>${employee.properties[p]}</td>
                </g:else>
              </g:each>
            </tr>
          </g:each>
          </tbody>
        </table>

        <button disabled="false" id="edit_button"><g:message code="default.edit.label" args="[entityName]" /></button>
      </g:form>

      <div class="pagination">
        <g:paginate total="${employeeCount ?: 0}" />
      </div>
    </div>
  </body>
</html>

Detailbildschirmansicht(grails-app/views/employee/show.gsp)


<!DOCTYPE html>
<html>
  <head>
    <meta name="layout" content="main" />
    <g:set var="entityName" value="${message(code: 'employee.label', default: 'Employee')}" />
    <title><g:message code="default.show.label" args="[entityName]" /></title>
  </head>
  <body>
    <a href="#show-employee" class="skip" tabindex="-1"><g:message code="default.link.skip.label" default="Skip to content&hellip;"/></a>
    <div class="nav" role="navigation">
      <ul>
        <li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
        <li><g:link class="list" action="index"><g:message code="default.list.label" args="[entityName]" /></g:link></li>
        <li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
      </ul>
    </div>
    <div id="show-employee" class="content scaffold-show" role="main">
      <h1><g:message code="default.show.label" args="[entityName]" /></h1>
      <g:if test="${flash.message}">
      <div class="message" role="status">${flash.message}</div>
      </g:if>

      <ol class="property-list employee">
        <li class="fieldcontain">
          <g:each in="${['id', 'name', 'department', 'gender', 'birth', 'serviceYears', 'payment', 'note']}" var="p">
            <span id="name-label" class="property-label">${p}</span>
            <g:if test="${p=='serviceYears'}">
              <div class="property-value" aria-labelledby="name-label">${employee.serviceYears()}</div>
            </g:if>
            <g:else>
              <div class="property-value" aria-labelledby="name-label">${employee.properties[p]}</div>
            </g:else>
          </g:each>
        </li>
      </ol>
      
      <g:form resource="${this.employee}" method="DELETE">
        <fieldset class="buttons">
          <g:link class="edit" action="edit" resource="${this.employee}"><g:message code="default.button.edit.label" default="Edit" /></g:link>
          <input class="delete" type="submit" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" />
        </fieldset>
      </g:form>
    </div>
  </body>
</html>

Das ist etwas praktischer.

Die Ansicht wird in Groovy Server Pages (GSP) beschrieben, und <g: link>, <g: form> usw. sind GSP-Tags. (Weitere Informationen finden Sie unter Groovy Server Pages (GSP).)

Führen Sie Twitter Bootstrap ein

Grails 3.3.5 führte standardmäßig Bootstrap 3.3.6 ein.

Es scheint Twitter-Bootstrap-Grails-Plugin des Grails-Plugins zu geben, aber die aktuelle Version ist 3.3.5 am 18. September '18. Es scheint, dass das endgültige Commit vor zwei Jahren stattgefunden hat, daher scheint es nicht gut gepflegt zu sein. Deshalb habe ich beschlossen, Bootstrap v4 manuell einzuführen.

Installationsverfahren für Twitter Bootstrap v4

  1. Entfernen Sie den installierten Bootstrap (js, css), JQuery
    • grails-app/assets/javascripts/bootstrap.js
    • grails-app/assets/stylesheets/bootstrap.css
    • grails-app/assets/javascripts/jquery-2.2.0.min.js
  2. Laden Sie Bootstrap v4 herunter
    • https://getbootstrap.com/docs/4.1/getting-started/download/ -Drücken Sie die Download-Schaltfläche von "Compiled CSS and JS"
  3. Laden Sie JQuery v3 herunter
    • https://jquery.com/download/ -Speichern Sie die verknüpfte Datei von "Laden Sie die komprimierte Produktions-jQuery 3.x.y herunter"
  4. Kopieren Sie Bootstrap v4, JQuery v3 in den Grails-Anwendungsordner
    • grails-app/assets/javascripts/bootstrap.bundle.js
    • grails-app/assets/javascripts/jquery-3.3.1.min.js
    • grails-app/assets/stylesheets/bootstrap.css --grails-app / assets / stylesheets / bootstrap.css.map (Nach Belieben hinzufügen, wie es für das CSS-Debugging ist)
  5. Bearbeiten Sie grails-app / assets / javascripts / application.js

Führen Sie die Anwendung erneut aus und Sie sind fertig. (Navbar bricht zusammen, aber ich benutze es nicht, also ignoriere es)

Bestätigung nach Einführung

Lassen Sie uns die zuvor beschriebene index.gsp-Ansicht bearbeiten.

grails-app/views/layouts/main.gsp


<head>
  : <snip>
  <asset:stylesheet src="application.css"/>
  <asset:javascript src="application.js"/> <!--Bewegen Sie die im Körper geschriebene Linie in den Kopf-->
  : <snip>
</head>
  : <snip>

grails-app/views/employee/index.gsp


  : <snip>
<button class="btn btn-secondary" disabled="false" id="edit_button"><g:message code="default.edit.label" args="[entityName]" /></button>
  : <snip>

Es ist in Ordnung, wenn auf die Schaltfläche der Bootstrap 4-Stil angewendet wird.

Fügen Sie dem Listenbildschirm mithilfe von DataTable eine Filterfunktion hinzu

Vorbereitungen

Fügen wir dem Bildschirm "Mitarbeiterliste" eine Filterfunktion hinzu, um ihn ein wenig praktischer zu gestalten.

Ich werde DataTables verwenden, um die Suchfunktion diesmal zu der Tabelle hinzuzufügen, die auf dem Listenbildschirm angezeigt wird.

Es gab grails-datatables als Grails-Plugin, aber installieren Sie die neueste Version von DataTables wie Bootstrap und jquery. Ich werde entscheiden.

Wählen Sie die folgenden Elemente auf der DataTables-Download-Seite aus, um die Datei herunterzuladen.

Kopieren Sie die folgenden Dateien aus der heruntergeladenen Datei entsprechend dem Typ in grails-app / assets / (javascripts | stylesheets) /.

Zum Schluss bearbeiten Sie grails-app / assets / application (Js | css). Die in der Anwendung beschriebenen erforderlichen Zieldateien (js | css) werden in der Reihenfolge von oben gelesen. Achten Sie daher auf die Beschreibungsreihenfolge für Pakete mit Abhängigkeiten.

grails-app/assets/javascripts/application.js


  : <snip>
//= require jquery-3.3.1.min
//= require bootstrap.bundle
//= require jquery.dataTables
//= require dataTables.bootstrap4
//= require_tree .
//= require_self
  : <snip>

grails-app/assets/stylesheets/application.css


/*
  : <snip>
*= require bootstrap
*= require dataTables.bootstrap4
*= require grails
*= require main
*= require mobile
*= require_self
  : <snip>
*/

Jetzt können Sie DataTables verwenden.

Wenden Sie DataTables auf Tabellen auf dem Listenbildschirm an

Wenden Sie DataTables auf die Tabellen im Listenbildschirm an.

Wenden Sie zum Anwenden von DataTables die Methode "dataTable ()" auf das DOM an, das auf die Tabelle verweist, die Sie in jQuery anwenden möchten.

grails-app/views/employee/index.gsp


<!DOCTYPE html>
<html>
  <head>
    : <snip>
    <script type="text/javascript">
      /*Legen Sie den Status der Bearbeitungsschaltfläche basierend auf dem Optionsfeldstatus fest*/
      function setEditButtonStatusByRadioButton() {
        var edit_button_id = "edit_button";
        var radios = document.getElementsByName('id');
        var checkedNum = 0;
        radios.forEach(e => e.checked && checkedNum++);
        if (checkedNum > 0) {
          document.getElementById(edit_button_id).disabled = false;
        } else {
          document.getElementById(edit_button_id).disabled = true;
        }
      }

      $(document).ready(function() {
        $('#employeeindex').dataTable();
      } );
    </script>
  </head>
  <body>
    : <snip>
        <table id="employeeindex" class="display table table-striped">
          : <snip>
        </table>
    : <snip>
  </body>
</html>

Wenn Sie die Anwendung ausführen, können Sie sehen, dass DataTables angewendet wurde.

image.png

Hier können Sie sehen, dass die Paginierungsfunktionen von DataTables und Grails überflüssig geworden sind.

Welche Funktion aktiviert werden soll, hängt vom Design der Anwendung ab. Dieses Mal verlassen wir jedoch die Paginierungsfunktion von Grails, um die Datenverarbeitung zu reduzieren.

Um die Paginierungsfunktion von DataTables zu deaktivieren, fügen Sie der dataTable () -Methode den Parameter "paging: true" hinzu, wie auf der offiziellen Seite (https://datatables.net/reference/option/paging) beschrieben. Ich werde es bestehen.

#Wenden Sie DataTables ohne Paginierung auf das Index-DOM an


$(document).ready(function() {
  $('#employeeindex').dataTable({
    "paging": false
  });
} );

Ändern Sie abschließend die Navigationsleiste am oberen Bildschirmrand. Ändern Sie außerdem den Stil entsprechend und fügen Sie Font Awesome im CDN hinzu, um ICON zu verwenden.

grails-app/assets/stylesheets/main.css


/* NAVIGATION MENU */

.nav, nav {
    zoom: 1;
}

.nav ul {
    overflow: hidden;
    padding-left: 0;
    zoom: 1;
}

.nav li {
    display: block;
    float: left;
    list-style-type: none;
    margin-right: 0.5em;
    padding: 0;
}

.nav a, nav a {
    color: #666666;
    display: block;
    padding: 0.25em 0.7em;
    text-decoration: none;
    -moz-border-radius: 0.3em;
    -webkit-border-radius: 0.3em;
    border-radius: 0.3em;
}

.nav a:active, .nav a:visited, nav a:active, nav a:visited {
    color: #666666;
}

.nav a:focus, .nav a:hover, nav a:focus, nav a:hover {
    background-color: #999999;
    color: #ffffff;
    outline: none;
    text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
}

.no-borderradius .nav a:focus, .no-borderradius nav a:focus, .no-borderradius .nav a:hover, .no-borderradius nav a:hover {
    background-color: transparent;
    color: #444444;
    text-decoration: underline;
}

.nav a.home, .nav a.list, .nav a.create, nav a.home, nav a.list, nav a.create {
    background-position: 0.7em center;
    background-repeat: no-repeat;
    text-indent: 25px;
}

.nav a.home, nav a.home {
    background-image: url(../images/skin/house.png);
}

.nav a.list, nav a.list {
    background-image: url(../images/skin/database_table.png);
}

.nav a.create, nav a.create {
    background-image: url(../images/skin/database_add.png);
}

.nav li.dropdown ul.dropdown-menu, nav li.dropdown ul.dropdown-menu {
    background-color: #424649;
}

grails-app/assets/stylesheets/mobile.css


@media screen and (max-width: 480px) {
    .nav, nav {
        padding: 0.5em;
    }

    .nav li, nav li {
        margin: 0 0.5em 0 0;
        padding: 0.25em;
    }
  : <snip>
}

grails-app/views/layouts/main.gsp


<!doctype html>
<html lang="en" class="no-js">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
  <title>
    <g:layoutTitle default="Grails"/>
  </title>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <asset:link rel="icon" href="favicon.ico" type="image/x-ico" />

  <asset:stylesheet src="application.css"/>
  <asset:javascript src="application.js"/>
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">

  <g:layoutHead/>
</head>
<body>

  <nav class="navbar-expand-lg pr-3 navbar navbar-default">
    <a class="navbar-brand" href="/#">
      <asset:image src="grails.svg" alt="Grails Logo"/>
    </a>
    <button class="navbar-toggler mx-2" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="fas fa-bars" style="font-size: 3rem;"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto">
        <g:pageProperty name="page.nav" />
      </ul>
    </div>
  </nav>

  <g:layoutBody/>

  <div class="footer" role="contentinfo"></div>

  <div id="spinner" class="spinner" style="display:none;">
      <g:message code="spinner.alt" default="Loading&hellip;"/>
  </div>

</body>
</html>
Large Display Size Small Display Size
image.png image.png

Datenbankmigration

Bisher wurde die Datenbank aktualisiert, indem "dbCreate: update" unter Bezugnahme auf die Modelldatei beim Starten der Anwendung festgelegt wurde. Aufgrund der begrenzten Bedingungen, die geändert werden können und die alten Spalten verbleiben, bleiben jedoch mehrere Personen übrig Bei der Entwicklung einer Anwendung können unterschiedliche Personen unterschiedliche Datenbankstrukturen haben.

Aus diesem Grund habe ich beschlossen, eine Migrationsdatei zu erstellen und daraus eine Datenbank zu erstellen.

Verwenden Sie das Plug-In "Datenbankmigration", um die Datenbankmigration in Grails durchzuführen. (Das Plugin "Datenbankmigration" verwendet die Bibliothek Liquibase.)

Die Migration erfolgt über eine oder mehrere Änderungsprotokolldateien, die in Groovy DSL oder nativem Liquibase XML geschrieben sind.

Änderungsprotokolldateien haben eine global eindeutige ID. (Die ID enthält den Benutzernamen des Benutzers, der das Änderungsprotokoll erstellt hat.)

Vorbereitungen

Bearbeiten Sie "bundle.gradle" wie folgt, um das Plug-In "Datenbankmigration" zu verwenden. (Ändern Sie die Plug-Version entsprechend)

Beachten Sie, dass "bundle.gradle" eine Konfigurationsdatei für Gradle ist und Gradle ein Open-Source-Build-Automatisierungssystem ist, das auf den Konzepten von Apache Ant und Apache Maven basiert. (Referenz: Wikipedia> Gradle)

buildscript {
  repositories {
    : <snip>
  }
  dependencies {
    : <snip>
    classpath 'org.grails.plugins:database-migration:3.0.4' # database-Migrations-Plug-In hinzugefügt
  }
}

dependencies {
    : <snip>
  compile 'org.grails.plugins:database-migration:3.0.4'
  compile 'org.liquibase:liquibase-core:3.5.5'
    : <snip>
}

  : <snip>

sourceSets {
  main {
    resources {
      srcDir 'grails-app/migrations'
    }
  }
}

Setzen Sie dann die Datenbank dbCreate auf none. Andernfalls erhalten Sie keinen Unterschied, wenn Sie eine Migrationsdatei mit der Option "dbm-gorm-diff" erstellen.

grails-app/conf/application.yml


environments:
  development:
    dataSource:
      dbCreate: none
      url: jdbc:h2:./devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
  : <snip>

Erstellen Sie eine Änderungsprotokolldatei

Erstellen Sie als Nächstes eine Änderungsprotokolldatei.

Sie können das Beschreibungsformat wählen, aber ich werde Groovy DSL verwenden.

Es gibt zwei Möglichkeiten, ein Änderungsprotokoll zu erstellen: eine stammt aus der Datenbank und die andere aus der Domänenklasse. Im Moment denke ich, dass die Datenbank beim Start automatisch aus der Domänenklasse erstellt wird. Wählen Sie daher die Methode zum Erstellen des Änderungsprotokolls aus der Datenbank aus.

So erstellen Sie ein Änderungsprotokoll aus einer Datenbank im Groovy DSL-Format


$ grails dbm-generate-changelog changelog.groovy
  : <snip>Plugins werden nach Bedarf heruntergeladen
:compileJava NO-SOURCE
:compileGroovy UP-TO-DATE
:buildProperties UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:dbmGenerateChangelog

BUILD SUCCESSFUL

Total time: 16.478 secs

Anschließend wird das folgende Änderungsprotokoll erstellt.

Änderungsprotokoll(grails-app/migrations/changelog.groovy)


databaseChangeLog = {

  changeSet(author: "tatsurou (generated)", id: "1537102923747-1") {
    createTable(tableName: "EMPLOYEE") {
      column(autoIncrement: "true", name: "ID", type: "BIGINT(19)") {
        constraints(primaryKey: "true", primaryKeyName: "CONSTRAINT_7")
      }

      column(name: "VERSION", type: "BIGINT(19)") {
        constraints(nullable: "false")
      }

      column(name: "NAME", type: "VARCHAR(255)") {
        constraints(nullable: "false")
      }
    }
  }
}

Jetzt können Sie die Datenbank basierend auf dem Änderungsprotokoll erstellen. (Es wird nur das Datenbankschema erstellt, es werden keine Daten migriert.)

Von nun an erstellen Sie nach dem Bearbeiten der Domänenklasse manuell oder automatisch ein Änderungsprotokoll und führen "dbm-update" aus.

  1. Bearbeiten Sie die Domänenklasse
  2. Bearbeiten Sie das Änderungsprotokoll
  1. Sichern Sie die Datenbank (falls etwas schief geht)
  2. Führen Sie "grails dbm-update" für jede Umgebung aus (Entwicklung, Test, Produktion).

Groovige Konsole

Die Groovy-Konsole ist eine Anwendung, mit der Sie Groovy-Quellcode eingeben und ausführen können. Sie können auch eine in einer Grails-Anwendung implementierte Domänenklasse laden oder das ORM dieser Domänenklasse verwenden, um die Datenbank zu bearbeiten.

Sie können die Grails-Konsole starten, indem Sie den Befehl grails console ausführen.

Starten Sie die groovige Konsole


$ cd ${Anwendungsverzeichnis}
$ grails console

image.png

package grails.sample.app

def id = 1
def e = Employee.get(id)
if (e == null) {
  println("Not found employee id " + id)
  exit()
}
println("employee: " + e)
println("name: " + e.name)
e.name = 'test99'
e.save(flush: true)

Fehlerbehandlung

Beschreibt die Fehler, die beim Ausführen des Befehls Grails auftreten, und wie mit ihnen umgegangen werden soll.

Could not acquire change log lock

Command execution error: Could not acquire change log lock.  Currently locked by ${COMPUTER_NAME} (${IP_ADDRESS}) since 18/09/17 0:09

Recommended Posts

Grale fangen an
Erste Schritte mit Android!
1.1 Erste Schritte mit Python
Erste Schritte mit apache2
Erste Schritte mit Python
Erste Schritte mit Django 1
Einführung in die Optimierung
Erste Schritte mit Spark
Erste Schritte mit Python
Erste Schritte mit Pydantic
Erste Schritte mit Jython
Erste Schritte mit Django 2
Übersetzen Erste Schritte mit TensorFlow
Einführung in Python-Funktionen
Einführung in Tkinter 2: Button
[Linux] [Grundeinstellung] Einführung
Erste Schritte mit PKI mit Golang ―― 4
Django Erste Schritte: 2_ Erstellen eines Projekts
Django Erste Schritte: 1_Umgebungsgebäude
Erste Schritte mit Python Django (1)
Erste Schritte mit Django: 4_MySQL-Integration
Erste Schritte mit Python Django (3)
Einführung in Python Django (6)
Erste Schritte mit Django mit PyCharm
Erste Schritte mit Python Responder v2
Einführung in Git (1) History-Speicher
Erste Schritte mit Sphinx. Generieren Sie Docstring mit Sphinx
Erste Schritte mit Python-Webanwendungen
Erste Schritte mit Python für PHPer-Klassen
Erste Schritte mit Sparse Matrix mit scipy.sparse
Erste Schritte mit Julia für Pythonista
Erste Schritte mit Python Grundlagen von Python
Erste Schritte mit der Cisco Spark REST-API
Erste Schritte mit genetischen Python-Algorithmen
Erste Schritte mit Python 3.8 unter Windows
Erste Schritte mit Python für PHPer-Funktionen
Erste Schritte mit der CPU-Diebstahlzeit
Erste Schritte mit Python3 # 1 Grundkenntnisse erlernen
Erste Schritte mit Python Web Scraping Practice
Erste Schritte mit Python für PHPer-Super Basics
Erste Schritte mit Python Web Scraping Practice
Erste Schritte mit Dynamo von Python Boto
Python gestartet
Erste Schritte: 30 Sekunden für die japanische Übersetzung von Keras
Erste Schritte mit Lisp für Pythonista: Ergänzung
Erste Schritte mit Heroku, Bereitstellen der Flaschen-App
Erste Schritte mit TDD mit Cyber-dojo bei MobPro
Erste Schritte mit Python mit 100 Klopfen bei der Sprachverarbeitung
MongoDB-Grundlagen: Erste Schritte mit CRUD mit JAVA
Erste Schritte mit dem Zeichnen mit matplotlib: Schreiben einfacher Funktionen
Erste Schritte mit der japanischen Übersetzung des Keras Sequential-Modells
[Übersetzung] Erste Schritte mit Rust für Python-Programmierer
Django Erste Schritte Teil 2 mit dem Eclipse Plugin (PyDev)
Erste Schritte mit AWS IoT in Python
Erste Schritte mit Pythons Ast-Modul (Verwenden von NodeVisitor)