# Add an operation for creating book reviews · Your first Rell app on Chromia · Learn Chromia

> 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.

Source: https://chromia.com/learn/book-review/book-review-entity/basic-operations/

Your first Rell app on ChromiaLesson 10 of 26

1. [01Your first Rell app on Chromia](https://chromia.com/learn/book-review/introduction/)
2. [02Set up your project](https://chromia.com/learn/book-review/setup/)
3. [03Rell project structure](https://chromia.com/learn/book-review/rell-structure/)

Part 1: Define your first entity

1. [04Overview](https://chromia.com/learn/book-review/book-entity/)
2. [05Create your first entity](https://chromia.com/learn/book-review/book-entity/tables/)
3. [06Add your first operation](https://chromia.com/learn/book-review/book-entity/basic-operations/)
4. [07Query every book](https://chromia.com/learn/book-review/book-entity/write-queries/)

Part 2: Add a related entity

1. [08Overview](https://chromia.com/learn/book-review/book-review-entity/)
2. [09Define the book review entity](https://chromia.com/learn/book-review/book-review-entity/tables/)
3. [10Add an operation for creating book reviews](https://chromia.com/learn/book-review/book-review-entity/basic-operations/)
4. [11Query all reviews for a book](https://chromia.com/learn/book-review/book-review-entity/write-queries/)

Part 3: Checking and validating inputs

1. [12Overview](https://chromia.com/learn/book-review/input-verification/)
2. [13Verify inputs](https://chromia.com/learn/book-review/input-verification/input-verification/)
3. [14Return structured results from queries](https://chromia.com/learn/book-review/input-verification/structure/)

Part 4: Signing transactions and filtering queries

1. [15Overview](https://chromia.com/learn/book-review/sign-transaction/)
2. [16Sign a transaction](https://chromia.com/learn/book-review/sign-transaction/sign-transaction/)
3. [17Filter and sort query results](https://chromia.com/learn/book-review/sign-transaction/structure/)

Part 5: Blockchain state and transactions explained

1. [18Overview](https://chromia.com/learn/book-review/blockchain-transactions/)
2. [19How blockchain state and transactions work](https://chromia.com/learn/book-review/blockchain-transactions/query-transaction/)
3. [20Walking through an example](https://chromia.com/learn/book-review/blockchain-transactions/example/)

Part 6: Create the client

1. [21Overview](https://chromia.com/learn/book-review/build-client/)
2. [22Prerequisites](https://chromia.com/learn/book-review/build-client/prerequisites/)
3. [23Establishing a connection to Chromia](https://chromia.com/learn/book-review/build-client/sign-transaction/)
4. [24Query the blockchain using postchain-client](https://chromia.com/learn/book-review/build-client/query-blockchain/)
5. [25Complete the example](https://chromia.com/learn/book-review/build-client/complete-example/)

1. [26What’s next?](https://chromia.com/learn/book-review/what-next/)

[Learn](https://chromia.com/learn/)[Your first Rell app on Chromia](https://chromia.com/learn/book-review/)

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`:

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:

rell

```
  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`:

src/test/book\_review\_test.rell

```nolines
import main.{ book, create_book, get_all_books, book_review, create_book_review };
```

Then add this test code to the same file:

src/test/book\_review\_test.rell

```
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:

shell

```nolines
chr test
```

The output should report that every test passed:

shell

```
TEST RESULTS:

OK test.book_review_test:test_add_book
OK test.book_review_test:test_get_books
OK test.book_review_test:test_add_book_review

SUMMARY: 0 FAILED / 3 PASSED / 3 TOTAL

***** OK *****
```

## Testing with a local Chromia node

To try the new operation against a local Chromia node:

1. **Update or start the local Chromia node:**

   * **If your node is already running**, update it with:

     shell

     ```nolines
     chr node update
     ```
   * **If your node is not running**, start it with:

     shell

     ```nolines
     chr node start
     ```

   **Note:** Changes from `chr node update` can take a short time to apply. You may have to wait until the next block is processed before the query is available.
2. **Submit a transaction that adds a book review:**

   Run this command to create the transaction:

   shell

   ```nolines
   chr tx --await create_book_review "ISBN1234" "Alice" "It was a great book" 5
   ```

   You should see:

   shell

   ```nolines
   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.

Written for this site from Chromia’s public course. Code samples are the course’s own.

[← Previous**Define the book review entity**](https://chromia.com/learn/book-review/book-review-entity/tables/)[Next →**Query all reviews for a book**](https://chromia.com/learn/book-review/book-review-entity/write-queries/)

On this page

* [Adding unit tests](#adding-unit-tests)
* [Testing with a local Chromia node](#testing-with-a-local-chromia-node)
