rom-rb / rom-sql

SQL support for rom-rb
https://rom-rb.org
MIT License
217 stars 93 forks source link

ManyToOne associations not being loaded when foreign key is an alias #340

Open waiting-for-dev opened 5 years ago

waiting-for-dev commented 5 years ago

Describe the bug

If you have a belongs_to association where the foreign key attribute has been aliased, the association is always loaded as nil even when the foreign key attribute is populated.

To Reproduce

git clone https://github.com/waiting-for-dev/rom_bug_aliased_fk
cd rom_bug_aliased_fk
bundle
ruby reproduce.rb

or

require "rom"

module Types
  include Dry::Types.module
end

rom = ROM.container(:sql, 'sqlite::memory') do |conf|
  conf.default.create_table(:users) do
    primary_key :id
    column :name, String, null: false
  end

  conf.default.create_table(:tasks) do
    primary_key :id
    column :name, String, null: false
    foreign_key :bad_name_id, :users, null: false
  end

  conf.relation(:users) do
    schema(infer: true)
  end

  conf.relation(:tasks_without_alias) do
    schema(:tasks, infer: true, as: :tasks_without_alias) do
      associations do
        belongs_to(:user)
      end
    end
  end

  conf.relation(:tasks_with_alias) do
    schema(:tasks, infer: true, as: :tasks_with_alias) do
      attribute :bad_name_id, Types::Integer.meta(alias: :user_id)

      associations do
        belongs_to(:user)
      end
    end
  end
end

joe = rom.relations[:users].command(:create).(name: "Joe Doe")
rom.relations[:tasks_without_alias].command(:create).(name: "Be happy", bad_name_id: joe[:id])

puts "Output combining from relation without FK aliased"
puts rom.relations[:tasks_without_alias].combine(:users).to_a
# => {:id=>1, :name=>"Be happy", :bad_name_id=>1, :user=>{:id=>1, :name=>"Joe Doe"}}
puts "====================="
puts "Output combining from relation with FK aliased"
puts rom.relations[:tasks_with_alias].combine(:users).to_a
# => {:user_id=>1, :id=>1, :name=>"Be happy", :user=>nil}

Expected behavior

I would expected that foreign key inference is not affected by aliasing the attribute at the application level.

Your environment

Resources

Original source in the discussion forum

solnic commented 5 years ago

I can't reproduce this anymore using master branches.

solnic commented 5 years ago

Quick update: I can reproduce it when it's:

attribute :bad_name_id, Types::Integer, alias: :user_id
solnic commented 5 years ago

I moved this to rom-sql since it's sql-specific. We need to set combine_keys option if there are fk aliases. ie if you do this:

        belongs_to(:user, combine_keys: { user_id: :id })

...then it's gonna work.