I’m new to ruby and rails and I’m wanting to following coding standards and conventions as best as possible, so I don’t pick up any bad habits. I have two models: Course and Location. A course belongs_to a location, as a course can only have one location. A location has_many courses, as a location could be shared by more than one course.
When creating a course, a location may already exist that is found by its ID. Or the location may not yet exist, in which case a new location record must be created. My Course controller has the following create action.
def create
@course = Course.new(params[:course])
if params[:course][:location][:id].blank?
@course.location = Location.create(params[:course][:location])
else
@course.location = Location.find_by_id(params[:course][:location][:id])
end
@course.save
respond_with @course
end
Note that this is a REST API that only responds with JSON. The javascript that makes the request posts a JSON array in the same format that would be returned by a GET request
{
"course":
{
"title":"US History",
"credits":"3",
"max_students":"100",
"location":
{
"id":"",
"building":"Freedom Hall",
"room":"301"
}
}
}
or
{
"course":
{
"title":"US History",
"credits":"3",
"max_students":"100",
"location":
{
"id":"12", # this is the only difference
"building":"Freedom Hall",
"room":"301"
}
}
}
- Compared with all of the examples I’ve read, this code doesn’t look so elegant. Is there better way to factor it?
- If Location.create raises an exception, will @course.save still be called? Do I need to use Location.create!?
- Likewise, will validation errors end up in @course.errors even though the errors were on the Location model? Do I need to rescue from the exception so that I can return the errors to the client?
Thank you very much for any and all help!
You can clean that up by using
find_or_initialize_by_id. This should work:Regarding your second question, in your code as you have it
@course.savewill not be called ifLocation.create(orLocation.find) raises an exception (because they would happen first). However, the way I have coded it above, the exception would happen at the same point in the code, whensaveis called, at which point the association is also saved.