curriculum
curriculum copied to clipboard
Ruby: Custom Enumerables Project: Add description of relationship between `Enumerable` and `#each`
Complete the following REQUIRED checkboxes:
- [x] I have thoroughly read and understand The Odin Project Contributing Guide
- [x] The title of this issue follows the
location for request: brief description of requestformat, e.g.NodeJS course: Add lessons on XYZ
The following checkbox is OPTIONAL:
- [ ] I would like to be assigned this issue to work on it
1. Description of the Feature Request:
Link to thread in the #suggestions-bugs channel: https://discord.com/channels/505093832157691914/1004082866419937341
I've noticed that a very common point of confusion with this project is not understanding the relationship between Enumerable and the classes that mix it in. I don't think puzzling over this should be the goal of the project (it should be about using blocks), and I also feel like telling the learner to research it risks spoiling solutions for some of the project's problems. If I google "how does ruby enumerable module work", the first hit shows an example of a custom created #map for demonstration purposes, which is giving away answers.
I think the explanation should contain two things:
- Mention that modules can use instance methods of classes that they're mixed into. We could show some type of example to demonstrate this. Here's a small dummy example that could maybe work, or for a practical example, we could demonstrate how
Comparableuses a class's<=>method. Learners are unlikely to have encountered this kind of module/class interaction before this point, and I think this contributes to the confusion people often have when trying to get started. - Tell users that the above concept describes
Enumerable's relationship with objects it's mixed into. It expects the object to define an#each, which it then uses to help implement its own methods. This allows it to adapt to different class's needs regarding iteration. In this project, you will define a#my_eachforArray, and then you will rebuild some of theEnumerablemethods, relying onArray#my_eachto help implement them.
Let me know any other suggestions or feedback. Would be glad to hammer out something more concrete / make a PR if maintainers think this is a good idea.
This issue is stale because it has had no activity for the last 30 days.
This issue is stale because it has had no activity for the last 30 days.
Hey @JoshDevHub
Apologies for the delay in response. We agree this is an area that needs improvement. Is it something you want to take on which we can support you on?
Hi @CouchofTomato
This is something I'd like to work on yeah. I might want a little direction for the best approach to take for getting the information across. I know from experience helping people through this exercise in the discord that it can be a tricky subject. I thought I might post a couple of different ideas here in this issue for feedback before making the PR. I should be able to get that done within the next few days if that seems like an okay approach.
And thanks for responding! No worries regarding the delay
@JoshDevHub
I thought I might post a couple of different ideas here in this issue for feedback before making the PR. I should be able to get that done within the next few days if that seems like an okay approach.
This sounds like a great approach :ok_hand:
Apologies for the slow velocity on this. Been a busy couple of months for me but I'm back around to thinking on this. Will try to post something concrete here this week.
No stress @JoshDevHub, thanks for the update
Apologies for how long it's taken me on this.
Here's a link to this project's introduction in the curriculum: https://github.com/TheOdinProject/curriculum/blob/main/ruby/advanced_ruby/project_custom_enumerables.md
And a link to the project itself: https://github.com/TheOdinProject/custom_enumerable_project
I think I'd like to propose two changes:
-
So this line in the introduction:
You should be very familiar with the Enumerable module that gets mixed into the Array and Hash classes-- From conversations I've had with learners going through this project, I feel like this could be assuming a lot. At this point in the curriculum, learners' experiences with builtin data structures will heavily favor arrays. A lot of theEnumerablemethods have overridden implementations in theArrayclass itself (including every method asked for in the Custom Enumerables project except forinject/reduce). This may mean learners haven't spent much time in the docs forEnumerable. I think it could be a good idea to link to the docs and/or the previous lesson on enumerable methods. -
I want to introduce a very brief example of the kind of mixin interaction happening with
Enumerable. I know in the top post of this issue, I specifiedComparableas a potential example to give, but I might think there's more value in keeping it very simple and brief here. I'm definitely open to feedback on this though. So for my concrete idea on this change, I was thinking something like:"The
Enumerablemodule works by piggybacking off the#eachmethod defined in the classes it's mixed into. This uses a property of mixins you may not have directly encountered: modules can use instance methods for classes they expect to be mixed into:class MyClass include Shoutable def say_hello_world "Hello, World" end end module Shoutable def say_hello_world_loudly say_hello_world + "!!!" end end puts MyClass.new.say_hello_world_loudly #-> "Hello, World!!!"So even though
#say_hello_worldisn't defined in theShoutmodule, it can still use it assuming it's mixed into a class that has it. With that pattern in mind, you will define#my_eachinside ofArray, and then inEnumerable, you will make use of#my_eachto help implement the different enumerable methods. This mirrors the interaction the realEnumerablehas with the#eachmethod that's defined inArray,Hash,Range, etc."
It might make more sense to place this 2nd change in the project repo's README -- possibly somewhere in this section: https://github.com/TheOdinProject/custom_enumerable_project/blob/main/README.md?plain=1#L65-L79
Let me know any other thoughts/concerns. I think this is definitely something where it can be easy to confuse or overwhelm learners if it's not done well.
This issue is stale because it has had no activity for the last 30 days.
I'm going to close this because I think the ideas can more effectively be communicated with completing #23481 -- which is under active development.