Topic: Modeling a schedule/appearance

I'm relatively new to rails and not a programmer by training. Something I've heard more than once in reference to Rails is that if it feels like Rails is fighting you, maybe you are doing something wrong. With that in mind, something that had been completely making my life miserable became cake after modifying my model. I'm curious what you guys think about the two approaches below.

The purpose of the app is to provide information about what services are available and who provides them, and when those people are available at a particular school. The Services bit is trivial, so I don't want to spend time discussing it. The fundamental information is a Provider at a School on a particular day of the week (like a college class schedule--MWF, or TuTh, or what have you).

Either way I approached it I use Schools and Providers. In both cases, both are has_many :through the third model. This model took two forms.

Initially, I chose "Appearances". I think one clue was how hard it was to even come up with a name for the model. My approach here was to have one record for each appearance. An appearance was defined as a Provider at a School on a Day of the Week. Multiple appearances are required to have a Provider at a School on more than one day. For MWF, there would be provider_id = 1, school_id = 1, day_of_week = 1, provider_id = 1, school_id = 1, day_of_week = 3, provider_id = 1, school_id = 1, day_of_week = 5. It conceptually seemed clean, and followed some of the approaches I've seen in various Rails bibles.

While it was easy to inspect appearances, it was quite difficult to edit them, primarily because Providers are the most likely to be editing their appearances. Since a provider could conceivable be at a different location every day of the week, that further complicated things.

The UI I envisioned for this was a series of checkboxes, like so: [x] Mon [ ] Tue [x] Wed [ ] Thu [x] Fri

In fact, I asked around (here, on IRC, on the local Rails list) and only got one person who could figure out how to do it, and it didn't really work. Even though we got the right blank checkboxes and such, I was going to have to loop through the response and look up the appearance given the school_id, provider_id, and day_of_week info in order to update or delete records. By then, I was totally out of gas and sick of beating my head against the problem.

I decided to try what seems to me to a much less "elegant" approach, which is to replace the Appearance model with a Schedule model (which is what I wanted to call the model all along). In this case, there's a boolean column in the table for each day of the week, which I called "day_1", "day_2", and so on. Using this, check_box pretty much "just works". I can even use the _form partial:

<p>
    <% 1.upto(5) do |i| %>
        <%= check_box("schedule", "day_"+i.to_s) %>&nbsp;<%=h Date::ABBR_DAYNAMES[i] %>
    <% end %>
</p>

I was about to write about how collecting the days a provider is at a school was challenging, but it's actually easier.

Anyway, do you think it was the right move to change model and table structure?

Thanks!

Re: Modeling a schedule/appearance

lrivers wrote:

Something I've heard more than once in reference to Rails is that if it feels like Rails is fighting you, maybe you are doing something wrong.

Exactly, if you don't do things the "Rails way", you will be fighting the framework. It wasn't until I accepted Rails ideas of doing things that I understood why it was such a great framework and became a better programmer because of it.

Irivers wrote:

Anyway, do you think it was the right move to change model and table structure?

The key is in the interface. How the interface behaves is a clue as to how you should build the models. This is why you should start with the interface.

Looking at the list of checkboxes, it reminds me of a HABTM (many-to-many) association. If you search the forums for "HABTM checkbox" you'll see a number of threads on the subject. Yes, it does seem a little silly to create a "Weekday" model, but I think it will make things easier in the long run.

So, we have a HABTM association, one side of the association is a Weekday model, what's the other side? It's hard to say, and this may be the missing piece. To find out, you have to go back to the interface. When you picture the checkboxes, what model's form are you filling out? Can you expound on the interface a little more?

Railscasts - Free Ruby on Rails Screencasts

Re: Modeling a schedule/appearance

ryanb wrote:

The key is in the interface. How the interface behaves is a clue as to how you should build the models. This is why you should start with the interface.

Looking at the list of checkboxes, it reminds me of a HABTM (many-to-many) association. If you search the forums for "HABTM checkbox" you'll see a number of threads on the subject. Yes, it does seem a little silly to create a "Weekday" model, but I think it will make things easier in the long run.

So, we have a HABTM association, one side of the association is a Weekday model, what's the other side? It's hard to say, and this may be the missing piece. To find out, you have to go back to the interface. When you picture the checkboxes, what model's form are you filling out? Can you expound on the interface a little more?

The way I see it is that the person that "owns" the schedule (the Provider) is filling out the form.

The direction I'm heading is to have a Provider page that shows:

Provider Name & Info
*link to "edit provider info*
------------------
Schedules (*loops through providers' schedules schools*):
School
Days
*link to delete schedule for school*
---
*link to edit schedules*


Edit Schedules Page
Edit Schedule for Provider
School Name
[x] Mon [ ] Tue [x] Wed [ ] Thu [x] Fri
edit button

School Name
[ ] Mon [x] Tue [ ] Wed [x] Thu [ ] Fri
edit button

Re: Modeling a schedule/appearance

Okay, I get it. When they are editing the checkboxes they are editing the Schedule model which belongs to both Provider and School.

In that case, here's what I was referring to above.

class Schedule < ActiveRecord::Base
  belongs_to :school
  belongs_to :provider
  has_and_belongs_to_many :weekdays
end

class Weekday < ActiveRecord::Base
  has_and_belongs_to_many :schedules
end


You would also have a schedules_weekdays table holding the join.

However, this approach may or may not be worth it. The primary benefit of extracting the weekdays into their own model allows a weekday to hold  its own attributes and behavior. If you do not need this, then it may be better to stick with boolean columns in the schedules table.

Railscasts - Free Ruby on Rails Screencasts