Rails 5:调用服务类 - 关系映射

时间:2017-02-13 00:35:09

标签: ruby-on-rails ruby service devise

我正在尝试学习如何在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

但这也不起作用。

有谁可以看到我如何设置我的应用程序来调用用户创建的服务类(从注册控制器或任何其他方法)?

1 个答案:

答案 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还是只扫描其中的代码,我希望它可能在某种程度上可以帮助