Upgrade to Pro — share decks privately, control downloads, hide ads and more …

rom-rb 4.0 - Moscow, RailsClub 2017

Piotr Solnica
September 23, 2017

rom-rb 4.0 - Moscow, RailsClub 2017

Piotr Solnica

September 23, 2017
Tweet

More Decks by Piotr Solnica

Other Decks in Programming

Transcript

  1. Typical ORM ! that we DO NOT HAVE → Relying

    on mutable objects → Complex association model → Leaky abstractions → [ActiveRecord] tight coupling with database schema → [ActiveRecord] n+1 query problem → [ActiveRecord] callbacks → [ActiveRecord] huge API
  2. Ease of use → Little code to write to get

    started → A lot of functionality OOTB → No boilerplate
  3. module Entities class User < ROM::Struct def first_name name.split(' ').first

    end def last_name name.split(' ').last end end end
  4. module Entities class User < ROM::Struct def first_name name.split(' ').first

    end def last_name name.split(' ').last end end end
  5. module Entities class User < ROM::Struct def has_tasks? !tasks.empty? end

    end end user = users.combine(:tasks).first user.has_tasks? # true
  6. user = users.first user.has_tasks? # ROM::Struct::MissingAttribute: # undefined method `tasks'

    for # #<Entities::User id=1 name="Jane"> (attribute not loaded?)
  7. → Dynamic query interface is maintained → Custom methods are

    maintained → Objects decoupled from the database are maintained too
  8. At any point in time, you can define structs with

    explicit attributes and ask rom-rb to load them
  9. class Users < ROM::Relation[:sql] schema(infer: true) do associations do has_many

    :tasks, override: true, view: :for_users end end end class Tasks < ROM::Relation[:yaml] gateway :external schema(infer: true) def for_users(users) tasks.restrict(UserId: users.pluck(:id)) end end
  10. class Users < ROM::Relation[:sql] schema(infer: true) do associations do has_many

    :tasks, override: true, view: :for_users end end end class Tasks < ROM::Relation[:yaml] gateway :external schema(infer: true) def for_users(users) tasks.restrict(UserId: users.pluck(:id)) end end
  11. users. combine(:tasks). changeset(:create, name: "Joe", tasks: [{ title: "Task 1"

    }]). commit # => #<Entities::User id=4 name="Joe" tasks=[ # #<Entities::Task id=3 user_id=4 title="Task 1"> # ]>
  12. class Users < ROM::Relation[:sql] schema(:SomehorriblyNamedUseRtable, as: :users) do attribute :UserIdentifier,

    Serial.meta(alias: :id) attribute :UserName, String.meta(alias: :name) end end users.first # #<ROM::Struct::User id=1, name="Jane">
  13. class EncryptionMapper < ROM::Mapper register_as :encryption def call(relation) relation.map {

    |tuple| # do whatever you want } end end users.map_with(:encryption)
  14. class NewUser < ROM::Changeset::Create map do rename_keys user_name: :name end

    end users.changeset(NewUser, user_name: "Jane").commit # #<ROM::Struct::User id=1 name="Jane">