2

I have been trying to figure out how to upload multiple images to one model through a nested model for a while now with no luck. I have a Project model, and for each project i would like to upload multiple images. I created a model called Picture and nested it within the Project model, and have set up paperclip and everything seems fine except when I upload an image and click on "Create project", the image does not show on the "show" page. There is no error message displayed. Please help as I do not know how to proceed from here.

here is my code:

Project form:

<%= bootstrap_nested_form_for @project, :html => {:multipart => true}  do |f| %>

 <% f.fields_for :pictures do |builder| %>
    <% if builder.object.new_record? %>

      <p>
        <%= builder.file_field :image %>
      </p>

    <% end %>
    <%= builder.link_to_remove "Remove" %>
  <% end %>

  <p>
   <%= f.link_to_add "Add Images", :pictures %>
 </p>

 <%= f.submit %>
<% end %>

Project controller:-

class ProjectsController < ApplicationController
  before_action :set_project, only: [:show, :edit, :update, :destroy]

  respond_to :html

  def index
    @projects = Project.all
    respond_with(@projects)
  end

  def show
    respond_with(@project)
  end

  def new
    @project = Project.new
    @project.pictures.build
    respond_with(@project)
  end


  def edit
  @project = Project.find(params[:id])
  @project.pictures.build
  end

  def create

    @project = Project.new(project_params)
    if @project.save
    flash[:notice] = "Successfully created project."
    redirect_to @project
    else
    render :action => 'new'
    end

  end

  def update
    @project.update(project_params)
    respond_with(@project)
  end

  def destroy
    @project.destroy
    respond_with(@project)
  end

  private
    def set_project
      @project = Project.find(params[:id])
    end

    def project_params
      params.require(:project).permit(:id, :title, :description, :status, :phase, :location, pictures_attributes: [:id, :image])
    end
end

Projects model:-

class Project < ActiveRecord::Base

  has_many :pictures, :dependent => :destroy
    accepts_nested_attributes_for :pictures, :reject_if => lambda { |t| t['picture'].nil? }

end

Pictures model:-

class Picture < ActiveRecord::Base
 belongs_to :project
 has_one :image

 has_attached_file :image,
:path => ":rails_root/public/system/:attachment/:id/:style/:filename",
:url => "/system/:attachment/:id/:style/:filename", 
:styles => { :medium => "300x300>", :thumb => "100x100>" }

 validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]

end

Show page:-

<% @project.pictures do |picture| %>

  <%= image_tag picture.image_url %>
<% end %>

<p>
  <strong>Title:</strong>
  <%= @project.title %>
</p>

<p>
  <strong>Description:</strong>
  <%= @project.description %>
</p>

<p>
  <strong>Status:</strong>
  <%= @project.status %>
</p>

<p>
  <strong>Phase:</strong>
  <%= @project.phase %>
</p>

<p>
  <strong>Location:</strong>
  <%= @project.location %>
</p>

<%= link_to 'Edit', edit_project_path(@project) %> |
<%= link_to 'Back', projects_path %>

schema :-

ActiveRecord::Schema.define(version: 20150728092717) do

create_table "pictures", force: true do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "image_file_name"
    t.string   "image_content_type"
    t.integer  "image_file_size"
    t.datetime "image_updated_at"
    t.integer  "project_id"
  end

  add_index "pictures", ["project_id"], name: "index_pictures_on_project_id"
create_table "projects", force: true do |t|
    t.string   "title"
    t.text     "description"
    t.string   "status"
    t.string   "phase"
    t.string   "location"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
2
  • If the image is created then you are displaying it wrong. This <%= image_tag picture.image_url %> should be <%= image_tag picture.image.url(:medium) %> Commented Jul 28, 2015 at 11:53
  • tried this but still the images are not showing. Any ideas what else might be causing the issue? Commented Jul 29, 2015 at 5:42

1 Answer 1

1

Your form and whitelist uses the property name image.

But you are rejecting any nested pictures if they don't have the picture param.

accepts_nested_attributes_for :pictures, :reject_if => lambda { |t| t['picture'].nil? }

Nested attributes params are not wrapped in a "model key" like rails form params usually are. This is what they look like:

params = {
  project: {
    pictures_attributes: [
      {
        image: 'foo.jpg'
      }
    ]
  }
}

You can catch these kind of errors quite simply with model specs:

require 'rails_helper'
RSpec.describe Project do
  it 'accepts nested pictures' do
     project = Project.new(pictures_attributes: [{ image: 'foo.jpg' }])
     expect(project.pictures.first).to to_be_a Picture
  end
end
Sign up to request clarification or add additional context in comments.

3 Comments

I don't think you should be doing has_one :image and has_attached_file :image. I haven't used paperclip but it does not really make sense at all since paperclip stores on the disk, not in an ActiveRecord model.
Hey thanks for taking the time to answer. I am still not exactly sure how to go about solving the problem though. I am quite new to rails and coding in general so I dont really know how to use model specs. Where should I implement the params code you mentioned?
Is there something I should add/change with the create action in my project controller?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.