shoulda-matchers
shoulda-matchers copied to clipboard
JoinTableMatcher doesn't find join tables with schema
I'm trying to have a test for a HBTM association where the join table name includes the schema:
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.
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
andsegment
models and relative tables in thesystem
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.