0

I'm working on a small project in Rails loosely following the Rails Tutorial. I have Carrierwave, Fog, and AWS working wonderfully on production for uploading a single image. I wanted to add a gallery of images, so I figured I would follow SSR's answer in the link: Rails 4 multiple image or file upload using carrierwave

Everything seems to work well for my model, and the tests even pass, but when I go to create or edit a listing, the uploader doesn't seem to work. It will hang for minutes without resolving (even on small file sizes), and the console doesn't read that an action was posted on submitting (just reads 200 for the last GET for the form itself). Other than naming conventions (I use Listing as the Post model and listing_gallery instead of post_attachment), the steps were identical. Did Rails 5 change anything about Carrierwave?

listing.rb

class Listing < ApplicationRecord
VALID_PHONE_REGEX = /(\(*(\d{3})\)|(\d{3}-)|(\d{3}))\s*(\d{3})-*(\d{4})/
VALID_ZIP_REGEX = /\d{5}((-)?\d{4})?/

# One use has many listings
belongs_to :user

# Listing_gallery
has_many :listing_galleries
accepts_nested_attributes_for :listing_galleries

# Descending order from newest to oldest as default
default_scope -> { order(created_at: :desc) }

# Carrier Wave mount uploader for images
mount_uploader :picture, PictureUploader
mount_uploader :image, PictureUploader

# Validation of parameters before accepting listing
validates :user_id, presence: true
validates :description, presence: true
validates :street_address, presence: true
validates :city, presence: true, length: { maximum: 30 }
validates :zip_code, presence: true, length: {minimum: 5, maximum: 10}, format: { with: VALID_ZIP_REGEX }
validates :primary_contact, presence: true, length: {minimum: 10, maximum: 15}, format: { with: VALID_PHONE_REGEX }


end

listings_controller.rb

class ListingsController < ApplicationController
before_action :logged_in_user, only: [:new, :create, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]

def new
    @listing = Listing.new
    @listing_gallery = @listing.listing_galleries.build
end

def create
    if current_user.admin?
        @listing = current_user.listings.build(listing_params)
        @listing.listing_status = "active"

        respond_to do |format|
            if@listing.save!
                params[:listing_galleries]['image'].each do |image|
                    @listing_gallery = @listing.listing_galleries.create!(:image => image)
                end

                flash[:success] = "New Listing created!"
                redirect_to root_url
            else
                render 'new'
            end
        end
    else
        flash[:failure] = "You must be an admin to create a listing."
        redirect_to root_url
    end
end

def show
  @listing = Listing.find(params[:id])
  @listing_galleries = @listing.listing_galleries.all
end

def edit
    if current_user.admin?
        @listing = Listing.find(params[:id])
        render 'edit'
    end
end

def update
    if current_user.admin?
        @listing = Listing.find(params[:id])

        respond_to do |format|
            if @listing.update_attributes(listing_params)
                if params[:listing_galleries] != []
                    params[:listing_galleries]['image'].each do |image|
                        @listing_gallery = @listing.listing_galleries.create!(:image => image)
                    end
                end

                flash[:success] = "Listing Updated!"
                redirect_to @listing
            else
                render 'edit'
            end
        end
    end
end

def destroy
    if current_user.admin?
        @listing.listing_status = "deleted"

        if @listing.save!
            flash[:success] = "Listing DELETED"
            redirect_to request.referrer || root_url
        else
            flash[:failure] = "Could not remove listing"
            redirect_to request.referrer || root_url
        end
    end
end

private

# Check for necessary paramters
def listing_params
    params.require(:listing).permit(:description, :street_address, :city, :state,
                                    :zip_code, :primary_contact, :secondary_contact,
                                    :listing_status, :asking_price, :renobb, :picture,
                                    { image: [] },
                                    listing_galleries_attributes: [:id, :listing_id, :image, :_destroy])
end

# Ensure only the creator of the listing is destroying it
def correct_user
    @listing = current_user.listings.find_by(id: params[:id])

    if current_user.admin?
        return true
    end

    redirect_to root_url if @listing.nil?
end

end

listings/new.html.erb

<% provide(:title, 'Create Listing') %>

<div id="content">

<div id="sectionbanner">
    <p class="goldtext">
        Create a New Listing
    </p>
</div>

