如何从rom-sql中的联接表中抽取别名列?

时间:2019-01-16 12:32:56

标签: ruby rom-rb rom-sql

我找不到如何使用rom-sql提取别名列的方法。

赋予用户和化身的关系(用户具有多个化身)。

# works
users.join(:avatars).select { |r| r.avatars[:id] }.pluck(:id)

# does not work
users.join(:avatars).select { |r| r.avatars[:id].as(:avatar_id) }.pluck(:avatar_id)
# NoMethodError: undefined method `[]' for nil:NilClass
# from /usr/local/bundle/gems/rom-core-4.2.1/lib/rom/schema.rb:195:in `[]'

# more examples
users.join(:avatars).select{|r| r.avatars[:id].as('avatar_id')}                                           
#=> #<Persistence::Relations::Users name=ROM::Relation::Name(users) dataset=#<Sequel::Postgres::Dataset: "SELECT \"avatars\".\"id\" AS \"avatar_id\" FROM \"users\" INNER JOIN \"avatars\" ON (\"users\".\"id\" = \"avatars\".\"user_id\") ORDER BY \"users\".\"id\"">>

users.join(:avatars).select{|r| r.avatars[:id].as('avatar_id')}.to_a
#> Dry::Struct::Error: [Entities::User.new] :avatar_id is missing in Hash input

users.join(:avatars).select{|r| r.avatars[:id].as('avatar_id')}.with(auto_struct: false).to_a
#=> [{:avatar_id=>88}, {:avatar_id=>89}]

1 个答案:

答案 0 :(得分:0)

如果未指定所用库的版本,则不可能提出任何解决方案。对于rom-sql 2.4.0,它就可以使用:

#!/usr/bin/env ruby

# frozen_string_literal: true

require 'bundler/inline'

gemfile(false) do
  source 'https://rubygems.org'

  gem 'sqlite3'
  gem 'rom-sql', '2.4.0'
  gem 'rspec'
end

require 'rspec'
require 'rspec/autorun'

require 'dry-types'
require 'rom-sql'
require 'sqlite3'

RSpec.describe do
  let(:uri) { 'sqlite::memory' }
  let(:conn) { Sequel.connect(uri) }
  let(:conf) { ROM::Configuration.new(:sql, conn) }
  let(:container) { ROM.container(conf) }

  let(:avatars) { container.relations[:avatars] }
  let(:users) { container.relations[:users] }

  before do
    conn.create_table(:avatars) do
      primary_key :id
      Integer :user_id
      String :url
    end

    conn.create_table(:users) { primary_key :id }

    conf.relation(:avatars) do
      schema(infer: true) do
        associations do
          belongs_to :user
        end
      end
    end

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

  subject(:relation) do
    users.join(:avatars).select { relations[:avatars][:url].as(:avatar_url) }
  end

  it do
    users.insert
    avatars.insert(user_id: 1, url: 'avatars/1')
    avatars.insert(user_id: 1, url: 'avatars/2')

    expect { relation.pluck(:avatar_url) }.not_to raise_error
    expect(relation.pluck(:avatar_url)).to eq ['avatars/1', 'avatars/2']
  end
end