Search code examples
javascriptcssruby-on-railscarrierwavephotos

Adding ProfileImage to Photos controller


I have the CarrierWave gem installed. There are no galleries, as I have it setup so that photos belong to a user not a gallery.

I added a avatar column to the Photos table. The other columns are: id, created_at, updated_at, image, name, user_id

The question is how do I set a action so the users can click 'Make Profile Image' and it will make changes to the avatar column? This should be done by either clicking on the thumbnail version of the image or having text overlay.

A example of what I mean:

User Z uploads four photos to their profile. User Z visits their profile and selects one of their uploaded photos to be their Profile image (avatar).

   class PhotosController < ApplicationController

  def new 
    @photo = Photo.new
  end

  def create
    @photo = Photo.new(params[:photo])
    @photo.user = current_user
    if @photo.save
      flash[:notice] = "Successfully created photos."
      redirect_to :back
    else
      render :action => 'new'
    end
  end

  def resize(width, height, gravity = 'Center')
    manipulate! do |img|
      img.combine_options do |cmd|
        cmd.resize "#{width}"
        if img[:width] < img[:height]
          cmd.gravity gravity
          cmd.background "rgba(255,255,255,0.0)"
          cmd.extent "#{width}x#{height}"
        end
      end
      img = yield(img) if block_given?
      img
    end
  end

  def edit
    @photo = Photo.find(params[:id])
  end

  def update
    @photo = Photo.find(params[:id])
    if @photo.update_attributes(paramas[:photo])
      flash[:notice] = "Successfully updated photo."
      redirect_to @photo.gallery
    else
      render :action => 'edit'
    end
  end

  def destroy
    @photo = Photo.find(params[:id])
    @photo.destroy
    flash[:notice] = "Successfully destroyed photo."
    redirect_to @photo.gallery
  end

  def avatar
    @photo = Photo.find params[:photo_id]
    current_user.default_photo = @photo
    redirect_to '/profile'
  end
end

view (shows thumb photos on profile):

<div class="parent-container">
    <% @user.photos.each do |photo| %>
        <%= link_to image_tag(photo.image_url(:thumb)), photo.image_url%>
<% end %></div></p>

Solution

  • You have a User and a User has Photos, of which one could be the Avatar...

    What I would recommend you do is have a avatar_id on User, and a relationship like the following:

    class User < ActiveRecord::Base
      has_many :photos
      belongs_to :avatar, class_name: 'Photo'
    end
    

    Then in your controller, if you preference is to add a new action, it would be like so:

    class PhotosController < ApplicationController
      ...
    
      def avatar
        if current_user.update_attribute(:avatar_id, params[:id])
          #set flash success
        else
          #set flash fail
        end
        redirect_to(current_user) # However you plan to handle this...
      end
    
      ...
    end
    

    (The reason why you might want to use a new controller is to maintain "DRY")

    Which I assume you would have a member route like so:

    resources :photos do
      member do
        post :avatar
      end
    end
    

    And an action like so:

    button_to('Set as Avatar', [:avatar, @photo])
    

    Then you reference it in the view like so:

    @user.avatar.image_url(:thumb)
    

    That should do the trick.