rom-rb / rom

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

Has many through fails under Rom 5 #540

Closed mrship closed 5 years ago

mrship commented 5 years ago

Describe the bug

When using a has many through relationship, Rom throws an exception:

/Users/shipmana/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rom-core-5.0.1/lib/rom/schema.rb:232:in `[]': nil attribute doesn't exist in groups schema (KeyError)

To Reproduce

#!/usr/bin/env ruby
require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'rom'
  gem 'rom-sql'
  gem 'rom-repository'
  gem 'dry-types'
  gem 'sqlite3'
end

module Types
  include Dry::Types(default: :nominal)
end

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

  c.gateways[:default].create_table :apps_groups do
    primary_key :id
    Integer :app_id
    Integer :group_id
  end

  c.gateways[:default].create_table :groups do
    primary_key :id
    String :name
  end

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

  c.relation(:apps) do
    schema(:apps, infer: false) do
      attribute :id, Types::Integer, primary_key: true
      attribute :name, Types::String

      associations do
        has_many :apps_groups
        has_many :groups, through: :apps_groups
      end
    end
  end

  c.relation(:groups) do
    schema(:groups, infer: false) do
      attribute :id, Types::Integer, primary_key: true
      attribute :name, Types::String
    end
  end

  c.relation(:apps_groups) do
    schema(:apps_groups, infer: false) do
      attribute :id, Types::Integer, primary_key: true
      attribute :app_id, Types::Integer, foreign_key: true, relation: :apps
      attribute :group_id, Types::Integer, foreign_key: true, relation: :groups

      associations do
        belongs_to :apps
        belongs_to :groups
      end
    end
  end
end

rom.relations[:apps].insert id: 1001, name: "rom"
rom.relations[:groups].insert id: 2002, name: "coders"
rom.relations[:apps_groups].insert app_id: 1001, group_id: 2002

class AppRepo < ROM::Repository[:apps]
  def by_name(name)
    apps.where(name: name).combine(:groups).one
  end
end

repo = AppRepo.new(rom)

puts repo.by_name("rom").inspect

Expected behavior

This code works under Rom4, so this appears to be a regression.

Your environment

% ruby -v
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin17]
solnic commented 5 years ago

Thanks for reporting. I'll deal with this ASAP.

solnic commented 5 years ago

@mrship it's fixed in master. I'll push 5.0.2 either later today or tomorrow morning.

mrship commented 5 years ago

@solnic thanks for fixing so quickly. 👍

solnic commented 5 years ago

@mrship this was fixed in https://rubygems.org/gems/rom/versions/5.0.2