LoginSignup
26
27

More than 5 years have passed since last update.

Rails4+Paperclip+ActiveAdminのメモ

Last updated at Posted at 2014-03-12

Paperclip

installation

brew install imagemagick

gem 'paperclip', '~> 4.1'

:Bundle

migration

:Rails generate migration AddFileUpload

:Rmigration

class AddFileUpload < ActiveRecord::Migration
  def up
    add_attachment :users, :avatar
  end

  def down
    add_attachment :users, :avatar
  end
end

:Rake db:migrate
:Rserver!

Model

  has_attached_file :avatar,
    styles: { medium: "300x300>", thumb: "100x100>" },
    default_url: "/images/:style/missing.png"

  validates_attachment_content_type :avatar,
    content_type: /\Aimage\/.*\Z/

ちなみ画像サイズの後に >はリサイズ、 #を指定するとトリミングしてくれるらしい。
 #はその大きさに拡大された
https://github.com/thoughtbot/paperclip/wiki/Thumbnail-Generation

View

<%= form_for @user, :html => { multipart: true } do |f| %>
  <%= f.text_field :title %>
  <%= f.file_field :avatar %>
  <%= f.submit %>
<% end %>

Controller

def create
@user = User.create(user_params)
end

private

private
def user_params
params.require(:user).permit(:title, :avatar)
end

表示

<%= image_tag user.avatar.url %>
<%= image_tag user.avatar.url(:medium) %>
<%= image_tag user.avatar.url(:thumb) %>

DBに追加されたカラムは?

:Rschema users

create_table "users", force: true do |t|
  t.string   "title"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "avatar_file_name"
  t.string   "avatar_content_type"
  t.integer  "avatar_file_size"
  t.datetime "avatar_updated_at"
end

ファイルの実態はどこ?

Modelに定義したsytylesディレクトリにはいってた

▾ system/
  ▾ users/
    ▾ avatars/
      ▾ 000/
        ▾ 000/
          ▾ 007/
            ▾ medium/
                くにお.gif
            ▾ original/
                くにお.gif
            ▾ thumb/
                くにお.gif

削除

@user.avatar = nil
@user.save

もしくは
@user.destroy

ファイルの実態も勝手に消えた

S3へアップロード

インストール

gem 'aws-sdk'

:Bundle

設定ファイルを作る

もしくはモデルに書くんだけど、設定ファイルの方が楽そうなのでそうした

config/s3.yml

production:
  bucket: xxxxxxxxxx
  access_key_id: yyyyyyyyyy
  secret_access_key: zzzzzzzzzz
development:
  bucket: xxxxxxxxxx
  access_key_id: yyyyyyyyyy
  secret_access_key: zzzzzzzzzz
test:
  bucket: xxxxxxxxxx
  access_key_id: yyyyyyyyyy
  secret_access_key: zzzzzzzzzz

:Rserver!

Model

has_attached_file :avatar,
  styles: { medium: "300x300>", thumb: "100x100>" },
  default_url: "/images/:style/missing.png",
  storage: :s3,
  s3_credentials: "#{Rails.root}/config/s3.yml",
  path: ":attachment/:id/:style/:filename"

画像を保存するパスの変更

デフォルトは
:rails_root/public/system/:attachment/:id/:style/:filename

使える変数
:attachment(画像フィールドの複数形)
:id (レコードid)
:style(指定した画像のサイズ)
:filename (アップロードした画像名)
:extension (画像の形式)
:class(Class名)

画像ファイルの縦横を取得

:Rails generate migration AddImageDimentions

class AddImageDimension < ActiveRecord::Migration
  def change
    add_column :users, :image_width, :integer
    add_column :users, :image_height, :integer
  end
end

:Rake db:migrate

Model

before_save :extract_dimentions
def image?
  avatar_content_type =~ %r{^(image|(x-)?application)/(bmp|gif|jpeg|jpg|pjpeg|png|x-png)$}
end

