Rails nested polymorphic form with javascripting

谁说我不能喝 提交于 2019-12-12 10:19:33

问题


I want the following on my form:

Degree is polymorphic partial with has_many relation to profile. This partial is called by main form - profile. By pressing 'Add a Qualification' user can add as many degrees. I've been able to attach only one degree to profile which is the last one others are all ignored. I even know why it's happening because link_to is not able to pass profile instance. so I have to create new profile in degrees_controller as you can see in my code here. Can final profile instance pick up all others above when submitting 'Create Profile'.

Kindly any help so that I can have all of the degrees attached with form, I'm stuck on this for last couple of days with all permutations and combinations from SO and google. I'm ready to change code even....any help with this will be appreciated.


回答1:


I've got this little helper to get me through these cases. Its reusable so you don't ever have to write all this stuff for different cases in the same app.

First the code:

module FormsHelper

  def data_for_field(f, subclass, options={})
    new_object = f.object.class.new.send(subclass.to_s).new(options[:attributes])
    id = new_object.object_id
    partial_path = options[:path] || new_object
    fields = f.fields_for(subclass, new_object, child_index: id) do |builder|
      render(partial_path, f: builder)
    end
    {id: id, fields: fields.gsub("\n", "")}
  end

end

Some JS magic:

$(document).on('click', '.add-fields', function(e){
  var time = new Date().getTime();
  var regexp = new RegExp($(this).data('id'), 'g');
  var content = $(this).data('fields').replace(regexp, time);
  $(target).append(content);
  e.preventDefault();
});

Now a view call:

<%= form_tag .... do |f|
    <div id="list"></div>
    <%= link_to 'Add an Organisation', '#', class: 'add-fields', data: data_for_field(f, :degrees, path: "/degrees/fields").merge(target: "#list") %></p>
<% end %>

Now create a partial where the degree fields to use.

/degrees/_fields.html.erb

<%= content_tag :div do %>
  <%= f.input :name %>
<% end %>

Now the explanation:

For data_for_field you pass: f (form), :degrees (the plural name of the associated model as a symbol), and any additional options like the path to the partial for the fields. It basically creates a scaffold of the form fields and sets them as a data attribute on the "Add Qualification" link. I've merged in a data-target which has the css ID of where to insert the new fields into the page as well.

When you click the JS event fires and replaces the id in the form fields with a timestamp so for each qualification you'll have a unique key.

I also usually have a little extra JS event for removing the fields as well.

Hope this helps.




回答2:


This is a polymorphic nested association and can be handled on client side with javascript. So, finally for nested fields I used the plugin Numerous.js. Just follow as the steps given in the qucikstart part of link by downloading the numerous.js file from the Github and saving to assets/javascripts.

In my code,

profile.rb

class Profile < ApplicationRecord
  has_many :degrees, :as => :degreeable
  accepts_nested_attributes_for :degrees, :reject_if => :all_blank, allow_destroy: true

  belongs_to :user, :class_name => 'User', :foreign_key => 'user_id'
end

degree.rb

class Degree < ApplicationRecord
   belongs_to :degreeable, polymorphic: true
end

profiles/_form.html.erb

    <div id="fields-for-list" class="numerous">
      <%= f.fields_for :degrees, Degree.new, :child_index => 'replace_this' do |degree_form| %>
         <%= degree_form.select :level, options_for_select(Job::EDUCATION, params[:level]), include_blank: "Select Degree", :class => 'span5' %>
         <%= degree_form.text_field :description, placeholder: "Add a new Degree here..."%>
         <%= link_to 'x Remove', '#', :class => 'numerous-remove', type: 'button' %>
     <% end %>
   </div>
   <div id="list"></div>
   <%= link_to (fa_icon 'plus').to_s + 'Add a Qualification', '#', :id => 'add-to-list' %>

and finally, with strong parameters,

  def profile_params
    params.require(:profile).permit(:user_id, :first_name, :last_name, degrees_attributes:[:id, :level, :description])
  end

Note that I had already set-up degree table with 2 extra fields for polymorphic association:- "degreeable_id" & "degreeable_type" and when entering in DB, the two fields were automatically filled with newly created profile_id and 'Profile'(the name of the model which is associating polymorphically with degree).

The trick in numerous.js is creating each nested form record(here degree) with unique temporary id such as Time.now.to_i so now each degree record created/destroyed at client side will have a diff degree_attribute 'id'. Hope it helps others.



来源:https://stackoverflow.com/questions/42503139/rails-nested-polymorphic-form-with-javascripting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!