rails/carrierwave : nil values saved after upload image by carrierwave, minimagick - carrierwave

I'm trying to upload images through carrier wave, and using rails.
using minimagick.
Actually, the uploads working properly I think, but images are not shown up.
Also it shows nil value in database.
here's my code.
app/models/user.rb
class User < ActiveRecord::Base
mount_uploader :image, ImageUploader
end
mypage.html.erb (form action to "edit_complete")
<input type="file" name='image'>
users_controller.rb
def edit_complete
user = User.find(session[:user_id])
user.image = params[:image]
user.save
redirect_to :back
end
app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
No errors appeared, but nothing saved in database.
I expect image files should be saved in public/upload folder, and image file should be shown in database in rails c User.all.
However, when I upload 1.png file,
there are nothing saved, and public/upload folder is not generated.
Also in database shows nil value.
Is there any solution for this?

In file upload You need to use multipart option in form tag ie multipart option should be true in form tag.

Try something like this:
<%= form_for #user, :html => {:multipart => true} do |f| %>
<%= f.file_field :image%>
<%= f.submit 'Edit'%>
<% end %>

Related

Rails 5.2 How to auto upload image by Carrierwave after choose a image

I used Carrierwave to upload images to polymorphic table.
With the following codes , I can upload and display the images correctly.
But now I want to auto upload and display image after choose a image in new.html.erb. In other words , I want to run
Attachment.create(:attachment => params[:attachment], :attachmentable =>#img) if params[:attachment]
before img create action, just after I choose a image.
What should I do with the codes? Thank you so much for giving me guidances.
Part of my codes as follows:
My Gemfiles :
gem 'rails', '~> 5.2'
gem 'carrierwave', '~> 1.2', '>= 1.2.2'
gem 'mini_magick'
My img.rb:
class Img < ActiveRecord::Base
has_many :attachments, as: :attachmentable, :dependent => :destroy
end
My models of attachment.rb:
class Attachment < ApplicationRecord
mount_uploader :attachment, ImageUploader
belongs_to :attachmentable, :polymorphic => true
end
My controller of imgs_controller
class ImgsController < ApplicationController
def index
#imgs = Img.all
end
def show
#img = Img.find(params[:id])
end
def new
#img = Img.new
end
def create
#img = Img.new(img_params)
if #img.save
Attachment.create(:attachment => params[:attachment], :attachmentable =>#img) if params[:attachment]
redirect_to #img
end
end
def destroy
#img = Img.find(params[:id])
#img.destroy
redirect_to #img
end
private
def img_params
params.require(:img).permit(:img_name)
end
end
My html of imgs
# new.html.erb
<%= form_for(#img,:html => {:multipart => true}) do |f| %>
<%= f.text_field :img_name %>
<%= file_field_tag :attachment %>
<%= f.submit "upload" %>
<% end %>
# show.html.erb
<% #img.attachments.each do |f| %>
<%= image_tag f.attachment.url %>
<% end %>
As per the description mentioned in the post you want that as soon as the user browses the image from location you want that image to be uploaded to cloud storage using carrierwave.
One way of doing this would be making an ajax call to the controller after the user has completed the browsing of image from his system and remotely uploading the image to cloud.
Unnecessary:
But what happens if user keeps on changing the image while browsing, will you uploading each image browsed irrespective of the fact that you would not be showing that image or will be needing it.
Workaround:
You can use jquery to the read the image browsed and then show the image to the user if needed and when the form is submitted then only you upload the image to cloud storage.

Ruby on Rails - Carrierwave - Blank/Empty images with resize_to_fill

I'm currently implementing CarrierWave into my app. A problem I noticed is that most images I've uploaded fail to correctly generate a thumbnail size (64x64).
I'm using resize_to_fit and resize_to_fill for different versions, and the resize_to_fill (for cropping) is failing most of the time.
Here I've generated two versions, gallery and thumb.
// image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :gallery do
process resize_to_fit: [400, 300]
end
version :thumb do
process :resize_to_fill => [64, 64]
end
def extension_whitelist
%w(jpg jpeg gif png)
end
end
They look correct; however, if you actually open thumb within Paint, it's completely blank.
I've tested this with a bunch of different pictures, and most have this happen. But I did notice that if I open the main image, save it (without doing anything), then recreate the versions, it's fixed. Must be something with how it's being saved, or something.
Here is the source image that I've been able to reproduce this issue with.
Thanks.
Very strange behavior. I was very curious about this problem, so I made very simple example on my dev. machine referencing Ryan's Bates
cropping images episode.
You can just follow up, it may help you.
Let's say we generated simple user scaffold, and we have in our DB fields called :name and :avatar of string types.
In our User model we'll mount uploader and create virtual attributes:
class User < ApplicationRecord
mount_uploader :avatar, AvatarUploader
attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
end
Method create in users_controller.rb will look like this (including strong params):
def create
#user = User.new(user_params)
if #user.save
if params[:user][:avatar].present?
render :crop # Render crop template
else
redirect_to #user, notice: "Successfully created user."
end
else
render :new
end
end
# Strong params# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit!
end
The image_uploader.rb you posted was good. I will just post mine, as I made large and thumb versions and used resize_to_limit process
instead of resize_to_fit:
version :large do
resize_to_limit(400, 300)
end
version :thumb do
resize_to_fill(64, 64)
end
We can create now crop.html.erb template in views/users folder and populate with code below:
<h1>Crop Avatar</h1>
<%= image_tag #user.avatar_url(:large) %>
<h4>Preview</h4>
<div style="width:100px; height:100px; overflow:hidden">
<%= image_tag #user.avatar.url(:large) %>
</div>
<%= form_for #user do |f| %>
<% %w[x y w h].each do |attribute| %>
<%= f.hidden_field "crop_#{attribute}" %>
<% end %>
<div class="actions">
<%= f.submit "Crop" %>
</div>
<% end %>
When you create new user form it will have avatar attachment. When you upload photo and submit it, it will trigger
def create method and it will check if params are presented, and render the crop.html.erb template:
if params[:user][:avatar].present?
render :crop # Render crop template
else
I haven't included in this example Jcrop library for cropping images, this was very simple example. At the end it should crop 64x64 pixels
by default.
There is also CarrierWave extension to crop uploaded images using Jcrop plugin with preview, which I haven't tried.
I hope it helps

can't generate a thumbnail of an image using carrierwave

my plan is i want to create a model only for images and use that model to create profile pictures, gallery etc..
so, i have created a separate model for images and i was able to store images in display those images. but, they are too big and so i want to create a thumbnail version.
my configuration is
class Image < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
end
controller:
class ImagesController < ApplicationController
def new
#image_upload=Image.new
end
def create
#image_upload=Image.create(uploading_image)
if #image_upload.save
redirect_to '/users'
end
end
def uploading_image
params.require(:image).permit(:avatar)
end
end
uploader:
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}...(default store only)"
end
version :thumb do
process :resize_to_limit => [50, 50]
end
user controller:
def index
#user_profile=Profile.find(1)
#imagefile=Image.first
end
users/index.html.erb:
<%= image_tag #imagefile.avatar.to_s %> #This gives me the whole image.
<%= image_tag #imagefile.image_url(:thumb).to_s %> #says undefined method `image_url' for #<Image:0x007f6cd0538010>
ps: i can see a thumbnail version in the folder
It would be so great, if anyone could help me out.
You call your other versions of the #imagefile the same way you call its original copy, just add the version name. And you can use the url helper. so:
<%= image_tag #imagefile.avatar.url %>
<%= image_tag #imagefile.avatar.thumb.url %>
<%= image_tag #imagefile.image_url(:thumb) %> should be <%= image_tag #imagefile.avatar_url(:thumb) %> as the field that has an uploader mounted is called 'avatar'. Also you shouldn't need to call .to_s on the url.

Unable to upload multiple images with Carrierwave

I'm having a problem uploading multiple images via Carrierwave and am not sure if it's a bug or user error (probably the latter). I'm doing everything in a rather standard way though (as per documentation) so it's weird that this doesn't work.
I have the following in my Gemfile:
gem 'carrierwave', github: 'carrierwaveuploader/carrierwave'
my image_uploader.rb:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process :resize_to_limit => [590, 590]
end
version :featured do
process :resize_to_fill => [390, 390]
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
My article.rb file:
class Article < ActiveRecord::Base
mount_uploaders :images, ImageUploader
end
I am letting the params pass from my controller with:
def article_params
params.require(:article).permit(:title, :images, :body)
end
And the _form.html.erb partial uses:
<%= form_for #article, html: { multipart: true } do |f| %>
<%= f.label :images %><br>
<%= f.file_field :images, multiple: true %><br>
<%= f.submit 'Update Article' %>
<% end %>
Oddly, when I upload two images, I am not seeing them passed into the article_params from the update method.
If I pry it, I can see that:
params.require(:article).permit(:images)
Unpermitted parameters: title, images, body
=> {}
Images seems to be unpermitted, even though I explicitly permit it...
Any clue as to what may be incorrect here?
The solution seems to be:
params.require(:article).permit(:title, :body, images: [])
If you take a look in pry on images param, its type is an Array:
> params[:article][:images].class
=> Array
From docs:
To declare that the value in params must be an array of permitted scalar values map the key to an empty array:
params.permit(id: [])
Source: 4.5.1 Permitted Scalar Values

Saving files using Paperclip without upload

I had a quick question. Is it possible to save a file without actually uploading it through a form?
For example, let's say I'm looking at attachments from emails, and I want to save them using a paperclip. How do I do this? Do I manually have to call a save_file(or something similar) somewhere?
Any help would be much appreciated!
I have a rake task that loads images (client logos) from a directory directly onto parperclip. You can probably adapt it to your needs.
This is my simplified Client model:
class Client < ActiveRecord::Base
LOGO_STYLES = {
:original => ['1024x768>', :jpg],
:medium => ['256x192#', :jpg],
:small => ['128x96#', :jpg]
}
has_attached_file :logo,
:styles => Client::LOGO_STYLES,
:url => "/clients/logo/:id.jpg?style=:style"
attr_protected :logo_file_name, :logo_content_type, :logo_size
Then on my rake task I do this:
# the logos are in a folder with path logos_dir
Dir.glob(File.join(logos_dir,'*')).each do |logo_path|
if File.basename(logo_path)[0]!= '.' and !File.directory? logo_path
client_code = File.basename(logo_path, '.*') #filename without extension
client = Client.find_by_code(client_code) #you could use the ids, too
raise "could not find client for client_code #{client_code}" if client.nil?
File.open(logo_path) do |f|
client.logo = f # just assign the logo attribute to a file
client.save
end #file gets closed automatically here
end
end
Regards!
The file saved in Paperclip doesn't have to be uploaded directly through a form.
I'm using Paperclip in a project to save files from URLs from webcrawler results. I'm not sure how you'd get email attachments (are they on the local file system of the server? Is your app an email app like GMail?) but as long as you can get a file stream (via something like open(URI.parse(crawl_result)) in my case...) you can attach that file to your model field that's marked has_attached_file.
This blog post about Easy Upload via URL with Paperclip helped me figure this out.
Since it now appears the original blog post is no longer available - here's the gist of it pulled from wayback machine:
This example shows a Photo model that has an Image attachment.
The technique we're using requires adding a *_remote_url (string) column for your attachment, which is used to store the original URL. So, in this case, we need to add a column named image_remote_url the photos table.
# db/migrate/20081210200032_add_image_remote_url_to_photos.rb
class AddImageRemoteUrlToPhotos < ActiveRecord::Migration
def self.up
add_column :photos, :image_remote_url, :string
end
def self.down
remove_column :photos, :image_remote_url
end
end
Nothing special is required for the controller...
# app/controllers/photos_controller.rb
class PhotosController < ApplicationController
def create
#photo = Photo.new(params[:photo])
if #photo.save
redirect_to photos_path
else
render :action => 'new'
end
end
end
In the form, we add a text_field called :image_url, so people can upload a file or provide a URL...
# app/views/photos/new.html.erb
<%= error_messages_for :photo %>
<% form_for :photo, :html => { :multipart => true } do |f| %>
Upload a photo: <%= f.file_field :image %><br>
...or provide a URL: <%= f.text_field :image_url %><br>
<%= f.submit 'Submit' %>
<% end %>
The meaty stuff is in the Photo model. We need to require open-uri, add an attr_accessor :image_url, and do the normal has_attached_file stuff. Then, we add a before_validation callback to download the file in the image_url attribute (if provided) and save the original URL as image_remote_url. Finally, we do a validates_presence_of :image_remote_url, which allows us to rescue from the many exceptions that can be raised when attempting to download the file.
# app/models/photo.rb
require 'open-uri'
class Photo < ActiveRecord::Base
attr_accessor :image_url
has_attached_file :image # etc...
before_validation :download_remote_image, :if => :image_url_provided?
validates_presence_of :image_remote_url, :if => :image_url_provided?, :message => 'is invalid or inaccessible'
private
def image_url_provided?
!self.image_url.blank?
end
def download_remote_image
self.image = do_download_remote_image
self.image_remote_url = image_url
end
def do_download_remote_image
io = open(URI.parse(image_url))
def io.original_filename; base_uri.path.split('/').last; end
io.original_filename.blank? ? nil : io
rescue # catch url errors with validations instead of exceptions (Errno::ENOENT, OpenURI::HTTPError, etc...)
end
end
Everything will work as normal, including the creation of thumbnails, etc. Plus, since we're doing all of the hard stuff in the model, "uploading" a file via URL works from within script/console as well:
$ script/console
Loading development environment (Rails 2.2.2)
>> Photo.new(:image_url => 'http://www.google.com/intl/en_ALL/images/logo.gif')
=> #<Photo image_file_name: "logo.gif", image_remote_url: "http://www.google.com/intl/en_ALL/images/logo.gif">

Resources