Form_for with multiple objects, each with a preset attribute?


#1

I’m using Rails to create a schedule of a shop’s opening and closing
hours. Simplified versions of the models I’ve set up is:

class Account < ActiveRecord::Base

has_many :opening_hours, :dependent => :destroy

end

class OpeningHour < ActiveRecord::Base

belongs_to :account

table schema

create_table “opening_hours”, :force => true do |t|

t.integer “account_id”

t.string “day_of_week”

t.string “begins”

t.string “ends”

end

end

So an account might have one opening_hour for Monday (:day_of_week =>
“Monday”, :opens =>“9am”, :closes => “5pm”), two for Tuesday
([:day_of_week => “Tuesday”, :opens => “9am”, :closes => “12pm”],
[:day_of_week => “Tuesday”, :opens => “1pm”, :closes => “5pm”]), etc.

As I begin work on the HTML form for this schedule, I realize I’m not
sure of the best way to allow the user to add multiple objects within
one form when each object already has an attribute defined (the
day_of_week attr).

The form I’m working on should look like this:

Monday Opening Hours

[begins text_input] - [ends text_input]

Tuesday Opening Hours

[begins text_input] - [ends text_input]

[begins text_input] - [ends text_input]

Does anyone know of a standard way to handle this sort of
requirement? I’m familiar with this method1 to add multiple child
objects in a single form, but in Ryan’s example, the tasks lack any
pre-determined attribute values.

Thanks very much for your help,

Jacob P.


#2

I’ve got this figured out now. I used a nested object form1 to
handle creating/updating multiple OpeningHour records:

class Account < ActiveRecord::Base

has_many :opening_hours, :dependent => :destroy

Add attributes for each day of the week

days_of_week = %w(Monday Tuesday Wednesday Thursday Friday Saturday
Sunday)
days_of_week.each do |day_of_week|
attribute = “#{day_of_week.downcase}_opening_hours”.to_sym
has_many attribute, :class_name => “OpeningHour”, :conditions =>
{:day_of_week => day_of_week}
accepts_nested_attributes_for attribute, :allow_destroy => true
attr_accessible (attribute.to_s + “_attributes”).to_sym
end

end

In the template, loop through the available fields by using
fields_for:

<%- form_for account do |f| %>

<% f.fields_for :monday_opening_hours do |opening_hour| %>

 <%= opening_hour.text_field :begins %>
 to
 <%= opening_hour.text_field :ends %>

<% end %>

<%- end %>

-Jacob P.


#3

This was really useful. Thanks for leaving info on how you did it.