delayed_jobを使う時の注意
delayed_jobを使う時、非同期に実行したいメソッドの前にdelayというメソッドを入れます。
例えば、TestBatchクラスのexecというクラスメソッドがあり、それを非同期に実行させたい場合、
TestBatch.delay.exec
となります。
ただここで注意が必要です。ここでいうexecというメソッドをsendというメソッドにするとエラーをおこします。何故でしょうか?エラーログを見て原因を見た時にdelayed_jobのコードの以下の部分をみて納得しました。
module Delayed class PerformableMethod attr_accessor :object, :method_name, :args delegate :method, :to => :object def initialize(object, method_name, args) raise NoMethodError, "undefined method `#{method_name}' for #{object.inspect}" unless object.respond_to?(method_name, true) if object.respond_to?(:persisted?) && !object.persisted? raise(ArgumentError, "job cannot be created for non-persisted record: #{object.inspect}") end self.object = object self.args = args self.method_name = method_name.to_sym end <途中省略> def perform object.send(method_name, *args) if object end
delayed_job内にもsendメソッドというのがあり、それでエラーに・・・。
sendというメソッド名にするなという話ではありますが、、、
ちょっと戸惑いましたが、原因がわかえればなるほどなーという感じです。
HerokuのpostgresqlのDBをリセットする
以下のコマンドを入れるとHerokuのpostgresqlがリセットされる
heroku pg:reset DATABASE
確認を求めるメッセージが表示されるので、heroku上のアプリの名前を入力する
これでデータベースが初期状態(テーブルがない状態)になる。
テーブルを再度作り直せば、データもまっさらな状態になる
heroku run rake db:migrate
RailsでHTMLメール実装するときにHelperメソッドを使いたい場合
RailsのHTMLメールのテンプレートないでApplicationHelperのメソッドを使おうと思ったが、デフォルトの状態では使えません。
じゃ、どうするかと言えば、app/mailers/以下のクラスに以下の一行を追加すれば良いのです。
HogeMailerというクラスがあるとして
class HogeMailer < ActionMailer::Base add_template_helper(ApplicationHelper) def send ~~~~ end end
ActiveRecordのrewhereメソッド
ちょっとどのような状況で使うのか、まだピンと来ないけどActiveRecordにはrewhereっていうメソッドがある。
これを使うと前に宣言していたwhere条件をoverrideすることができる。
#rewhereを使ってもその前にpointっていうカラムで条件指定してないからoverrideされない Todo.where(title: 'test').rewhere(point: 10) -> SELECT "job_cards".* FROM "job_cards" WHERE "job_cards"."type" IN ('Todo') AND "job_cards"."title" = 'test' AND "job_cards"."point" = 10 #rewhereでtitleの指定を上書き Todo.where(title: 'test').rewhere(title: 'hoge') Todo Load (0.1ms) SELECT "job_cards".* FROM "job_cards" WHERE "job_cards"."type" IN ('Todo') AND "job_cards"."title" = 'hoge'
ActiveRecordのmergeメソッドについて
ActiveRecordでテーブルのjoinをする場合以下のように書くと思います。
User.joins(:auth_providers).all.where(auth_providers: { provider: 'facebook' })
発行されるSQLは次のようになります。
SELECT "users".* FROM "users" INNER JOIN "auth_providers" ON "auth_providers"."user_id" = "users"."id" WHERE "auth_providers"."provider" = 'facebook'
これとは別にmergeメソッドを使う書き方もあります。
まずはモデルにscropを定義します。
class AuthProvider < ActiveRecord::Base belongs_to :user scope :facebook, -> { where(provider: 'facebook') } scope :developer, -> { where(provider: 'developer') } end
でこのscopeとmergeメソッドを使って書くと次のようになります。
User.joins(:auth_providers).all.merge(AuthProvider.facebook)
で、発行されるSQLは次のようになります
SELECT "users".* FROM "users" INNER JOIN "auth_providers" ON "auth_providers"."user_id" = "users"."id" WHERE "auth_providers"."provider" = 'facebook'
同じになりますね。
最初に書いた方のやり方で「.where(auth_providers: { provider: 'facebook' })」と書いているところをmergeメソッドで「.merge(AuthProvider.facebook)」で書くかどうかとういう話ですが、mergeメソッドを使った方が短く書けるから良い気もします。
皆様はどうでしょか?
rubyでメソッドの処理速度をはかるとき
rubyで処理速度をはかる時は以下のようにbenchmarkモジュールを使います。
で、この前Railsのコミットログを眺めていたら、gsubメソッドをtrに置き換えたというのがあったので、
試しに以下のように処理の計測を行ってみました。
require 'benchmark' hoge = 'aaaaaabbbbbceerwrrweqgaga123rgurwfkja' n = 50 Benchmark.bm do |x| # fast x.report { n.times { hoge.tr('aa', 'xx') } } # slow x.report { n.times { hoge.gsub('aa', 'xx') } } end
で、何回か流したのですが、結果は以下のようにtrの方が確かに早いですね。
1回目
user system total real
0.000000 0.000000 0.000000 ( 0.000039)
0.000000 0.000000 0.000000 ( 0.000166)
2回目
user system total real
0.000000 0.000000 0.000000 ( 0.000041)
0.000000 0.000000 0.000000 ( 0.000153)
3回目
user system total real
0.000000 0.000000 0.000000 ( 0.000038)
0.000000 0.000000 0.000000 ( 0.000134)
4回目
user system total real
0.000000 0.000000 0.000000 ( 0.000037)
0.000000 0.000000 0.000000 ( 0.000113)
一番左の値が実際の計測時間になります。
で、それ以外にも書き方によっては速い遅いがあって以下のようにコードを書き換えて幾つか検証してみました
require 'benchmark' hoge = 'aaaaaabbbbbceerwrrweqgaga123rgurwfkja' n = 50 Benchmark.bm do |x| # fast x.report('fast') { n.times { hoge.tr('aa', 'xx') } } # slow x.report('slow') { n.times { hoge.gsub('aa', 'xx') } } end Benchmark.bm do |x| # fast x.report('fast') { n.times { hoge.sub('aa', 'xx') } } # slow x.report('slow') { n.times { hoge.gsub('aa', 'xx') } } end h = { a: 1, b: 2, c: 3 } Benchmark.bm do |x| # fast x.report('fast') { n.times { h.each_key { |k| k } } } # slow x.report('slow') { n.times { h.keys.each { |k| k } } } end Benchmark.bm do |x| # fast x.report('fast') { n.times { a = 1; b = 2 } } # slow x.report('slow') { n.times { a, b = 1, 2 } } end
結果は
user system total real
fast 0.000000 0.000000 0.000000 ( 0.000092)
slow 0.000000 0.000000 0.000000 ( 0.000132)
user system total real
fast 0.000000 0.000000 0.000000 ( 0.000058)
slow 0.000000 0.000000 0.000000 ( 0.000134)
user system total real
fast 0.000000 0.000000 0.000000 ( 0.000018)
slow 0.000000 0.000000 0.000000 ( 0.000019)
user system total real
fast 0.000000 0.000000 0.000000 ( 0.000005)
slow 0.000000 0.000000 0.000000 ( 0.000034)
なるほど、勉強になります。