Introduces Hanami::Relation
:warning: Achtung: This is a true draft PR. The code is messy. The commit history is changing all the time and broken tests are a thing. :warning:
This PR is the first step towards bringing model closer to rom.
In this we introduce the Relation abstraction in the same terms as rom does. This simplifies our code, boot process and exposes more of ROM to the users.
Most important changes
Modules instead of suffixes
Repositories, Entities and Relations are expected to be under a certain directory structure that should reflect a module structure. This follows the same rules for ROM auto-registration feature
Bookshelf::Relations::Books #=> should exist under bookshelf/relations/books.rb
- [x] Relations
- [x] Entities
- [ ] Repositories
Hanami::Relation
This PR introduces Hanami::Relation which maps directly to a ROM::Relation and offers the exact same API (being only an alias to it).
class ProjectName::Relations::Users < Hanami::Relation[:sql]
schema(infer: true) do
associations do
has_many :books
end
end
end
Hanami::Repository
Hanami::Repository now takes the name of its root relation. Overall functionality is the same.
# This is moving to module namespacing soon
class BookRepository < Hanami::Repository[:books]
end
Hanami::Entity
Entity becomes a ROM::Struct
TODO
- [ ] Update YARD docs
- [ ] Remove unnecessary tests due to the new approach
- [ ] Find a way to silence
Repositorymethod override (create, delete, update) (or remove if not needed) - [ ] Setup an easy way to instantiate an Entity (ROM)
- [ ] Workout why some queries return
ROM::Structand othersHanami::Entityforcing bothRelationandRepositoryto have thestruct_namespacemacro on them - [ ] Work out some unexpected behaviour:
class Books < ROM::Relation[:sql]
schema(infer: true) do
associations { belongs_to :author }
end
end
class Authors < ROM::Relation[:sql]
schema(infer: true) do
associations { has_many :books }
end
end
class Comments < ROM::Relation[:sql]
schema(infer: true) do
associations { belongs_to :user, as: :author }
end
end
class Users < ROM::Relation[:sql]
schema(infer: true) do
associations { has_many :comments }
end
end
class Repositories::Comment < ROM::Repository[:comments]
def with_author
root.combine(:author).to_a
end
end
Repositories::Comment.new.with_author.first.author
#=> <ROM::Struct::Author id=50 name="Bob from the Upside Down" email=nil age=19 comments_count=0 active=true created_at=2020-07-17 14:20:24 UTC updated_at=2020-07-17 14:20:24 UTC>
In the case above, the returned struct is in fact a User, but ROM renamed it Author as the association is aliased (and this is kinda neat). Why this can become an issue? In the above example the project has an Author entity and relation, so this can get a little confusing.