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 bookspublic/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.0bundle installrails 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 %>