Protecting upload

Before protecting uploading, we need to add the association between the user and the albums/photos.

Execute the following migration generation commands and migrate the database.

$ rails generate migration AddUserIdToAlbum user_id:integer
$ rails generate migration AddUserIdToPhoto user_id:integer
$ rake db:migrate
==  AddUserIdToAlbum: migrating ===========================
-- add_column(:albums, :user_id, :integer)
   -> 0.0016s
==  AddUserIdToAlbum: migrated (0.0018s) ==================

==  AddUserIdToPhoto: migrating ===========================
-- add_column(:photos, :user_id, :integer)
   -> 0.0009s
==  AddUserIdToPhoto: migrated (0.0011s) ==================

Then add belongs_to :user to both album.rb class and photo.rb class.

And the following to user.rb class.

1has_many :photos
2has_many :albums

Next, we would like to protect user upload in the photos controller.

1before_filter :authenticate_user, only: [:new, :edit]
2
3def authenticate_user
4  redirect_to new_user_session_url unless user_signed_in? and !@album.user.nil? and current_user == @album.user
5end

And we add the user association @photo.user = current_user in the create method.

 1def create
 2  @photo = @album.photos.new params[:photo]
 3  @photo.user = current_user
 4  if @photo.save
 5    redirect_to @album
 6  else
 7    render :new
 8  end
 9end

Now when we go to any photo upload URL without logged in to the album owner, we will be redirected to the sign_in page.

Then we apply the same to the albums controller.

In the albums_controller file.

1before_filter :authenticate_user, only: [:new]
2
3def authenticate_user
4  redirect_to new_user_session_url unless user_signed_in?
5end

And the user-albums association in the create method.

 1def create
 2  @album = Album.new params[:album]
 3  @album.user = current_user
 4  if @album.save
 5    redirect_to @album
 6  else
 7    render :new
 8  end
 9end

Note: If both `authenticate_user` share the same logic, we can further extract it into their common parent class — application_controller.

It’s time to test the function in web browser.

We can create albums and upload photos as normal after we logged in. Now try to create another user account and access the album you just created, you should not be able to upload any new photos.

The view

One last thing, we don’t want the upload photo or edit link appears on the photo that isn’t belonged to the current user.

In the views/photos/show.html.erb file.

1<%- if user_signed_in? and current_user == @photo.user %>
2  <%= link_to 'Edit', edit_album_photo_path(@album, @photo) %>
3<%- end %>

And the views/albums/show.html.erb file.

1<%- if user_signed_in? and current_user == @album.user %>
2  <p><%= link_to 'Upload new photo', new_album_photo_path(@album) %></p>
3<%- end %>

What’s next? We’re going to take a look at “Challenges”.

overlaied image when clicked on thumbnail

Makzan | Ruby on rails 101 | Table of Content