Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shoulda-matchers looking for join table names including schema #625

Closed
EleanorRagone opened this issue Dec 9, 2014 · 15 comments
Closed

Comments

@EleanorRagone
Copy link

So I've got two models with habtm between them; called Region and User. So I need a join table called "regions_users"; however, doing:

RSpec.describe Region, :type => :model do
  it { should have_and_belong_to_many(:region_admins) }
end

Gives me the error:

       Expected Region to have a has_and_belongs_to_many association called users (join table public.regions_public.users doesn't exist)

Obviously that's not accurate postgres syntax, and the code works as it should. Please correct me if I'm wrong, but it seems to be a problem with shoulda-matcher.

@mcmire
Copy link
Collaborator

mcmire commented Dec 9, 2014

Hmm, interesting. What does your model look like?

@EleanorRagone
Copy link
Author

I should add what is almost certainly involved: I'm using the Apartment gem, which implements multitenancy via multiple schemas, and Region and User are two excluded classes that are always referenced through the public schema. In fact, having read through more of Apartment, that is absolutely involved here. I'm just not sure how. I can also post this as a bug report on their repository too.

Even though I don't think it's gonna help, I want to answer your question anyway:

class Region < ActiveRecord::Base
  has_paper_trail

  has_and_belongs_to_many :region_admins, class_name: "User"
end

@mcmire
Copy link
Collaborator

mcmire commented Dec 10, 2014

I see. Well, it is certainly odd to me that you're getting that message. It at least should say

Expected Region to have a has_and_belongs_to_many association called region_admins (join table public.regions_public.region_admins doesn't exist)

As far as the join table is concerned, it pulls that from the association itself, that is, it should be getting an association called region_admins and then asking which table it's referring to (which I guess should be public.regions_public.region_admins in this case).

@yogodoshi
Copy link

I'm getting a strange error, it may be related. If you don't think so I can open another issue:

class Course < ActiveRecord::Base
  has_and_belongs_to_many :categories, join_table: :course_categories
end

class Category < ActiveRecord::Base
  has_and_belongs_to_many :courses, join_table: :course_categories
end

RSpec.describe Course, type: :model do
  describe 'associations' do
    it { is_expected.to have_and_belong_to_many(:categories).join_table(:course_categories) }
  end
end

Error:

Failure/Error: it { is_expected.to have_and_belong_to_many(:categories).join_table(:course_categories) }
       Expected Course to have a has_and_belongs_to_many association called categories (join table course_categories doesn't exist)

Using version 3.0.1

@mcmire
Copy link
Collaborator

mcmire commented Nov 3, 2015

Obvious question, but just to be sure -- I'm assuming that course_categories does exist?

@yogodoshi
Copy link

@mcmire yup! its in the schema and I've tried dropping the db, creating again, checked for typos and all that :)

@mcmire
Copy link
Collaborator

mcmire commented Nov 3, 2015

@yogodoshi Okay, weird. This may be related, but go ahead and make a new issue for this.

If you can re-create this bug in a fresh Rails app and then post it up in a repo, that'll help me zero in on what the deal is here.

@kofiasare
Copy link

@pcragone please were you able to resolve this issue in your app, I have run into the same problem,
I' having a similar setup where am using apartment gem

class User < ApplicationRecord
  has_and_belongs_to_many :markets
end

class Market < ApplicationRecord
  has_and_belongs_to_many :administrators, class_name: 'User'
end

describe User, type: :model do
   it { is_expected.to have_and_belong_to_many :markets }
end

Error

User should have and belong to many markets
     Failure/Error: it { is_expected.to have_and_belong_to_many :markets }
       Expected User to have a has_and_belongs_to_many association called markets (join table public.markets_users doesn't exist)


@superchell
Copy link

I have the same problem. Did you get a fix?

@allisonphillips
Copy link

allisonphillips commented Feb 20, 2020

I am also experiencing this when trying to add shoulda matcher specs for has_and_belongs_to_many relationships for classes that are not dependent on any gem. At first I thought I had forgotten to configure something, but then I reproduced by writing the same example for similar classes that has long been functioning in a production environment without issue. All this syntax works:

# class
has_and_belongs_to_many :association_name,
  class_name:              '::AssociationClass',
  join_table:              :join_table_name_that_definitely_exists,
  foreign_key:             foreign_key_id,
  association_foreign_key: association_foreign_key_id

# spec
it do
  should have_and_belong_to_many(:association_name)
    .class_name('::AssociationClass')
    .with_foreign_key(:foreign_key_id)
    .with_foreign_key(:association_foreign_key_id)
end

But as soon as I add .join_table(:join_table_name_that_definitely_exists) to the example block in the spec, I get the equivalent of this message:

"Expected #{described_class} to have a has_and_belongs_to_many association " \
"called #{association_name} (join table #{join_table_name} doesn't exist)"

Was another issue ever opened for this?


Update: I figured out that the matcher works if you pass the join table name as a string. It appears that the matcher doesn't support table names as a symbol. Leaving that here in case it helps others.

@nimeshnikum
Copy link

nimeshnikum commented Apr 26, 2020

@allisonphillips Yes, this was already answered here: #914 (comment)

Try dropping the "s". It looks like you have have_and_belongs_to_many, the method you want is have_and_belong_to_many

Million thanks to @adammcfadden for solution!

@allisonphillips
Copy link

@allisonphillips Yes, this was already answered here: #914 (comment)

Try dropping the "s". It looks like you have have_and_belongs_to_many, the method you want is have_and_belong_to_many

Million thanks to @adammcfadden for solution!

@nimeshnikum I'm confused... is that supposed to be in response to me? I did not pluralize 'belongs' in my matcher example code, nor did the other commenters. The references to has_and_belongs_to_many in this thread are sample code for the association definitions in the class (which is the correctly named Rails method #has_and_belongs_to_many), not the spec (that's why they start with 'has' instead of 'have'). The issue I and the other users experienced here is that the matcher rejects symbolized join table names. The issue you're linking to has the matcher name misspelled and doesn't use the join table matcher at all.

@mcmire
Copy link
Collaborator

mcmire commented Apr 27, 2020

Hi @allisonphillips, I don't think an Issue has been created yet around the problem you're seeing (using a symbol with join_table not working). Would you mind creating a new one so that we can track it better?

@mcmire
Copy link
Collaborator

mcmire commented Jul 12, 2020

I'm going to close this issue since this is pretty rare and (although I can't say for certain) I don't think it's the fault of shoulda-matchers. The have_and_belongs_to_many matcher simply asks the Reflection object for the association what table name it thinks is associated. If you think the matcher has got it wrong you can override the join table name using have_and_belongs_to_many(...).join_table(...). If someone else out there is using Apartment and runs into this again, then I'm happy to look further into it but for now I'm going to close this so as not to clutter up the issues list.

@allisonphillips
Copy link

allisonphillips commented Jul 23, 2020

Hi @allisonphillips, I don't think an Issue has been created yet around the problem you're seeing (using a symbol with join_table not working). Would you mind creating a new one so that we can track it better?

@mcmire Done, see #1321. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants