rom-sql icon indicating copy to clipboard operation
rom-sql copied to clipboard

Support for has_many-through with a join table that "has many targets"

Open v-kolesnikov opened this issue 8 years ago • 3 comments

require 'rom'
require 'sqlite3'

rom = ROM.container(:sql, 'sqlite::memory') do |conf|
  conf.default.create_table(:bookings) do
    primary_key :booking_id
  end

  conf.default.create_table(:tickets) do
    primary_key :ticket_id
    column :booking_id, Integer
  end

  conf.default.create_table(:passes) do
    primary_key :pass_id
    column :ticket_id, Integer
  end

  conf.relation(:bookings) do
    schema(infer: true) do
      associations do
        has_many :tickets
        has_many :passes, through: :tickets
      end
    end

    def with_passes
      join(passes)
    end
  end

  conf.relation(:tickets) do
    schema(infer: true) do
      associations do
        belongs_to :booking
        has_many :passes
      end
    end
  end

  conf.relation(:passes) do
    schema(infer: true) do
      associations do
        belongs_to :tickets
      end
    end
  end
end

joined = rom.relation(:bookings).join(rom.relation(:passes))

Expected SQL:

SELECT `bookings`.`booking_id`
FROM `bookings`
INNER JOIN `tickets` ON (`bookings`.`booking_id` = `tickets`.`booking_id`)
INNER JOIN `passes` ON (`tickets`.`ticket_id` = `passes`.`pass_id`)
ORDER BY `bookings`.`booking_id`

Actual SQL:

SELECT `bookings`.`booking_id`
FROM `bookings`
INNER JOIN `tickets` ON (`bookings`.`booking_id` = `tickets`.`booking_id`)
INNER JOIN `passes` ON (`bookings`.`booking_id` = `tickets`.`booking_id`)
ORDER BY `bookings`.`booking_id`

v-kolesnikov avatar Apr 30 '17 11:04 v-kolesnikov

OK I'm not sure if this is a bug after all. tickets is not a typical join table (it would be if it had a belongs_to :passes and has_many-through is designed to work with join tables exclusively. I'm gonna put this one on hold for now.

solnic avatar Apr 30 '17 12:04 solnic

@flash-gordon wdyt about supporting has-many-through when join table is not a typical join table that has both FKs, and instead it 'has-many' targets?

solnic avatar Apr 30 '17 12:04 solnic

@solnic the actual problem is that it's not obvious how to join a relation through another relation

this doesn't work too:

joined = rom.relation(:bookings).join(rom.relation(:tickets)).join(rom.relation(:passes))
 :passes doesn't exist in ROM::AssociationSet registry (ROM::Registry::ElementNotFoundError)

flash-gordon avatar Apr 30 '17 12:04 flash-gordon