Edit the migrations:

  1. # db/migrations/20171024081558_create_authors.rb
  2. Hanami::Model.migration do
  3. change do
  4. create_table :authors do
  5. primary_key :id
  6. column :name, String, null: false
  7. column :created_at, DateTime, null: false
  8. column :updated_at, DateTime, null: false
  9. end
  10. end
  11. end
  1. # db/migrations/20171024081617_create_books.rb
  2. Hanami::Model.migration do
  3. create_table :books do
  4. primary_key :id
  5. foreign_key :author_id, :authors, on_delete: :cascade, null: false
  6. column :title, String, null: false
  7. column :created_at, DateTime, null: false
  8. column :updated_at, DateTime, null: false
  9. end
  10. end
  11. end

Now we can prepare the database:

Let’s edit BookRepository with the following code:

  1. # lib/bookshelf/repositories/book_repository.rb
  2. class BookRepository < Hanami::Repository
  3. associations do
  4. belongs_to :author
  5. end
  6. def find_with_author(id)
  7. aggregate(:author).where(id: id).map_to(Book).one
  8. end

Let’s create a book:

  1. repository = BookRepository.new
  2. book = repository.create(author_id: 1, title: "Hanami")
  3. # => #<Book:0x00007f89ac270118 @attributes={:id=>1, :author_id=>1, :created_at=>2017-10-24 08:25:41 UTC, :updated_at=>2017-10-24 08:25:41 UTC}>

What happens if we load the author with BookRepository#find?

Because we haven’t the associated records, book.author is nil. We can use the method that we have defined on before (#find_with_author):

  1. book = repository.find_with_author(book.id)
  2. # => #<Book:0x00007fb3f88896a0 @attributes={:id=>1, :author_id=>1, :created_at=>2017-10-24 08:25:41 UTC, :updated_at=>2017-10-24 08:25:41 UTC, :author=>#<Author:0x00007fb3f8888980 @attributes={:id=>1, :name=>"Luca", :created_at=>2017-10-24 08:25:15 UTC, :updated_at=>2017-10-24 08:25:15 UTC}>}>
  3. book.author
  4. # => => #<Author:0x00007fb3f8888980 @attributes={:id=>1, :name=>"Luca", :created_at=>2017-10-24 08:25:15 UTC, :updated_at=>2017-10-24 08:25:15 UTC}>

What if we need to unassociate a book from its author?

Because we declared a foreign key with the , we cannot set author_id to NULL or to reference to an unexisting author. This is a mechanism against orphaned records: a book is forced to reference a valid author.

The only way to remove a book from an author is to delete the book record.

  1. repository.delete(book.id)
  2. # => nil