· 8 years ago · Jun 23, 2018, 02:06 AM
1### Image Uploading using Basic Rails
2
3----
4
5#### Structure
6
7* In the root of your rails app, there is `public` folder used to hold **static** files!
8 * This folder is hit before Rails is! For example, inside this public folder, there static html
9 error pages (404), if you go to your browser and type `localhost:3000/404` you will see that
10 page renders immediately, Rails does not need to process it and serve it (no database lookups
11 or route lookups)
12* Inside `public`, you can create a file that will store the images for your model!
13* You will need to design the file structure of the images: for example, using a `Book` model:
14 * `cd public && mkdir books`
15* What if we have several images for the book? (Front cover, back cover, author image ...)
16* Before that, you can use the id of the model object to create dynamic folders for each object
17 * Book with an id of 2 will have it images located in the path: `public/books/2/`
18 * Possible image paths for different types of images: `public/books/2/cover`,
19 `public/books/2/back`, `public/books/2/author`
20 * You can then save the image in the respective folder!
21 * Then in your views, to show the image:
22 `<%= image_tag "/books/#{@book.id}/cover/cover.jpg" %>`
23* Now the image will appear. Next, add the uploader to your `edit` page:
24 * You will need to add a database field to your model for the image, this way you can save that
25 attribute and be able to change it!
26 * Then, in your form, you can add the new field via: `<%= f.file_field :db_name %>`
27 * **Add the new changes to your permitted params into your controller! **
28 * In the model, add an `attr_accessor` for the database name field!
29 * Add an `after_save :save_cover_image, if: :cover` callback: which allows us to take the file
30 that was uploaded and save it to the public directory!
31
32```ruby
33class Book
34 after_save :save_cover_image, if: :cover
35
36 def save_cover_image
37 filename = cover.original_filename #given by the file upload
38 folder = "public/books/#{id}/cover"
39
40 FileUtils::mkdir_p folder # generates the given folder path rather then checking to see
41 # if each path exists one by one
42
43 f = File.open File.join(folder, filename), "wb"
44 f.write cover.read()
45 f.close
46
47 self.cover = nil
48 update cover_filename: filename # cover_filename is the actual database name in the books table
49
50 end
51end
52```
53
54* The above code creates an attribute reader and writer method called `cover`.
55* The object has a database field called `cover_filename` (which is a string).
56* After an object has created or updated, the after_save callback is used to store the file in your
57rails app (within the public directory), then the object has its `cover_filename` attribute updated
58
59* Then you can edit the show page:
60`<%= image_tag "/books/#{@book.id}/cover/#{@book.cover_filename}" if @book.cover_filename? %>`
61
62---
63
64### Using Carrierwave
65* Install carrierwave via gemfile: `gem 'carrierwave', ~> 0.10.0`
66* `bundle install`
67* `rails g uploader Cover` (Cover for example)
68* Make sure your model has a db column named after the uploader (so it would have to be cover,
69not cover_filename like above)
70* In your model class, `mount_uploader :cover, CoverUploader`
71* Finally, in your view: `<%= link_to @object.url if @object.cover? %>`