rom-rb / rom

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

Use "table name" from relation in assocoations #383

Closed kwando closed 7 years ago

kwando commented 7 years ago

I have a relation in my app that is not registered with the same name as the underlying SQL table. In the example below my users table is registered with the relation name :authors.

Is there a way to make this work as "expected" (as I expect)?

require 'bundler'
Bundler.setup

require 'sequel'

DB = Sequel.connect('sqlite::memory')

DB.create_table(:users) do
  primary_key(:id)
  String :name, null: false
end

DB.create_table(:books) do
  primary_key(:id)
  foreign_key(:author_id, :users, null: false)
  String :name, null: false
end

require 'rom-sql'
rom = ROM.container(:sql, DB) { |config|
  config.relation(:authors) {
    schema(:users, infer: true)
  }

  config.relation(:books) {
    schema(:books, infer: true) {
      associations {
        belongs_to(:author, foreign_key: :author_id)
      }
    }
  }
}

user_id  = rom.relation(:authors).insert(name: 'kwando')
book_id = rom.relation(:books).insert(name: 'Learn ROM', author_id: user_id)

puts rom.relation(:books).assoc(:author).to_a

This blows up at the last line with the following error

/Users/kwando/.rbenv/shims/bundle exec /Users/kwando/.rbenv/versions/2.3.3/bin/ruby -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) /Users/kwando/projects/rom-playground/repo-bug.rb
/Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:91:in `initialize': SQLite3::SQLException: no such column: authors.id (Sequel::DatabaseError)
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:91:in `new'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:91:in `prepare'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:264:in `query'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/adapters/sqlite.rb:192:in `block (2 levels) in _execute'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/database/logging.rb:44:in `log_connection_yield'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/adapters/sqlite.rb:192:in `block in _execute'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/database/connecting.rb:280:in `block in synchronize'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/connection_pool/threaded.rb:107:in `hold'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/database/connecting.rb:280:in `synchronize'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/adapters/sqlite.rb:185:in `_execute'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/adapters/sqlite.rb:130:in `execute'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/dataset/actions.rb:1064:in `execute'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/adapters/sqlite.rb:328:in `fetch_rows'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/sequel-4.43.0/lib/sequel/dataset/actions.rb:149:in `each'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/rom-3.0.3/lib/rom/relation.rb:106:in `each'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/rom-3.0.3/lib/rom/relation.rb:135:in `each'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/rom-3.0.3/lib/rom/relation.rb:135:in `to_a'
    from /Users/kwando/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/rom-3.0.3/lib/rom/relation.rb:135:in `to_a'
    from /Users/kwando/projects/rom-playground/repo-bug.rb:37:in `<top (required)>'
    from -e:1:in `load'
    from -e:1:in `<main>'
solnic commented 7 years ago

This will be auto-inferred in rom-sql 2.0 but for now you need to do:

belongs_to :users, as: :author, relation: :authors, foreign_key: :author_id

The reason why this is needed now is because when associations are defined we don't have relations yet.

kwando commented 7 years ago

Thanks a lot for the quick reply, that works like I want :)

solnic commented 7 years ago

I'm gonna close this one since it'll be improved in rom-sql 2.0 and it's on the roadmap