Rails has_many :through и has_one :through ассоциации

Сначала я использую Rails 3.1 из ветки 3-1-stable, обновленной час назад.

Я разрабатываю приложение, в котором у меня есть 3 основные модели: Пользователь, Компания и Работа. Вот соответствующая часть моделей:

class User < ActiveRecord::Base
  has_many :companies_users, class_name: "CompaniesUsers"
  has_many :companies, :through => :companies_users, :source => :company
end

class Company < ActiveRecord::Base
  has_many :companies_users, class_name: "CompaniesUsers"
  has_many :employees, :through => :companies_users, :source => :user
  has_many :jobs, :dependent => :destroy
end

class Job < ActiveRecord::Base
  belongs_to :company, :counter_cache => true
end

class CompaniesUsers < ActiveRecord::Base
  belongs_to :company
  belongs_to :user
end

Код работает отлично, но мне было интересно, возможно ли:

Я хочу связать вакансию с работодателем, поэтому подумайте о следующем сценарии: пользователь Джон, который является сотрудником пример. strong>, он разместил вакансию Rails Developer, поэтому я хочу получить доступ к @job.employer, и это должно вернуть мне пользователя John, другими словами:

@user = User.find_by_name('john')
@job   = Job.find(1)
@job.employer == @user       #=> true

Поэтому я подумал о двух возможных решениях

Первое решение

class Job
  has_one :employer, :through => :employers
end

class User
  has_many :jobs, :through => :employers
end

class Employer
  belongs_to :job
  belongs_to :user
end

Второе решение

class Job
  has_one :employer, :class_name => "User"
end

class User
  belongs_to :job
end

По какому маршруту мне идти? Мой код правильный?

У меня другой вопрос, как избавиться от параметра class_name => «CompaniesUsers», переданного has_many, должен ли класс быть в единственном или множественном числе? Должен ли я переименовать его во что-то вроде Employees?

P.S. Тот же вопрос я отправил в Ruby on Rails: Talk.


person kalbasit    schedule 22.06.2011    source источник
comment
Вы хотите, чтобы одна работа принадлежала только одному работодателю (пользователю)?   -  person Dogbert    schedule 22.06.2011
comment
Да, Вакансия должна принадлежать только одному работодателю (Пользователю), а у пользователя может быть много Вакансий. Однако пользователь, которому принадлежит вакансия, должен быть сотрудником компании, в которой размещена вакансия.   -  person kalbasit    schedule 22.06.2011


Ответы (2)


Если я что-то упустил, я бы предложил просто сделать

class Job
  belongs_to :employer, :class_name => "User"
end

class User
  has_many :jobs
end

Это даст вам такие методы, как

user = User.first
user.jobs.create(params)
user.jobs # array
job = user.jobs.first
job.employer == user # true

Чтобы это работало, вам понадобится целочисленное поле employer_id в таблице Jobs.

person Dogbert    schedule 22.06.2011
comment
Проблема в том, что работа уже принадлежит компании (см. мой код выше), поэтому я должен сделать ее полиморфной ассоциацией, верно? Хотя у меня включен :counter_cache для связи между заданием и компанией, как я могу включить это через полиморфную ассоциацию? - person kalbasit; 22.06.2011
comment
Работа, принадлежащая компании, не должна быть проблемой. Это будет храниться в company_id. - person Dogbert; 22.06.2011
comment
В вашей компании много пользователей, а у пользователя много компаний, но работа должна принадлежать только одной компании и одному пользователю, верно? - person Dogbert; 22.06.2011
comment
Именно, вакансия принадлежит одной компании и одному пользователю, а не просто любому пользователю, пользователю, являющемуся сотрудником этой компании.. другими словами company.employee.include?(user) #=› true - person kalbasit; 22.06.2011
comment
Но поскольку у пользователя может быть много компаний, вам придется хранить и компанию, и пользователя в модели работы. Вам, вероятно, потребуется некоторая проверка, чтобы убедиться, что у пользователя действительно есть эта компания. - person Dogbert; 22.06.2011
comment
Итак, я должен реализовать его как own_to/has_many, как описано выше, но добавить некоторую проверку того, что пользователь принадлежит компании, прежде чем сохранять задание? - person kalbasit; 22.06.2011
comment
Да, мне кажется, это единственный выход в данном случае. Можете ли вы придумать лучшую альтернативу? - person Dogbert; 22.06.2011
comment
Я тоже не знаю. Спасибо, я поработаю над этим. Если у меня когда-нибудь возникнут проблемы или у меня появится идея получше, я снова открою вопрос. Спасибо. - person kalbasit; 22.06.2011

Обычно вы хотите назвать свою сквозную модель:

company_user

Тогда вам не нужно это:

class_name: "CompaniesUsers"

Просто убедитесь, что имя вашей таблицы базы данных:

company_users

То, что у вас есть, работает на вас, так что это здорово. Я просто обнаружил, что когда я не следую условностям, я сталкиваюсь с проблемами в будущем.

person jacklin    schedule 03.03.2013