【问题标题】:How do I specify the join table on a has_many through association?如何通过关联在 has_many 上指定连接表?
【发布时间】:2015-08-04 17:50:51
【问题描述】:

这是我的表上的架构信息:

  • table_name:admin_users,primary_key:id
  • table_name:UserCompanies,primary_key:UserCompanyId,foreign_keys:[CompanyId, UserId]
  • table_name:Companies,primary_key:CompanyId'

我想做如下的事情:

AdminUser.first.companies

但是,到目前为止,我的尝试都不起作用,我假设是因为我需要指定表名、模型名或键名,但我不知道它如何与 has_many through 关系一起工作。这是我迄今为止定义它的最佳尝试:

class AdminUser < ActiveRecord::Base
    has_many :user_companies, class_name:"TableModule::UserCompany", foreign_key:"UserId"
    has_many :companies, through: :user_companies, class_name: "TableModule::Company"
end

# this code is from a rails engine separate from the app where AdminUser is defined
# the purpose of the engine is to provide access to this particular database 
# the CustomDBConventions class adapts the models for this database to work with ActiveRecord so we can use snake case attributes, reference the primary key as 'id', and it specifies the correct tables names.
module TableModule
    class UserCompany < CustomDBConventions
        belongs_to :admin_user
        belongs_to :company
    end

    class Company < CustomDBConventions
        has_many :admin_users, through: :user_companies
    end

    class CustomDBConventions < ActiveRecord::Base
        self.abstract_class = true
        def self.inherited(subclass)
            super
            subclass.establish_connection "table_module_#{Rails.env}".to_sym
            tb_name = subclass.table_name.to_s.gsub(/^table_module_/,"").classify.pluralize
            subclass.table_name = tb_name
            subclass.primary_key = tb_name.singularize + "Id"
            subclass.alias_attribute :id, subclass.primary_key.to_sym
            subclass.column_names.each do |pascal_name|
                subclass.alias_attribute pascal_name.underscore.to_sym, pascal_name.to_sym
                subclass.alias_attribute "#{pascal_name.underscore}=".to_sym, "#{pascal_name}=".to_sym
            end
        end
    end
end

编辑:所以这个设置非常接近,我只缺少 1 个外键规范。当我运行 AdminUser.first.companies 时出现 sql 错误:

TinyTds::Error: Invalid column name 'company_id'.: EXEC sp_executesql N'SELECT [Companies].* FROM [Companies] INNER JOIN [UserCompanies] ON [Companies].[CompanyId] = [UserCompanies].[company_id ] WHERE [UserCompanies].[UserId] = @0', N'@0 int', @0 = 1

所以我只需要指定在此加入上使用 UserCompanies.CompanyId。如何正确指定此外键?

【问题讨论】:

    标签: ruby-on-rails activerecord active-record-query


    【解决方案1】:

    假设 TableModule::UserCompany 模型具有这些关联...

    class TableModule::UserCompany < ActiveRecord::Base
      belongs_to :admin_user
      belongs_to :company
    end
    

    ...那么我认为这就是你所追求的:

    class AdminUser < ActiveRecord::Base
      has_many :companies, through: :user_company, class_name: "TableModule::UserCompany"
    end
    

    【讨论】:

    • 我试过这个并且得到一个错误“ActiveRecord::HasManyThroughAssociationNotFoundError: 找不到关联:user_company in model AdminUser”
    【解决方案2】:

    我不确定你在用 TableModule 前缀做什么,但以下应该可以工作:

    class AdminUser < ActiveRecord::Base
      has_many :user_companies
      has_many :companies, through: :user_companies
    end
    
    class Company < ActiveRecord::Base
      has_many :user_companies
      has_many :admin_users, through: :user_companies
    end
    
    class UserCompany < ActiveRecord::Base
      belongs_to :admin_user
      belongs_to :comany
    end
    

    【讨论】:

    • 我试过这个并且得到一个错误“ActiveRecord::HasManyThroughAssociationNotFoundError: 找不到关联:user_companies in model AdminUser”
    • 是的,我实际上已经尝试过了,它可以工作,除了有 1 个外键规范仍然不准确。你知道如何指定那个吗?添加关于公司关系的 foreign_key 争论并没有做到这一点。 (见我更新的问题)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多