CarrierWave 環境ごとにディレクトリ変更

こんにちは。麺処まつば副店長です。
いやぁ…暑いですね…。ガリガリ君梨味を食べてもまだ暑いです…

今回は、予告通り carrierWave のファイル保存先ディレクトリを
環境ごとに切り替えた話でもしようと思います。

大した作業は必要ないです。
cache_dir/store_dir をオーバーライドするだけです。

参考
https://github.com/carrierwaveuploader/carrierwave#changing-the-storage-directory

app/uploaders/hoge_uploader.rb

 1 class HogeUploader < CarrierWave::Uploader::Base
 2   
 3   def store_dir
 4     "uploads/#{Rails.env}/file/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
 5   end
 6   
 7   def cache_dir
 8     "uploads/#{Rails.env}/file/tmp/#{model.class.to_s.underscore}/#{mounted_as}"
 9   end
10   
11 end

3~5行目で store_dir のオーバーライド、
7~9行目で cache_dir をオーバーライドしています。

それぞれ「Rails.env」を使うことで環境毎にディレクトリが切り替わるようになっています。
それ以外は適宜変更すると良いです。

CarrierWave + RSpec ディレクトリ問題

こんにちは。麺処まつば副店長です。

今回も引き続き git のブランチ周りの記事でも書こうと思ったのですが
うまい例が降りて来ず…一旦CarrierWaveに逃げました。

そんな訳で、今回はCarrierWave関連のrspecを実行する際の
落とし穴についてでも書いてみようと思います。

CarrierWave系関連のテストを実行する場合、特に何も指定していないと
1)デフォルトのディレクトリにファイル保存される
2)ファイルがひたすら溜まっていく
という状況になります。

この1)実はクセモノで、確か development 環境でも特に指定がないと
同じディレクトリにファイルを保存してしまうのです。
なので今回は、以前コレ↓をやったときのことでも書いてみます。
a)rspecで保存されるファイルのディレクトリを指定
b)テスト終了後にファイルを削除する

やったことは下記にある通りなんですが、自分用メモということで
https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Cleanup-after-your-Rspec-tests


spec/spec_helper.rb

RSpec.configure do |config|
  …略…
  #「b)テスト終了後にファイルを削除する」のための記述
  config.after(:all) do
    if Rails.env.test?
      FileUtils.rm_rf(Dir["#{Rails.root}/spec/support/uploads"])
    end
  end
end

#「a)rspecで保存されるファイルのディレクトリを指定」のための記述
if defined?(CarrierWave)
  CarrierWave::Uploader::Base.descendants.each do |klass|
    next if klass.anonymous?
    klass.class_eval do
      def cache_dir
        "#{Rails.root}/spec/support/uploads/tmp"
      end 
               
      def store_dir
        "#{Rails.root}/spec/support/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
      end 
    end
  end
end

a)rspecで保存されるファイルのディレクトリを指定
コレに該当するのが下の方の「if defined?(CarrierWave)」からの記述。
chache_dir と store_dir それぞれをオーバライドし、保存用のディレクトリを変更しています。
ディレクトリは適宜変更すると良いと思います。

Uploader が1つなのであれば
その Uploader 内でオーバーライドしちゃえばいいと思うのですが
副店長の環境では Uploader が沢山あったので、spec_helperで指定しています。

b)テスト終了後にファイルを削除する
RSpec.configure」中の「config.after(:all)」の記述で
テスト終了後に rspec 実行中に保存された画像をディレクトリごとごっそり削除しています。
当然ですが、削除するディレクトリはa)で指定したディレクトリです。


見落としがちなんですが CarrierWave の Wiki って結構大事な事かいてあるんですよね…
https://github.com/carrierwaveuploader/carrierwave/wiki

次回は、環境毎に保存先ディレクトリを変更した時の話でも書こうと思います。

Git と仲良くなりたい(希望) リポジトリの管理・設定編

リポジトリの管理や設定のためのコマンドをまとめてみました。

