Topic: RESTful Form Design

I am having trouble figuring out how to make a form I need. Here's a toy example to set up my problem.
Models: Users, Parties, Guests (to be clear "guests" are not "users")
User has_many Parties
Party has_many Guests

I have a table that looks like this:[code="show.rhtml # GET /parties/1"]<% @party.guests.each do |guest| %>
  <tr>
    <td>guest.name</td>
    <td>guest.email</td>
    ...
  </tr>
<% end %>[/code]I want the last column in the table to be a checkbox and for there to be a button below the table that will send a reminder email to all of the guest.email that are selected.

I have a mailer setup already with a send_reminder(quest) method but I need to call

guests.each do |guest|
  Mailer.deliver_send_reminder(quest)
end

So my question is I've been looking at form_for a lot but I'm not sure how to go about this. I'm trying to stay RESTful. Any advice? maybe even example code?

Re: RESTful Form Design

form_for is for editing model attributes, here you're just using the form to make a selection with checkboxes so I recommend sticking with form_tag.

Now how to do this in a RESTful manner? I recommend creating a custom REST action to be performed on the party.

map.resources :parties, :member => { :remind_guests => :post }

You can use it like this:

<% form_tag remind_guests_party_path(@party) do %>
  #...
<% end %>

Now you need need to format the checkboxes. I recommend using check_box_tag like this:

<%= check_box_tag "guest_ids[]", guest.id %>

Then you should be able to access the guests through params[:guest_ids] in the resulting controller action.

def remind_guests
  @guests = Guest.find(params[:guest_ids])
  #...
end

Railscasts - Free Ruby on Rails Screencasts

Re: RESTful Form Design

I decided to make a Railscasts episode about this. It will be out Monday.

Railscasts - Free Ruby on Rails Screencasts

Re: RESTful Form Design

Sweet deal Ryan. Thanks for your help! Can't wait for the Railscast.

Re: RESTful Form Design

Great episode Ryan. I wasn't sure if I needed another model or not but I think you are right this is simple and small enough to just use a custom action.

I do have one more question for anyone who may know. If there is a chance that in our example a husband and wife have both been invited and have the same email. If we only want to send one email to them, is there like a .unique  or .compact method for collections that I could call in the controller so I get rid of duplicates?
Thanks

EDIT: found it myself: .uniq

Last edited by JackVandaL (2007-07-02 14:33:41)

Re: RESTful Form Design

How would one save the guest_id in a the party table?

Re: RESTful Form Design

ravvuinn wrote:

How would one save the guest_id in a the party table?

I don't think one would.  I can think up a few examples of how you might choose to model this.  In all cases the guest_id would not be saved in the party table.   If you have a simple one to many relationship on parties to guetss you might have two tables like:

parties      (has_many_guets)
guests       (belongs_to_party, party_id goes here)

You could expand on this and say, guests might go to many parties and I want to track each guest individually without duplication when they go to many parties.  In this case you might do:

parties         (has_and_belongs_to_many guests)
guests_parties  (party_id, guest_id, no id column, simple join table)
guests          (has_and_belongs_to_many parties)

Now we can get even fancier and say, Id like to store with each maping of a guest to a party a rsvp message (like I'll be 30 mins late, or Im brinning steak for the grill...).  We can't do this (or shouldn't) with a HABTM relationship, so we need to add a 3rd model.

parties       (has_many party_guests)
party_guests  (party_id, guest_id, rsvp, etc)
guests        (has_many party_guests)

Now we can tack into the party_guests tables our rsvps and other such things.  However, this is only a start.  We might want to use other rails goodies to make this make more sense.  Example, we might want to access the guest models without needing to load up the party_guests.  We also might want to rename some of these relationships to something more natural-language-like.

parties       (has_many rsvps, class_name PartyGuests
               has_many guests through rsvps)

party_guests  ...

guests        (has_many rsvps, class_name PartyGuests
               has_many parties through rsvps


I am using sudo-code.  You will want to look up the exact syntax, but this quick example will give you some ideas.  As you can see, adding a guest id into the party table doesn't really work, but you have *lots* of choices on where to go with it.  I recommend starting with something simple and refactoring only when you need a feature you don't have. 

Trevor Rowe