<!-- Article -->
<div id="article">

    <div class="form">
        <%= form_for(@listing, html: { multipart: true}) do |form| %>
            <%= render 'shared/error_messages_listings' %>

            <%= form.label :street_address %>
            <br>
            <%= form.text_field :street_address, class: 'form-control' %>

            <br>
            <%= form.label :city %>
            <br>
            <%= form.text_field :city, class: 'form-control' %>

            <br>
            <%= form.label :state %>
            <br>
            <%= form.text_field :state, class: 'form-control' %>

            <br>
            <%= form.label :zip_code %>
            <br>
            <%= form.text_field :zip_code, class: 'form-control' %>

            <br>
            <%= form.label :primary_contact %>
            <br>
            <%= form.text_field :primary_contact, class: 'form-control' %>

            <br>
            <%= form.label :secondary_contact %>
            <br>
            <%= form.text_field :secondary_contact, class: 'form-control' %>

            <br>
            <%= form.label :asking_price %>
            <br>
            <%= form.number_field :asking_price, class: 'form-control' %>

            <br>
            <%= form.label :description %>
            <br>
            <%= form.text_area :description, placeholder: "Details of the lot, rules, etc..." %>

            <br>
            <%= form.label :renobb %>
            <br>
            <%= form.check_box :renobb %>

            <br>
            <span class="picture">
                <%= form.file_field :picture, accept: 'image/jpeg, image/gif, image/png' %>
            </span>

            <br>
            <%= form.label :image %>
            <br>
            <%= form.file_field :image, :multiple => true, name: "listing_galleries[image][]" %>

            <br>
            <%= form.submit "Create Listing", class: "button" %>

        <% end %>
    </div>

</div>

</div>

listing_gallery.rb

class ListingGallery < ApplicationRecord

belongs_to :listing

mount_uploader :image, PictureUploader


end

listing_galleries_controller.rb

class ListingGalleriesController < ApplicationController
before_action :set_listing_gallery, only: [:show, :edit, :update, :destroy]

# GET /listing_galleries
# GET /listing_galleries.json
def index
@listing_galleries = ListingGallery.all
end

# GET /listing_galleries/1
# GET /listing_galleries/1.json
def show
end

# GET /listing_galleries/new
def new
@listing_gallery = ListingGallery.new
end

# GET /listing_galleries/1/edit
def edit
end

# POST /listing_galleries
# POST /listing_galleries.json
def create
@listing_gallery = ListingGallery.new(listing_gallery_params)

respond_to do |format|
  if current_user.admin?
    if @listing_gallery.save
      format.html { redirect_to @listing_gallery, notice: 'Listing gallery was successfully created.' }
      format.json { render :show, status: :created, location: @listing_gallery }
    else
      format.html { render :new }
      format.json { render json: @listing_gallery.errors, status: :unprocessable_entity }
    end
  end
end
end

# PATCH/PUT /listing_galleries/1
# PATCH/PUT /listing_galleries/1.json
def update
respond_to do |format|
  if current_user.admin?
    if @listing_gallery.update(listing_gallery_params)
      format.html { redirect_to @listing_gallery, notice: 'Listing gallery was successfully updated.' }
      format.json { render :show, status: :ok, location: @listing_gallery }
    else
      format.html { render :edit }
      format.json { render json: @listing_gallery.errors, status: :unprocessable_entity }
    end
  end
end
end

# DELETE /listing_galleries/1
# DELETE /listing_galleries/1.json
def destroy
  if current_user.admin?
    @listing_gallery.destroy
    respond_to do |format|
    format.html { redirect_to listing_galleries_url, notice: 'Listing   gallery was successfully destroyed.' }
    format.json { head :no_content }
  end
end
end

private
# Use callbacks to share common setup or constraints between actions.
def set_listing_gallery
  @listing_gallery = ListingGallery.find(params[:id])
end

# Never trust parameters from the scary internet, only allow the white list through.
def listing_gallery_params
  params.require(:listing_gallery).permit(:listing_id, :image, { image: [] },  :_destroy)
end
end

EDIT More files from the controllers and views. (Alignment may be funky on SO, but it's alright in project.)

Community
  • 1
  • 1

2 Answers2

0

I really don't know if this is a typo, but your problem is on line 1 of your view.

%= form_for(@listing, html: { mulipart: true}) do |form| %>

You are also missing the spelling of Multipart which I suppose is the reason you couldn't upload multiple pictures.

Change it to:

<%= form_for(@listing, html: { multipart: true}) do |form| %>

For more insight, refer to Multiple File Uploads section of Carrierwave Documentation.

Afolabi Olaoluwa
  • 1,898
  • 3
  • 16
  • 37
0

For multiple image upload you need to add this gem to your gemfile

gem 'carrierwave', github: 'carrierwaveuploader/carrierwave'

and permit the params as an open array in your controller: {image: []} Check gem documentation for more details https://github.com/carrierwaveuploader/carrierwave

You also seem to have an uploader 'image' which you are not mounting in your model. You only mount 'picture'.

KcUS_unico
  • 513
  • 3
  • 9
  • Added the gem, ran the bundle install with no errors, and added the notes you pointed out in every combination between the controllers I could think of, and it's still acting the same. x.x I appreciate the tips. Any other thoughts? – Brittany Mcgarr Feb 21 '17 at 00:08
  • What is the error you get or what is happening? Can you please update your model and controller here so we can see the changes you have made? please also update the form if you have made changes and may be the uploader. Which param are you using for multiple file upload? – KcUS_unico Feb 21 '17 at 09:51
  • Updated the text with the changes (although, I tried adding/removing :images every which way). I'm not getting any sort of response, even on the command line. It just hangs as if it's trying to upload the images. Followed both instruction sets almost to the T. Thanks for looking at all that. – Brittany Mcgarr Feb 21 '17 at 21:35