ruby-on-rails - 如何在 Rails 控制器中处理和干燥验证
问题描述
我试图找到一种优雅的方式来处理两个控制器之间的一些共享验证。
例子:
我有两个帐户控制器。一个用于同步处理与用户的帐户关联(例如,使用包含此案例逻辑的 PORO),另一个用于与工作人员异步处理关联。请假设每种情况下的逻辑都不同,并且同步/异步并不是唯一的区别。
然后我有这两个控制器:
module Accounts
class AssociationsController < ApplicationController
def create
return already_associated_account_error if user_has_some_account_associated?
# action = call some account association PORO
render json: action.response, status: action.status_code
end
private
def user_has_some_account_associated?
params[:accounts].any? { |account_number| user_account_associated?(account_number) }
end
def user_account_associated?(account_number)
current_user.accounts.exists?(number: account_number)
end
def already_associated_account_error
render json: 'You already have associated one or more accounts', status: :unprocessable_entity
end
end
end
现在我有另一个控制器,我想在其中应用相同的验证:
module Accounts
class AsyncAssociationsController < ApplicationController
def create
return already_associated_account_error if user_has_some_account_associated?
# Perform asynchronously some account association WORKER
render json: 'Your request is being processed', status: :ok
end
private
def user_has_some_account_associated?
params[:accounts].any? { |account_number| user_account_associated?(account_number) }
end
def user_account_associated?(account_number)
current_user.accounts.exists?(number: account_number)
end
def already_associated_account_error
render json: 'You already have associated one or more accounts', status: :unprocessable_entity
end
end
end
...
我如何以及在何处将验证逻辑仅放置在一个位置并在两个控制器中使用它?我认为首先要解决一个问题,但我不确定它们是否仅适用于这种验证逻辑的情况。
解决方案
为此,您应该使用关注点。这就是它们的设计目的。
在controllers
目录下创建一个concerns
目录(如果它不存在)并在其中创建association_concern.rb
具有以下内容的文件:
module AssociationConcern
extend ActiveSupport::Concern
private
def user_has_some_account_associated?
params[:accounts].any? { |account_number| user_account_associated?(account_number) }
end
def user_account_associated?(account_number)
current_user.accounts.exists?(number: account_number)
end
def already_associated_account_error
render json: 'You already have associated one or more accounts', status: :unprocessable_entity
end
end
控制器共有的任何东西都可以引起关注
然后在你的控制器中简单地include AssociationConcern
class AssociationsController < ApplicationController
include AssociationConcern
def create
return already_associated_account_error if user_has_some_account_associated?
# action = call some account association PORO
render json: action.response, status: action.status_code
end
end
推荐阅读
- python - 有没有办法让 tkinter 单选按钮在 tkinter 画布上透明?
- swift - 将视频大小调整为特定分辨率 Swift
- javascript - 从 Replit 数据库获取密钥不起作用
- reactjs - React State 落后一个状态
- python - Matplotlib - 使用 plt.yscale('log') 绘制内容消失
- javascript - 制作模态库并在 .onclick 时更改图像
- c++ - 为什么在同一个 Visual Studio 解决方案中生成 C++ 调试符号不匹配?
- python - 如何在 discord.py 中创建一个不断变化的 Discord bot 丰富的存在?
- c# - 如何将 cookie Json 添加到 chromdriver [C#]
- ansible - 如何检查日志中的字符串并验证应用程序状态?