Adding new entity
Today we will work on extending Shyshka application with the possibility of adding examples to the words. To each word we will be able to add as many examples of usages as we wish.
What are associations?
In simple words, associations model relationships between entities. In our case, our one entity will be Word and the second one will be Example. Each Word can have many Examples but every Example can have only one Word associated to it.
Associations in Hanami
Since associations represents how data is linked in the database, we define associations in repositories.
Unlike associations in Ruby on Rails framework, associations does not add any public method to the repository. Instead, Hanami prefers explicit interface - which means that if we want to perform specific action, like adding word with examples, we need to explicitly add method to perform this operation. This design choice is supposed to prevent repositories from having extensive and mostly unused public API.
Another difference between Ruby on Rails and Hanami associations is lacking of eager loading - if we want to load a Word with associated Examples we have to add additional method to do it. If we don’t add this method, then the result of the association will be
The first we need to do is creating a new entity called Example.
bundle exec hanami generate migration create_examples
Open newly created migration file and add this code:
Hanami::Model.migration do change do create_table :examples do primary_key :id foreign_key :word_id, :words, on_delete: :cascade, null: false column :text, String, null: false column :created_at, DateTime, null: false column :updated_at, DateTime, null: false end end end
Most of the code above is familiar - we define a new table called examples, set primary_key and some columns. The new thing here is foreign_key - we specify here a column that will link Example with a Word. By setting
on_delete: :cascade we define how this entry should behave when associated Word will be deleted - in our case we want to delete Examples as well.
To run the migration type in the console:
bundle exec hanami db prepare
Now, let’s generate Example model. We will do this by typing:
bundle exec hanami generate model example
Next, let’s open
WordRepository and define the association with Example here:
class WordRepository < Hanami::Repository associations do has_many :examples end def create_with_examples(data) assoc(:examples).create(data) end def add_example(word, data) assoc(:examples, word).add(data) end def find_with_examples(id) aggregate(:examples).where(id: id).as(Word).one end end
We have defined a
has_many association between Word and Example models and we have added three new methods:
create_with_examplesfor creating Word with Example at one go
add_examplefor adding Example to an existing Word
find_with_examplesfor retrieving Word with all Examples preloaded
Today we’ve stepped out of basic CRUD app and we’ve extended our app with the first association. In the next post, we will prepare our frontend for adding and displaying words with associated examples.Written on May 8, 2017