Giter Site home page Giter Site logo

rom-repository's Introduction

ROM::Repository

Gem Version Build Status Dependency Status Code Climate Test Coverage Inline docs

Repository for ROM with auto-mapping and relation extensions.

Conventions & Definitions

Repositories in ROM are simple objects that allow you to compose rich relation views specific to your application layer. Every repository can access multiple relations that you define and use them to build more complex views.

Repository relations are enhanced with a couple of extra features on top of ROM relations:

  • Every relation has an auto-generated mapper which turns raw data into simple, immutable structs
  • Relation#combine can accept a simple hash defining what other relations should be joined
  • Relation#combine_parents automatically joins parents using eager-loading
  • Relation#combine_children automatically joins children using eager-loading
  • Relation#wrap_parent automatically joins a parent using inner join

Relation Views

A relation view is a result of some query which returns results specific to your application. You can define them using a simple DSL where you specify a name, what attributes resulting tuples will have and of course the query itself:

class Users < ROM::Relation[:sql]
  view(:by_id, [:id, :name]) do |id|
    where(id: id).select(:id, :name)
  end

  view(:listing, [:id, :name, :email, :created_at]) do
    select(:id, :name, :email, :created_at).order(:name)
  end
end

This way we can explicitly define all our relation view that our application will depend on. It encapsulates access to application-specific data structures and allows you to easily test individual views in isolation.

Thanks to explicit definition of attributes mappers are derived automatically.

Auto-combine & Auto-wrap

Repository relations support automatic combine and wrap by using a simple convention that every relation defines for_combine(keys, other) and for_wrap(keys, other).

You can override the default behavior for combine by defining for_other_rel_name in example, if you combine tasks with users you can define Tasks#for_users and this will be used instead of the generic for_combine.

Mapping & Structs

Currently repositories map to ROM::Struct by default. In the near future this will be configurable.

ROM structs are simple and don't expose an interface to mutate them; however, they are not being frozen (at least not yet, we could add a feature for freezing them).

They are coercible to Hash so it should be possible to map them further in some special cases using ROM mappers.

class Users < ROM::Relation[:sql]
  view(:by_id, [:id, :name]) do |id|
    where(id: id).select(:id, :name)
  end

  view(:listing, [:id, :name, :email, :created_at]) do
    select(:id, :name, :email, :created_at).order(:name)
  end
end

class UserRepository < ROM::Repository::Base
  relations :users, :tasks

  def by_id(id)
    users.by_id(id)
  end

  def with_tasks(id)
    users.by_id(id).combine_children(many: tasks)
  end
end

rom = ROM.finalize.env

user_repo = UserRepository.new(rom)

puts user_repo.by_id(1).to_a.inspect
# [#<ROM::Struct[User] id=1 name="Jane">]

puts user_repo.with_tasks.to_a.inspect
# [#<ROM::Struct[User] id=1 name="Jane" tasks=[#<ROM::Struct[Task] id=2 user_id=1 title="Jane Task">]>, #<ROM::Struct[User] id=2 name="Joe" tasks=[#<ROM::Struct[Task] id=1 user_id=2 title="Joe Task">]>]

Decorating Structs

Nothing is stopping you from decorating your structs using registered mappers and custom decorator models:

class UserStructMapper < ROM::Mapper
  register_as :ui_presenter
  model UI::UserPresenter
end

user_repo.by_id(1).as(:ui_presenter)

Limitations

This is an early alpha and works only with rom-sql for now. There are a couple improvements waiting to be done in the rom core and then rom-repository will receive more love and features.

Stay tuned.

License

See LICENSE file.

rom-repository's People

Contributors

solnic avatar

Watchers

Chris Flipse avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.