-
Notifications
You must be signed in to change notification settings - Fork 641
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
Add a way to reach specific training modules and slides via ID numbers #5502
Add a way to reach specific training modules and slides via ID numbers #5502
Conversation
… to be able to reach a training module by their id
… be able to reach individual slides by id
spec/factories/training_slides.rb
Outdated
FactoryBot.define do | ||
factory :training_slide do | ||
id { 456875} | ||
title { 'How to create a slide' } | ||
slug { 'how-to-create-a-slide' } | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this because I want to test the behavior for an orphan slide (one that doesn't belong to any module).
…rom module slug, and 2) a module from slide slug
Thanks for approving the workflow. It looks like the new
Edit: ragesoss told me I can ignore those ^^ |
training_module = find_module_from_slide_slug(training_slide.slug) | ||
raise ActionController::RoutingError, 'module not found' unless training_module | ||
training_library = find_library_from_module_slug(training_module.slug) | ||
raise ActionController::RoutingError, 'library not found' unless training_library |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's possible to have a module that is not in any library, and it would render if you visited a path that had any valid training library slug. (You can view a module from one library even if you substitute the slug from another library.)
It would be good to find the library as you do here, but if no library is found, it would be better to use TrainingLibrary.first as a fallback instead of throwing a 404.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm interesting. That behavior is not so intuitive I guess.
I changed the logic for the controllers and updated specs on fbb894f
Note that the new definitions may result in failure if no library exists. In such a scenario, calling TrainingLibrary.first
would return nil
, causing an error when attempting to access the slug.
Not sure if a world with no libraries makes sense, or it is not worth considering this case and we can suppose TrainingLibrary.first
is always well defined.
It looks like modules and slides render even using a non-existing library slug, so we could use a literal string
'mylibrary'
as default library slug value if no libraries at all.
What's your opinion here?
app/helpers/training_helper.rb
Outdated
# Given a module slug, it returns the first library that has a | ||
# category including that module slug. It returns nil if no such | ||
# library is found. | ||
def find_library_from_module_slug(module_slug) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both of these helper methods would make more sense as instance methods of TrainingSlide
and TrainingModule
respectively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, agreed. I made all your suggested changes on 54f8848
app/helpers/training_helper.rb
Outdated
end | ||
end | ||
|
||
# Given a slide slug, it returns the first module including it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a TrainingSlide instance method, you could implement this as
TrainingModule.all.detect { |tm| tm.slide_slugs.include? slug }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much more idiomatic, I like it!
This looks great overall. |
app/helpers/training_helper.rb
Outdated
# category including that module slug. It returns nil if no such | ||
# library is found. | ||
def find_library_from_module_slug(module_slug) | ||
TrainingLibrary.all.find_each do |library| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this method, I would suggest implementing TrainingLibrary#training_module_slugs (for example:
def training_module_slugs
categories.map do |cat|
cat['modules'].map { |mod| mod['slug'] }
end.flatten
end
)
and then using that to implement TrainingModule#library:
TrainingLibrary.all.detect { |tl| tl.training_module_slugs.include? slug }
…e TrainingLibrary.first as a default library instead.
…brary from slug as instance methods instead
…ion in controllers
# Returns a specific training library for the module, | ||
# or a default library if it is not found. | ||
def find_or_default_library | ||
find_library_by_slug || TrainingLibrary.first | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created this method only to avoid code duplication in controllers.
Alternatively, I guess I could define just something like this:
# Returns the first library that has a category including the module slug,
# or a default library if it is not found.
def find_library_by_slug_or_default
TrainingLibrary.all.detect(-> { TrainingLibrary.first }) { |tl| tl.training_module_slugs.include? slug }
end
Nice work! |
What this PR does
The purpose of this PR is to add:
In order to do that, two new routes were added (
find_training_module
andfind_training_slide
), as long as their corresponding controllers and specs.The logic behind the controllers is to redirect the user to the URL for the given training module (
/training/library-slug/module-slug
) or to the individual slide (/training/library-slug/module-slug/slide-slug
).Closes #4940
Screenshots
After this PR, users are redirected to the training module or slide site.
Screencast.from.08-10-23.23.50.00.webm
Open questions and concerns