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.
Hmm, interesting. What does your model look like?
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
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).
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
Obvious question, but just to be sure -- I'm assuming that course_categories _does_ exist?
@mcmire yup! its in the schema and I've tried dropping the db, creating again, checked for typos and all that :)
@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.
@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)
I have the same problem. Did you get a fix?
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.
@allisonphillips Yes, this was already answered here: https://github.com/thoughtbot/shoulda-matchers/issues/914#issuecomment-195552836
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 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.
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?
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.
Hi @allisonphillips, I don't think an Issue has been created yet around the problem you're seeing (using a symbol with
join_tablenot working). Would you mind creating a new one so that we can track it better?
@mcmire Done, see https://github.com/thoughtbot/shoulda-matchers/issues/1321. Thank you!