ruby-on-rails - 我应该在哪里创建创建后挂钩
问题描述
我有以下型号:
class Page < ApplicationRecord
has_one :architecture
end
class Architecture < ApplicationRecord
belongs_to :page
end
保存新页面后,我需要捕获它的架构(例如段落数)。我想知道这样做的正确方法是什么。我不确定我是否应该让页面模型负责:
class Page < ApplicationRecord
has_one :architecture
after_create :scrape_architecture
private
def scrape_architecture
data = call_something_to_capture_architecture(url)
create_architecture(data)
end
end
class Architecture < ApplicationRecord
belongs_to :page
end
或者如果它应该是架构模型的责任:
class Page < ApplicationRecord
has_one :architecture
after_create :create_architecture
end
class Architecture < ApplicationRecord
belongs_to :page
before_create :scrape_page
private
def scrape_page
data = call_something_to_capture_architecture(page.url)
create(data)
end
end
这实际上是错误的,因为before_create
在验证之后运行 - 由于非空约束导致 MySQL 错误
谢谢你。
解决方案
class PageScrapingJob < ApplicationJob
queue_as :default
def perform(page)
data = call_something_to_capture_architecture(page.url)
architecture = page.create_actitecture(data)
# ...
end
end
保存页面后,您将在控制器中调用服务/作业:
class PagesController < ApplicationController
def create
@page = Page.new(page_params)
if @page.save
PageScrapingJob.perform_now(@page)
redirect_to @page
else
render :new
end
end
end
这使您可以完美地控制何时触发,并避免将更多责任置于模型上。即使您的模型可能包含很少的代码,它们也有大量的职责,例如 ActiveModel 和 ActiveRecord 提供的验证、I18n、表单绑定、脏跟踪等。这个名单真的很长。
相反,这会创建一个离散对象,它只完成一项工作(并且希望做得很好),并且可以独立于控制器进行测试。
推荐阅读
- python - 如何使用 GeoPandas 绘制多个图层
- wpf - WPF Grid ColumnSpan 内容动态宽度重新格式化其他内容
- javascript - 将 QtQuick / QML 对象传递给 javascript 函数后访问其属性
- php - 从页面上的mysql清除所有显示的记录
- node.js - 需要从 Config 属性中选择值 - Node plus react app
- ruby-on-rails - restrict_dependent_destroy 的 I18n 错误消息:插值 %{record} 是小写的,这在德语中的语法不正确
- php - 如何使用 PHP 反射 API 编写和使用 PHP 依赖注入容器
- java - DataOutputStream.writeBytes 产生空指针异常
- jquery - Jquery 自动完成导致未定义错误的“_renderItem”
- powershell - Remove-WebBindings 从所有 IIS 站点中删除绑定