Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When editing a record that has a previously successfully uploaded image, how do I not have to re-upload on edit?

I am using Carrierwave, Fog to store images upload to S3.

The issue is that when I go to edit a record, the "file" & "photo" field automatically goes blank. So if I want to preserve the image or file in the record I have to re-upload it.

Otherwise, what happens is that the uploaded file/image just disappears. I am not even sure if it gets deleted from S3, but the association with my record in the db disappears.

This is my SimpleForm _form.html.erb partial for my Post model:

<%= simple_form_for(@post, html: {class: 'form-horizontal' }) do |f| %> 
    <%= f.error_notification %>
    <%= f.input_field :title, placeholder: "Enter Title"  %>
    <%= f.input_field :body, id: "body-field", placeholder: "Provide all the facts." %>
    <%= f.input_field :photo %>
    <%= f.input_field :file %>
    <%= f.button :submit, class: "btn btn-primary pull-left" %>
<% end %>

Here is my PhotoUploader

class PhotoUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick
  storage :fog

  include CarrierWave::MimeTypes
  process :set_content_type

  def store_dir
    "images/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

    version :main_thumb_mobile do
      process :resize_to_fit => [52, 52]
    end

    version :main_thumb do
      process :resize_to_fit => [150, 150]
    end

    version :post_thumb do
      process :resize_to_fit => [200, 200]
    end

    version :large do
      process :resize_to_limit => [400, 400]
    end

  def extension_white_list
    %w(jpg jpeg gif png)
  end
end

This is my FileUploader

class FileUploader < CarrierWave::Uploader::Base
  storage :fog
  def store_dir
    "files/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_white_list
    %w(pdf doc docx xls xlsx ppt pptx txt mp4 m4v mov avi mkv mp3 wav)
  end    
end

This is the Schema for my Post:

# == Schema Information
# truncated for brevity
# Table name: posts
#
#  id                    :integer          not null, primary key
#  title                 :text
#  photo                 :string(255)
#  body                  :text
#  user_id               :integer
#  file                  :string(255)

Edit 1

This is my Post.rb:

# == Schema Information
#
# Table name: posts
#
#  id                    :integer          not null, primary key
#  title                 :text
#  photo                 :string(255)
#  body                  :text
#  created_at            :datetime
#  updated_at            :datetime
#  user_id               :integer
#  ancestry              :string(255)
#  file                  :string(255)
#  status                :integer          default(0)
#  slug                  :string(255)
#  publication_status    :integer          default(0)
#  has_eyewitness        :boolean          default(FALSE)
#  youtube_embed_code    :text
#  soundcloud_embed_code :text
#

class Post < ActiveRecord::Base
  has_ancestry
  belongs_to :user
  resourcify
  enum status: [ :unconfirmed, :corroborated, :confirmed ]
  enum publication_status: [ :unpublished, :published ]
  extend FriendlyId
  friendly_id :title, use: [:slugged, :history, :finders]

  attr_accessor :country

  mount_uploader :photo, PhotoUploader
  mount_uploader :file, FileUploader

  validates_presence_of :body
  validates_length_of :body, maximum: 150, too_long: 'The report must be less than 150 words.',
                        tokenizer: ->(str) { str.scan(/\w+/) }
  validates_length_of :title, maximum: 7, too_long: 'The title must be less than 7 words.',
                                              tokenizer: ->(str) { str.scan(/\w+/) }

  def publish
    published!
  end

  def unpublish
    unpublished!
  end

  def is_published?
    if self.published?
      "yes"
    else
      "no"
    end
  end      
end

Edit 2

I changed the f.input_field :photo in my form to f.file_field :photo per jaspreet's suggestion and it still doesn't work. This is my log from an update request:

Started PATCH "/posts/ognr-takes-over-amcham-6a6f01ba-a9f9-44d5-924a-72f666f20ca8" for 127.0.0.1 at 2014-12-28 13:51:38 -0500
Processing by PostsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"S7FOq956fox6XYpar7Yd6V7AL+bwypQQxZktjHW3PNc=", "post"=>{"parent_id"=>"", "status"=>"unconfirmed", "publication_status"=>"unpublished", "title"=>"OGNR takes over AMCHAM", "body"=>"OGNR storms the rerl.", "has_eyewitness"=>"1", "youtube_embed_code"=>"", "soundcloud_embed_code"=>""}, "commit"=>"Update Post", "id"=>"ognr-takes-over-amcham-6a6f01ba-a9f9-44d5-924a-72f666f20ca8"}
  User Load (1.7ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  ORDER BY "users"."id" ASC LIMIT 1
   (1.2ms)  SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["user_id", 1]]
   (6.4ms)  SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'editor') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["user_id", 1]]
   (0.2ms)  BEGIN
  Post Exists (1.0ms)  SELECT  1 AS one FROM "posts" INNER JOIN "friendly_id_slugs" ON "friendly_id_slugs"."sluggable_id" = "posts"."id" AND "friendly_id_slugs"."sluggable_type" = 'Post' WHERE ("posts"."id" IS NOT NULL) AND "posts"."slug" = 'ognr-takes-over-amcham' LIMIT 1
  SQL (0.6ms)  INSERT INTO "posts" ("body", "created_at", "has_eyewitness", "slug", "soundcloud_embed_code", "title", "updated_at", "youtube_embed_code") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"  [["body", "OGNR storms the rerl."], ["created_at", "2014-12-28 18:51:39.183091"], ["has_eyewitness", "t"], ["slug", "ognr-takes-over-amcham-cd491a8e-9a4e-4d5e-b13a-898de4adf135"], ["soundcloud_embed_code", ""], ["title", "OGNR takes over AMCHAM"], ["updated_at", "2014-12-28 18:51:39.183091"], ["youtube_embed_code", ""]]
  FriendlyId::Slug Load (0.5ms)  SELECT  "friendly_id_slugs".* FROM "friendly_id_slugs"  WHERE "friendly_id_slugs"."sluggable_id" = $1 AND "friendly_id_slugs"."sluggable_type" = $2  ORDER BY "friendly_id_slugs".id DESC LIMIT 1  [["sluggable_id", 43], ["sluggable_type", "Post"]]
  SQL (0.4ms)  DELETE FROM "friendly_id_slugs" WHERE "friendly_id_slugs"."sluggable_id" = $1 AND "friendly_id_slugs"."sluggable_type" = $2 AND "friendly_id_slugs"."slug" = 'ognr-takes-over-amcham-cd491a8e-9a4e-4d5e-b13a-898de4adf135'  [["sluggable_id", 43], ["sluggable_type", "Post"]]
  SQL (0.4ms)  INSERT INTO "friendly_id_slugs" ("created_at", "slug", "sluggable_id", "sluggable_type") VALUES ($1, $2, $3, $4) RETURNING "id"  [["created_at", "2014-12-28 18:51:39.242475"], ["slug", "ognr-takes-over-amcham-cd491a8e-9a4e-4d5e-b13a-898de4adf135"], ["sluggable_id", 43], ["sluggable_type", "Post"]]
   (2.6ms)  COMMIT
