在两个不同的数据库上遇到与 ActiveRecord has_many 的关系问题

Encountering relationship issues with ActiveRecord has_many through on two different databases

我正在尝试在两个不同的数据库上建立 has_many :through 关系,但遇到了问题。

我的模型如下:

公司:

# this model lives in database main_db
class Company < ActiveRecord::Base
  has_many :company_custom_plans
  has_many :custom_plans, through: :company_custom_plans
end

custom_plan

# this model lives in database other_app_db
class CustomPlan < ActiveRecord::Base
  has_many :company_custom_plans
  has_many :companies, through: :company_custom_plans
end

联合模型:

# this model lives in other_app_db
class CompanyCustomPlan < ActiveRecord::Base
  belongs_to :custom_plan
  belongs_to :company
end

### Schema ###
#  create_table "company_custom_plans", force: :cascade do |t|
#    t.integer "company_id",     limit: 4, null: false
#    t.integer "custom_plan_id", limit: 4, null: false
#  end

所以它在 Company 模型上工作得很好但是当试图在 CustomPlan 上使用这个关系时我得到一个错误因为 has_many :through 在 [= 中寻找 company_custom_plans 17=] 而不是 other_app_db

示例:

ccp = CompanyCustomPlan.create!(company: company, custom_plan: custom_plan)
company.company_custom_plans == [ccp] # true
company.custom_plans == [custom_plan] # true
custom_plan.company_custom_plans == [ccp] # true

custom_plan.companies # error
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'main_db.company_custom_plans' doesn't exist: SHOW FULL FIELDS FROM `company_custom_plans`

我尝试使用 has_many 的不同选项:through(例如设置 source: 'company'),但不知道如何实现。

谢谢,

在为 has_many through: 关联(或具有复合名称的一般模型)命名连接模型时,您应该遵循模型的 SingularSingular 格式和 table。所以你应该命名模型 CompanyCustomPlan 和 table company_custom_plans。这与 has_and_belongs_to_many.

不同

例如:

class User
  has_many :user_courses
  has_many :courses, though: :user_courses
end

class Course
  has_many :user_courses
  has_many :users, though: :user_courses
end

class UserCourse
  belongs_to :user
  belongs_to :course
end

这会将关联正确映射到 UserCourse class。如果我们使用 has_many :users_courses 我们会得到 NameError: uninitialized constant Users::Courses 由于 ActiveRecord 从关联派生 class 名称的方式 - 复数词被解释为模块!

您当然可以通过提供 class_name 选项来覆盖它,但是首先遵循惯例可能是一个更好的主意,除非您有充分的理由不这样做。

如果有更好地描述域的东西,您当然可以为连接模型使用完全不同的名称 - 例如 Enrollment 而不是 UserCourse

我最终弄清楚了如何强制 has_many :throughWhosebug answer 之后使用正确的数据库。

class CompanyCustomPlan < ActiveRecord::Base

  self.table_name = "#{ActiveRecord::Base.connection.current_database}.company_custom_plans"

  belongs_to :custom_plan
  belongs_to :company
end