アソシエーション

協会は、2つのエンティティ間の論理的な関係です。

現在のバージョンのとおり、花見は、SQLアダプターのための実験的な機能として、関連付けをサポートしています。

 

設計

アソシエーションがデータベースに一緒にリンクされたデータで構成されているので、我々は、リポジトリ内の関連付けを定義します。

 

明示的インターフェイス

我々は関連付けを宣言すると、そのリポジトリはしませんそのパブリックインターフェイスに余分な方法を取得します。この花見はしばしば使用されていないいくつかの方法でリポジトリを膨らませるために予防したいと考えているため。

我々は関連を定義すると、リポジトリは余分なパブリックメソッドを取得していません。

私たちは、文脈数冊の本で、著者を作成する必要がある場合、我々は明示的にその操作を実行するためのメソッドを定義する必要があります。

 

明示的なロード

同じ原理は、読み取り操作に適用されます。私たちは熱心な負荷に関連した本で、著者をしたい場合は、私たちがそうするように、明示的な方法が必要になります。

私たちは、明示的にその本をロードしない場合は、その結果のデータになりますnil

 

いいえプロキシローダーありません

団体での操作が明示的なリポジトリのメソッドを介して行われていることを覚えておいてください。花見はしません、デザインによって以下のユースケースをサポートしています。

  • author.books (データベースから本をロードしようとします)
  • author.books.where(on_sale: true)(ロードしようとする販売上のデータベースから図書)
  • author.books << book (著者に本を関連付けしようとします)
  • author.books.clear (著者からの本関連付けを解除しようとします)

それは覚えておいてくださいauthor.booksその変異は単なる配列で、データベースには反映されません

 

団体の種類

 

多くを持っています

知られている一対多、単一のエンティティ(の間の関連付けであるAuthor)、および多くの他のリンクされたエンティティ(の集まりBook)。

% bundle exec hanami generate migration create_authors
      create  db/migrations/20161115083440_create_authors.rb
# db/migrations/20161115083440_create_authors.rb
Hanami::Model.migration do
  change do
    create_table :authors do
      primary_key :id

      column :name,       String,   null: false
      column :created_at, DateTime, null: false
      column :updated_at, DateTime, null: false
    end
  end
end
% bundle exec hanami generate migration create_books
      create  db/migrations/20161115083644_create_books.rb
# db/migrations/20161115083644_create_books.rb
Hanami::Model.migration do
  change do
    create_table :books do
      primary_key :id
      foreign_key :author_id, :authors, on_delete: :cascade, null: false

      column :title,      String,   null: false
      column :created_at, DateTime, null: false
      column :updated_at, DateTime, null: false
    end
  end
end
% bundle exec hanami db prepare
% bundle exec hanami generate model author
      create  lib/bookshelf/entities/author.rb
      create  lib/bookshelf/repositories/author_repository.rb
      create  spec/bookshelf/entities/author_spec.rb
      create  spec/bookshelf/repositories/author_repository_spec.rb

% bundle exec hanami generate model book
      create  lib/bookshelf/entities/book.rb
      create  lib/bookshelf/repositories/book_repository.rb
      create  spec/bookshelf/entities/book_spec.rb
      create  spec/bookshelf/repositories/book_repository_spec.rb

さんが編集してみましょうAuthorRepository次のコードで:

# lib/bookshelf/repositories/author_repository.rb
class AuthorRepository < Hanami::Repository
  associations do
    has_many :books
  end

  def create_with_books(data)
    assoc(:books).create(data)
  end

  def find_with_books(id)
    aggregate(:books).where(id: id).as(Author).one
  end
end

私たちは、定義した明示的なメソッドをのみ、我々は我々のモデルのドメインのために必要な操作のために。このように、我々は、肥大化しないようAuthorRepository、不要な方法のダースと。

のは、と本のコレクションと作者を作成してみましょう単一のデータベース操作

repository = AuthorRepository.new

author = repository.create_with_books(name: "Alexandre Dumas", books: [{title: "The Count of Montecristo"}])
  # => #<Author:0x007f811c415420 @attributes={:id=>1, :name=>"Alexandre Dumas", :created_at=>2016-11-15 09:19:38 UTC, :updated_at=>2016-11-15 09:19:38 UTC, :books=>[#<Book:0x007f811c40fe08 @attributes={:id=>1, :author_id=>1, :title=>"The Count of Montecristo", :created_at=>2016-11-15 09:19:38 UTC, :updated_at=>2016-11-15 09:19:38 UTC}>]}>

author.id
  # => 1
author.name
  # => "Alexandre Dumas"
author.books
  # => [#<Book:0x007f811c40fe08 @attributes={:id=>1, :author_id=>1, :title=>"The Count of Montecristo", :created_at=>2016-11-15 09:19:38 UTC, :updated_at=>2016-11-15 09:19:38 UTC}>]

我々が著者をロードする場合はどうなるのAuthorRepository#find

author = repository.find(author.id)
  # => #<Author:0x007f811b6237e0 @attributes={:id=>1, :name=>"Alexandre Dumas", :created_at=>2016-11-15 09:19:38 UTC, :updated_at=>2016-11-15 09:19:38 UTC}>
author.books
  # => nil

私たちはしていないので、明示的にロードされた関連レコードを、author.booksですnil。私たちは(前に定義したメソッドを使用することができます#find_with_books):

author = repository.find_with_books(author.id)
  # => #<Author:0x007f811bbeb6f0 @attributes={:id=>1, :name=>"Alexandre Dumas", :created_at=>2016-11-15 09:19:38 UTC, :updated_at=>2016-11-15 09:19:38 UTC, :books=>[#<Book:0x007f811bbea430 @attributes={:id=>1, :author_id=>1, :title=>"The Count of Montecristo", :created_at=>2016-11-15 09:19:38 UTC, :updated_at=>2016-11-15 09:19:38 UTC}>]}>

author.books
  # => [#<Book:0x007f811bbea430 @attributes={:id=>1, :author_id=>1, :title=>"The Count of Montecristo", :created_at=>2016-11-15 09:19:38 UTC, :updated_at=>2016-11-15 09:19:38 UTC}>]

この時間はauthor.books、関連図書のコレクションを持っています。


私たちは、著者から本を追加または削除する必要がある場合は?私たちは、これを行うには、新しいメソッドを定義する必要があります。

# lib/bookshelf/repositories/author_repository.rb
class AuthorRepository < Hanami::Repository
  # ...

  def add_book(author, data)
    assoc(:books, author).add(data)
  end
end

さんが本を追加してみましょう:

book = repository.add_book(author, title: "The Three Musketeers")

そして、それを削除します。

BookRepository.new.delete(book.id)