Рельсы "has_one" отношение. Присвоить проект заказчику (метка времени)

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

Отношения между таблицами с has_many работают отлично, но у меня проблема с отношением has_one.

Мои таблицы:

timestamps              customers             projects
----------              ------------          -----------
id:integer              id:integer            id:integer
desc:string             customer_name:string  project_name:string
customer_id:interger    project_id:integer

Мои модели:

timestamp.rb

class Timestamp < ActiveRecord::Base
    has_one :customer
    has_one :project, through: :customer
end

customer.rb

class Customer < ActiveRecord::Base
   belongs_to :timestamp
   has_many :projects, dependent: :destroy
end

project.rb

class Project < ActiveRecord::Base
    belongs_to :customer  
end

Мои цели:

  1. Создайте одну временную метку со связанным клиентом и проектом: Timestamp.create({desc: "Something", customer_id: "1", project_id: "6"})
  2. Получить проект из отметки времени: Timestamp.find(1).customer.project

Моя проблема:

Я могу сделать это, если я добавлю timestamp_id в таблицу проектов, но с помощью этого метода Rails дублирует каждый проект с определенным timestamp_id при создании новой отметки времени. Но я хочу назначить один project_id метке времени.

К вашему сведению: я использую рельсы 4.2.6 с базой данных MYSQL.

2 ответа

Решение

Поскольку вы не хотите иметь дубликаты проектов и дублирующих клиентов на временную метку, вам нужно будет установить только внешние ключи для временной метки. При этом вы хотели бы иметь таблицы со следующими столбцами:

Timestamps
  customer_id:integer:index
  project_id:integer:index

Customers

Projects
  customer_id:integer:index

Вам нужно будет написать и запустить миграцию, чтобы удалить столбцы и добавить столбцы, чтобы это выглядело выше.

Затем измените ассоциации:

class Timestamp < ActiveRecord::Base
  belongs_to :customer # change to belongs_to
  has_many :projects, through: :customer # you might not need this anymore because of the line below
  belongs_to :project # add this line
end

class Customer < ActiveRecord::Base
   has_one :timestamp # change to has_one
   has_many :projects, dependent: :destroy
end

class Project < ActiveRecord::Base
  belongs_to :customer
  has_one :timestamp # add this line
end

Тогда вы можете теперь использовать следующее

Timestamp.find(1).customer
Timestamp.find(1).project
Timestamp.find(1).projects # these projects are customer.projects and are not directly associated to the line above, so I don't think you would need to call this

Хорошо, спасибо всем! @Jay-Ar Polisario, ваш ответ не сработал идеально, но заставил меня задуматься о моих отношениях "has_one / has_many", и из-за этого он сработал после нескольких часов переосмысления этих отношений. Спасибо.

Для всех, кто пришел сюда из Google, чтобы найти ответ на похожую проблему:

Начните рисовать ваши таблицы и столбцы на доске или бумаге. Сделайте отношения визуальными! Это помогло мне выяснить правильные отношения.

Другие вопросы по тегам