rom-rb / rom-mongo

(Looking for a maintainer) MongoDB support for rom-rb
https://rom-rb.org
MIT License
32 stars 22 forks source link

Relation with association can not be finalized #26

Open v-kolesnikov opened 6 years ago

v-kolesnikov commented 6 years ago

Relation can not be finalized if it has at least one defined association.

#!/usr/bin/env ruby

require 'bundler/inline'

gemfile(true) do
  gem 'dry-struct', '~> 0.3.1'
  gem 'rom-mongo', github: 'rom-rb/rom-mongo', branch: :master
  gem 'rspec'
end

require 'rspec'
require 'rspec/autorun'

require 'rom-mongo'

RSpec.configure do |config|
  config.color = true
  config.formatter = :documentation
end

RSpec.describe ROM::Mongo do
  let(:conn) { Mongo::Client.new('mongodb://0.0.0.0:27017/rom_mongo') }
  let(:conf) { ROM::Configuration.new(:mongo, conn) }
  let(:container) { ROM.container(conf) }

  before do
    conn[:users].drop

    conf.relation(:users) do
      schema(:users) do
        attribute :_id,   ROM::Types.Definition(BSON::ObjectId)
        attribute :name,  ROM::Types::String
        attribute :email, ROM::Types::String
      end
    end
  end

  it { expect { container }.not_to raise_error }

  describe 'relation with association' do
    before do
      conf.relation(:tasks) do
        schema(:tasks) do
          attribute :_id,     ROM::Types.Definition(BSON::ObjectId)
          attribute :user_id, ROM::Types::Int

          associations do
            belongs_to :user, foreign_key: :u_id
          end
        end
      end
    end

    it { expect { container }.not_to raise_error }
  end
end
Failures:

  1) ROM::Mongo relation with association should not raise Exception
     Failure/Error: it { expect { container }.not_to raise_error }

       expected no Exception, got #<LocalJumpError: no block given (yield)> with backtrace:
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/schema.rb:380:in `finalize_associations!'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/schema.rb:44:in `block (2 levels) in <class:Schema>'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/registry.rb:61:in `block in each'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/registry.rb:61:in `each'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/registry.rb:61:in `each'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/schema.rb:42:in `block in <class:Schema>'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/support/notifications.rb:141:in `trigger'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/support/notifications.rb:69:in `block in trigger'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/support/notifications.rb:68:in `each'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/support/notifications.rb:68:in `trigger'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/setup/finalize/finalize_relations.rb:59:in `run!'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/setup/finalize.rb:86:in `load_relations'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/setup/finalize.rb:62:in `run!'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/create_container.rb:38:in `finalize'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/create_container.rb:14:in `initialize'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/create_container.rb:59:in `initialize'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/create_container.rb:65:in `new'
         # /Users/v.kolesnikov/.rvm/gems/ruby-2.5.0/gems/rom-core-4.1.0/lib/rom/create_container.rb:65:in `container'
         # ./associations_spec.rb:24:in `block (2 levels) in <main>'
         # ./associations_spec.rb:54:in `block (4 levels) in <main>'
         # ./associations_spec.rb:54:in `block (3 levels) in <main>'
     # ./associations_spec.rb:54:in `block (3 levels) in <main>'

It can be fixed by defining self own finalize_associations! method for ROM::Mongo::Schema or inheriting this class from ROM::Memory::Schema.

solnic commented 6 years ago

This adapter doesn’t support associations yet. So this is expected to fail. It should have its own schema and custom implementation of individual association types.

v-kolesnikov commented 6 years ago

Thank you @solnic ! So, I assume if I want to combine mongo relations with other (sql relations for instance) - I have to use combine_with and custom mappers?

solnic commented 6 years ago

@v-kolesnikov I have to use combine_with and custom mappers?

yes, until somebody adds association API 😅

v-kolesnikov commented 6 years ago

yes, until somebody adds association API

ОК) Should the association API combines only relations of the same adapter (mongo) ? Or it's possible to have cross-adapter associations? With override: true option for instance.

solnic commented 6 years ago

@v-kolesnikov yes you can have cross-adapter associations and yes it will require override: true