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
Can create new courses #15148
Can create new courses #15148
Conversation
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.
Sorry for all the comments! Feel free to ignore the style comments, but we should add authorization to the CoursesController#create
action.
course_name = params[:course_name].tr('-', '_').titleize | ||
course = Course.find_by_name!(course_name) | ||
# only support this alternative course name for plc courses | ||
raise ActiveRecord::RecordNotFound unless course.plc_course |
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 don't think this is necessary — find_by_name!
should raise if the course isn't found.
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 believe you are right
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.
find_by_name!
raises if the course is not found, but we also want to raise if we found a course, but it is a regular course rather than a plc_course
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 point. Could change find_by_name!
-> find_by_name
for clarity.
|
||
def new | ||
render 'new' | ||
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: We should standardize on whether we want to include these boilerplate action definitions if they are only rendering the default view. I know you prefer explicit, but Rails is CoC by default 😛.
end | ||
|
||
def create | ||
course = Course.new(name: params.require(:course).require(:name)) |
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.
Worth pulling this out to a private course_params
method, and re-using in the show
action? For example: ScriptsController#script_params
.
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.
They use two different sets of params? show
takes params[:course_name]
, where as here we have params[:course][:name]
end | ||
end | ||
|
||
test "should allow uppercase letters if it is a plc course" do |
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.
Are we tracking the debt to unify & redirect professional learning courses that don't match the format?
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 somewhat less important for these to be unified, given that PLC courses aren't being serialized to a file based on their name (unlike regular courses in the near future).
dashboard/app/models/course.rb
Outdated
|
||
# As we read and write to files with the course name, to prevent directory | ||
# traversal (for security reasons), we do not allow the name to start with a | ||
# tilde or dot or contain a slash. |
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.
Same as in Script
, this is redundant with the above name validation. If we really want defense-in-depth maybe we should pull this validator out as a concern?
dashboard/app/models/course.rb
Outdated
end | ||
end | ||
|
||
validates_with CourseNameValidator |
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.
Why this format instead of validates :name
(with unless: :plc_course
)? It looks like there's common functionality in Script
we could maybe combine into a single concern. If we want to start standardizing on this format for all names that appear in URLs...
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.
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.
You're way is much better than mine. I will try that approach.
@@ -1,4 +1,6 @@ | |||
class CoursesController < ApplicationController |
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.
Auth for modify actions?
if course.save | ||
redirect_to action: :edit, course_name: course.name | ||
else | ||
render 'new', locals: {error_messages: course.errors.full_messages} |
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.
A common way of doing this is to set @course
, and have the form in the view be form_for @course
. That way any params are saved between attempts, and errors are already on the @course
object and don't need to be passed separately.
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've been trying to avoid using instance variables in my views, as I find them much more difficult to follow than explicitly passing things in via locals. This might be a case where there's a good argument for doing it the way you say.
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.
Or if you prefer it to be explicit, pass course
as a local, do form_for course
, and inspect course.errors
dashboard/app/models/course.rb
Outdated
end | ||
end | ||
|
||
validates_with CourseNameValidator |
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.
else | ||
render 'new', locals: {course: course} | ||
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.
Looks like this action is missing test coverage?
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'm not sure how interesting this method is to test. I might add a quick and dirty test in a future PR.
unless: :plc_course, | ||
with: /\A[a-z0-9\-]+\z/, | ||
message: 'can only contain lowercase letters, numbers and dashes' | ||
} |
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.
Would be good to have this de-duped against the name validation in Script
.
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.
Using a concern to do this may be easier to do than I thought. I will explore doing this in a follow on PR
This PR makes it so that we can create new courses (by going to /courses/new on LB). It also enforces some validation on the name, which is stricter than the name for PLC courses (in part because we will need to serialize these in ways that wont happen with PLC).