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

Prevent moving scripts between unit groups when they have resources or vocabulary #38702

Merged
merged 10 commits into from
Feb 3, 2021

Conversation

bethanyaconnor
Copy link
Contributor

@bethanyaconnor bethanyaconnor commented Jan 22, 2021

A step in PLAT-505. This PR prevent adding or removing a script from a unit group if any lessons in that script have resources or vocabulary. This PR does not handle standalone scripts as I was having trouble getting that to work.

I'm definitely open to ideas on how to do this better. I originally wanted to add a model validation but I struggled to figure out where.

  • Lessons do not have a direct connection to course version and their course version will change only when their script's course version does, so that's not the right place for this check.
  • A script's course version could change without ever directly changing the script (if they're part of a unit group) so that won't catch all cases
  • Not all scripts are in unit groups so a validation on the unit group won't catch all cases
  • A script could change course version without the course version object being modified (if they're part of a unit group) so that won't catch all cases

So I've gone for the strategy of "closing the gaps". This unfortunately means that in places we'll have to bake the logic of how these relationships work into the code more than I'd like.

Background

Resources and vocabulary belong to a course version and it is expected that they belong to the same course version as any lesson they're in. This becomes an issue if a script's course version changes as the resources and vocabulary in lessons in that script will still belong to the previous course version.

Links

Testing story

Reviewer Checklist:

  • Tests provide adequate coverage
  • Privacy and Security impacts have been assessed
  • Code is well-commented
  • New features are translatable or updates will not break translations
  • Relevant documentation has been added or updated
  • User impact is well-understood and desirable
  • Pull Request is labeled appropriately
  • Follow-up work items (including potential tech debt) are tracked and linked

@bethanyaconnor bethanyaconnor changed the title Prevent course version change with resources Prevent moving scripts between unit groups when they have resources or vocabulary Jan 29, 2021
@bethanyaconnor bethanyaconnor marked this pull request as ready for review January 29, 2021 22:12
Copy link
Member

@davidsbailey davidsbailey left a comment

Choose a reason for hiding this comment

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

Nice progress Bethany! The new tests look good too.

@@ -466,7 +466,7 @@
t.index ["name", "version"], name: "index_foorm_forms_on_name_and_version", unique: true
end

create_table "foorm_libraries", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
create_table "foorm_libraries", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci", force: :cascade do |t|
Copy link
Member

Choose a reason for hiding this comment

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

this line looks like it should be reverted

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops -- this file shouldn't be committed here at all 🤦‍♀️

script = Script.find_by_name!(script_name)
if scripts_to_delete.any?(&:prevent_course_version_change?)
raise 'Cannot remove scripts that have resources or vocabulary'
end
Copy link
Member

Choose a reason for hiding this comment

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

I am trying to wrap my head around what we will do in the case where a curriculum writer decides that they do not want a unit in their unit group any more. perhaps the curriculum writer will have to keep the script in the unit group until they are ready to destroy it entirely?

I don't necessarily see a better way, and I'd rather have this protection than not. So I am ok with waiting for someone to run into this before dealing with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If it doesn't have resources or vocabulary, it should be possible to remove it still. If it does, the options are going to be to go through each lesson and remove these objects or wait until they want to destroy it entirely I guess.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will admit the error handling is not pretty on this but I'd be surprised if this is an error path hit commonly.

@Hamms
Copy link
Contributor

Hamms commented Feb 2, 2021

Almost feels like resources and vocabularies should be primarily associated with a script (or with a course version? Whichever model is the closest to the source of truth for versioning), and then lessons should do something like reference some subset of that content for the script that they're in, rather than themselves being directly associated with resources and vocab.


new_scripts.each_with_index do |script_name, index|
script = Script.find_by_name!(script_name)
if scripts_to_delete.any?(&:prevent_course_version_change?)
Copy link
Contributor

Choose a reason for hiding this comment

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

is there a reason we want this logic to live here, rather than in, say, a before_destroy hook on Script?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The variables could be better named but this isn't actually destroying a script, just removing it from the unit group.

Copy link
Contributor

Choose a reason for hiding this comment

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

ahhhhh, right. Yeah, something like scripts_to_remove would be clearer

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed -- I'll make that change

@bethanyaconnor
Copy link
Contributor Author

Vocabularies and resources are directly associated with a course version, which is how we do that versioning you're referencing. I'm not sure I understand what you're suggesting about referencing a subset? I'm very open to adjusting how we maintain these associations if we can do it without breaking things so ideas are very welcome :)

@Hamms
Copy link
Contributor

Hamms commented Feb 2, 2021

Oh, nice! We're halfway to my suggestion already, then.

So right now, resources are unique per (course_version, key) combination. What if instead of lessons having a direct has_and_belongs_to_many relationship with resource, they just had a list of resource keys, and we find the specific resource for the lesson by getting the appropriate course version from the lesson's script.

Copy link
Contributor

@Hamms Hamms left a comment

Choose a reason for hiding this comment

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

to clarify: my suggestions for an alternative approach are suggestions for future work, not something I think we need to do in this PR.

This change LGTM for what it is! Love the tests, too; very clear.

@davidsbailey
Copy link
Member

Thank you for suggesting this, Elijah! I think there have been a bunch of times recently where the topic of "decoupling vs deduplication" have come up, and so far we (our team, the org, etc) have tended to side with deduplication. is this a case where the approach you're suggesting has a benefit that you'd describe as "decoupling", or is there another motivation?

@Hamms
Copy link
Contributor

Hamms commented Feb 2, 2021

I don't know that I'd describe it as either decoupling or deduplication. Rather, this is about recognizing that the underlying implementation does not align with our intended usage scenarios. Or at least it doesn't align as well as it could. Right now we're addressing this by adding some situational logic to make sure that we avoid one scenario in which the misalignment could cause an issue. I'm suggesting that there is an underlying implementation which could be better aligned, and would render this special logic unnecessary.

@bethanyaconnor bethanyaconnor merged commit 0c18fb1 into staging Feb 3, 2021
@bethanyaconnor bethanyaconnor deleted the prevent-course-version-change-with-resources branch February 3, 2021 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants