编辑一行
机器翻译
本页由英文原文机器翻译而来,尚未经过母语审校,欢迎在 GitHub 上提出修改。内容如有出入,以英文原文为准。
任务: 一个从列表进入、编辑一本书的页面。
yaml
# Recipe: open a form with a row's values and save it back.
paths:
components: ./components
migrations: ./migrations
datasources:
db:
driver: sqlite
database: ./data/books.dbsql
CREATE TABLE books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title VARCHAR(120) NOT NULL,
genre TEXT NOT NULL CHECK (genre IN ('novel', 'poetry', 'essay'))
);
INSERT INTO books (title, genre) VALUES ('Dom Casmurro', 'novel'), ('Libertinagem', 'poetry');列表把每本书链接到 /book/{id}:
xml
<q:component name="Books">
<q:query name="books" datasource="db">
SELECT id, title, genre FROM books ORDER BY id
</q:query>
<ui:window title="Books">
<q:if condition="flash">
<ui:alert variant="success">{flash}</ui:alert>
</q:if>
<q:loop query="books">
<ui:hbox gap="sm">
<ui:text>{books.title} ({books.genre})</ui:text>
<ui:link to="/book/{books.id}">Edit</ui:link>
</ui:hbox>
</q:loop>
</ui:window>
</q:component>components/book/[id].q 以 id = 2 响应 /book/2。动作从数据表中获取 title 和 genre(根据数据表生成表单),values="{book}" 让表单打开时带着这一行的值。一个只返回一行的查询就够了。
xml
<q:component name="EditBook">
<!-- /book/2 gives id = 2. The action takes title and genre, with their
rules, from the table (UI-10); id comes from the URL. -->
<q:action name="save" method="POST" table="books" datasource="db" columns="title,genre">
<q:query name="saved" datasource="db">
UPDATE books SET title = :title, genre = :genre WHERE id = :id
<q:param name="title" value="{title}" type="string" />
<q:param name="genre" value="{genre}" type="string" />
<q:param name="id" value="{id}" type="integer" />
</q:query>
<q:redirect url="/" flash="Saved: {title}" />
</q:action>
<q:query name="book" datasource="db">
SELECT id, title, genre FROM books WHERE id = :id
<q:param name="id" value="{id}" type="integer" />
</q:query>
<ui:window title="Edit a book">
<q:if condition="book_result.recordCount == 0">
<ui:alert variant="danger">There is no book {id}.</ui:alert>
</q:if>
<q:else>
<!-- values= opens the form with the row's values; a one-row query works. -->
<ui:form on-submit="save" values="{book}" submit="Save" />
</q:else>
<ui:link to="/">Back</ui:link>
</ui:window>
</q:component>xml
<q:test name="the form opens on the row's page" page="/book/2">
<test:visit />
<test:expect text="Edit a book" />
<test:expect text="Save" />
<test:expect no-text="There is no book" />
</q:test>
<q:test name="saving changes only that row" page="/book/2">
<test:submit action="save" title="Libertinagem (1930)" genre="poetry" />
<test:expect redirect="/" flash="Saved: Libertinagem (1930)" />
<test:expect table="books" count="1" where="id = 2 AND title = 'Libertinagem (1930)'" />
<test:expect table="books" count="1" where="id = 1 AND title = 'Dom Casmurro'" />
<test:expect text="Libertinagem (1930) (poetry)" />
</q:test>
<q:test name="the table's rules still apply" page="/book/2">
<test:submit action="save" title="Libertinagem" genre="comic" />
<test:expect error="genre" message="Must be one of: novel, poetry, essay" />
<test:expect table="books" count="1" where="id = 2 AND genre = 'poetry'" />
</q:test>
<q:test name="a book that does not exist says so" page="/book/99">
<test:visit />
<test:expect text="There is no book 99." />
<test:expect no-text="Save" />
</q:test>text
tests/edit.test.q
PASS the form opens on the row's page
PASS saving changes only that row
PASS the table's rules still apply
PASS a book that does not exist says so
4 passed, 0 failed参见 UI-10。