Redirected to http://localhost:3000/posts/ognr-takes-over-amcham-cd491a8e-9a4e-4d5e-b13a-898de4adf135
Completed 302 Found in 372ms (ActiveRecord: 17.3ms)

Edit 3

The PostController#Update looks like this:

class PostsController < ApplicationController
  load_and_authorize_resource

  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to @post, notice: 'Report was successfully updated.' }
        format.json { render :show, status: :ok, location: @post }
      else
        format.html { render :edit }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

Edit 4

Routes

like image 278
marcamillion Avatar asked Dec 17 '14 23:12

marcamillion


2 Answers

You need to use an input field for upload image to show the image name, and use javascript function to display the file name in input field as the following:

<%= text_field_tag 'file_name', "#{@post.photo_file_name}", {disabled: true, class: 'browse-input form-control'} %>
<%= f.input_field :photo %>
:javascript
  $("#post_photo").change(function () {
      $("#file_name").val(this.value.replace(/^.*[\\\/]/, ''));
  });

And You can use the same code for upload file.

For Prevent to re-upload unchanged photo

You can use changed? method to check if photo changed or not as the following:

def update
  if @post.photo && [email protected]?
     @post.update(post_update_params_without_photo)
  end
end
# Example method, don't forgot set the necessary attributes
def post_update_params_without_photo
  params.require(:post).permit(:title)
end

Explain: This code to update changed attributes only i.e (title, status, and so on).

like image 141
Mohamed Yakout Avatar answered Oct 03 '22 23:10

Mohamed Yakout


I think the simple_form_for is doing some extra work in making params. It might be sending params as 'post' => { 'file' => { 'id' => '29', 'image' => '' } }, when no file is selected.

Whereas if you try to use a simple file_field_tag or f.file_field then it only sends as 'post' => { 'file' => { 'id' => '29' } }, if no image file is selected, and the old one is preserved.

Try this and it would surely solve your problem.

Remember if using file_field_tag you need to pass the name attribute correctly for the params to be built up in the right way as the rails expect. In your case it must be like 'post[file][image]' and a hidden field too(this is automatically built if using f.file_field) whose name will be post[file][id]

Sharing my console

Started PATCH "/requirements/2162" for 127.0.0.1 at 2015-01-05 10:44:53 +0530
Processing by RequirementsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"mqoPYjGir/3aA/ZFCjpr79KY/xXEoyTd95Dis8HDH7g=", "requirement"=>{"category_ids"=>["40", "47"], "title"=>"gefd gefd gefd", "details"=>"dsfg", "expiration_date(1i)"=>"2015", "expiration_date(2i)"=>"12", "expiration_date(3i)"=>"31", "address_attributes"=>{"street"=>"ewfg", "city"=>"deaf", "country_code"=>"DZ", "state_code"=>"01", "id"=>"60"}}, "commit"=>"Update Requirement", "id"=>"2162"}
  User Load (4.3ms)  SELECT  `people`.* FROM `people`  WHERE `people`.`type` IN ('User') AND `people`.`id` = 28  ORDER BY `people`.`id` ASC LIMIT 1
  Requirement Load (1.0ms)  SELECT  `requirements`.* FROM `requirements`  WHERE `requirements`.`id` = 2162 LIMIT 1
   (1.7ms)  BEGIN
  Category Load (6.1ms)  SELECT `categories`.* FROM `categories`  WHERE `categories`.`id` IN (40, 47)
  Category Load (5.0ms)  SELECT `categories`.* FROM `categories` INNER JOIN `category_requirements` ON `categories`.`id` = `category_requirements`.`category_id` WHERE `category_requirements`.`requirement_id` = 2162
  Address Load (0.4ms)  SELECT  `addresses`.* FROM `addresses`  WHERE `addresses`.`id` = 60 LIMIT 1
  DonorRequirement Exists (0.4ms)  SELECT  1 AS one FROM `donor_requirements`  WHERE `donor_requirements`.`requirement_id` = 2162 LIMIT 1
  SQL (7.6ms)  UPDATE `requirements` SET `expiration_date` = '2015-12-31', `title` = 'gefd gefd gefd', `updated_at` = '2015-01-05 05:14:53' WHERE `requirements`.`id` = 2162
   (6.0ms)  COMMIT
like image 32
jaspreet21anand Avatar answered Oct 03 '22 23:10

jaspreet21anand