-
Notifications
You must be signed in to change notification settings - Fork 13.6k
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
feat: rails | AR queries | enums (#29099) #29116
base: main
Are you sure you want to change the base?
Conversation
Add lesson content: section on enums * use cases * benefits * readability * maintainability * speed * disk space * how to implement * model * migration * warn about changing persisted data after change to enum declaration * comparison to scopes * class/instance methods exposed
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 double-linked the enum docs in the assignment and additional resources sections. Will leave it up to reviewer to determine where it fits better.
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.
Thanks for doing this @sean-garwood, lots of great stuff here! I've left a few suggestions, please let me know if I can clarify or help with any of them.
|
||
How much do you need to understand or care about scopes? In the early going, you probably won't run into them or see why to use them. Keep them in the back of your mind for when you start working on some slightly more complicated projects that might need them. | ||
|
||
### Enums | ||
|
||
Enums (short for "enumerations") map symbolic names to integer constants. They |
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.
Nit: It is likely for an enum to be backed by an integer, but some databases will have an enum type built in. We'll likely have this corrected by someone later, best to get ahead of them 😆
Enums (short for "enumerations") map symbolic names to integer constants. They | |
Enums (short for "enumerations") map a database column, typically an integer, to a set of symbolic names. |
make code more readable and maintainable, and they offer a performance boost | ||
since queries involving integers are faster than those involving strings. | ||
|
||
Enums are perfect for representing the state of an attribute that has a [discrete |
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.
Nit: Can we drop: that has a [discrete value](https://en.wikipedia.org/wiki/Continuous_or_discrete_variable)
please? I think the concept should be clear enough without it, and it'll be one less link to sidetrack students 😆
since queries involving integers are faster than those involving strings. | ||
|
||
Enums are perfect for representing the state of an attribute that has a [discrete | ||
value](https://en.wikipedia.org/wiki/Continuous_or_discrete_variable). As an |
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.
Nit: I like this light switch example, but worry it might be too abstract to give learners a good idea of how they can apply enums to their projects.
Can something more practical/real world be used in the example? heres some ideas off the top of my head:
- Article model - status of draft and published
- Order model - status of pending, shipped and delivered
- Github PR model - status of open, closed and merged
|
||
#### How to use enums | ||
|
||
To implement `enum`s, we need to declare them in the model and add a column to |
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.
Nit: would it be worth showing the data migration adding the enum column? I think it might help flesh it out a little more and give learners a complete picture of how it works from database to model.
Edit: I just saw you've done this at the bottom of the example. I think it would be worth promoting it to here as the "first step".
|
||
```ruby | ||
# Array declaration | ||
class LightSwitch < ApplicationRecord |
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.
Nit: I think it would be worth focusing on the hash version of the enum syntax and dropping the array approach. It's not used that often in the wild, and focusing on demonstrating one approach should make it simpler and easier to understand.
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 told them to include this in the issue, but I think you're actually correct and omitting this keeps things simpler 👍
enum :status, { off: 0, on: 1 } # Value independent of position; explicit | ||
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.
Nit: After showing how to define an enum, and before we get into the convenience methods. I think it would be good to come full circle and show learners how enums are used when creating a new record.
For example, if we end up using article status for the example:
class Article < ApplicationRecord
enum :status, { draft: 0, published: 1 }
end
article = Article.create(status: :draft)
article.status #=> "draft"
And, just like scopes, this exposes a number of class methods that return | ||
collections: | ||
|
||
```ruby |
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.
Nit: I think it would be worth switching this example and the scopes example above this one around. First demonstrating the class methods and then tying them back to scopes seems like the better flow.
bin/rails g migration AddToLightSwitch status:integer | ||
``` | ||
|
||
Importantly, changing the model declaration **will not change** values that have |
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.
Nit: I'm not sure if this will be necessary, but don't mind keeping it if you do. Could we include an example with it to demonstrate it?
details of scopes, but you should understand the concept and when it might be | ||
useful. | ||
1. Read [How to Use Enums in | ||
Rails](https://blog.saeloun.com/2022/01/05/how-to-use-enums-in-rails/). |
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.
Good find with this article. I think it should be enough for the assignment and the docs will be a better fit in additional resources.
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.
Stylistic nit, but in a lot of places you've added manual line breaks in the markdown. Paragraphs should all occur on one continuous line -- which makes reviewing and suggesting changes much more intuitive for us. You can still configure your editor to wrap long lines in md files for better readability locally. Hopefully that all makes sense.
Thanks a lot for adding this in btw! I think enums are a great addition to the curriculum, and they're something that pretty much every professional Rails dev works with often.
If you have a formatter that's inserting these, I recommend disabling it while working on the curriculum.
Importantly, changing the model declaration **will not change** values that have | ||
already been stored in the database; you must update them yourself. |
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.
Importantly, changing the model declaration **will not change** values that have | |
already been stored in the database; you must update them yourself. | |
Importantly, changing the model declaration **will not change** values that have already been stored in the database; you must update them yourself. |
There shouldn't be a line break here.
And, just like scopes, this exposes a number of class methods that return | ||
collections: |
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.
And, just like scopes, this exposes a number of class methods that return | |
collections: | |
And, just like scopes, this exposes a number of class methods that return collections: |
Removing the manual line break.
Enums are declared in the model's class as either an array or a hash. The hash flavor has a slight advantage | ||
in that the integer values mapped to the `enum` are independent of their | ||
position and the values stored in the database are explicitly stated. |
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.
Enums are declared in the model's class as either an array or a hash. The hash flavor has a slight advantage | |
in that the integer values mapped to the `enum` are independent of their | |
position and the values stored in the database are explicitly stated. | |
Enums are declared in the model's class as either an array or a hash. The hash flavor has a slight advantage in that the integer values mapped to the `enum` are independent of their position and the values stored in the database are explicitly stated. |
Removing manual line breaks.
Enums (short for "enumerations") map symbolic names to integer constants. They | ||
make code more readable and maintainable, and they offer a performance boost | ||
since queries involving integers are faster than those involving strings. |
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.
Enums (short for "enumerations") map symbolic names to integer constants. They | |
make code more readable and maintainable, and they offer a performance boost | |
since queries involving integers are faster than those involving strings. | |
Enums (short for "enumerations") map symbolic names to integer constants. They make code more readable and maintainable, and they offer a performance boost since queries involving integers are faster than those involving strings. |
Removing manual line breaks
Enums are perfect for representing the state of an attribute that has a [discrete | ||
value](https://en.wikipedia.org/wiki/Continuous_or_discrete_variable). As an | ||
example, consider a light switch: it is either in an on or an off state. It is | ||
never between these two states, and it is never both on and off. |
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.
Enums are perfect for representing the state of an attribute that has a [discrete | |
value](https://en.wikipedia.org/wiki/Continuous_or_discrete_variable). As an | |
example, consider a light switch: it is either in an on or an off state. It is | |
never between these two states, and it is never both on and off. | |
Enums are perfect for representing the state of an attribute that has a [discrete value](https://en.wikipedia.org/wiki/Continuous_or_discrete_variable). As an example, consider a light switch: it is either in an on or an off state. It is never between these two states, and it is never both on and off. |
Removing manual line breaks.
To implement `enum`s, we need to declare them in the model and add a column to | ||
store them in the database table that stores instances of the model. |
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.
To implement `enum`s, we need to declare them in the model and add a column to | |
store them in the database table that stores instances of the model. | |
To implement `enum`s, we need to declare them in the model and add a column to store them in the database table that stores instances of the model. |
Removing manual line break.
1. Read section 14 in the [Rails Guide on | ||
Querying](https://guides.rubyonrails.org/active_record_querying.html#scopes) | ||
for a look at scopes. Again, you don't necessarily need to memorize all the | ||
details of scopes, but you should understand the concept and when it might be | ||
useful. |
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.
1. Read section 14 in the [Rails Guide on | |
Querying](https://guides.rubyonrails.org/active_record_querying.html#scopes) | |
for a look at scopes. Again, you don't necessarily need to memorize all the | |
details of scopes, but you should understand the concept and when it might be | |
useful. | |
1. Read section 14 in the [Rails Guide on | |
Querying](https://guides.rubyonrails.org/active_record_querying.html#scopes) | |
for a look at scopes. Again, you don't necessarily need to memorize all the | |
details of scopes, but you should understand the concept and when it might be | |
useful. |
1. Read section 14 in the [Rails Guide on | |
Querying](https://guides.rubyonrails.org/active_record_querying.html#scopes) | |
for a look at scopes. Again, you don't necessarily need to memorize all the | |
details of scopes, but you should understand the concept and when it might be | |
useful. | |
1. Read section 14 in the [Rails Guide on Querying](https://guides.rubyonrails.org/active_record_querying.html#scopes) for a look at scopes. Again, you don't necessarily need to memorize all the details of scopes, but you should understand the concept and when it might be useful. |
Removing line breaks.
1. Read [How to Use Enums in | ||
Rails](https://blog.saeloun.com/2022/01/05/how-to-use-enums-in-rails/). |
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.
1. Read [How to Use Enums in | |
Rails](https://blog.saeloun.com/2022/01/05/how-to-use-enums-in-rails/). | |
1. Read [How to Use Enums in Rails](https://blog.saeloun.com/2022/01/05/how-to-use-enums-in-rails/). |
Removing line break.
- [ActiveRecord::Enum API | ||
docs](https://api.rubyonrails.org/classes/ActiveRecord/Enum.html) |
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.
- [ActiveRecord::Enum API | |
docs](https://api.rubyonrails.org/classes/ActiveRecord/Enum.html) | |
- [ActiveRecord::Enum API docs](https://api.rubyonrails.org/classes/ActiveRecord/Enum.html) |
Removing line break.
Add lesson content: section on enums
Because
Enums are a useful way of storing discrete states and expose useful querying class and instance methods.
This PR
Issue
Closes #29099
Additional Information
Pull Request Requirements
location of change: brief description of change
format, e.g.Intro to HTML and CSS lesson: Fix link text
Because
section summarizes the reason for this PRThis PR
section has a bullet point list describing the changes in this PRIssue
section