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

Automatic associations #1633

Merged
merged 1 commit into from
Oct 27, 2020

Conversation

pablobm
Copy link
Collaborator

@pablobm pablobm commented May 1, 2020

Fixes #1597

Summary

Currently, associative dashboard fields (BelongsTo, HasMany, HasOne) require explicit configuration options (:class_name, :foreign_key, :primary_key) for Administrate to find their associated models. There are details that Administrate can figure out automatically, but not everything, and not always reliably.

This PR changes these field types so that they do not need this configuration, instead detecting associations by using ActiveRecord's reflection API.

Implementation notes

The core change of the feature specs is at spec/example_app/app/dashboards/customer_dashboard.rb. I started by introducing that change, then proceeded slowly to make everything work.

This implementation relies on Field::Base.new always receiving a :resource_class option. I think this is safe as it's already the case throughout the codebase. However third party gems may have incompatibilities here.

Third party gems

I have had a look at third-party plugins listed at https://rubygems.org/gems/administrate/reverse_dependencies. From this list, only administrate-field-nested_has_many appear to have incompatibilities, which is not surprising as it adds a new associative field with some advanced features. Specifically you'll find that:

Deprecations

I could have removed the deprecated options completely, but I decided against it because:

  • I want to minimise disruption when updating Administrate.
  • I don't have 100% trust that just removing the options will work for everyone. There may be a corner case I'm missing.

Instead I'm allowing the old behaviour to exist for a bit longer, while showing abundant deprecation warnings. Hopefully this will get people to upgrade quickly and report any incompatibility.

General review tips

The option "Hide whitespace changes" is very useful here, as I have changed a lot of indent at the specs, in order to avoid style warnings (Hound).

Also due to style warnings, I have reformatted a lot of code, adding more diff noise in the process.

So this is to say: this MR looks huge, but it's just... large, I guess.

The future

The current code relies a lot on globals (eg: class methods) that are difficult to test and generally work with. In the future, we may want to change the interface for field types to improve the situation, but I think that would be too much for this PR.

There's still some risky string-to-class metaprogramming going on, for example a "#{associated_class_name}Dashboard".constantize.new in lib/administrate/field/associative.rb (not shown in the diff as unchanged). I have let this be for now. I think it should be reviewed in the future as part of work in the resolved to fix issues such as namespacing bugs, which are out of scope here.

@pablobm pablobm force-pushed the automatic-associations branch 2 times, most recently from b90e85d to 422fdc8 Compare May 14, 2020 09:43
@pablobm pablobm force-pushed the automatic-associations branch from 422fdc8 to d777ff2 Compare June 1, 2020 14:57
@pablobm pablobm force-pushed the automatic-associations branch 2 times, most recently from 0641b30 to f9a1575 Compare June 25, 2020 08:29
@nickcharlton nickcharlton added feature new functionality that’s not yet implemented models models, associations and fetching the underlying data labels Jun 25, 2020
@pablobm pablobm force-pushed the automatic-associations branch 2 times, most recently from b7edde7 to e27224e Compare July 9, 2020 12:58
@pablobm pablobm force-pushed the automatic-associations branch 2 times, most recently from dd87b6c to 2a6f0b1 Compare July 14, 2020 13:42
@pablobm pablobm force-pushed the automatic-associations branch from 65b80ad to 19689fb Compare July 23, 2020 16:43
@pablobm pablobm force-pushed the automatic-associations branch 3 times, most recently from 3050298 to 27d9f8a Compare August 15, 2020 07:18
@pablobm pablobm force-pushed the automatic-associations branch 4 times, most recently from bdb88f0 to 50421aa Compare August 27, 2020 13:38
@pablobm pablobm marked this pull request as ready for review August 27, 2020 16:08
@pablobm
Copy link
Collaborator Author

pablobm commented Aug 27, 2020

@sedubois - Would you be able to try this out in your project? I'm looking out for possible incompatibilities, and your project appears to be amongst the most complex use cases for Administrate.

@sedubois
Copy link
Contributor

@pablobm OK I'll try to have a look. Sorry for not answering other PRs, hopefully I'll find time in the next couple of weeks.

@c4lliope
Copy link
Contributor

Your changes look incredibly good; could you rebase?

It seems like your test coverage is more than enough to catch any bugs people would run into. While it would be nice if @sedubois is able to test this in his application, I don't think we should let his non-feedback block us from merging in your changes. This is a change that much simplifies the usage of Assemble, and our goal is being as simple as possible for developers to build on.

Really nice going, I'm behind you 💯 .

