rom-rb / rom

Data mapping and persistence toolkit for Ruby
https://rom-rb.org
MIT License
2.08k stars 161 forks source link

Combine does not work when used from relations #525

Closed alexandru-calinoiu closed 5 years ago

alexandru-calinoiu commented 6 years ago

Hi,

The title might not be so suggestive of the issue, here is the problem (code might not compile):

class Users < Relation[sql]
 def with_tasks
  combine(:tasks)
 end

 def with_friends
  combine(:friends)
 end
end

This works:

class UserRepo < Repository[:users]
 def create(user) 
  users.combine(:tasks :friends).commad(:create, user)
 end

 def altenate_create_that_works
  users.combine(:tasks).combine(:friends).commad(:create, user)
 end
end

This does not work :-1: it just appears to have worked by friends don't get inserted.

class UserRepo < Repository[:users]
 def create(user)
  users.with_tasks.with_friends.command(:create, user)
 end
end

Thinking about it makes sens not to work because the receiver is not the relation, but I expected a method not found exception or something along this lines.

solnic commented 5 years ago

Repro:

require 'rom/sql'
require 'rom/repository'
require 'rom/transformer'
require 'dry/types'
require 'byebug'

module Types
  include Dry::Types()
end

rom = ROM.container(:sql, 'sqlite::memory') do |c|
  c.gateways[:default].create_table :users do
    primary_key :id
    column :name, String
  end

  c.gateways[:default].create_table :friends do
    primary_key :id
    foreign_key :user_id, :users
    column :name, String
  end

  c.gateways[:default].create_table :tasks do
    primary_key :id
    foreign_key :user_id, :users
    column :title, String
  end

  c.relation(:users) do
    schema(infer: true) do
      associations do
        has_many :friends
        has_many :tasks
      end
    end

    def with_tasks
      combine(:tasks)
    end

    def with_friends
      combine(:friends)
    end
  end

  c.relation(:friends) do
    schema(infer: true) do
      associations do
        belongs_to :user
      end
    end
  end

  c.relation(:tasks) do
    schema(infer: true) do
      associations do
        belongs_to :user
      end
    end
  end
end

rom.gateways[:default].use_logger(Logger.new($stdout))

users = rom.relations[:users]

user = { name: 'Jane', friends: [{ name: 'Joe' }], tasks: [{ title: 'Do something' }] }

puts users.with_tasks.with_friends.command(:create).call(user).inspect
puts users.combine(:tasks).combine(:friends).command(:create).call(user).inspect
solnic commented 5 years ago

This was finally fixed. Sorry it took me so long.