Skip to content

AASMでInvalidTransitionが出る件

AASMをアップデートしたら、テストで例外が出るようになった。
正しくない状態遷移を行うと例外を返すようになったらしい。
AASMの初期化オプションに:whiny_transitions => falseを与えてやればいい。
以下は例。

aasm :column => :aasm_status, :whiny_transitions => false do
  state :prepared, :initial => true
  state :queued
 state :accepted
...
  event :accept do
    transitions :to => :accepted, :from => [:queued]
  end
...
end

この例だと、whiny_transitionsがtrueならpreparedから直接accept!とかすると例外を投げる。
以前は単に遷移せずpreparedのままだった。

まぁ、例外を投げるのが正しい動作だとは思う。作者もそう言ってるみたい
あくまで既存のコードをいじりたくない場合ってことで。

Rails3.1へのアップグレード

諸事情からRails3.0のアプリケーションを3.1にアップグレードした。
「簡単」と書かれていることが多く、Railsの流儀に則っていれば実際簡単なんだけど、それ以外の部分についてだいぶ手間取ったので書いておく。

続きを読む ‘Rails3.1へのアップグレード’ »

unscopedとkaminari

default_scopeを外そうとしてunscopedしてからkaminariのpageオブジェクトにすると奇妙なことになる。

class Item < ActiveRecord::Base
  default_scope where(:closed => nil)
  paginates_per 20
end
> Item.scoped.to_sql
# => "SELECT `items`.* FROM `items` WHERE `items`.`closed` IS NULL"
> Item.scoped.page.to_sql
# => "SELECT `items`.* FROM `items` WHERE `items`.`closed` IS NULL LIMIT 20 OFFSET 0"
> Item.unscoped.to_sql
# => "SELECT `items`.* FROM `items`"
# ここまでは想定通り
> Item.unscoped.page.to_sql
# => "SELECT  `items`.* FROM `items` WHERE `items`.`closed` IS NULL LIMIT 20 OFFSET 0"
# えええなんで?

Rails3.0.10で確認。3.1.3だと直っているので、3.0系のみの問題かな。

回避方法探してstackoverflow漁ったらamatsudaさんが回答してた

> Item.unscoped{ Item.page.to_sql }
# => "SELECT  `items`.* FROM `items` LIMIT 20 OFFSET 0"

3.0系でdefault_scopeは注意した方がいいよねってことで。

controller_specでcookieのテスト

メモ。
controller_specでcookie付きのリクエストをテストするには、

controller.stub!(:cookies).and_return(:some_cookie => { :value => 'cookie_is_here', :expires => 1.hour.from_now })

みたいにstubしてからgetすればOK。

favicon

faviconを設定してないとログに404がずらずら並んで鬱陶しいですね。

そんな時はfaviconを適当に作って、headerに
<%= favicon_link_tag 'favicon.ico' %>
とか書いておけばOK。
rails3.1ならファイルはapp/assets/imagesに置く。

なお、faviconのために毎回インスタンス食われるのはもったいないので、前の記事を参考にnginxで静的ファイルを返すようにしておくのが良いかと。

Facebookアルバムへの投稿

Facebookアプリからアルバムに投稿する方法。
通常のwall postと違って目立つので、アルバムに投げるのが流行ってたりする。
ちなみにpermissionはpublish_streamでOK。

FBGraphにはアルバムに投げるメソッドがあるようだけど、RestGraphにはないため自分で実装しなければならない。
既にやってる人がいるので真似させてもらった。以下のURL参照。

http://forrst.com/posts/post_a_photo_to_the_fb_graph_api_with_ruby-CSa

multipart-postとmyme-typesのgemが必要。
なお、URLを投げても拾ってくれないので、動的に生成される画像についてはローカルにいったん保存してアップロードする必要がある。

Ominauthでtwitter/facebook認証

あけましておめでとうございます。

TwitterとFacebookのどちらでも認証できて、なおかつログイン後にもう一方のアカウントを紐付けできるようにしてみた。

続きを読む ‘Ominauthでtwitter/facebook認証’ »

railsのアップデート

Rails3.1.1のプロダクトをRails3.1.3にアップグレードした時のメモ。

1.Gemfileを書き換える

gem 'rails', '3.1.3'
gem 'rack' , '1.3.5'

しかしrackの最新が幾つなのか分かりにくいな。gem outdatedで出てこないから1.3.5で合ってるんだろうけど。

2.bundle update rails
bundle updateだけだと本体はアップデートされない。

必要なのはここまで。以下は必要なら。

3.rake rails:update
config以下の変更を自動的にやってくれるけど、大抵の場合必要ないと言うか、マイナーアップデートなら手でやった方がいいと思う。

4.rake doc:rails
APIドキュメント生成。いらなければ別に。

 

Agile Web Development with Rails第4版の翻訳がやっと出ますね。楽しみ。

nginx+fastcgi+APC

このサーバのフロントエンドをapacheからnginxに入れ替えた。
passenger経由で動かしていたredmineがとても遅いというクレームがあったのと、最近apacheいじってなくて設定にちょっと不安が出てきたので。つーかnginxのが設定項目が少なくて楽だし。
参考にしたのはここここここ。init scriptとかまんまコピペですいません。

続きを読む ‘nginx+fastcgi+APC’ »

delayed_job

Railsで非同期実行する際の定番、delayed_job
ドキュメントが今一分かりにくかったりforkされまくっててどれがオリジナルか分からなかったりするので、メモしておく。

起動・終了・再起動

bundle exec script/delayed_job start   # 起動
bundle exec script/delayed_job stop    # 終了
bundle exec script/delayed_job restart # 再起動

restartはプロセスが無いと起動してくれないので、stop→startの方が無難。

capistranoのレシピ

namespace :delayed_job do
  desc "Start delayed_job process"
  task :start, :roles => :job do
    run "cd #{current_path}; RAILS_ENV=#{stage} bundle exec script/delayed_job start"
  end

  desc "Stop delayed_job process"
    task :stop, :roles => :job do
    run "cd #{current_path}; RAILS_ENV=#{stage} bundle exec script/delayed_job stop"
  end

  desc "Restart delayed_job process"
    task :restart, :roles => :job do
    run "cd #{current_path}; RAILS_ENV=#{stage} bundle exec script/delayed_job restart"
  end
end

roleはお好みで。appとかやると全サーバで動き始めるのでお勧めしない。

遅延実行

job = Job.new
job.delay.execute

非同期で実行。デフォルトだと5分おき?にリトライされる。

時刻指定実行

job = Job.new
job.send_at Time.zone.now.tomorrow :execute

これくらいで十分ではないかと。
rails runnerで実行してるバッチもdelayed_jobにしたいんだけど(runnerだとRailsのプロセスが丸々一個上がるのでリソースの無駄)、いい方法ないかな。