config 各種設定を変更
gc リポジトリ最適化


config

各種設定を変更します。

コマンド 内容
git config --global user.email [email] メールアドレスを設定
git config --global user.name [name] ユーザ名を設定
git config --global color.ui auto 表示を色付きにする
git config --global alias.[aliasname] [commandname] エイリアスを設定。
例えば「svn ci」みたいにしたい場合はこう↓
例)git config --global alias.ci "commit"
git config -l そのリポジトリでのgitの設定内容を表示
git config -l --global gitで使われる共通のデフォルト設定内容を表示

実際の設定値は
globalでの設定が「~/.gitconfig」、
リポジトリでの設定が「[対象ディレクトリ]/.git/config」
に書いてあるようです。



gc

リポジトリを圧縮、不要なファイルを削除して、リポジトリ最適化。
履歴情報を圧縮したりするようです。お掃除コマンド。

コマンド 内容
git gc リポジトリ最適化

具体的にどのようなファイルが不要ファイルとして扱われるのか?
と疑問に思って、色々試してみたのですが良くわからず…店長に聞いて見ました。↓

<店長>
gcは例えば<git reset>した時の宙ぶらりんのコミット内容とかが対象となる
あとは、削除したブランチとか。他にもあると思う。
重くなった時にやる。

だそうです。


目次へ

Git と仲良くなりたい(希望) ファイル状態・履歴編

ファイルの変更や履歴を確認するためのコマンドをまとめてみました。

status 変更したファイルを表示
diff 差分を表示
log コミットログを表示
show コミット詳細を表示



status

変更したファイルを表示

コマンド 内容
git status 変更のあるファイルを表示

statusは、svn status と同じ感覚で使って問題なさそうです。



diff

差分を取ります。

コマンド 内容
git diff 作業コピーとインデックスの比較
git diff [path] path指定で
git diff HEAD 作業コピーとHEAD最新との比較
git diff HEAD^ 作業コピーとHEAD最新の1つ前と比較
git diff --cached インデックス最新とHEAD最新を比較

Subversion と違って Git は3本柱なので、
それぞれ比較用にコマンドが…沢山…大変…。


log

コミットのログ表示

コマンド 内容
git log ログ参照
git log [path] 指定したpathのログを表示
git log -[数字] 指定した数字の数分のログ表示
git log -p パッチ形式でログ出力
git log --pretty=short ログメッセージの最初の1段落だけ表示
git log --grep='hoge' ログをhogeでgrepして表示
git log --name-status 変更されたファイルと追加、変更等を表示

こちらも、svn log と同じ感覚で使って問題なさそうです。


show

コミットの詳細を表示

コマンド 内容
git show 最新のコミット詳細を表示
git show [コミットID] 指定したコミットの詳細を表示
git show HEAD 最新のコミット情報を表示
git show HEAD^ 最新の1つ前のコミット情報を表示
git show HEAD^^ 最新の2つ前のコミット情報を表示
git show HEAD~3 最新の3つ前のコミット情報を表示



一覧へ

Git と仲良くなりたい(希望) ファイル変更・操作編

実際のファイルの変更等に使うコマンドをまとめてみました。

add インデックスに変更を追加
mv ファイル名の変更・移動
rm ファイル削除
commit インデックスの中身をリポジトリに登録
reset コミットの取り消し
revert 過去のバージョンに上書きコミット


add

add は インデックスに追加するためのコマンドのようです。

コマンド 内容
git add [path] 指定 path を add
git add [path1] [path2] 複数 path のとき
git add -u 既に git で管理しているファイルを全部add
git add -A 既に git で管理しているファイル
+新規(無視リスト以外)を全部 add
git add -p 対話型 add

一度 commit したファイルでも、変更を加えてcommit したい場合は
再度 add する必要があるとの事。
Subversion の 「svn add」とはちょっと意味合いが違うようです。



mv

ファイル名を変更、または移動します。

