Skip to content

Instantly share code, notes, and snippets.

@elvisgiv
Last active July 8, 2016 15:35
Show Gist options
  • Save elvisgiv/89b44d4f51cc6ba82f5d to your computer and use it in GitHub Desktop.
Save elvisgiv/89b44d4f51cc6ba82f5d to your computer and use it in GitHub Desktop.

#Avatar with gem paperclip http://www.peoplecancode.com/en/tutorials/users-avatars-uploading-images-using-paperclip

https://github.com/thoughtbot/paperclip

##Задача - сделать аватар для пользователей Сначала устанавливаем гем paperclip в Gemfile проекта

 gem 'paperclip', '~> 4.3'

делаем bundle install

затем в терминале в папке с проектом пишем rails generate migration add_avatars_to_users, которая создаст файл в папке db/migrate//20140516064357_add_avatars_to_users.rb

заходим в него и заполняем кодом:

db/migrate/20140516064357_add_avatars_to_users.rb
 class AddAvatarsToUsers < ActiveRecord::Migration
   def self.up
     change_table :users do |t|
       t.attachment :avatar
     end
   end
 
   def self.down
     drop_attached_file :users, :avatar
   end
 end

затем в терминале в папке с проектом пишем rake db:migrate

заходим в модель user.rb и пишем

 class User < ActiveRecord::Base
   # existing code
 
   has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100#" }, :default_url => "/images/:style/missing.png"
   validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
 end

создаем в папке public папки с файлами images/medium/missing.png images/thumb/missing.png

добавляем :avatar in permit params

  def update
    @user = current_user
    avatar = user_params_for_avatar
    @res = @user.update(avatar)
    respond_to do |format|
      if @res
        format.html {
          redirect_to profileshow_path, notice: 'User was successfully updated'
        }
        #format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit }
        #format.json { render json: @user.errors, status: :unprocessable_entity }
    end
  end
  
   def user_params_for_avatar
     params.require(:user).permit(:avatar)
   end

для show.htm.haml можем использовать на выбор:

      = image_tag avatar_url(@user)

метод avatar_url мы определяем в хэлпере

/../app/helpers/application_helper.rb
module ApplicationHelper

  def avatar_url(user)
    if user.avatar.present?
      user.avatar.url(:medium)
    else
      gravatar_id = Digest::MD5.hexdigest(user.email.downcase)
      "http://gravatar.com/avatar/#{gravatar_id}.png?s=100&d=identicon"
    end
  end

end

в форме _form.html.haml

    = horizontal_simple_form_for(@user, :url => profileupdate_path, :method => :put, :html => { :multipart => true}) do |f|
      -#= f.error_notification
      = render 'shared/form_errors', {f: f}
      = f.input :avatar, as: :file

Изменение пути сохранения фото и изменение отображения фото в браузере

https://github.com/thoughtbot/paperclip#uri-obfuscation

http://stackoverflow.com/questions/7593548/paperclip-converting-tiff-images-into-jpg-or-png

../models/user.rb
class User < ActiveRecord::Base
  
  has_attached_file :avatar, {
                               url: "/users/:attachment/:id_partition/:style/:hash.:extension",
                               hash_secret: "BlaBlaBla",
                               :styles => {
                                   :thumb => ["150x172#",:jpg],
                                   :medium => ["300x300#",:jpg],
                                   :large => ["100%", :jpg]
                               }
                           }
  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
  ...some code here
end

url: "/users/:attachment/:id_partition/:style/:hash.:extension", сохраняет в папку public, создавая директорию users/avatars/000/000/папка с номером id в базе данных с папками для каждого из ключей хэша (thumb, medium, large) и соответствующим каждому ключу файлами в этих папках с расширением файла, написанным в хэше.

hash_secret: "BlaBlaBla", шифрует название файла для отображения в браузере (например загружаемый файл flower.jpg в браузере будет называться 038974650239487523489570293645.jpg). В базу заносится название файла, загружаемое юзером (flower.jpg)

"300x300#" - точный размер "300x300>" - не обрезает

Задача - сделать рандомные аватарки, если нет фото

