加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

sql – Rails与子类的STI关联

发布时间:2020-12-12 06:44:10 所属栏目:MsSql教程 来源:网络整理
导读:在使用STI时从rails 3的has_many关联中获取集合时,我遇到了一些奇怪的行为.我有: class Branch ActiveRecord::Base has_many :employees,class_name: 'User::Employee' has_many :admins,class_name: 'User::BranchAdmin'endclass User ActiveRecord::Baseen
在使用STI时从rails 3的has_many关联中获取集合时,我遇到了一些奇怪的行为.我有:
class Branch < ActiveRecord::Base
   has_many :employees,class_name: 'User::Employee'
   has_many :admins,class_name: 'User::BranchAdmin'
end

class User < ActiveRecord::Base
end

class User::Employee < User
  belongs_to :branch
end

class User::BranchAdmin < User::Employee
end

期望的行为是branch.employees返回所有员工,包括分支管理员.当branch.admins访问分支管理员时,它们似乎只在这个集合下被“加载”,这是从控制台输出的:

Branch.first.employees.count
=> 2

Branch.first.admins.count
=> 1

Branch.first.employees.count
=> 3

这可以在生成的SQL中看到,第一次:

SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee') AND "users"."branch_id" = 1

第二次:

SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee','User::BranchAdmin') AND "users"."branch_id" = 1

我只需指定以下内容即可解决此问题:

class Branch < ActiveRecord::Base
   has_many :employees,class_name: 'User'
   has_many :admins,class_name: 'User::BranchAdmin'
end

因为它们都是从他们的branch_id中找到的,但这会在控制器中产生问题,如果我想做branch.employees.build那么该类将默认为User,我必须在某处修改type列.我现在已经解决了这个问题:

has_many :employees,class_name: 'User::Employee',finder_sql: Proc.new{
      %Q(SELECT users.* FROM users WHERE users.type IN          ('User::Employee','User::BranchAdmin') AND users.branch_id = #{id})
    },counter_sql: Proc.new{
      %Q(SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee','User::BranchAdmin') AND "users"."branch_id" = #{id})
    }

但如果可能,我真的想避免这种情况.任何人,任何想法?

编辑:

finder_sql和counter_sql还没有真正解决它,因为看起来父联想似乎没有使用它,所以organisation.employees has_many:employees,通过:: branches将再次只在选择中包含User :: Employee类.

解决方法

基本上,该问题仅存在于根据需要加载类的开发环境中. (在生产中,类被加载并保持可用.)

问题来自于,当您第一次运行Employee.find等调用时,解释器还没有看到Admins是一种Employee.

(请注意,它稍后使用IN(‘User :: Employee’,’User :: BranchAdmin’))

每次使用深度超过一级的模型类时都会发生这种情况,但仅限于开发模式.

子类始终自动加载其父层次结构.基类不会自动加载他们的子级别.

哈克修复:

您可以通过显式要求基类rb文件中的所有子类来强制在dev模式下执行正确的行为.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读