I'm trying to create a simple dojo attendance app in RoR, and am currently stuck between what I know I can do, vs what I'd like to be able to do, at least with regards to displaying, creating and updating attendance records. (The rest of the app seems straightforward to me.)
Here's the schema for the table in question:
create_table "attendances", :force => true do |t|
t.date "class_date"
t.integer "student_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "class_hours", :default => 0
end
I know I can leverage the basic scaffold view for this, but doing so would be tedious, ie, new attendance record, select date, student and hours spent, save, go back to index view (modified to be limited to a specific month). That's a lot of clicking for a single record creation. Not horrible in and of itself, but I can see it getting tedious with each new entry. That said, this approach would be quite straightforward to update, if the user of the system realizes that the wrong number of hours was entered for that student. Dead simple for deleting the record altogether, if needed.
I could see myself enhancing the above such that:
- the index view lists all students for a given month, regardless of whether they have attended class or not
- possibly make the student's name a link to the New Attendance page (described above)
- if a student has an entry for that month for the date in question, then that cell in the grid would be a link to the Edit Attendance page for that record
- I figure I could add a Delete link at the bottom of the Edit Attendance page
What I'd really like to have is a view which provides the following:
- month-at-a-glance grid (name of month at top of view, ideally using jQuery's datepicker)
- first column of grid lists all students
- header for each column (after the first column) for the days of the month, from 1 to N (last day of the month)
- if an attendance record exists for the student on a specific date, display the hours in the cell
- if an attendance record does not exist for the student on a specific date, display nothing (or display "-" or a similar placeholder)
I've gone round and round trying to figure this one out. If the grid had values for every cell (ie, every student had a record for every day of the month being displayed), then I could use best_in_place to get past this. Done and done. But bloating up the table in this way seems like a terribly inefficient use of the table, especially when you consider that a) the students will likely be kept on the roster forever, unless they've done something so egregious that they've been banned from the dojo, b) nobody attends every available class, c) very few students attend a majority of available classes. I considered trying to make it work with best_in_class_if, except that it would still require that the record exists, in order to display it. Argh.
I only recently learned of find_or_create_by which briefly gave me hope as a way of getting past this. I then learned of this approach for creating create_or_update_by which gave me another glimmer of hope as a way to get past this, but there was still something bugging me about how to approach it to make it happen. Namely, I would have to create some sort of reference in the grid (html table) to records which do not exist, which seems unattainable. (I also had a problem while testing create_or_update_by from the rails console which threw a LocalJumpError: no block given (yield)
but I wasn't able to nail down why.)
If I haven't been clear about the look and feel I'm trying to get with the month-at-a-glance Attendance view, think of it as an Excel spreadsheet: students down the left column, days-of-the-month across the top, if a cell is empty a value can be added to it, if a cell has a value it can be changed. (Blue sky: If the class_hours value is set to zero, delete the record.)
I've tried to find inspiration in the Routes documentation, as well as the Controllers documentation. No joy.
I will gladly consider alternative RoR solutions, so long as the following points are considered, as I realize I could be completely missing a more obvious/elegant approach:
- Attendance month-at-a-glance view (using DataTables, which I've already succeeded in leveraging) which lists all students in the system, regardless of whether they attended class that month
- simple approach to adding/updating a student's attendance, ideally with less clicking than the basic scaffold views
Cheers.
Edit: On further contemplation, it would seem that one reasonable approach would be to make the cells in the datagrid which don't yet have representation in the Attendance table to be a link which passes the params student_id, class_date, and class_hours to the /attendances/new route (modified from the scaffold to accept and use the params), and likewise for clicking a cell which does already have a value. (I could still consider using best_in_place for the latter, but for the sake of a consistent UI, perhaps I should avoid that.)
I'll still gladly take insightful suggestions, if I've missed a golden opportunity to approach this in a better way.