1

I'm trying to take the idea of adding a picture to a post from Rails Tutorial, and extending it to my needs. I have a Guide, which can have many pictures associated with it, not just one like in the tutorial.

I want there to be one button to upload a picture. A user should be able to use this button repeatedly to upload multiple pictures.

I'm trying to use accepts_nested_attributes, like in this answer, but I'm not sure how to use it: Rails 4 multiple image or file upload using carrierwave

My Guide model:

class Guide < ActiveRecord::Base
  belongs_to :user
  has_many :guide_pics, dependent: :destroy
  accepts_nested_attributes_for :guide_pics
end

My GuidePic model:

class GuidePic < ActiveRecord::Base
  belongs_to :guide
  validates :guide_id, presence: true

  default_scope -> { order(created_at: :desc) }

  mount_uploader :picture, PictureUploader
end

My edit view renders the picture uploader, which allows me to select a picture. I don't think I need to show the code for it, but I can provide it if necessary. When I click upload, it goes into my Guide controller. I have nothing in my GuidePics controller.

I think my Guide controller has to update the picture, which I'm trying to do with a call to guide_params

@guide.update_attributes guide_params

But I don't understand what my guide_params function needs to be. What I have give me an error "unpermitted parameter: picture" :

def guide_params
   params.require(:guide).permit(:name, :city, :province, :country, :description, 
                                guide_pics_attributes: [:id, :guide_id, :picture]) 
end

Also, here is my form for uploading pictures:

<!-- Upload pictures -->
<div class="col-md-2 col-md-offset-1">
   <strong>Upload A Picture</strong>
</div>
<div class="col-md-8 guide-edit-form guide-pic-upload">
  <%= form_for(@guide, html: { multipart: true }) do |f| %>
    <div class="picture" style="float:left;">
      <%= f.file_field :picture %>
    </div>
    <div style="">
      <%= f.submit "Upload", class: "btn btn-primary edit-guide-btn" %>
  </div>
  <% end %>
</div>

The problem was with my form. Here is the solution, based on Matt's answer:

<!-- Upload pictures -->
<div class="col-md-2 col-md-offset-1">
   <strong>Upload A Picture</strong>
</div>
<div class="col-md-8 guide-edit-form guide-pic-upload">
  <%= form_for(@guide, html: { multipart: true }) do |f| %>
    <%= f.fields_for :guide_pics, @guide.guide_pics.build do |p| %>
      <div class="picture" style="float:left;">
        <%= p.file_field :picture %>
      </div>
    <% end %>
    <div style="">
      <%= f.submit "Upload", class: "btn btn-primary edit-guide-btn" %>
  </div>
  <% end %>
</div>
Community
  • 1
  • 1
Terrytreks
  • 266
  • 3
  • 11

1 Answers1

1

Read the guide you linked again, you need to use fields_for for the child item component of the form:

<%= form_for(@post, :html => { :multipart => true }) do |f| %>
    <div class="field">
        <%= f.label :title %><br>
        <%= f.text_field :title %>
    </div>

    <%= f.fields_for :post_attachments do |p| %>
        <div class="field">
            <%= p.label :avatar %><br>
            <%= p.file_field :avatar, :multiple => true, name: "post_attachments[avatar][]" %>
        </div>
    <% end %>

    <div class="actions">
        <%= f.submit %>
    </div>
<% end %>

So in your case, more like:

<%= form_for(@guide, html: { multipart: true }) do |f| %>
    <%= f.fields_for :post_attachments do |p| %> 
        <div class="picture" style="float:left;">
            <%= p.file_field :picture %>
        </div>
    <% end %>
    <div style="">
        <%= f.submit "Upload", class: "btn btn-primary edit-guide-btn" %>
    </div>
<% end %>
Matt
  • 13,948
  • 6
  • 44
  • 68