Forum: Ruby on Rails form selection- nested attributes

F099abfef46715b41b4d3d0e5764e697?d=identicon&s=25 Sean Kelley (Guest)
on 2014-08-24 16:31
(Received via mailing list)
I am working on my first rails project using rails 4.1x and cocoon
<https://github.com/nathanvda/cocoon> for nested forms,and formtastic
<https://github.com/justinfrench/formtastic> .    I am not sure if my
problem is just form related or also a problem with models.
A 'user' adds 1 or more 'entries.'  Each entry has 1 or more 'rides'.
Each
ride can have only 1 'horse' . A horse will be related to many rides.
 Saving and retrieving the related horse in create and edit forms is my
problem.

My form currently saves entry (date), ride (test), and new horse (via
cocoon link_to_add_association) correctly.  My ability to select
existing
horses for new rides or for editing is not working.

Right now my new entry does not have existing horse select available
when I
click to add ride.  I can only add new horse. When editing an existing
horse, existing horse select shows select with horse name and id, but
does
mark existing value as selected.  It saves incorrect names/ids to params
so
really the line in view is a placeholder to place correct select code.

params on new entry create with new horse:
{"utf8"=>"√", "authenticity_token"=>"xxxx=",
"entry"=>{"show_date"=>"2014/10/26",
"rides_attributes"=>{"1408889669745"=>{"test"=>"Intro B",
"horse_attributes"=>{"name"=>"aa"}}}}, "commit"=>"Create Entry",
"action"=>"create", "controller"=>"entries"}

attempting to edit same entry attempts to set name to id of previous
horse.
 I have tried many variations on select but have not figured it out :
{"utf8"=>"√", "_method"=>"patch", "authenticity_token"=>"xxxx=",
"entry"=>{"show_date"=>"2014/10/26",
"rides_attributes"=>{"0"=>{"test"=>"Intro B",
"horse_attributes"=>{"name"=>"43", "id"=>"44"}, "id"=>"72"}}},
"commit"=>"Update Entry", "action"=>"update", "controller"=>"entries",
"id"=>"75"}

In my views:

_form.html.haml:

= semantic_form_for @entry do |f|
  = f.inputs do
    = f.input :show_date, :as => :select, :collection => ['2014/08/03',
'2014/09/14', '2014/10/26', '2014/11/15']
    %h3 Rides
    #rides
      = f.semantic_fields_for :rides do |ride|
        = render 'ride_fields', :f => ride
      .links
        = link_to_add_association 'add ride', f, :rides

  = f.actions do
    = f.action :submit

_ride_fields.html.haml:

.nested-fields
  = f.inputs do
    = f.label :test, "Test"
    = f.input :test, :as => :select, :collection => [['Intro A', 'Intro
A'], ['Intro B', 'Intro B'], ['Intro C', 'Intro C']]

    #shows existing horses to choose
    = if !@horses.empty?
      = f.semantic_fields_for :horse do |horse|
        = horse.input :name, :as => :select, :collection => @horses

    -# shows new horse form elements immediately if user has no horses
    = if @horses.empty?
      = f.semantic_fields_for :horse do |horse|
        = render 'horse_fields', :f => horse

    .links
      = link_to_add_association 'add new horse', f, :horse

partial entries_controller:

class EntriesController < ApplicationController
  before_action :set_entry, only: [:show, :edit, :update, :destroy]
  before_filter :set_horses, :except => [:destroy, :index]


  def new
    @user=current_user
    @entry = current_user.entries.new
  end

  def create
      @entry = current_user.entries.new(entry_params)
      respond_to do |format|
      if @entry.save
format.html { redirect_to @entry, notice: 'Entry was successfully
created.'
}
        format.json { render :show, status: :created, location: @entry }
      else
        format.html { render :new }
        format.json { render json: @entry.errors, status:
:unprocessable_entity }
      end
    end
  end

  def update

    respond_to do |format|
      if @entry.update(entry_params)
        format.html { redirect_to @entry, notice: 'Entry was
successfully
updated.' }
        format.json { render :show, status: :ok, location: @entry }
      else
        format.html { render :edit }
        format.json { render json: @entry.errors, status:
:unprocessable_entity }
      end
    end
  end


  private
    # Use callbacks to share common setup or constraints between
actions.
    def set_entry
      @entry = Entry.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the
white
list through.
    def entry_params
  params.require(:entry).permit(:show_date, rides_attributes: [:id,
:test,
 :_destroy, horse_attributes: [:name, :id]] )
    end

    def set_horses
     id = current_user[:id]
     if current_user.admin?
       @horses=Horse.all
     else
@horses = current_user.horses
     end
    end

end

my models:

class Entry < ActiveRecord::Base
  belongs_to :user
  has_many :rides, :dependent => :destroy
  has_many :horses, :through => :rides, :dependent => :destroy

  accepts_nested_attributes_for :rides, :reject_if => lambda { |a|
a[:test].blank? }, :allow_destroy => true
  accepts_nested_attributes_for :horses #, :reject_if => lambda { |a|
a[:name].blank? }, :allow_destroy => true

  validates_presence_of :show_date
end

class Ride < ActiveRecord::Base
  belongs_to :entry, inverse_of: :entry
  belongs_to :horse
  belongs_to :user, inverse_of: :user

  accepts_nested_attributes_for :horse
end

class Horse < ActiveRecord::Base
  has_many :rides
  belongs_to :user, :dependent => :destroy
end


Incidentally, as I type this question I realized another problem I will
have once it works:

I can add more than one ride to each entry.  The second ride, for
example,
could have the same horse again but it has not yet been created until
this
form is submitted to create the entry.  How can I add horse to db
immediately, without leaving this entry form so that horse is available
for
next added ride?

I will also need to hide existing horses select if user opts to add new
(however I think this may be covered in cocoon docs or howto)

<https://lh3.googleusercontent.com/-UldCRXjV6Hs/U_Z...
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.