コマンド 内容
git mv before.txt after.txt ファイル before.txt の名前を after.txt に変更。
さらに変更情報をインデックスに登録
git mv before.txt [dir path] before.txt を指定したディレクトリに移動。
さらに変更情報をインデックスに登録


rm

ファイルを削除します。

コマンド 内容
git rm [file path] 指定されたファイルをワークツリーから除去
さらにインデックスに削除情報を登録
git rm -r [dir path] ディレクトリを消す場合は -r オプションを追加
git rm --cached [path] ワークツリーにファイルを残し、インデックスからのみ除去。
図で言う「①」を行わず、「②」のみを行います。



commit

commit で インデックスの中身をリポジトリ登録です。

コマンド 内容
git commit エディタが立ち上がるタイプ
git commit -m "message" エディタなし一発
git commit -a [git add -u] + [git commit]
git commit [path] path 指定して commit

エディタをvimに変えたいときはこう。

$ git config --global core.editor 'vim -c "set fenc=utf-8"'



reset

コミットを取り消す。

コマンド 内容
git reset [path] 指定したpathをHEADの最新の状態に戻す
git reset HEAD^
git reset --soft HEAD^
リポジトリとインデックスをHEAD最新の1つ前の状態に戻す。
git reset --hard HEAD^ ワークツリーもろともHEAD最新の1つ前の状態にする

HEAD^で1つ前、HEAD^^で2つ前。
HEAD~3で3つ前。
「--soft」または「指定なし」とすることで、リポジトリとインデックスに反映。
「--hard」とすることで、リポジトリとインデックスとワークツリー全部に反映。



revert

ある時点のコミットを、
1)ワークツリーに反映し、2)さらにコミットまでする。
resetと違って、コミットを消すわけではなく上書きコミットするようなイメージ。

コマンド 内容
git revert [コミットID] ワークツリーをコミットID時点のものに上書きしコミット
git revert HEAD^ HEAD最新の1つ前の状態に revert

<オマケ>
ワークツリー・インデックスに変更がある場合に revert を
実行するとどうなるのかな?と思って実験してみました。
ワークツリー変更状態(インデックスには add していない状態)で revert するとエラー。

error: Your local changes to the following files would be overwritten by merge:
hoge.txt
Please, commit your changes or stash them before you can merge.
Aborting

インデックスに add している状態で revert してもエラー。

fatal: Your local changes would be overwritten by revert.
Please, commit your changes or stash them to proceed.

そうですかダメですか…。



目次へ

Git と仲良くなりたい(希望) リポジトリの作成・コピー編

gitのリポジトリ作成、複製など一番最初に必要なものをまとめました

init リポジトリの新規作成
clone 既存リポジトリをローカルにコピー。svn checkoutぽいもの



init

$ cd [対象ディレクトリ]
$ git init

こうすることで、「. git」なる隠しディレクトリができて
この中にインデックスとリポジトリのデータが入っているようです。
# Subversion だと、「. svn」ディテクトリが至る所にありましたけど
# Git だと、トップのディレクトリにしか設置されないようです。
# (最近はSubversionでもトップのディレクトリにしか設置されなくなったようですね)



clone

既存リポジトリの内容をクローンします。
svn checkoutと同じようなものと思います。

コマンド 内容
git clone [git url] 指定されたGitの中身をコピー。
例)git clone git://github.com/schacon/grit.git
urlの指定は、gitの他に、httpやsshrsync等もあるようです。
git clone [git url] [dir name] 指定されたGitの中身を指定されたディレクトリにコピー。


目次へ

CarrierWave + RMagick 画像のリサイズをまとめてみました

こんにちは。麺処まつば副店長です。
久々の投稿ですけど、もう色々気にしないことにしました。
店長の視線がなんだって言うんですか。(キッ)

