Problem with nested form has_many through using dynamic form

0

I'm having the following problem on a form using has_many through.

I have a registration where I created dynamic forms. These dynamic forms are inserted in another screen.

I'm having difficulty in the controller where I insert these fomularies and in the view that I make the insertion.

Appointments - > where I can have lots of dynamic forms (record_forms) Record_Forms - > dynamic forms registration Record_Form_Fields - > dynamic form fields Appointment_Record_Forms - > table for relationship between Appointments and Record_Forms

Schema

create_table "appointment_record_forms", force: :cascade do |t|
    t.integer  "appointment_id", limit: 4
    t.integer  "record_form_id", limit: 4
    t.datetime "created_at",                   null: false
    t.datetime "updated_at",                   null: false
    t.text     "properties",     limit: 65535
  end

  create_table "appointments", force: :cascade do |t|
    t.string   "duration",         limit: 255
    t.date     "appointment_date"
    t.integer  "patient_id",       limit: 4
    t.integer  "doctor_id",        limit: 4
    t.datetime "created_at",                   null: false
    t.datetime "updated_at",                   null: false
  end

  create_table "record_form_fields", force: :cascade do |t|
    t.string   "name",           limit: 255
    t.string   "field_type",     limit: 255
    t.boolean  "required"
    t.integer  "record_form_id", limit: 4
    t.datetime "created_at",                 null: false
    t.datetime "updated_at",                 null: false
  end

  create_table "record_forms", force: :cascade do |t|
    t.string   "name",       limit: 255
    t.datetime "created_at",             null: false
    t.datetime "updated_at",             null: false
  end

Models

class Appointment < ActiveRecord::Base
  belongs_to :patient
  belongs_to :doctor

  has_many   :appointment_record_forms, dependent: :destroy
  has_many   :record_forms, through: :appointment_record_forms
  has_many :record_form_fields

  accepts_nested_attributes_for  :appointment_record_forms, allow_destroy: true
 end

class AppointmentRecordForm < ActiveRecord::Base
  belongs_to :appointment
  belongs_to :record_form

  serialize :properties, Hash

  def validate_properties
    record_form.record_form_fields.each do |record_form_field|
      if record_form_field.required? && properties[record_form_field.name].blank?
        errors.add record_form_field.name, "must not be blank"
      end
    end
  end
end

class RecordForm < ActiveRecord::Base
    has_many :record_form_fields

    has_many :appointment_record_forms, dependent: :destroy
    has_many :appointments, through: :appointment_record_forms

    accepts_nested_attributes_for :record_form_fields, allow_destroy: true

end

class RecordFormField < ActiveRecord::Base
  belongs_to :record_form
end

**Controller**


class AppointmentsController < ApplicationController

.
.
.
def appointment_params
      params.require(:appointment).permit(:duration, :appointment_date, :patient_id, :doctor_id,
                                           :record_form_ids, :appointment_form_ids
          )
    end
end

View

Appointments / _form.html.erb

<!-- onde escolho um formulario dinamico e clico para inseri-lo -->

...
<%= f.fields_for :appointment_record_forms do |builder| %>
    <%= f.select_tag :record_form_id, options_from_collection_for_select(RecordForm.all, :id, :name) %>
    <%= render 'appointment_record_form_fields', f: builder %>
  <% end %>
  <%= link_to_add_fields "Add Field", f, :appointment_record_forms %>
....

Partial

Appointments / _appointment_record_form_fields.html.br

<!-- Aqui é onde eu carrego os campos do formulario dinamico e salvo e busco os valores desses campos atraves do hash 'properties' --> 

 <fieldset>  
  <%= f.fields_for :properties, OpenStruct.new(@appointment_record_forms.properties) do    |builder| %>
    <% @appointment_record_forms.record_form.record_form_fields.each do |record_form_field| %>

      <%= render "appointments/fields/#{record_form_field.field_type}", record_form_field: record_form_field, f: builder %>
    <% end %>
  <% end %>

  <%= f.hidden_field :_destroy %>
  <%= link_to "remove", '#', class: "remove_fields" %>
</fieldset>

Currently running the application has the error:

undefined method 'properties' for :appointment_record_forms:Symbol

I would like to know how I should do in the appointment controller to receive the join, in the view to insert the dynamic form and Partial to list saving the hash record and display the form fields correctly.

From now on I thank you if anyone can help.

    
asked by anonymous 22.06.2016 / 17:19

1 answer

1

first

class RecordForm < ActiveRecord::Base
    has_many :record_form_fields

    has_many :appointment_record_forms, dependent: :destroy
    has_many :appointments, through: :appointment_record_forms

    accepts_nested_attributes_for :record_form_fields, allow_destroy: true
     

you do accepts_nested from record_form_fields and not appointment_record_forms

end

second

<%= f.fields_for :appointment_record_forms do |builder| %>
     

You call by appointment_record_forms without having accepts_nested

    <%= f.select_tag :record_form_id, options_from_collection_for_select(RecordForm.all, :id, :name) %>

    <%= render 'appointment_record_form_fields', f: builder %>

    <% end %>
    <%= link_to_add_fields "Add Field", f, :appointment_record_forms %>
....

I do not think serializing the hash should be instantiating this way. I do something like this down

= form_for @widget do |f|
  = f.fields_for :options, OpenStruct.new(f.object.options || {}) do |f2|
    = f2.text_field :axis_y
    = f2.text_field :axis_x
    = f2.text_field :unit

link

What's in here? @appointment_record_forms.properties

third and most important, start at baby-steps.

Make the /_appointment_record_form_fields.html.br view first work without these nested form all. Comment everything else by leaving the renders or put it below in the views/appoiment..../new without the rest of the forms and fields_for

<%= form_for AppointmentRecordForm.new do |f| %>
   <%= f.fields_for :properties, OpenStruct.new(AppointmentRecordForm.new.properties || {} ) do    |ff| %>
     <%= ff.text_field :coluna_do_properties_1 %>
     <%= ff.text_field :coluna_do_properties_2 %>
    <% end %>
  <% end %>
    
02.08.2016 / 11:14