I'm setting up an uploader (which I've done without any problems a million times before) however when I submit the form, it doesn't appear that carrierwave has any interaction with the mounted column. The form submission is successful, however for some reason the mounted column simply defaults to nil. Below is my server log as well as my setup. My question is, how do i know that carrierwave has actually been initialized and the column mounted to the uploader?
server log:
Processing by DocumentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"oCw+WOBL7OIUjaOLh9Z0VR1g5KxErMBtLATmMQI6OJk=", "document"=>{"title"=>"Spec Sheet", "category"=>"Spec Sheet", "file_location"=>"my_file.pdf"}, "commit"=>"Create Document", "product_id"=>"1"}
Product Load (0.3ms) SELECT "products".* FROM "products" WHERE "products"."id" = $1 LIMIT 1 [["id", "1"]]
(0.1ms) BEGIN
SQL (4.0ms) INSERT INTO "documents" ("category", "created_at", "documentable_id", "documentable_type", "file_location", "title", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["category", "Spec Sheet"], ["created_at", Thu, 06 Feb 2014 05:29:31 UTC +00:00], ["documentable_id", 1], ["documentable_type", "Product"], ["file_location", nil], ["title", "Spec Sheet"], ["updated_at", Thu, 06 Feb 2014 05:29:31 UTC +00:00]]
(6.3ms) COMMIT
Redirected to http://localhost:3000/products/1
Completed 302 Found in 19ms (ActiveRecord: 10.7ms)
Uploader
class DocumentUploader < CarrierWave::Uploader::Base
# include CarrierWaveDirect::Uploader
# Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
include CarrierWave::MimeTypes
process :set_content_type
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(pdf doc)
end
end
carrierwave.rb initializer:
CarrierWave.configure do |config|
if Rails.env.production?
config.storage = :fog
config.fog_credentials = {
provider: 'AWS',
aws_access_key_id: 'xxx',
aws_secret_access_key: 'xxx'
}
config.fog_directory = 'my_file_location'
config.fog_public = false
else
config.storage = :file
config.enable_processing = false
end
end
model:
class Document < ActiveRecord::Base
attr_accessible :file_location, :category, :title, :documentable_type, :documentable_id
mount_uploader :file_location, DocumentUploader
belongs_to :documentable, polymorphic: true
end
Class.include?(CarrierWave) => This will return true if your CarrierWave is included in to your class.
Class.uploaders => It will give you hash of mounted fields with uploaders.i.e: {:image => FileUploader}
Here is your problem
"file_location"=>"my_file.pdf"
if you have mounted file_location column in the carrierwave uploader .
Carrierwave expect it to be a file or remote_url look here what is the expected input to cache which is basically first step before carrierwave upload the file to the desired location
Pass a file in params and I believe the carrierwave would work as expected then
Related
I try to use Active Storage with Amazon Web Services, instead of Carrierwave and Cloudinary.
With Carrierwave I had some features that allow to resize images before uploading trough an UploaderController.
But how to do that with Active Storage ?
I try this :
Gemfile :
gem 'aws-sdk-s3', require: false
gem 'image_processing', '~> 1.2'
gem 'mini_magick', '~>4.9'
item.rb
class Item < ApplicationRecord
has_one_attached :photo
end
I have a form in my view :
<%= f.input :photo, input_html: { accept: ('image') } %>
I get this object as photo :
#<ActiveStorage::Attached::One:0x00005641d296e1b8 #name="photo", #record=#<Item id: nil, name: "test0941", verbe: "To Lend", collection_id: nil, created_at: nil, updated_at: nil, price_cents: 0, description: "", category_id: 78, photo: nil>, #dependent=:purge_later>
And in my controller :
#item = Item.new(item_params)
#item.photo.combine_options do |b|
b.resize "250x200>"
end
I can't achieve to resize my photo with methods of MiniMagick gem.
Does anybody have any ideas to do that ?
Thanks for your help,
Thibault
If params[:item][:photo] is the param from your post you can add
image = MiniMagick::Image.new(params[:item][:photo].tempfile.path)
image.resize "250x200>"
With ImageProcessing::Vips (default in rails7)
path = params[:game][:photo].tempfile.path
image = ImageProcessing::Vips.source(path)
result = image.resize_to_limit!(800, 800)
params[:game][:photo].tempfile = result
I did it like this:
# config/initializers/activestorage.rb
# Ability to auto apply :default variant (if defined) before uploading original image
Rails.application.config.after_initialize do
ActiveStorage::Blob.class_eval do
alias_method :upload_without_unfurling_orig, :upload_without_unfurling
def upload_without_unfurling(io)
variant = attachments.first.send(:variants)
default_variant = variant[:default]
if default_variant
ActiveStorage::Variation.wrap(default_variant).transform(io) do |output|
unfurl output, identify: identify
upload_without_unfurling_orig(output)
end
else
upload_without_unfurling_orig(io)
end
end
end
end
# user.rb
class User < ApplicationRecord
has_one_attached :photo do |attachable|
attachable.variant :thumb, resize_to_fill: [100, nil]
# This variant will be applied before uploading the original image
attachable.variant :default, strip: true, quality: 70, resize_to_fill: [500, 500]
end
end
# rspec
RSpec.describe User, type: :model do
describe 'when uploading photo' do
it 'applies :default variant before uploading the original image' do
allow(ActiveStorage::Variation).to receive(:wrap).and_call_original
create(:user, :with_photo)
exp_args = hash_including(resize_to_fill: [500, 500])
expect(ActiveStorage::Variation).to have_received(:wrap).with(exp_args)
end
end
end
Active storage has a solution for your problem.
You don't need to resize images in your controller.You can just use it as
item.photo.variant(resize: '100x100') in your view file. Active Storage will create new variant images like magic.
Here is the documentation for active storage.
https://edgeguides.rubyonrails.org/active_storage_overview.html
I am using virtus(1.0.5) with rails (5.0.2). I am using Virtus for a model since it has validations based on the page being accessed.
My Organization model is as
class Organization < ApplicationRecord
validates :name, presence: true
end
and form created using virtus is as
class OrganizationProfileForm
include ActiveModel::Model
include Virtus.model
attribute :call_center_number, String, default: :org_call_center_number
validates :call_center_number, presence: true
def initialize(organization)
#organization = organization
end
private
def org_call_center_number
#organization.call_center_number
end
end
Unfortunately, the above code doesn't work
Loading development environment (Rails 5.0.2)
2.3.0 :001 > of = OrganizationProfileForm.new(Organization.last)
Organization Load (0.6ms) SELECT "organizations".* FROM "organizations" ORDER BY "organizations"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> #<OrganizationProfileForm:0x007f9d61edd6a8 #organization=# <Organization id: 1, name: "Some name", call_center_number: "4892374928", created_at: "2017-03-29 09:35:22", updated_at: "2017-03-29 09:37:59">>
2.3.0 :002 > of.call_center_number
=> nil
We need to call super() in the initialize method.
Try removing the line private, as this may be preventing the call to the method org_call_center_number. The example given for default values on the Virtus repo uses a public instance method, not a private one.
See: What are the differences between "private", "public", and "protected methods"?
I inherited a Rails project and was asked to update it so I am migrating the Rails 2.2.2 project to Rails 3.2.
I went through a few migration tutorials and ran the rails upgrade script and it loads fine when the default /public/index.html is there.
I then went ahead and removed /public/index.html, so the app would point to the file indicated in routes.rb and then I get:
LoadError (Expected /var/www/vendor_sandbox/app/controllers/application.rb to define Application):
app/controllers/application_controller.rb:1:in `<top (required)>'
app/controllers/home_controller.rb:1:in `<top (required)>'
The file that is causing the error was from the original Rails 2.2.2 code base. I left it because there was no indication in the migration docs that I was reading that mentioned removing it but clearly something is wrong.
I find it strange that I now have a Rails 3 version of application.rb in /config and an application.rb in /app/controllers/
Not sure what to do with /app/controllers/application.rb.
Here are the files mentioned:
#### /app/controllers/application.rb
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
# See ActionController::RequestForgeryProtection for details
# Uncomment the :secret if you're not using the cookie session store
protect_from_forgery # :secret => 'mysecretkey'
# See ActionController::Base for details
# Uncomment this to filter the contents of submitted sensitive data parameters
# from your application log (in this case, all fields with names like "password").
# filter_parameter_logging :password
def authenticate
return true if session[:user_id].to_i > 0
session[:after_login] = params
redirect_to :controller => "login"
return false
end
def authenticate_admin
user = User.find(session[:user_id])
#nav = [{:title => "Home", :action => {:controller => "home"}}]
return true if user and user.is_admin?
redirect_to :controller => "login"
return false
end
def clean_date_for_4D date
return "00/00/00" if !date or date == ""
return date.strftime("%m/%d/%Y") if date.class.to_s == "Date"
return Date.parse(date).strftime("%m/%d/%Y") # assume it's a string
end
def pad text, length=20
while text.length < length do
text = text + " "
end
return text
end
end
#### /config/routes.rb
VendorSandbox::Application.routes.draw do
match '/' => 'home#index'
match '/:controller(/:action(/:id))'
end
#### /config/application.rb
require File.expand_path('../boot', __FILE__)
require 'rails/all'
if defined?(Bundler)
Bundler.require(*Rails.groups(:assets => %w(development test)))
end
module VendorSandbox
class Application < Rails::Application
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
# Enable escaping HTML in JSON.
config.active_support.escape_html_entities_in_json = true
config.active_record.whitelist_attributes = true
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
# Session key
config.session_store(:cookie_store, {:key => '_vendor_sandbox_session', :secret => 'secretkey'
# Time zone
config.time_zone = 'Central Time (US & Canada)' #'UTC' # Had to change this to keep created_at from being 4 hours in advance!
config.active_record.default_timezone = 'Central Time (US & Canada)'
end
end
Trying renaming your app/controllers/application.rb to application_controller.rb.
I think Rails is expecting your controller to be named with a _controller suffix, and the application.rb you have in your controllers folder isn't following that convention.
I wanted to comment on #Zajn answer, but I don't have the required "50 reputation".
Just for reference, app/controllers/application.rb was renamed to application_controller.rb in Rails 2.3
http://guides.rubyonrails.org/2_3_release_notes.html#application-controller-renamed
I am trying to crop image using mini magick gem with carrierwave. I am facing following issue when i am creating user.
Errno::ENOENT in UsersController#create
No such file or directory - identify -ping /tmp/mini_magick20120919-5600-ai31ph.jpg
My Code :
model/user.rb
class User < ActiveRecord::Base
attr_accessor :crop_x, :crop_y, :crop_h, :crop_w
attr_accessible :username,:profile
after_update :reprocess_profile, :if => :cropping?
#field :username
mount_uploader :profile, ProfileUploader
def cropping?
!crop_x.blank? and !crop_y.blank? and !crop_h.blank? and !crop_w.blank?
end
def profile_geometry
#img = MiniMagick::Image.open(self.profile.large.path)
##geometry = {:width => img[:width], :height => img[:height] }
end
private
def reprocess_profile
#puts self.profile.large.path
#img = MiniMagick::Image.open(self.profile.large.path)
#crop_params = "#{crop_w}x#{crop_h}+#{crop_x}+#{crop_y}"
#img.crop(crop_params)
#img.write(self.profile.path)
#profile.recreate_versions!
end
end
uploader/profile_uploader.rb
# encoding: utf-8
class ProfileUploader < CarrierWave::Uploader::Base
# Include RMagick or ImageScience support:
#include CarrierWave::RMagick
# include CarrierWave::ImageScience
include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_white_list
%w(jpg jpeg gif png)
end
version :large do
end
version :thumb do
process :resize_to_fill => [100, 100]
end
end
What would be the problem ? please suggest any solution.
Need to install imagemagick.
In ubuntu:
sudo apt-get install imagemagick
I am using Rails 3 and carrierwave gem.
My problem is the next:
I am coding a wizard form with multiple models and relations. So My application has products which has many images through Image model (Its has been mounted with carrierwave).
Because the form has many steps I want save temporaly the images with cache option in CarrierWave. then i last step i want recover the images and load my product. So I create a model called TempData which save temporaly data (In this case cache_name), a type_identifier and a mark can_be_deleted.
For example these are my models:
Product Model:
class Product < ActiveRecord::Base
has_many :images, :as => :imageable, :dependent => :destroy
def save_images_in_temporal_folder(images_attributes)
begin
uploader = ImageUploader.new
images_attributes.to_hash.each do |image|
uploader.cache!(image[1]['filename'])
TempData.create(:data => uploader.cache_name, :can_deleted => false, :type_name => TempDataType.product_image_upload_to_words)
end
rescue
end
end
def load_images_from_temporal_folder
begin
uploader = ImageUploader.new
tmp_images = []
TempData.find_all_by_can_deleted_and_type_name(false, TempDataType.product_image_upload_to_words).map(&:data).each do |cache_name|
tmp_images << uploader.retrieve_from_cache!(cache_name)
end
tmp_images
rescue
end
end
end
Image model
class Image < ActiveRecord::Base
attr_accessible :imageable_type, :imageable_id, :filename
belongs_to :imageable, :polymorphic => true
mount_uploader :filename, ImageUploader
#validates :filename, :presence => true
end
My ImageUploader:
class ImageUploader < CarrierWave::Uploader::Base
configure do |config|
config.remove_previously_stored_files_after_update = false
end
include CarrierWave::RMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def self.store_dir_for_file(model, mounted, filename, version = "")
filename = "#{version}_#{filename}" unless version.blank?
"uploads/#{model.class.to_s.underscore}/#{mounted}/#{model.id}/#{filename}"
end
process :resize_to_limit => [200, 300]
version :thumb do
process :resize_to_limit => [50, 50]
end
version :big do
process :resize_to_limit => [400, 400]
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
So How i save/cache the images with model and mount information?. How retrieve the cache and load my product with images in cache?
Thanks in advance. Sorry for my english and if you need more information comment this post.
View the next link:
CarrierWave with ActiveResource
Also I create a model which storage temporal data. Here I save the cache_name of carrierwave. When i save the product mark these register as can_be_deleted. Then I write a task which delete these registers and clean Carrierwave cache files.