def extract_dimentions
  return unless image?
  tempfile = avatar.queued_for_write[:original]
  unless tempfile.nil?
    geometry = Paperclip::Geometry.from_file(tempfile)
    self.image_width = geometry.width.to_i
    self.image_height = geometry.height.to_i
  end
end

画像のURLの難読化

/config/initializers/paperclip_defaults.rb

イニシャライザに設定しておく。:hash_sercretはSecureRandom.base64(128)をつかってる。

Paperclip::Attachment.default_options.update({
:path => ":rails_root/public/system/:attachment/:hash/:id.:extension",
:hash_secret => "適当な文字列"
})

:Rserver!

Model

has_attached_file :avatar,
  url: "#{ActionController::Base.relative_url_root}/system/:attachment/:hash/:id.:extension"

ファイルのパスやURLを取得したい

save後、モデル.:attachment.pathで取得できた

@user.save
@user.avatar.path
@user.avatar.url

activeadminで使いたい

installation

Gemfile

gem 'formtastic', github: 'justinfrench/formtastic'
gem 'ransack', github: 'activerecord-hackery/ransack', branch: 'rails-4.1'
gem 'polyamorous', github: 'activerecord-hackery/polyamorous'
gem 'activeadmin', github: 'gregbell/active_admin'

:Bundle
:Rails generate active_admin:install

このへんをやる、予定

1. Ensure you have defined default url options in your environments files. Here
   is an example of default_url_options appropriate for a development environment
   in config/environments/development.rb:

     config.action_mailer.default_url_options = { :host => 'localhost:3000' }

   In production, :host should be set to the actual host of your application.

2. Ensure you have defined root_url to *something* in your config/routes.rb.
   For example:

     root :to => "home#index"

3. Ensure you have flash messages in app/views/layouts/application.html.erb.
   For example:

     <p class="notice"><%= notice %></p>
     <p class="alert"><%= alert %></p>

4. If you are deploying on Heroku with Rails 3.2 only, you may want to set:

     config.assets.initialize_on_precompile = false

   On config/application.rb forcing your application to not access the DB
   or load models when precompiling your assets.

5. You can copy Devise views (for customization) to your app by running:

     rails g devise:views

:Rake db:migrate

:Rserver!
:Rails generate active_admin:resource user

ActiveAdminでPaperclipを動かす

admin/user.rb

ActiveAdmin.register user do
  form multipart: true do |f|
    f.inputs 'user' do
      f.input :title
      #f.input :avatar, as: :file
      f.input :avatar, required: false
    end

    f.actions
  end
  permit_params :title, :avatar
end

ArgumentError in Admin::users#new になったけど、
現状required: falseにすれば回避できた
http://stackoverflow.com/questions/22002259/activeadmin-and-paperclip-argumenterror

まとめ:S3(Tokyo region)を使ってpathにhashを使って、保存パスと画像サイズをDB保存

Photoモデルにresourceをattach
app/models/photo.rb

class Photo < ActiveRecord::Base
  before_save :append_resource_info

  has_attached_file :resource,
    storage: :s3,
    s3_credentials: "#{Rails.root}/config/s3.yml",
    path: "/photos/:resource_user_id/:file_updated_hash.:extension",
    url: ":s3_path_url",
    s3_host_name: "s3-ap-northeast-1.amazonaws.com"


  validates_attachment_content_type :resource,
    content_type: /\Aimage\/.*\Z/

  private

    Paperclip.interpolates :file_updated_hash  do |attachment, style|
      Digest::SHA256.hexdigest(format("%s/%d", attachment.instance.resource_file_name, attachment.instance.resource_updated_at.to_i))
    end

    def image?
      resource_content_type =~ %r{^(image|(x-)?application)/(bmp|gif|jpeg|jpg|pjpeg|png|x-png)$}
    end

    def append_resource_info
      return unless image?
      tempfile = resource.queued_for_write[:original]
      unless tempfile.nil?
        geometry = Paperclip::Geometry.from_file(tempfile)
        self.resource_file_width = geometry.width.to_i
        self.resource_file_height = geometry.height.to_i
        self.resource_path = self.resource.path
      end
    end

end


26
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
27