thoughtbot / shoulda-matchers

Simple one-liner tests for common Rails functionality
https://matchers.shoulda.io
MIT License
3.51k stars 912 forks source link

Associations foreign key issue with namespaced models #589

Closed gdlx closed 10 years ago

gdlx commented 10 years ago

I can't make have_many/belong_to work with namespaced models associations.

I'm using model classes like Company::Project::Group has_many Company::Project::Members

When testing this:

  it do
    should have_many(:members).class_name('Company::Project::Member')
  end

I get this (as expected):

Failure/Error: should have_many(:members).class_name('Company::Project::Member')
  Expected Company::Project::Group to have a has_many association called members (Company::Project::Member does not have a group_id foreign key.)

I change my test to this:

  it do
    should have_many(:members).
      class_name('Company::Project::Member').
      with_foreign_key('company_project_group_id')
  end

The company_project_group_id field exists, but I still get this error:

Failure/Error: should have_many(:members).class_name('Company::Project::Member').with_foreign_key('company_project_group_id')
  Expected Company::Project::Group to have a has_many association called members()

As you can see, there's no error detail so I don't know why the test is failing... I get the same behavior testing the inverse belongs_to relation:

Failure/Error: should belong_to(:group).class_name('Company::Project::Group').with_foreign_key('company_project_group_id')
  Expected Company::Project::Members to have a belongs_to association called group ()

Using rails-4.1.6, active-record 4.1.6 w/ MySQL, rspec-rails-3.1.0, shoulda-matchers 2.7.0

Nothing special in my models associations:

class Company::Project::Group < ActiveRecord::Base
  has_many :members,
    class_name: 'Company::Project::Member',
    inverse_of: :group
[...]

class Company::Project::Member < ActiveRecord::Base
  belongs_to :group,
    class_name: 'Company::Project::Group',
    inverse_of: :members
[...]

Am I doing something wrong ?

gdlx commented 10 years ago

My models didn't work that well: I've forgotten foreign_key definitions in my associations...now everything works without even specifying class_name and with_foreign_key...

mcmire commented 10 years ago

Okay, glad you were able to figure it out. It sounds like there's an error message that's missing on our side that would have made things easier for you? In other words, were you getting a "expected Company::Project::Group to have a has_many association called members" message even though the association was defined in your model?

By the way: class_name and with_foreign_key never need to be added to the matchers, but doing so will add extra checks.

gdlx commented 10 years ago

Yes, I think a message explaining that the foreign key field doesn't exists on the belonging side could help troubleshooting the issue.

In my case, the message could have been (in both cases): "Company::Project::Member should have a group_id foreign key", because that was the default foreign key, which wasn't the one defined in my migrations.

Thanks !

DiegoOrejuela commented 4 years ago

@mcmire Hi. I am a bit confused about this. I think the expected behavior is that it identifies the foreign key that the relationship should have based on where the class is located. In the case of Company::Project::Group the default foreign key is company_project_group_id . So I think it could be something that could be improved.

mcmire commented 4 years ago

@DiegoOrejuela It sounds like the OP was able to solve his problem, so that's why I closed this particular issue, but it's possible there is still a bug here — I would need more information to know for sure. So if you are getting this error I think what would be most helpful is a complete example of the association in your model and the tests you have in your test file. Preferably also in a new issue :)