如何在Ruby on Rails的控制器中引用另一个类?

3

我正在尝试在控制器中使用服务类。我无法弄清楚如何在Rails中引用其他类。这是我的users_controller,位于app/controllers/api/v1

class Api::V1::UsersController < ApplicationController
  respond_to :json
  skip_before_filter :verify_authenticity_token
  before_filter :initialize_user_service

  def create
    @service.create
    render json: CustomResponse.new(
      {
        user: @service.user,
      }
    )
  end

  def initialize_user_service
    @service = Services::UserService.new(user_params)
  end

  def user_params
    params.permit(:email, :password, :password_confirmation, :first_name, :last_name)
  end
end

我要引用位于app/services/users_service.rbusers_service.rb类。

class Services::UserService
  attr_reader :session, :user

  def initialize(params)
    # @user_id = params[:id]
    @params = params
  end

  def create
    user = User.create(@params)
    if user.save
      return user
    else
      false
    end
  end
end

但是我在控制台中得到了以下错误:
NameError (uninitialized constant Api::V1::UsersController::Services):

有人知道我该怎么做才能访问这个类吗?我找不到解决方法。我想可能与我的 config/application.rb 文件有关,但我不确定。

6个回答

3
我认为问题出在你的文件名上:app/services/users_service.rb。因为你的类名是UserService,所以应该改成:app/services/user_service.rb(用user_service代替users_service)。 UserService会期望从一个称为user_service.rb的文件中加载这个类。
按照以下方式定义你的服务: 文件名:app/services/user_service.rb。 定义:
module Services
  class UserService
    attr_reader :session, :user

    def initialize(params)
      # @user_id = params[:id]
      @params = params
    end

    def create
      user = User.create(@params)
      if user.save
        return user
      else
        false
      end
    end
  end
end

Services::UserService.new(user_params) 应该按照预期工作。


哇,第六个答案是第一个“几乎”正确的答案 :) 请注意三重检查services目录是否包含在自动加载路径列表中。 - Aleksei Matiushkin
我避免编写该代码,因为app/中的所有子目录默认情况下都是自动加载的(不记得在Rails 4之前的行为)。我错了吗? - kiddorails
1
啊,确实。我错过了它是app/services而不仅仅是services。无论如何,我已经点赞了。 - Aleksei Matiushkin
我尝试添加模块,但它仍然无法工作。如果我删除所有模块/命名空间,只引用UserService,那么它可以工作。但我真的不想这样做。我想使用命名空间。它似乎使代码更有组织性和可维护性。 - hermt2
我已经将文件名更新为user_service.rb - hermt2
你还在使用 class Services::UserService 的方式创建类吗? - kiddorails

0
应该是 ::Services::UserService.new(user_params),Ruby 假设您在 Api::V1 模块中声明了这个类,:: 表示根模块。或者您可以像这样声明您的服务:

class Api::V1::Services::UserService end


错误的。如果 UserService 的名称与文件名相对应,并且路径已包含在自动加载路径中(或文件被显式地要求),Ruby 常量将会成功解析。 - Aleksei Matiushkin
@mudasobwa 谢谢,但是 UserService 在自动加载路径中的文件名不对应。我的答案是针对这个问题的正确解决方案。 - Daniel
不同的文件名会完全阻止自动加载。 - Aleksei Matiushkin

0

我认为这是由于命名空间的定义。只需直接将您的服务类放在服务目录中即可。检查ActiveSupport::Dependencies.autoload_paths以了解包含哪些文件夹的基本概念。即使您正在使用命名空间,也需要更新它的自动加载路径。

config.autoload_paths += %W( #{config.root}/app/your_xyz_path )

-1
定义服务像这样就足够了。不需要为此使用命名空间:
class UserService
end

# using
@service = UserService.new(user_params)

该OP明确表示他们想要使用命名空间。建议“不要使用命名空间”是完全错误的。 - Aleksei Matiushkin
是的,它可以在没有命名空间的情况下工作。但我更喜欢使用它们。 - hermt2

-1

无需定义命名空间,只需使用您的服务名称编写即可,如下所示

class UserService

  attr_reader :session, :user

  def initialize(params)
    # @user_id = params[:id]
    @params = params
  end

  def create
     user = User.create(@params)
       if user.save
            return user
       else
            false
       end
  end

end

并使用 UserService.new(params) 进行调用。 对于生产模式,请在 application.rb 文件中定义,以自动加载服务,如下所示: config.autoload_paths += Dir[Rails.root.join('app', 'services')]


听起来像是“到处使用全局变量!”原帖明确表示他们想要使用命名空间/完全限定名称。建议“不要使用命名空间”对我来说看起来离题了。 - Aleksei Matiushkin
@mudasobwa,他只是询问“Api :: V1 :: UsersController :: Services”的错误是什么,而我并没有建议不使用命名空间,我只是给出了解决错误的方法。 您可以发表自己的意见,请不要根据个人观点对答案进行投票。 - ashvin
请不要告诉我该怎么做。这个答案质量很低,没有解释真正的问题所在,最终也没有解决问题。此外,“我没有建议不使用命名空间”是一个谎言,你可能需要重新阅读你回答的第一句话。 - Aleksei Matiushkin
我不想对你说任何话。 你只是来给所有答案投反对票。 - ashvin
我已经给所有不正确的答案投了反对票,是的。而且我给正确的答案投了赞成票。这就是在SO上投票的方式。 - Aleksei Matiushkin
显示剩余2条评论

-2

app目录下的代码是自动加载的,所有的目录也都是。因此,在您的服务类中不应该有命名空间。

class UserService
end

这应该适用于任何控制器或模型/类,例如

user_service = UserService.new

“不应该没有命名空间” - 这是完全错误的。每个人都有使用命名空间的权利。 - Aleksei Matiushkin
1
在服务类中,如果使用命名空间,则目录结构应与命名空间类似。例如: module Services class UserService end end在这里,目录结构应该是app/services/services/user_service.rb - Parry
这个最后的评论真的很有帮助。谢谢! - Guillermo García López

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接