我正在尝试学习如何在rails 5 app中编写服务类。
当用户使用devise注册时,我正在尝试合并一个服务类,该服务类在创建用户帐户时使模型与用户帐户相关联。
在我的设计注册控制器中,我有:
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_permitted_parameters, if: :devise_controller?
def create
super do |user|
if user.persisted?
User::CompleteRegistration.call(user: user)
end
end
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :email])
devise_parameter_sanitizer.permit(:account_update, keys: [:first_name, :last_name, :email, ])
end
private
end
在我的app / services / user文件夹中,我有一个名为:complete_registration.rb的文件:
class User::CompleteRegistration #< ActiveRecord::Base
def self.call(user: u)
new(user: user).call
end
def initialize(user: u)
self.user = user
end
def call
Profile::SetupService.call(user: user)
Setting::SetupService.call(user: user)
User::OrganisationMapperService.new(user: user).call
end
# def join_an_organisation
# render "organisation_requests/new"
# end
private
attr_accessor :user
end
当我尝试保存并以用户身份注册时,我会看到一条错误消息:
NameError - uninitialized constant User::CompleteRegistrations:
我注意到它已复数“注册”这个词。我不知道这是否与问题有关。我尝试将文件保存为复数,并将该类重命名为复数,但这不起作用。
呈现的实际错误说:
PG::UndefinedTable at /users
ERROR: relation "complete_registration_services" does not exist
LINE 8: WHERE a.attrelid = '"complete_registration_se...
我无法扩展消息以获取更多细节,但没有找到任何关系,因为它不是我想要调用的活动记录表。
我还尝试将回调添加到我的用户模型中作为替代解决方案:
class User < ApplicationRecord
after_update :after_confirmation_setup
def after_confirmation_setup
return unless !self.confirmed_at.blank?
User::CompleteRegistration.call(user: @user)
end
但这也不起作用。
有谁可以看到我如何设置我的应用程序来调用用户创建的服务类(从注册控制器或任何其他方法)?
答案 0 :(得分:1)
从外观上看,这似乎是一个命名问题 从第一次出现(我不能说没有实际使用你的代码库在控制台和调试中),但基于快速扫描并查看你收到的错误这似乎是Ruby的怪癖之一,我已经碰到了一些倍。
您在全局范围内有一个User类(在您的models目录中),并且您有一个服务类User :: CompleteRegistration,当您从某处调用时,假定将指向已定义的User :: CompleteRegistration是完全符合逻辑的类。但是,Ruby并不认为这样。
User::CompleteRegistration
可以分为两部分,首先是User :: Is,并且Ruby搜索User类,并抓取您的模型。然后,它会评估CompleteRegistration,并查找可在User类中使用的已定义的CompleteRegistration。这可能是您收到关系错误的原因。它正在用户模型范围内搜索关系。
所以基本上,当你写User::CompleteRegistration
Ruby并没有说对!让我们抓住一个User :: CompleteRegistration类! Ruby说对!让我们获取一个可以在用户范围内使用的CompleteRegistration类!
为了防止这种情况,我可能会将您的服务命名更改为更简单的内容,例如:Registration::Complete
并避免在全局范围内任何类/模块名称重叠。
同样在旁注,我也非常喜欢在代码中使用服务,而且我真的不想在SO上写一个无耻的插件,但也许你的情况它可以帮助吗?我写了一个gem to provide easy to use services,它的实现与你使用的实现并不太相似,也许它可能有用,无论你是将它用作gem还是只扫描其中的代码,我希望它可能在某种程度上可以帮助