SchemaPlus / schema_associations

ActiveRecord extension that automatically (DRY) creates associations based on the schema
Other
46 stars 8 forks source link

force has_many :through for a has_and_belongs_to_many like relationship #18

Closed urkle closed 8 years ago

urkle commented 8 years ago

I have a HABTM "looking" join table, but I want to access the underlying table easily in my code. Currently this gem is generating a HABTM relationship and I'd rather have it generate a has_many + a has_many :through relationship which gives far greater flexibility.

It would be nice to have an option to choose has_many through style instead of only has_and_belongs_to_many.

ronen commented 8 years ago

@urkle I'm somewhat OK with that if you can come up with a decent way of specifying the option and if it doesn't muddy things up too much. I'm a bit concerned in that the current code doesn't generate any has_many :through associations and so it'd be opening a new can of worms for what I think is a pretty unusual case...

That is, schema_associations is a little bit opinionated and it doesn't completely bother/surprise me that if you have something that looks like a rails HABTM table--i.e. it's named "table1_table2" and has foreign keys back to table1 and table2--that it'd be treated like a rails HABTM table.

So if you are at liberty to modify your schema, a reasonable workaround would be to give the table a different name (even just "join_table1_table2" if nothing more semantic comes to mind).

And of course there's the workaround of manually specifying the associations you want instead of having schema_associations do it :)

urkle commented 8 years ago

coming up with a descent way is the trouble :-D

Right now I had to do

# in my user model
  schema_associations concise_names: false, except_type: [:has_and_belongs_to_many]
  has_many :linked_client_applications, through: :user_client_applications, source: :client_application
# in my cient model
  schema_associations concise_names: false, except_type: [:has_and_belongs_to_many]
  has_many :linked_users, through: :user_client_applications, source: :user
# in my intermediary model
  schema_associations concise_names: false

in order for it to work the way I wanted it.

Now are you saying that I completely rename the table with a join_ prefix it'll behave like this by default?

ronen commented 8 years ago

Well it won't quite do all of that. If the intermediary model's table isn't named liked HABTM joins table, then instead of making a has_and_belongs_to_many relation across that table it'll just make the ordinary has_many/belongs to relations:

user has_many intermediaries client has_many intermediaries

intermediary belongs_to user intermediary belongs_to client

But you'd still need to manually create the has_many through: relations you want to reach across the intermediary. schema_associations has know way of knowing which through relations you might want.

(Actually if you rename the intermediary table i think you'll need to rename the intermediary model analogously, since schema_associations infers the model class name from the table name.)

urkle commented 8 years ago

Right.. that's what I would expect that I would have to add the has_man trough: manually which is fine. So I think this is a workable option that doesn't require any modifications to the gem. (other then some clearer documentation to that end)

ronen commented 8 years ago

@urkle I'm happy to accept a PR with better documentation :)

Closing out this issue. Thanks for your thoughts.