Для создания приложения grails нужно в консоли набрать следующие команды:
sa@noname:~/projects$ grails create-app
| Environment set to development.....
> Application name not specified. Please enter: contacts
| Created Grails Application at /home/sa/projects/contacts
sa@noname:~/projects$ cd contacts
sa@noname:~/projects/contacts$ grails
| Enter a script name to run. Use TAB for completion:
grails> create-domain-class Contact
| Compiling 38 source files
| Created file grails-app/domain/contacts/Contact.groovy
| Created file test/unit/contacts/ContactTests.groovy
grails> generate-all contacts.Contact
| Finished generation for domain class contacts.Contact
grails> run-app
| Server running. Browse to http://localhost:8080/contacts
| Application loaded in interactive mode. Type 'exit' to shutdown.
Итак мы создали каркас приложения contacts.
У каждого контакта (как мы выяснили путем анализа предметной области) есть
список телефонов. В качестве хранилища телефонов можно ( и правильно с точки зрения ООП) ввести новый класс - Телефон. Однако, следуя традиции ремесленного программирования - пытаемся облегчить( упростить) задачу, исходя из размышлений о том, что телефоны будут учитываться для себя и круг контактов у нас не так велик, а следовательно и изменения в его (линейную на сейчас) структуру вносить вряд ли понадобится. Итак имеем класс Contact:
package contacts
class Contact {
String name
Date dateCreated //
Date lastUpdated // - автополя(заполняются grails автоматически!)
static hasMany=[phones:String,emails:String]
static constraints = {
}
}
Если теперь сгенерировать представления командой generate-all, в шаблоне _form.gsp вместо списка телефонов мы увидим лишь метку(label), которая напомнит нам несмотря ни на что, телефоны все-таки существуют. Вот так облегчили задачу! Да если бы мы не поленились и добавили еще пару классов, то grails сделал бы все эти поля редактируемыми! Но мы не намерены сдаваться. Модифицируем класс следующим образом:
package contacts
class Contact {
String name
Date dateCreated
Date lastUpdated
String listPhone
static hasMany=[phones:String,emails:String]
public String getListPhone() {
def lst = ""
phones.each{ lst=lst+it}
return lst
}
public void setListPhone(String listPhone) {
this.phones=listPhone.split('/n');
this.listPhone=listPhone
}
static transients = ['listPhone']
static constraints = {
}
}
и добавим в _forms.gsp вот такой код:
<g:textArea name="listPhone" value="${contactInstance?.listPhone}" rows="5" cols="40"/>
Т.е. используя несохраняемое поле будем, передавать через него данные в phones.
В качестве логического разделителя договоримся использовать символ новой строки. Вуаля! Осталось добавить колонку в представление list.gsp:
<thead>
<tr>
.......................
<g:sortableColumn property="listPhone" title="${message(code: 'contact.listPhone.label', default: 'List Phone')}" />
...................
</tr>
</thead>
<tbody>
<g:each in="${contactInstanceList}" status="i" var="contactInstance">
............................
<td>${fieldValue(bean: contactInstance, field: "listPhone")}</td>
................................................
В следующих уроках: полнотекстовый поиск по базе, ограничение доступа к приложению, добавление отчета.
sa@noname:~/projects$ grails create-app
| Environment set to development.....
> Application name not specified. Please enter: contacts
| Created Grails Application at /home/sa/projects/contacts
sa@noname:~/projects$ cd contacts
sa@noname:~/projects/contacts$ grails
| Enter a script name to run. Use TAB for completion:
grails> create-domain-class Contact
| Compiling 38 source files
| Created file grails-app/domain/contacts/Contact.groovy
| Created file test/unit/contacts/ContactTests.groovy
grails> generate-all contacts.Contact
| Finished generation for domain class contacts.Contact
grails> run-app
| Server running. Browse to http://localhost:8080/contacts
| Application loaded in interactive mode. Type 'exit' to shutdown.
Итак мы создали каркас приложения contacts.
У каждого контакта (как мы выяснили путем анализа предметной области) есть
список телефонов. В качестве хранилища телефонов можно ( и правильно с точки зрения ООП) ввести новый класс - Телефон. Однако, следуя традиции ремесленного программирования - пытаемся облегчить( упростить) задачу, исходя из размышлений о том, что телефоны будут учитываться для себя и круг контактов у нас не так велик, а следовательно и изменения в его (линейную на сейчас) структуру вносить вряд ли понадобится. Итак имеем класс Contact:
package contacts
class Contact {
String name
Date dateCreated //
Date lastUpdated // - автополя(заполняются grails автоматически!)
static hasMany=[phones:String,emails:String]
static constraints = {
}
}
Если теперь сгенерировать представления командой generate-all, в шаблоне _form.gsp вместо списка телефонов мы увидим лишь метку(label), которая напомнит нам несмотря ни на что, телефоны все-таки существуют. Вот так облегчили задачу! Да если бы мы не поленились и добавили еще пару классов, то grails сделал бы все эти поля редактируемыми! Но мы не намерены сдаваться. Модифицируем класс следующим образом:
package contacts
class Contact {
String name
Date dateCreated
Date lastUpdated
String listPhone
static hasMany=[phones:String,emails:String]
public String getListPhone() {
def lst = ""
phones.each{ lst=lst+it}
return lst
}
public void setListPhone(String listPhone) {
this.phones=listPhone.split('/n');
this.listPhone=listPhone
}
static transients = ['listPhone']
static constraints = {
}
}
и добавим в _forms.gsp вот такой код:
<g:textArea name="listPhone" value="${contactInstance?.listPhone}" rows="5" cols="40"/>
Т.е. используя несохраняемое поле будем, передавать через него данные в phones.
В качестве логического разделителя договоримся использовать символ новой строки. Вуаля! Осталось добавить колонку в представление list.gsp:
<thead>
<tr>
.......................
<g:sortableColumn property="listPhone" title="${message(code: 'contact.listPhone.label', default: 'List Phone')}" />
...................
</tr>
</thead>
<tbody>
<g:each in="${contactInstanceList}" status="i" var="contactInstance">
............................
<td>${fieldValue(bean: contactInstance, field: "listPhone")}</td>
................................................
В следующих уроках: полнотекстовый поиск по базе, ограничение доступа к приложению, добавление отчета.
Комментарии
Отправить комментарий