Shoulda-matchers: JoinTableMatcher doesn't find join tables with schema

Created on 27 Aug 2020  路  7Comments  路  Source: thoughtbot/shoulda-matchers

I'm trying to have a test for a HBTM association where the join table name includes the schema:

1) Application associations is expected to have and belong to many segments
Failure/Error:
expect(subject).to have_and_belong_to_many(:segments)
.join_table('system.applications_segments')

   Expected Application to have a has_and_belongs_to_many association called segments (join table system.applications_segments doesn't exist)

The problem that I found is that if I include the schema in the test (as it should be), the JoinTableMatcher doesn't find the table in the list of tables provided by ActiveRecord.
I think the problem is that the tables_and_views method returns a list without the schemas, so the join_table_exists? method raises the error.
How could I solve this problem?
Thank you for your support.

Need to Investigate

All 7 comments

Oh, interesting. We previously received an issue, #625, which I think is related to this, and at the time I didn't know what was going on here. If tables_and_views doesn't include the schemas, though, then that would make a lot of sense. That said, I don't really know what the solution here would be. So if you can figure something out, then we would certainly be glad to incorporate it into the gem.

Hi, yes I saw that issue too.
I was not 100% sure it was directly related, so I opened a new issue.

I don't really know what the solution here would be

I'm in the same situation, I don't know what should be the solution.
I think the best would be to find a way to get the schemas with the table names, but I don't know how yet, since we are simply using ActiveRecord methods.
Maybe this is an issue with ActiveRecord that could be raised there.

Hi, @afdev82, are you working on this? If not can I start working on it? Thanks! :smile:

Hi @VSPPedro, no I'm not working on this issue.
Thank you for having a look at it! :smile:

Hi, @afdev82, can you help me create a simple rails app with this problem, please? (Or tell me what should I do.) I'm really sorry, but I'm not sure how to replicate this problem locally.

The problem is when I use PostgreSQL as DBMS, because then I have the possibility to use different schemas inside the same database. To reproduce I've done the following steps.

  • create a rails app with rails new . inside an empty folder
  • add the pg, rspec-rails, shoulda-matchers gems to the Gemfile:
gem 'pg', '>= 1.2.3', '< 2.0'

group :development, :test do
  gem 'rspec-rails', '~> 4.0.1'
end

group :test do
  gem 'shoulda-matchers', '4.4.1', require: false
end
  • configure the database in config/database.yml:
# SQLite. Versions 3.8.0 and up are supported.
#   gem install sqlite3
#
#   Ensure the SQLite 3 gem is defined in your Gemfile
#   gem 'sqlite3'
#
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: 5
  schema_search_path: public,system

development:
  <<: *default
  database: spec_dev

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: spec_test

production:
  <<: *default
  database: spec_prod

  • add the 'should-matchers' code to spec/rails_helper.rb file:
require 'shoulda-matchers'

Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end
  • use the sql dump instead of schema.rb to dump the database, adding the following to the config/application.rb file:
...
class Application < Rails::Application
    ...

    config.active_record.schema_format = :sql
    config.active_record.dump_schemas = :all
  end
  • create the application and segment models and relative tables in the system schema with a migration:
class CreateApplicationsSegments < ActiveRecord::Migration[6.1]
  def change
    create_schema :system

    create_table 'system.applications' do |t|
      t.string :name
    end

    create_table 'system.segments' do |t|
      t.string :name
    end

    create_table 'system.applications_segments' do |t|
      t.belongs_to :application
      t.belongs_to :segment
    end
  end
end

application.rb

class Application < ApplicationRecord
  self.table_name = 'system.applications'

  has_and_belongs_to_many :segments, join_table: 'system.applications_segments'
end

segment.rb

class Segment < ApplicationRecord
  self.table_name = 'system.segments'

  has_and_belongs_to_many :applications, join_table: 'system.applications_segments'
end
  • create, migrate the database and run the tests:
RAILS_ENV=test bin/rake db:create
RAILS_ENV=test bin/rake db:migrate
RAILS_ENV=test bundle exec rspec

Thank you very much for all this information! I will try to find a solution.

Was this page helpful?
0 / 5 - 0 ratings