paperclipを使ってて「縦長の画像をアップしたら横長になる」という問題。

これはpaperclipが悪いんじゃなくて、元のファイルもMacのPreviewで見ると縦長なんだけど、ブラウザで見ると横長。MacのPreview他、ExifのOrientationタグに対応したソフトで見ると縦長に見える。

Webアプリ的にはちょっと困る。「縦長の画像をアップしたら横長になった!」と言われても見てるツールの違いで最初から横長なんだから。

imagemagickのconvertにはExifのOrientationタグの内容に合わせて画像データを回転させてくれる超便利な-outo-orientオプションがあるのでそれを使えばいい。

paperclipはrmagickを使わず、convertコマンドを呼び出すだけで、好きなオプションが渡せるというイカシタ作りになっているのでこんな感じでOK。

class User < ActiveRecord::Base
  has_attached_file :picture, convert_options: {all: '-auto-orient'}
end

allは複数のstyleが合った場合に全部にこのオプションを付けるという指定。originalも残るから安心。

# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  if Rails.env.production?     
    provider :twitter, 'xxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxx'
  else
    provider :twitter, 'ooooooooooo', 'oooooooooooooooooooo'
  end
end

今まで通りだと動きません。test/test_helper.rbに下記を追加。

require 'shoulda/rails'

今βのshoulda 3.xなら大丈夫なのでもうすぐこれも必要無くなるみたいです。

rails3.1でMySQLからやってくる文字列がASCII-8BITになっているのでto_jsonすると壊れる(to_jsonがencodingを見て処理するので)。sqlite3では起こらない。

環境はSnow Leopard、ruby1.9.2-p290、homebrewで入れたmysql 5.1.54。

% rails new foo
% cd foo
% vi Gemfile
(...)
gem 'mysql'
(...)
% bundle
% vi config/database.yml
(...)
development:
  adapter: mysql
  encoding: utf8
  database: foo_development
  pool: 5
  username: root
  password: 
  host: localhost
  socket: /tmp/mysql.sock
(...)
% rails g model post title:string
% rake db:create
% rake db:migrate
% vi db/seeds.rb
Post.create!(title: 'うんk')
% rake db:seed
% rails c
ruby-1.9.2-p290 :001 > puts Post.first.title
うんk
 => nil 
ruby-1.9.2-p290 :002 > Post.first.title.encoding
 => #<encoding:ascii-8bit>
ruby-1.9.2-p290 :003 > puts Post.first.title.to_json
"\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd"
 => nil

CentOS 5.6でも同じ。

解決:

mysql gemはruby1.9.1からのencodingに対応してない。だからmysql2を使えば解決でした。

% vi Gemfile
(...)
  gem 'mysql2'
(...)
% vi config/database.yml
(...)
  adapter: mysql2
(...)
% rails c
ruby-1.9.2-p290 :001 > Post.first.title.encoding
 => #<Encoding:UTF-8>

adapterにmysql2と書けるというところが盲点でした・・・。

% node -v  
v0.4.8
% rails -v
Rails 3.1.0
% rails new foo
% cd foo
% vi app/assets/stylesheets/foo.css.scss
body {
  background: image-url("rails.png");
}
% rake assets:precompile
rake aborted!
rails.png isn't precompiled
  (in /Users/komagata/tmp/foo/app/assets/stylesheets/foo.css.scss)

Tasks: TOP => assets:precompile
(See full trace by running task with --trace)

何故だろう?

とりあえずはconfig/environments/production.rbconfig.assets.compile = true

にしてLive compileして凌いでいる。

追記:

rails3.1のバグでした。3.1.1を待て。

先週、怖話.jpのランキングを重いサブクエリを書いて実装しましたが、Rails3レシピブック(Recipe 093 カウンタキャッシュを利用する)を見ていたらcounter_cacheというので簡単に速くなりそうだったのでやってみた。

ASCIIcasts - “Episode 23 - Counter Cache Column”

要はfoo has many barsという関係の時にbarのbelongs_toに:counter_cache => trueと書いて、fooのDBにbars_countというカラムを追加すればいいらしい。

怖い話(story)に付いている怖い(scare)とコメント(comment)の集計にcounter_cacheを使ってみた。

class Scare < ActiveRecord::Base
  belongs_to :story, :counter_cache => true
end
class Comment < ActiveRecord::Base
  belongs_to :story, :counter_cache => true
