Reputation: 144
I am building a Rails app where I need users to upload a profile image on the registration form/have an image edit feature for profile photo. Carrierwave should be properly installed and so far Devise seems to be running fine. When I go to upload the photo and then click "Create Profile", it simply refreshes to the same page and resets the file upload field each time.
SOLUTION: Updated update method in controller to:
def update
@pet = Pet.find(params[:id])
if @pet.update(pet_params)
redirect_to pets_path
else
render :edit
end
end
It's uploaded in my app/uploaders/profile_photo_uploader.rb file:
class ProfilePhotoUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
I have a "profile_photo" string in my schema, as well.
And my controller actions for create and edit/update are here:
def create
@pet = Pet.new(pet_params)
if @pet.save
flash[:notice] = 'Your pet profile was saved!'
redirect_to pets_path
else
flash.now[:notice] = 'Your pet profile could not be saved.'
render :new
end
end
def show
@pet = Pet.find(params[:id])
end
def edit
@pet = Pet.find(params[:id])
end
def update
@pet = Pet.find(params[:id])
if @pet.save
redirect_to pets_path
else
render :edit
end
end
def pet_params
params.require(:pet).permit(:name, :breed, :age,
:color, :weight, :personality, :favorite_things, :owner_id, :profile_photo)
end
My new form using SimpleForm:
<h1>New Pet Profile</h1>
<%= simple_form_for @pet, html: { multipart: true } do |f| %>
<%= f.input :name, required: true, label: "Pet Name:" %>
<%= f.input :profile_photo, type: :file %>
...
<%= f.button :submit %>
<% end %>
Routes:
Rails.application.routes.draw do
devise_for :owners
resources :pets
resources :owners do
resources :pets, shallow: true
end
end
Application Controller:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :profile_photo
end
end
Upvotes: 0
Views: 3037
Reputation: 2445
You need to have your model set app/models/pet.rb
with
class Pet < ActiveRecord::Base
validates_presence_of :profile_photo
belongs_to :owner
mount_uploader :profile_photo, ProfilePhotoUploader
end
Also, side note, if you're using Heroku it won't save pictures since it's a static service. You need to integrate a service like Cloudinary with Carrierwave.
After your form line <%= simple_form_for @pet, html: { multipart: true } do |f| %>
put this in
<% if @pet.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@pet.errors.count, "error") %> prohibited this pet from being saved:</h2>
<ul>
<% @pet.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
and this line <%= f.input :profile_photo, type: :file %>
to this <%= f.file_field :profile_photo %>
At the end of your pet_controller's file make sure you've given permission for the form to submit the data
def pet_params
params.require(:pet).permit(:name, :profile_photo)
end
Since I see you're using devise you might consider assigning the owner to the pet. Consider the line in your pet_controller.rb
def create
@pet = Pet.new(pet_params)
@pet.owner = current_user
And see the line in model belongs_to :owner
Upvotes: 1