# Model inheritance

**URL:** <https://discourse.rom-rb.org/t/model-inheritance/82>\
**Category:** Usage Stories\
**Created:** [September 11, 2016, 4:24pm UTC](https://discourse.rom-rb.org/t/model-inheritance/82 "2016-09-11T16:24:46Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![dmgr](https://avatars.discourse-cdn.com/v4/letter/d/ecd19e/32.png) [@dmgr](https://discourse.rom-rb.org/u/dmgr)\
**Post date:** [September 11, 2016, 4:24pm UTC](https://discourse.rom-rb.org/t/model-inheritance/82/1 "2016-09-11T16:24:46Z")

</div>

Hi ROM community,

Could you just give me a hint where I have to look on to implement a simple inheritance based on a attribute. To keep things simple, lets say I want to have a `SimpleProject` and `ComplexProject` and the inheritance attribute would be a `type`.

What is more interesting:

- `SimpleProject` has a `value` attribute which is just a String.
- `ComplexProject` has a `value` attribute which is a hash and serialized to JSON.

So then if I want to fetch projects:  
`projects.to_a`  
it will return me instances of `SimpleProject` or `ComplexProject` based on the `type` attribute.

Do I need to implement that by hand using a `map` method inside users reposioty or ROM provides any predefined methods for that or at least guidelines how to do it in the most efficient way?

PS.  
I am new to the ROM, I used DataMapper even before diving in to the Rails and ActiveRecord.  
Now ROM seems to be a really production ready solution.

---

<div class="post-metadata">

**Author:** ![solnic](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.rom-rb.org/solnic/32/279_2.png) [@solnic](https://discourse.rom-rb.org/u/solnic)\
**Post date:** [October 1, 2016, 6:01am UTC](https://discourse.rom-rb.org/t/model-inheritance/82/2 "2016-10-01T06:01:06Z")

</div>

You could do something like this:

```ruby
require "rom-repository"
require "dry-struct"

config = ROM::Configuration.new(:sql, 'sqlite::memory')

config.gateways[:default].create_table(:users) do
  primary_key :id
  column :name, String
  column :type, String
end

class Users < ROM::Relation[:sql]
  schema do
    attribute :id, Types::Serial
    attribute :name, Types::String
    attribute :type, Types::Strict::String.enum('User', 'Admin')
  end
end

config.register_relation(Users)

config.mappers do
  register(:users,
    sti: -> users {
      users.map { |tuple| Object.const_get(tuple[:type]).new(tuple) }
    }
  )
end

container = ROM.container(config)

module Types
  include Dry::Types.module
end

class User < Dry::Struct
  attribute :id, Types::Int
  attribute :name, Types::String
end

class Admin < User
end

class UserRepo < ROM::Repository[:users]
  commands :create

  def all
    users.map_with(:sti).to_a
  end
end

repo = UserRepo.new(container)

repo.create(name: 'Jane', type: 'Admin')
repo.create(name: 'John', type: 'User')

repo.all
# [#<Admin id=1 name="Jane">, #<User id=2 name="John">]

```