さて副店長、先日中ずっとCarrierWaveを扱っておりまして
その中でRMagickを使った画像のリサイズもやっておりました。
このリサイズ用のメソッドがいくつか存在するのですが
http://rubydoc.info/gems/carrierwave/CarrierWave/RMagick
副店長は鳥頭のため…、何度やっても「どれがどうなるんだっけ?」という状況に…。
そこで、リサイズメソッドと実行の結果を何パターンかまとめてみます。

まずはオリジナルのこのような画像を用意してみました。
↓100×100(各マス20x20)の画像です。
(なぜか5段目の青だけ濃ゆいのですが、どうかお気になさらず…。)
f:id:noodles_mtb:20130708123634p:plain

では、この画像を下記のメソッドにかけてみます。
・resize_to_fit
・resize_to_limit
・resize_and_pad
・resize_to_fill

resize_to_fit(width, height)

まずはお馴染みの resize_to_fit です。
縦横比を保持したまま、指定されたサイズに収まるようリサイズします。

指定サイズ 元画像 実行後の画像 備考
150x150 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708135235p:plain  
150x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708123634p:plain  
150x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
100x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708123634p:plain
100x100 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708123634p:plain  
100x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  

resize_to_geometry_string(geometry_string)

引数に与えられた文字列から、リサイズを行います。

  resize_to_geometry_string("150x50")

このような形で150x50でリサイズします。
実行したときの挙動はおそらく resize_to_fit のそれと同じです。
違っていたらどなたかツッコミお願いします。

resize_to_limit(width, height)

resize_to_fitと同様に縦横比を維持したままリサイズします。
resize_to_fitとの違いは、対象の画像のサイズが引数に指定された縦横サイズ以内の場合はリサイズしません。
指定された縦横サイズをオーバーした場合にのみ、指定されたサイズに収まるようリサイズします。

指定サイズ 元画像 実行後の画像 備考
150x150 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708125306p:plain resize_to_fitと違うところ。
150x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708125306p:plain  
150x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
100x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708125306p:plain
100x100 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708125307p:plain
100x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  

resize_and_pad(width, height, background = :transparent, gravity = ::Magick::CenterGravity)

与えられたwidthとheightで resize_to_fit のリサイズをします。
さらに足りない部分にbackgroundの色を敷きます(副店長は座布団と呼んでいます。)
座布団を敷くので、必ず指定されたサイズぴったりの画像になります。
gravityは座布団の上のどの位置に画像を配置するか、です。
下記の例では、黒い座布団の中央にリサイズした画像を配置するようにしています。

指定サイズ 元画像 実行後の画像 備考
150x150 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708142755p:plain 所々黒いのは元画像が透過のため
150x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708142942p:plain  
150x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143058p:plain  
100x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143209p:plain
100x100 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708143255p:plain
100x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143342p:plain  
50x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143430p:plain  
50x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143525p:plain  
50x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143606p:plain  

resize_to_fill(width, height, gravity = ::Magick::CenterGravity)

縦横比固定でリサイズをして、さらにgravityで指定された位置をくりぬきます。
指定された width と height のサイズでくり抜ける所まで引き伸ばして、くりぬくイメージ。

指定サイズ 元画像 実行後の画像 備考
150x150 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708144240p:plain  
150x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144331p:plain  
150x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144550p:plain  
100x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144639p:plain
100x100 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708123634p:plain
100x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144729p:plain  
50x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144815p:plain  
50x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708145018p:plain  
50x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708145117p:plain  

オマケ:manipulate!(options = {}, &block)

上記にないリサイズ・加工をする場合は manipulate! を使う必要があります。
このような感じで。

class MenuPhotoUploader < CarrierWave::Uploader::Base 
  include CarrierWave::RMagick
  MAX_WIDTH = MAX_HEIGHT = 300
  
  process :set_bgcolor
  
  def set_bgcolor
    manipulate! do |img|
      img.background_color = 'whitesmoke'
      img.extent(MAX_WIDTH, MAX_HEIGHT, -(MAX_WIDTH-img.columns)/2, -(MAX_HEIGHT-img.rows)/2)
    end
  end # end set_bgcolor

end