如何在 Rails 上的 Ruby 中引用模型 class 中的模型实例?
How do you refer an instance of a model in model class in Ruby on Rails?
我正在尝试在 Rails 中引用用户 class 的实例以进行地理编码
class User < ActiveRecord::Base
geocoded_by :address
after_validation GeocodeJob.perform_later(self), if: :address_changed?
end
我要传递的是用户的当前实例。但是很明显,我最终传递的是 class 而不是实例,无法启动我的作业队列。
如何在模型回调中引用和传递用户实例?我知道我可以使用控制器使用实例变量,想知道我是否可以直接作为模型回调进行排队。
根据您当前编写的内容,GeocodeJob.perform_later(self)
将在加载 class 时调用,并且它的 return 值将用作传递给对 [= 的调用的参数12=]。正如你所说,这不是你想要的。
相反,您可以传递一个符号来调用方法,如下所示:
class User < ActiveRecord::Base
geocoded_by :address
after_validation :setup_geocode_job, if: :address_changed?
def setup_gecode_job
GeocodeJob.perform_later(self)
end
end
这将通过调用模型的实例方法来完成您想要的操作,self
将成为模型实例。
参见:http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
直接使用 ActiveRecord 实例作为作业参数肯定是个坏主意。这里的主要问题是将 Ruby 对象序列化为某种可写格式(JSON、YAML 等)。阅读更多内容的链接:
- 阅读来自ActiveJob source code
的评论
- 第一个点来自Sidekiq Best Practices
要在 job worker 上下文中访问 ActiveRecord 实例,最好通过给定的 id 值查找记录:
class GeocodeJob < ActiveJob::Base
def perform(user_id)
user = User.find user_id
# do hard geocode work here
end
end
从回调中开始作业,例如:
class User < ActiveRecord::Base
geocoded_by :address
after_validation if: :address_changed? do |user|
GeocodeJob.perform_later(user.id)
end
end
PS。我强烈建议使用 after_commit
回调而不是 after_validation
,因为有时记录保存过程可能会在其他回调中被取消,或者如果数据库出现问题。这里还有一件事 - 如果用户之前没有被保存过(比如 User.create(...)
),它的实例没有 id 值。
我正在尝试在 Rails 中引用用户 class 的实例以进行地理编码
class User < ActiveRecord::Base
geocoded_by :address
after_validation GeocodeJob.perform_later(self), if: :address_changed?
end
我要传递的是用户的当前实例。但是很明显,我最终传递的是 class 而不是实例,无法启动我的作业队列。
如何在模型回调中引用和传递用户实例?我知道我可以使用控制器使用实例变量,想知道我是否可以直接作为模型回调进行排队。
根据您当前编写的内容,GeocodeJob.perform_later(self)
将在加载 class 时调用,并且它的 return 值将用作传递给对 [= 的调用的参数12=]。正如你所说,这不是你想要的。
相反,您可以传递一个符号来调用方法,如下所示:
class User < ActiveRecord::Base
geocoded_by :address
after_validation :setup_geocode_job, if: :address_changed?
def setup_gecode_job
GeocodeJob.perform_later(self)
end
end
这将通过调用模型的实例方法来完成您想要的操作,self
将成为模型实例。
参见:http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
直接使用 ActiveRecord 实例作为作业参数肯定是个坏主意。这里的主要问题是将 Ruby 对象序列化为某种可写格式(JSON、YAML 等)。阅读更多内容的链接:
- 阅读来自ActiveJob source code 的评论
- 第一个点来自Sidekiq Best Practices
要在 job worker 上下文中访问 ActiveRecord 实例,最好通过给定的 id 值查找记录:
class GeocodeJob < ActiveJob::Base
def perform(user_id)
user = User.find user_id
# do hard geocode work here
end
end
从回调中开始作业,例如:
class User < ActiveRecord::Base
geocoded_by :address
after_validation if: :address_changed? do |user|
GeocodeJob.perform_later(user.id)
end
end
PS。我强烈建议使用 after_commit
回调而不是 after_validation
,因为有时记录保存过程可能会在其他回调中被取消,或者如果数据库出现问题。这里还有一件事 - 如果用户之前没有被保存过(比如 User.create(...)
),它的实例没有 id 值。