10 / 26Part 2: Add a related entityBeginner
Add an operation for creating book reviews
Your model now has two entities, so the next step is a way to add new book review entries. You do this with an operation that creates a book review.
Add the following Rell code to src/main/operations.rell:
operation create_book_review(isbn: text, reviewer_name: text, review: text, rating: integer) { val book = book @ { .isbn == isbn }; create book_review ( book, reviewer_name, review, rating );}The structure mirrors the create_book operation, with one difference: it links the review to a book. Books are keyed by isbn, so that value identifies which book the review belongs to.
Inside the operation
When you submit the create-review operation to a Chromia node, the node produces a new transaction and stores the data in the dapp table state. The flow looks like this:
- A user signs the transaction
create_book_review("ISBN1234", "Alice", "It was a great book!", 5). - The Chromia Node receives the transaction, validates it, and passes it on to the blockchain.
- Inside the operation:
val book = book @ { .isbn == isbn }; create book_review ( book, reviewer_name, review, rating );The operation looks up the book in the dapp table state and inserts a new book_review row that references that book.
- Once the transaction is confirmed, it goes into a block on the blockchain and the dapp table state reflects the change.
Adding unit tests
Next, write a test that confirms the book review operation behaves correctly. Rell supports test modules, which make writing tests simple.
In src/test/book_review_test.rell, extend the imports so they include book_review and create_book_review:
import main.{ book, create_book, get_all_books, book_review, create_book_review };Then add this test code to the same file:
function test_add_book_review() { rell.test.tx() .op(create_book("123", "Book1", "Author1")) .op(create_book_review("123", "Reviewer1", "ReviewText1", 5)) .op(create_book_review("123", "Reviewer2", "ReviewText2", 3)) .run(); val reviews = book_review @* { }; val book = book @ { .isbn == "123" }; assert_equals(reviews.size(), 2); assert_equals(book, reviews[0].book); assert_equals(reviews[0].reviewer_name, "Reviewer1"); assert_equals(reviews[0].review, "ReviewText1"); assert_equals(reviews[0].rating, 5);}The test runs a single transaction containing three operations: one creates a book, and the other two create reviews linked to that book.
assert_equals(reviews.size(), 2);confirms that exactly two entries exist.assert_equals(book, reviews[0].book);confirms that the review points to the right book.assert_equals(reviews[0].reviewer_name, "Reviewer1")checks the reviewer's name.assert_equals(reviews[0].review, "ReviewText1")checks the review text.assert_equals(reviews[0].rating, 5)checks the rating.
Run the tests with this command:
chr testThe output should report that every test passed:
TEST RESULTS:OK test.book_review_test:test_add_bookOK test.book_review_test:test_get_booksOK test.book_review_test:test_add_book_reviewSUMMARY: 0 FAILED / 3 PASSED / 3 TOTAL***** OK *****Testing with a local Chromia node
To try the new operation against a local Chromia node:
-
Update or start the local Chromia node:
-
If your node is already running, update it with:
shell chr node update -
If your node is not running, start it with:
shell chr node start
Note: Changes from
chr node updatecan take a short time to apply. You may have to wait until the next block is processed before the query is available. -
-
Submit a transaction that adds a book review:
Run this command to create the transaction:
shell chr tx --await create_book_review "ISBN1234" "Alice" "It was a great book" 5You should see:
shell transaction with rid TxRid(rid=<RID>) was posted CONFIRMED
This output means the transaction is on the blockchain and the state now holds a row containing your book review.