Проблемы с отношениями с ActiveRecord has_many через две разные базы данных - PullRequest
0 голосов
/ 23 января 2019

Я пытаюсь настроить отношения 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 в main_db вместо 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'), но не могу понять, как заставить это работать.

Спасибо

Ответы [ 2 ]

0 голосов
/ 24 января 2019

В итоге я понял, как заставить has_many :through использовать правильную базу данных после этого stackoverflow-ответа .

class CompanyCustomPlan < ActiveRecord::Base

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

  belongs_to :custom_plan
  belongs_to :company
end
0 голосов
/ 23 января 2019

При именовании моделей соединения для has_many through: ассоциаций (или моделей в целом, имеющих составные имена) вы должны следовать формату SingularSingular для модели и singular_plural для таблицы. Поэтому вам следует назвать модель CompanyCustomPlan и таблицу 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. Если бы мы использовали has_many :users_courses, мы бы получили NameError: uninitialized constant Users::Courses благодаря тому, что ActiveRecord извлекает имя класса из ассоциации - множественные слова интерпретируются как модули!

Конечно, вы можете переопределить это, предоставив опцию class_name, но, в первую очередь, лучше придерживаться соглашения, если у вас нет веских причин не делать это.

Конечно, вы можете использовать совершенно другое имя для модели соединения, если есть что-то, что лучше описывает домен - например, Enrollment вместо UserCourse.

...