【问题标题】:superclass mismatch for class User - inheriting from ActiveRecord::Base类 User 的超类不匹配 - 从 ActiveRecord::Base 继承
【发布时间】:2016-10-24 21:42:33
【问题描述】:

我正在尝试找出我的超类不匹配错误。我读过的所有关于此的帖子都将问题描述为 User 在我的应用程序中被定义为一个类两次。

就我而言,它没有定义两次。我有一个服务文件夹,其中有一个用户文件夹(用于用户服务类)。在该用户文件夹中,我有一个名为 organization_mapper_service.rb 的文件,其中包含:

class User < ActiveRecord::Base
      class OrganisationMapperService
        def self.call(user: u)
          new(user: user).call
        end

        def initialize(user: u)
          self.user = user
        end

        def call
          if matching_organisation.present?
            # user.organisation_request.new(organisation_id: matching_organisation.id)
            # user.update_attributes!(organisation_id: matching_organisation.id)
          else
            #SystemMailer.unmatched_organisation(user: user).deliver_now
          end
        end

        private

        attr_accessor :user

        def matching_organisation
          User::OrganisationMapperService.new(user).matching_organisation
        end
      end
    end

除此之外,我的用户模型将用户定义为:

class User < ApplicationRecord

我认为按照我的方式定义服务类应该没问题,因为它继承自 ActiveRecord::Base 而不是 ApplicationRecord。

谁能看到我在这里做错了什么?我还能在哪里寻找用户的第二个定义?

采纳塞尔吉奥的建议

我将用户组织映射器服务改为如下打开:

class User::OrganisationMapperService < ActiveRecord::Base

但这会给我的 Users::OrgRequestsController 一个错误,它的新定义如下:

def new
    @all_organisations    = Organisation.select(:title, :id).map { |org| [org.title, org.id] }
    @org_request = OrgRequest.new#form(OrganisationRequest::Create)

    matched_organisation = User::OrganisationMapperService.new(current_user).matching_organisation
    @org_request.organisation_id = matched_organisation.try(:id)
  end

然后错误消息说:

PG::UndefinedTable at /users/4/org_requests/new
ERROR:  relation "user_organisation_mapper_services" does not exist
LINE 8:                WHERE a.attrelid = '"user_organisation_mapper...

**采纳塞尔吉奥的建议(完全正确)**

我将我的服务类别更改为:

class User::OrganisationMapperService 

然后我收到一条错误消息:

wrong number of arguments (given 1, expected 0)

该错误突出显示了我的服务类的这一行:

def initialize(user: u)
      self.user = user
    end

我不知道该怎么做,因为如果有来自用户的继承,我显然有一个用户。

【问题讨论】:

    标签: ruby-on-rails ruby inheritance activerecord superclass


    【解决方案1】:

    即使你解决了所有其他问题,你实际上也有一个无限递归。

    User::OrganisationMapperService.call(user: User.first)
    

    相当于调用:

    User::OrganisationMapperService.new(user: User.first).call
    

    内部调用matching_organisation,所以有点等价于:

    User::OrganisationMapperService.new(user: User.first).matching_organisation
    

    同时,matching_organisation 调用

    User::OrganisationMapperService.new(user).matching_organisation
    

    它只是会转圈圈。

    它没有的唯一原因是wrong number of arguments (given 1, expected 0) 错误。这是因为在您的 matching_organisation 方法中,它应该是 User::OrganisationMapperService.new(user: user) 而不是 User::OrganisationMapperService.new(user)

    根据评论更新:

    据我了解,User::OrganisationMapperService 是一个服务类,可以找到一些Organisation,然后执行某种工作。

    User::OrganisationMapperService#matching_organisation 方法实际上应该包含返回给定用户的匹配组织的代码。实现将完全取决于您如何构建数据库,但我将给出几个示例以帮助您走上正轨或给您一些想法。

    首先,您的organisations 表可能有一个user_id 列。在这种情况下,您可以对 Organisation 模型进行简单查询并使用用户 ID 执行搜索:

    class User::OrganisationMapperService
      def matching_organisation
        # find the organisation and cache the result
        @matching_organisation ||= ::Organisation.where(user_id: user).first
      end
    end
    

    或者,您可能有某种联接表,其中一个组织中可能有多个用户(仅在此示例中,我们将此表称为“就业”):

    class Employment < ApplicationRecord
      belongs_to :user
      belongs_to :organisation
    end
    

    我们可以在Organisation模型中添加scopes (this is a must read)来辅助查询:

    class Organisation < ApplicationRecord
    
      has_many :employments
      has_many :users, through: :employments 
    
      scope :for_user, ->(user) {
        # return organisations belonging to this user
        joins(:users).merge( Employment.where(user_id: user) )
      }
    
    end
    

    那么最后,OrganisationMapperService#matching_organisation 方法就变成了:

    class User::OrganisationMapperService
      def matching_organisation
        # find the organisation and cache the result
        @matching_organisation ||= ::Organisation.for_user(user).first
      end
    end
    

    【讨论】:

    • hmmm - 听起来我有点超前了。你能给我一些建议,让我试着学习一下,再尝试一下吗?我花了一整天的时间阅读有关递归的内容,我明白你的意思,但现在我不清楚该怎么做才能以更好的方式解决这个问题。
    • 我已经用一些可能有帮助的例子更新了我的答案。显然我只能推断出你想要达到的目标。希望我的示例接近您想要实现的目标。
    • 另外,除了推荐Mastering ActiveRecord and AREL 的链接之外,我认为您已经对服务对象进行了研究,还有什么。我实际上并没有看到太多关于什么是好的服务对象的详细信息的好帖子。他们主要描述他们的什么,诚然这不是很有帮助。他们都提到了单一职责和依赖注入以及其他good 设计实践......真的只是使用你自己的直觉,不要想太多......这可能是一个陷阱。
    • 非常感谢。我再试一次
    【解决方案2】:

    正在用两个独立的父类定义User 类。不要那样做。

    应该是

    class User::OrganisationMapperService
    

    这样,您现有的User 类将被加载和使用,而不是创建一个新类。

    我认为按照我的方式定义服务类应该没问题,因为它继承自 ActiveRecord::Base 而不是 ApplicationRecord。

    您示例中的服务类不继承自任何东西。

    【讨论】:

    • 你的意思是我应该像你那样写,还是应该有:class User::OrganisationMapperService
    • 为什么你认为你需要从activerecord继承服务?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多