@pablobm pablobm force-pushed the automatic-associations branch 2 times, most recently from 0d0f44e to 6161af9 Compare October 15, 2020 12:45
Copy link
Collaborator Author

@pablobm pablobm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@c4lliope, thank you for your review. I have made some changes, but also left a couple of questions to see what you think. Additionally, I have added a couple of commits on top to change a couple of documentation-related details. It would be great to hear your thoughts again if you have the time!

lib/administrate/field/associative.rb Show resolved Hide resolved
lib/administrate/field/has_many.rb Outdated Show resolved Hide resolved
lib/administrate/field/has_one.rb Show resolved Hide resolved
lib/administrate/field/has_one.rb Outdated Show resolved Hide resolved
Copy link
Contributor

@c4lliope c4lliope left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All your code here looks really good!

I say 🚢.

lib/administrate/field/has_one.rb Show resolved Hide resolved
Copy link
Member

@nickcharlton nickcharlton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny thing on including FactoryBot. Also our illusive tmp/pids/.keep seems to be back in here!

spec/lib/fields/belongs_to_spec.rb Outdated Show resolved Hide resolved
@sedubois
Copy link
Contributor

@pablobm I've just done a quick run of this branch on my app and did not notice particular issues, except for the unrelated #1788 (undefined local variable page). For my test I've removed some .with_options(class_name: "PaperTrail::Version") and similar that were sprinked in my dashboards and things still seemed to work.

@nickcharlton nickcharlton force-pushed the automatic-associations branch from 6d9c2c9 to 56773da Compare October 27, 2020 18:46
Currently, associative dashboard fields (`BelongsTo`, `HasMany`, `HasOne`)
require explicit configuration options (`:class_name`, `:foreign_key`,
`:primary_key`) for Administrate to find their associated models. There are
details that Administrate can figure out automatically, but not everything,
and not always reliably.

This PR changes these field types so that they do not need this
configuration, instead detecting associations by using ActiveRecord's
reflection API.

This implementation relies on `Field::Base.new` always receiving a
`:resource_class` option. This is safe as it's already the case throughout
the codebase. However third party gems may have incompatibilities here.

From looking at the list of reverse dependencies[1]. From this list, only
`administrate-field-nested_has_many` appear to have incompatibilities, which
is not surprising as it adds a new associative field with some advanced
features. Specifically you'll find that:

* It will not work if you remove your `:class_name` options from
  `NestedHasMany` fields.
* You can work around this by continuing to use the deprecated options (just
  for your `NestedHasMany` fields), although you'll get deprecation warnings.
* There's a branch that will bring this plugin in sync [2].

The old behviour will still exist for a while, to help with backwards
compatibility. This commit introduces a set of deprecation warnings.

Finally, notes for the future:

* The current code relies a lot on globals (eg: class methods) that are
  difficult to test and generally work with. In the future, we may want to
  change the interface for field types to improve the situation.
* There's still some risky string-to-class metaprogramming going on, for
  example a `"#{associated_class_name}Dashboard".constantize.new` in
  `lib/administrate/field/associative.rb` (not shown in the diff as unchanged).
  This should be reviewed in the future as part of work in the resolved to fix
  issues such as namespacing bugs, which are out of scope here.

[1]: https://rubygems.org/gems/administrate/reverse_dependencies
[2]: nickcharlton/administrate-field-nested_has_many@master...pablobm:automatic-associations

Fixes thoughtbot#1597
@nickcharlton nickcharlton force-pushed the automatic-associations branch from 56773da to fe3ae81 Compare October 27, 2020 18:48
@nickcharlton nickcharlton merged commit 7cddab1 into thoughtbot:master Oct 27, 2020
@pablobm
Copy link
Collaborator Author

pablobm commented Oct 27, 2020

Thank you all!

milkfarm pushed a commit to milkfarmproductions/administrate-field-acts_as_taggable that referenced this pull request Apr 26, 2021
See administrate merged pull request #1633 that changed the arguments:
thoughtbot/administrate#1633
@thoughtbot thoughtbot deleted a comment from katonabence6666 Apr 29, 2021
@pablobm pablobm deleted the automatic-associations branch April 29, 2021 15:31
nickcharlton pushed a commit to nickcharlton/administrate-field-nested_has_many that referenced this pull request Aug 20, 2021
This brings compatibility with recent Administrate additions

thoughtbot/administrate#1633
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature new functionality that’s not yet implemented models models, associations and fetching the underlying data
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Associative fields should figure out association options automatically
4 participants