Use carrierwave
to upload images.
For now, since this is just a sample, we’ll use scaffold to create an item. Later, we’ll add image:string
, but you can create it here as well.
$ rails g scaffold item description:text
Add the following to the Gemfile and run bundle install
.
gem 'carrierwave'
Add an image column to the items
table.
$ rails g migration AddImageToItems image:string
$ rake db:migrate
With CarrierWave, you can enable image upload functionality by creating a program file called an uploader. Here, since we created image
, we’ll match the column name to this. The name itself is arbitrary.
$ rails g uploader image
If app/uploaders/image_uploader.rb
is generated, you’re good to go.
Next, add the following code to app/models/item.rb
.
class Item < ActiveRecord::Base
mount_uploader :image, ImageUploader
end
Add code to the view and controller to upload and save images. When creating a new item, you can select a file to upload and save the URL to the table when saving the item.
Update app/views/items/_form.html.erb
as follows. This allows you to select and attach an image file.
<%= form_for(@item) do |f| %>
<% if @item.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@item.errors.count, "error") %> prohibited this item from being saved:</h2>
<ul>
<% @item.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
<%= f.file_field :image %> ← Added this line.
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Next, configure the controller.
Update items_controller
as follows. Add image
to the permitted keys in the strong parameters.
private
# Use callbacks to share common setup or constraints between actions.
def set_item
@item = Item.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def item_params
params.require(:item).permit(:description, :image)
end
end
Make the images visible on the index page. Update app/views/items/index.html.erb
as follows.
<p id="notice"><%= notice %></p>
<h1>Listing Items</h1>
<table>
<thead>
<tr>
<th>Description</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @items.each do |item| %>
<tr>
<td><%= item.description %></td>
<td><%= image_tag item.image.url %></td> ← Added this line.
<td><%= link_to 'Show', item %></td>
<td><%= link_to 'Edit', edit_item_path(item) %></td>
<td><%= link_to 'Destroy', item, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Item', new_item_path %>
That’s it.
However, you may encounter a NameError uninitialized-constant
. I did too.
After some searching, I found that restarting Spring resolved the issue. Some people resolved it by modifying config/application.rb
, but restarting is simpler if it works.
Spring is an application preloader.
Check the status.
$ spring status
Stop Spring.
$ spring stop
Start it again.
$ rails c