Skip to content

Instantly share code, notes, and snippets.

@carlisia
Last active January 8, 2019 10:23
Show Gist options
  • Save carlisia/1269fa6680487b658c9f to your computer and use it in GitHub Desktop.
Save carlisia/1269fa6680487b658c9f to your computer and use it in GitHub Desktop.
ROM - References for creating a custom adapter
@carlisia
Copy link
Author

carlisia commented May 8, 2015

@carlisia
Copy link
Author

carlisia commented May 8, 2015

Q: "What are the minimum interfaces that my Adapter's Repository, Relation, and Dataset need to implement?"

A: "linter specs / tests that you can mixin to ensure you're providing the minimal interface (for an api adapter):"
https://github.com/rom-rb/rom/tree/master/lib/rom/lint

@carlisia
Copy link
Author

carlisia commented May 8, 2015

Q: "Where to register the custom adapter?"

A: "Typically the main adapter file does that, ie, https://github.com/rom-rb/rom-sql/blob/master/lib/rom/sql.rb#L30"

@carlisia
Copy link
Author

carlisia commented May 8, 2015

Q: "What is env?"

A: "env is rom’s object registry, it gets setup when you call ROM.finalize. So, after you defined and loaded all your classes, you call finalize and you get the registry under ROM.env."

@carlisia
Copy link
Author

carlisia commented May 8, 2015

Q: "What do you do with Mappers?"

A: "You don't need Mappers. But, typically, people use mappers to turn that into something more “higher-level. It's how you map a relation to a Rails model, which is explicit in ROM. You always need to provide which mapper it should use, ie, rom.relation(:users).as(:entity) would send users through its entity mapper.

The interface was designed in a way that you should be able to memoize some relation and refer to it from other places so ie you’d do sth like @users = rom.relation(:users).as(:entity) and then @users.active.page(2) or something.

Q: "Why the .as(:entity)?"

A: ".as(:entity) means “send data through :entity mapper (see: register_as :name -> .as(:name) and tasks.index_view(params[:status]).as(:tasks))."

@carlisia
Copy link
Author

carlisia commented May 9, 2015

require 'rom'

ROM.setup(:memory)

class User
  attr_reader :name, :age

  def initialize(attributes)
    @name, @age = attributes.values_at(:name, :age)
  end
end

class Users < ROM::Relation[:memory]
  def by_name(name)
    restrict(name: name)
  end

  def adults
    restrict { |user| user[:age] >= 18 }
  end
end

class UserMapper < ROM::Mapper
  relation :users
  register_as :entity

  model User

  attribute :name
  attribute :age
end

class CreateUser < ROM::Commands::Create[:memory]
  register_as :create
  relation :users
  result :one
end

class UpdateUser < ROM::Commands::Update[:memory]
  register_as :update
  relation :users
  result :one
end

rom = ROM.finalize.env

user1 = rom.command(:users).as(:entity).create.call(name: "Joe", age: 17)
user2 = rom.command(:users).as(:entity).update.set(name: "Jane", age: 18)
puts user1.class, user2.class # => User, Hash

@carlisia
Copy link
Author

Q: "What's a repository?"

A: ""Repository" is poorly named, as it doesn't actually reflect a repository pattern
the Adapter's repository is the class it uses to interact with whatever it's backend is
more of a gateway
thus, each adapter has 1 repository
but, what you register is an instance of an adapter
which in turn ends up with an instance of it's internal repository class"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment