The first step is to add the CarrierWave gem to our application. The gem is installed in the usual way by adding a reference to it in the application’s Gemfile.
In /Gemfile,
gem 'carrierwave'
We’ll need to run bundle to make sure that the gem is installed on our system. Once it has installed the first thing we’ll need to do is generate an uploader class. CarrierWave provides a generator called uploader to do this to which we pass the name we want to give our uploader, in this case image.
$ rails g uploader image create app/uploaders/image_uploader.rb
The generator creates a new directory called uploaders under the app directory and in it a file called image_uploader.rb. In this file are a number of comments explaining how to customize the uploader. For example there is code to change the upload location, perform processing on the image after uploading and to restrict the type of files that can be uploaded. We’ll leave the defaults as they are for now and come back and make some customizations later.
Next we’ll need to add the uploader to the Post model. We’ll need a column in the posts table to store it in so we’ll generate a migration to do add it.
$ rails g migration add_image_to_posts image:string
Note that the new column is a string and has the same name as we gave the uploader when we generated it. We’ll need to run $ rake db:migrate to update the database.
Next we’ll add the uploader to the Post model which is done by calling the mount_uploader method, passing in the column name that we generated above and the class for the uploader. We also need to add the image column to the list in the attr_accessible call so that it can be accessed from the controllers.
In /app/models/post.rb,
class Post < ActiveRecord::Base attr_accessible :body, :title, :author_id, :image belongs_to :author has_many :comments has_many :favourites has_many :post_tags has_many :tags, through: :post_tags has_and_belongs_to_many :labels mount_uploader :image, ImageUploader validates_presence_of :body, :title end
With this in place we can modify the form for adding or modifying a post so that it has a file upload field.
In /app/views/posts/_form.html.erb,
<%= form_for(@post) do |f| %> <% if @post.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2> <ul> <% @post.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= f.label :title %><br /> <%= f.text_field :title %> </div> <div class="field"> <%= f.label :body %><br /> <%= f.text_area :body %> </div> <div class="field"> <%= f.label :author %><br /> <%= collection_select(:post, :author_id, Author.all, :id, :name) %> </div> <div class="field"> <%= f.label :image %><br /> <%= f.file_field :image %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>
Step 2: Securing Uploads
Certain file might be dangerous if uploaded to the wrong location, such as php files or other script files. CarrierWave allows you to specify a white-list of allowed extensions.
If you're mounting the uploader, uploading a file with the wrong extension will make the record invalid instead. Otherwise, an error is raised.
class MyUploader < CarrierWave::Uploader::Base def extension_white_list %w(jpg jpeg gif png) end end
Step 3: Viewing The Uploaded Images
In /app/views/posts/show.html.erb,
<h2>Images</h2> <div id="images"> <%= image_tag @post.image_url %> </div>
Step 4: Uploading Images via a URL
Another feature that CarrierWave provides is the ability to add photographs via a URL instead of uploading them directly. We can do this by adding another field to the upload form called remote_image_url. The name is important, when CarrierWave sees a field with that name it knows that it has to fetch the image from a URL.
In /app/views/posts/_form.html.erb,
<%= form_for(@post) do |f| %> <% if @post.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2> <ul> <% @post.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= f.label :title %><br /> <%= f.text_field :title %> </div> <div class="field"> <%= f.label :body %><br /> <%= f.text_area :body %> </div> <div class="field"> <%= f.label :author %><br /> <%= collection_select(:post, :author_id, Author.all, :id, :name) %> </div> <div class="field"> <%= f.label :image %><br /> <%= f.file_field :image %><br /> <%= f.label :remote_image_url, "or image URL" %> <%= f.text_field :remote_image_url %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>
As we’ve added a field to the post form we’ll need to add it to the list of attr_accessible fields in the Post model.
In /app/models/post.rb,
class Post < ActiveRecord::Base attr_accessible :body, :title, :author_id, :image, :remote_image_url belongs_to :author has_many :comments has_many :favourites has_many :post_tags has_many :tags, through: :post_tags has_and_belongs_to_many :labels mount_uploader :image, ImageUploader validates_presence_of :body, :title end
Now in the form we’ll have a remote_image_url field and we can enter a URL in that field to add an image to the post without uploading it manually.
carrierwaveuploader/carrierwave · GitHub
Return to Internship Note (LoanStreet)
Previous Episode: Authentication with Devise
Next Episode: User Authorization with Rolify and Cancan
0 comments:
Post a Comment