http://guides.railsgirls.com/gravatar/

http://railscasts.com/episodes/244-gravatar?autoplay=true

https://github.com/chrislloyd/gravtastic

http://en.gravatar.com/site/implement/images/

в Gemfile добавляем gem 'gravtastic' делаем bundle install

добавляем в модель user.rb

class User < ActiveRecord::Base
  include Gravtastic
  gravtastic
end

теперь во вьюхе мы можем использовать = image_tag @user.gravatar_url

для того, чтобы у нас были рандомные граватарки

в application_helper.rb (см. выше) код в методе avatar_url

   ...
      gravatar_id = Digest::MD5.hexdigest(user.email.downcase)
      "http://gravatar.com/avatar/#{gravatar_id}.png?s=100&d=identicon"

дает нам возможность генерировать рандомные аватарки по ключу user.email, если в базе для данного юзера нет аватарки, то генерится рандомная identicon

также можно воспользоваться другими шаблонами для создания рандомных аватарок:

404: do not load any image if none is associated with the email hash, instead return an HTTP 404 (File Not Found) response
mm: (mystery-man) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)
identicon: a geometric pattern based on an email hash
monsterid: a generated 'monster' with different colors, faces, etc
wavatar: generated faces with differing features and backgrounds
retro: awesome generated, 8-bit arcade-style pixelated faces
blank: a transparent PNG image (border added to HTML below for demonstration purposes)

Изменение формы аватарки

http://stackoverflow.com/questions/8789820/rounded-corners-with-paperclip

http://www.imagemagick.org/Usage/thumbnails/#rounded

для содания любых форм и рамок для аватарки можно воспользоваться примером из ссылки выше.

задача - сделать круглую аватарку

для этого создаем метод convert_options в модели и подправляем styles в параметрах метода has_attached_file в модели user.rb

../models/user.rb

class User < ActiveRecord::Base
  has_attached_file :avatar, {
                               url: "/users/:attachment/:id_partition/:style/:hash.:extension",
                               hash_secret: "BlaBlaBla",
                               :styles => {
                                   :thumb => ["100x100#",:jpg],
                                   :medium => ["300x300#",:png],
                                   :original => ["100%", :jpg],
                               },
                               :convert_options => {:medium => Proc.new{self.convert_options}}
                           }
                           
  def self.convert_options(px = 150)
    trans = ""
    trans << " \\( +clone  -alpha extract "
    trans << "-draw 'fill black polygon 0,0 0,#{px} #{px},0 fill white circle #{px},#{px} #{px},0' "
    trans << "\\( +clone -flip \\) -compose Multiply -composite "
    trans << "\\( +clone -flop \\) -compose Multiply -composite "
    trans << "\\) -alpha off -compose CopyOpacity -composite "
  end

ВАЖНО!!!

расширение изменяемого файла нужно ставить .png, как здесь :medium => ["300x300#",:png]

Задача - ссылки на загружаемые файлы

models

 ../app/models/product_document.rb
 
 class ProductDocument < ActiveRecord::Base
  belongs_to :product, class_name: "Product", foreign_key: 'product_id'

  has_attached_file :doc,
                    styles:{},
                    url: "/docs/:id_partition/:basename.:extension"

  do_not_validate_attachment_file_type :doc
end

controllers

 ../app/controllers/product_documents_controller.rb
 
 class Admin::ProductDocumentsController < Admin::MyAdminBaseController
  def model_name
    :product_document
  end
  
  def index
    @product = Product.find(params[:product_id])
    @items = @product.documents
  end
  
  def item_params
   params.require(model_name).permit(:doc)
  end
 end

views

../app/views/product_documents/_form.html.haml

= horizontal_simple_form_for([:admin, @item], html: { class: 'form-horizontal' }) do |f|
  = f.error_notification

  = f.input :doc, as: :file
../app/views/product_documents/_form.html.haml

%table.table.table-striped.table-bordered.table-hover
  %tr
    %th File

  - @items.each do |item|
    %tr
      %td
        - if item.doc.exists?
          = link_to "#{item.doc.url}", item.doc.url, target: "_blank"
        - else
          N/A
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment