Search code examples
ruby-on-railsruby-on-rails-3formtasticnested-attributes

saving the child fields on a failed validation?


I am using formtastic like this

class Court < ActiveRecord::Base
  belongs_to :tournament    
end

class Tournament < ActiveRecord::Base
  has_many  :courts, :dependent => :destroy
  accepts_nested_attributes_for :courts, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
  validates :name, :presence => true, :length => { :maximum => 100 }
end

and all works fine but on a failed validation of the tournament form the courts that were created are not preserving on a failed form.

here is my controller

def new
  @tournament = Tournament.new
  1.times do
    @tournament.courts.build
  end

def create
  @tournament = Tournament.new(params[:tournament])

i assumed that i could do something like this in the create but no go

    if params[:tournament][:courts_attributes]
         params[:tournament][:courts_attributes].each { |attribute| 
             @tournament.courts.build(attribute)
        }
      end


<%= semantic_form_for @tournament do |f| %>
  <%= f.inputs do %>
    <%= f.input :number_courts, :hint => "How many courts are available?" %>

        <%= f.semantic_fields_for :courts do |builder| %>
            <%= render :partial => "court_fields", :locals => { :f => builder } %>
            <span class="links">
             <%= link_to_add_fields "Add More Court", f, :courts %>
            </span>
        <% end %>

partial

<div class="nested_fields">
<%= f.input :name %>
<%= f.input :address %>
<%= f.input :city %>
<%= f.input :state %>
<%= f.input :zip %>
<%= f.input :phone %>
<%= f.input :contact_name %>
<%= link_to_remove_fields "Remove Court", f %>
</div>

UPDATE---

here is my create action

def create
  @tournament = Tournament.new(params[:tournament])
  respond_to do |format|
    if @tournament.save
      format.html { redirect_to @tournament, notice: 'Tournament was successfully created.' }
      format.json { render json: @tournament, status: :created, location: @tournament }
    else
      format.html { render action: "new" }
        end

also here there the params just in case that will help

Processing by TournamentsController#create as HTML
 Parameters: {"utf8"=>"✓", "authenticity_token"=>"xv+p7QdpkJdEUaTGqrKue63869hlwh3Zv1xvkO5qx6A=", "tournament"=>{"name"=>"", "sport_id"=>"1", "entry_fee"=>"", "start_date"=>"", "end_date"=>"", "number_courts"=>"", "courts_attributes"=>{"0"=>{"name"=>"hello", "_destroy"=>"false"}, "1318725283928"=>{"name"=>"asdfsadfas", "_destroy"=>"false"}, "1318725286739"=>{"name"=>"asdfasdfa", "_destroy"=>"false"}}, "available_times"=>"", "available_end_times"=>"", "min_games"=>"", "time_allowed"=>"1:15", "number_teams_per_bracket"=>"1", "gender_id"=>"1", "entry_deadline"=>"", "age_limit"=>"", "rules"=>"", "coach_meeting"=>"0", "meeting_location"=>"", "meeting_date"=>"", "future_tournament"=>"0", "private_service"=>"0", "add_blog"=>"0"}, "commit"=>"Create Tournament"}

any ideas on how to preserve the data over a failed validation


Solution

  • I assume that when you try to create a Tournament, and the validation fails, its child Courts are not actually created. What you want is for the Court data that was entered on the Tournament form to be preserved across creation attempts. Does that sound correct?

    I haven't used formatastic. However, if its API is really just comprised of wrappers around Rails form helpers, then I would give this a shot:

        <%= f.semantic_fields_for :courts do |builder| %>
            <%= render :partial => "court_fields", :collection => @tournament.courts, :locals => { :f => builder } %>
            <span class="links">
             <%= link_to_add_fields "Add More Court", f, :courts %>
            </span>
        <% end %>    
    

    Notice the change to the rendering of the court fields partial.

    When you attempt to create a tournament, this should render the court you built in TournamentsController.new. When the attempt fails, it should render the courts that were input during the first attempt.