Understanding how carrierwave implements image uploading
public
folder used to hold static files!
localhost:3000/404
you will see that
page renders immediately, Rails does not need to process it and serve it (no database lookups
or route lookups)public
, you can create a file that will store the images for your model!Book
model:
cd public && mkdir books
public/books/2/
public/books/2/cover
,
public/books/2/back
, public/books/2/author
<%= image_tag "/books/#{@book.id}/cover/cover.jpg" %>
edit
page:
<%= f.file_field :db_name %>
attr_accessor
for the database name field!after_save :save_cover_image, if: :cover
callback: which allows us to take the file
that was uploaded and save it to the public directory!class Book
after_save :save_cover_image, if: :cover
def save_cover_image
filename = cover.original_filename #given by the file upload
folder = "public/books/#{id}/cover"
FileUtils::mkdir_p folder # generates the given folder path rather then checking to see
# if each path exists one by one
f = File.open File.join(folder, filename), "wb"
f.write cover.read()
f.close
self.cover = nil
update cover_filename: filename # cover_filename is the actual database name in the books table
end
end
The above code creates an attribute reader and writer method called cover
.
The object has a database field called cover_filename
(which is a string).
After an object has created or updated, the after_save callback is used to store the file in your
rails app (within the public directory), then the object has its cover_filename
attribute updated
Then you can edit the show page:
<%= image_tag "/books/#{@book.id}/cover/#{@book.cover_filename}" if @book.cover_filename? %>
gem 'carrierwave', ~> 0.10.0
bundle install
rails g uploader Cover
(Cover for example)mount_uploader :cover, CoverUploader
<%= modelclass.file_field :cover %>
<%= image_tag(@post.image.url, alt: 'Image') if @post.image? %>
include Carrierwave::MiniMagick
resize_to_fill
method option:
process resize_to_fill: [200, 100]
, for exampleresize_to_limit
, resize_to_fill
, resize_to_fit
# Create different versions of your uploaded files:
version :optimised do
process convert: 'webp'
process :set_content_type_to_webp
def full_filename(for_file = model.file_name.file)
extension = File.extname(for_file)
"#{for_file.sub(extension, '.webp')}"
end
def exists?
file&.exists?
end
end
protected
# Required to actually force Amazon S3 to treat it like an image
def set_content_type_to_webp
file.instance_variable_set(:@content_type, 'image/webp')
end
instance = MyUploader.new
instance.recreate_versions!(:thumb)
has_many
of Model Bbelongs_to
Model A# in model_a.rb
has_many :model_bs
accepts_nested_attributes_for :model_bs
# make sure this is plural
# -------------------------------------------
# in model_b.rb
belongs_to :model_a
mount_uploader .... # used for carrierwave
# make sure that this model has a db field named after the uploader
# t.references :model_a # singular!!!
# -------------------------------------------
# in model_a_controller.rb
def new
@modela = ModelA.new
@modela.modelbs.build
end
def create
# normal stuff
end
private
def modela_params
params.require().permit(model_bs_attributes: [database names for model b])
# MUST BE PLURAL model_bS_attributeS: []
end
# -------------------------------------------
# in the form for creating this new model
<%= form_for ....
#...other code
<%= f.fields_for :model_bs do |ff| %>
<%= ff.label ...%>
<%= ff.file_field :uploader, multiple: true, name: "model_a[model_b_attributes][][uploader]" %>
<% end %>
<% end %>