Home>

I want to implement a function to create a post with information in multiple locations. (Multiple spots for one post)
for that reason,
(1) Duplicate a part (fields_for part) of the new post form and place it with the values ​​initialized.
(2) Save all fields_for data as a separate record, including the copy source form.
I want to do the process, but I'm addicted to it because I don't know how to do it.

In particular,
Clicking "Add Form" will add a clone of the surrounding fields_for below with the entered values ​​initialized.
When you click the "Post" button, the data of all forms on the page will be saved (post and all spots associated with it). I am assuming that.

The spot model has a post_id attribute, and records with the same post_id are linked to one post.

In the current code,
-The added form will be added with the values ​​entered in the copy source form remaining.
・ When a form is added, only the data of the last added form is saved.
(The copy source or the form between the copy source and the last form is not saved)

Corresponding source code

post.rb

belongs_to: user
  has_many: spots, dependent:: destroy
  accepts_nested_attributes_for: spots
  mount_uploader: image, ImageUploader


spot.rb

belongs_to: post
  mount_uploader: image, ImageUploader
  validates: title, length: {maximum: 30}
  #validates: post_id, presence: true
  validates: content, presence: true, length: {maximum: 140}
  validate: image_size
  #Convert address and save latitude in latitude and longitude in longitude
  geocoded_by: address
  after_validation: geocode


posts_controller.rb

def new
    @post = Post.new
    @ post.spots.build
  end
def create
    @post = current_user.posts.build (post_params)
    @ post.save
    redirect_to root_path
  end
def post_params
    params.require (: post) .permit (: content, spots_attributes: [: address,: image,: content,: title])
  end


posts/new.html.erb


   Post 
<% = form_with model: @post do | f |%>
    
    <% = f.text_area: content, placeholder: "post.content"%><br>
      
        
        <% = f.fields_for: spots do | s |%>
          <% = s.text_field: title, placeholder: "title"%><br>
          <% = s.text_field: address, placeholder: "address"%><br>
          <% = s.text_area: content, placeholder: "spot.content"%>
          <span>
            <% = s.file_field: image, accept:'image/jpeg, image/gif, image/png'%>
          </span><br>
        <% end%>
        
      
    
     Add form 
  <% = f.submit "Post", class: "btn btn-primary"%>
<% end%>

<!-Add Form->
<script>
$(function () {
  $('# add-form'). on ('click', function () {
    var clone = $('#forms .spot-form: first'). clone (true);
    clone.appendTo ('#forms')
  });
});
</script>

spots table

t.string: title
t.text: content
t.string: image
t.string: address
t.float: latitude
t.float: longitude
t.references: post, foreign_key: true
t.timestamps


post table

t.text: content
t.references: user, foreign_key: true
What I tried

If i copy and paste the fields_for part without using jQuery or plain JavaScript and make multiple forms prepared from the beginning, the data of all the forms will be saved.

Supplement

Sorry for the confusing post and spot ...
Please point out any points that are difficult to understand or missing information.

  • Answer # 1

    As I wrote in the previous comment, I think that it can be easily implemented using cocoon.
    https://qiita.com/hitochan/items/5a45a95e644492d66160


    Because it's a big deal. .. ..
    For the future as well, I think you should check "what is happening" by the following method.

    Approach ① ~ Code comparison ~

    Right-click Chrome ⇒ Display the page source with "Multiple forms prepared from the beginning", and then paste it to https://difff.jp/.
    Next, paste the source of "When the same number of forms are added with jQuery" above and compare.

    ⇒ You can see why ...


    Approach ② ~ Code comparison ~

    Try debugging what values ​​are being sent from the form.
    I don't see the description debugged from the question, so if you don't know how to do it, you should learn it once.

    Reference: How to debug