end
class AddCounterCacheToStories < ActiveRecord::Migration
  def self.up
    add_column :stories, :comments_count, :integer, :null => false, :default => 0
    add_column :stories, :scares_count, :integer, :null => false, :default => 0

    Story.all.each do |story|
      Story.update_counters(story.id, :comments_count => story.comments.count)
      Story.update_counters(story.id, :scares_count => story.scares.count)
    end
  end

  def self.down
    remove_column :stories, :comments_count
    remove_column :stories, :scares_count
  end
end

counter_cacheはfooのcreateとdestroyのコールバックとして数を増減するというだけの動作なので、後付けする場合はupdate_countersメソッドで集計し直してやる必要がある。

class Story < ActiveRecord::Base
  scope :order_by_ranking, joins(:user).order("view + (select count(*) from scares where scares.story_id = stories.id) * #{Scare::RANKING_WEIGHT} + (select count(*) from comments where comments.story_id = stories.id) * #{Comment::RANKING_WEIGHT} desc, stories.id desc").includes(:user)
end

お陰でこんな醜悪なクエリが、

class Story < ActiveRecord::Base
  # scares_count and comments count is using counter_cache.
  scope :order_by_ranking, joins(:user).order("view + scares_count * #{Scare::RANKING_WEIGHT} + comments_count * #{Comment::RANKING_WEIGHT} desc, stories.id desc").includes(:user)
end

ホッとするシンプルなクエリに。

しかし、キャッシュ系によくあることですが、カウンタキャッシュを使っているということをちゃんと意識してないと端からみたらわかり辛いことになるので、現在は一人開発ですが、将来の自分を含めた他人に向けて注意を喚起するコメントを残しておくことにしました。

rails + jenkinsでgithubにpushしたらテストというところまでは下記を参照してください。

ウェブオペレーション継続的デプロイというキャッチーな単語を知ったので試してみた。

kowabana Config [Jenkins]

継続的デプロイなんつっても、上記の様にいつものテストにcapのタスクを追加するだけ。簡単。

kowabana [Jenkins]

githubにpushされると勝手にjenkinsが動き出して…

怖話 | スマホで怖い話

ステージング環境にデプロイ。

これでデザイナーの@machidaさんがgit pushした時も勝手にステージング環境が最新になる。デザインが変わっただけでも頻繁にデプロイされるので問題点などが議論し易い。(特にスマホサイトは実機からアクセス出来る環境があると便利。)

最近はデザイナーも簡単にGithubが使える環境が揃ってきたので、テスト・開発・チェックイン・デプロイというサイクルにデザイナーが入る良いタイミングかも。

デザイナーのためのGithub for Mac の使い方「リポジトリ作成編」 - KUROIGAMEN(黒い画面)

% rake
`include Capybara` is deprecated please use `include Capybara::DSL` instead.

include Capybaraがdeprecatedになってたので指示通り書き換えました。

# test/test_helper.rb:
class ActiveSupport::TestCase  
  (...)
  class ActionDispatch::IntegrationTest 
    include Capybara::DSL      
    Capybara.app = KowabanaJp::Application
  end
end

Unit::TestとCapybaraでのIntegrationTestは簡単なのにちゃんと動く(バグを見つけたりデグレを防ぐ役割をちゃんと果たすという意味で)のでお気に入りです。

Paperclipで画像サイズの最後に使うコレ

has_attached_file :foo, :style => {:thumb => '100x80>'}

いつも意味忘れてググるけどImageMagickのオプションなので下記に書いてある。

Resize or Scaling -- IM v6 Examples

  • Ignore Aspect Ratio ('!')
  • Only Shrink Larger ('>')
  • Only Enlarge Smaller ('<')
  • Fill Given Area ('^')
  • Percentage Resize ('%')
  • Pixel Area Limit ('@')
  • Cropping ('#')

参照:[rails]PaperClipでクロッピング - func09

まだ空きがあるはず!今日はTokyo PayPal Developers Groupのイベントですよ!

PayPal Express Checkout, Subscriptions - Tokyo PayPal Developers Group

セレゴ・ジャパン様がミーティングルームとプロジェクターを貸してくださいました。場所は渋谷駅の北川、セルリアンタワーから歩いて2分ほどです。地図:http://www.cerego.com/en/contact-us/

開場は19:30から、発表の開始は20:00頃です。イベント終了後、おそらく近くのお店で懇親会が行われます。

paypal-express@novさんのお話も絶対聞きたいし、@mreinschさんが作った、簡単にPayPalの定期支払いが出来るRailsプラグインのsubscription_fuも超注目なのです。

っていうか、今やってる仕事のプロジェクトでもsubscription_fu使うので行かなければならないのです。そしてsubscription_fuの低レイヤー部分はpaypal-expressに置き換えられる予定なので両方必聴なのです。